mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-28 06:53:29 +00:00
- backend sync from gzdoom
This commit is contained in:
parent
68ccf7a1c4
commit
090973f8d7
31 changed files with 707 additions and 243 deletions
|
@ -1826,6 +1826,7 @@ void S_SetSoundPaused(int state)
|
||||||
|
|
||||||
if ((state || i_soundinbackground) && !pauseext)
|
if ((state || i_soundinbackground) && !pauseext)
|
||||||
{
|
{
|
||||||
|
if (!paused)
|
||||||
S_ResumeSound(true);
|
S_ResumeSound(true);
|
||||||
if (GSnd != nullptr)
|
if (GSnd != nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -822,9 +822,4 @@ bool FRemapTable::AddColors(int start, int count, const uint8_t*colors, int tran
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// placeholder
|
|
||||||
FTranslationID R_FindCustomTranslation(FName name)
|
|
||||||
{
|
|
||||||
return NO_TRANSLATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -294,6 +294,21 @@ bool FSerializer::BeginObject(const char *name)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
bool FSerializer::HasKey(const char* name)
|
||||||
|
{
|
||||||
|
if (isReading())
|
||||||
|
{
|
||||||
|
return r->FindKey(name) != nullptr;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
bool FSerializer::HasObject(const char* name)
|
bool FSerializer::HasObject(const char* name)
|
||||||
{
|
{
|
||||||
if (isReading())
|
if (isReading())
|
||||||
|
|
|
@ -91,6 +91,7 @@ public:
|
||||||
void ReadObjects(bool hubtravel);
|
void ReadObjects(bool hubtravel);
|
||||||
bool BeginObject(const char *name);
|
bool BeginObject(const char *name);
|
||||||
void EndObject();
|
void EndObject();
|
||||||
|
bool HasKey(const char* name);
|
||||||
bool HasObject(const char* name);
|
bool HasObject(const char* name);
|
||||||
bool BeginArray(const char *name);
|
bool BeginArray(const char *name);
|
||||||
void EndArray();
|
void EndArray();
|
||||||
|
@ -245,6 +246,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundI
|
||||||
FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def);
|
FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def);
|
||||||
FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def);
|
FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def);
|
||||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &mo, struct ModelOverride *def);
|
FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &mo, struct ModelOverride *def);
|
||||||
|
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimModelOverride &mo, struct AnimModelOverride *def);
|
||||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def);
|
FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &ao, struct AnimOverride *def);
|
||||||
FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval);
|
FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval);
|
||||||
|
|
||||||
|
@ -259,6 +261,16 @@ FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **)
|
||||||
return arc;
|
return arc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class A, class B>
|
||||||
|
FSerializer &Serialize(FSerializer &arc, const char *key, std::pair<A, B> &value, std::pair<A, B> *def)
|
||||||
|
{
|
||||||
|
arc.BeginObject(key);
|
||||||
|
Serialize(arc, "first", value.first, def ? &def->first : nullptr);
|
||||||
|
Serialize(arc, "second", value.second, def ? &def->second : nullptr);
|
||||||
|
arc.EndObject();
|
||||||
|
return arc;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T, class TT>
|
template<class T, class TT>
|
||||||
FSerializer &Serialize(FSerializer &arc, const char *key, TArray<T, TT> &value, TArray<T, TT> *def)
|
FSerializer &Serialize(FSerializer &arc, const char *key, TArray<T, TT> &value, TArray<T, TT> *def)
|
||||||
{
|
{
|
||||||
|
|
|
@ -985,6 +985,7 @@ bool OpenDecompressor(FileReader& self, FileReader &parent, FileReader::Size len
|
||||||
// read everything into a MemoryArrayReader.
|
// read everything into a MemoryArrayReader.
|
||||||
FileData data(nullptr, length);
|
FileData data(nullptr, length);
|
||||||
fr->Read(data.writable(), length);
|
fr->Read(data.writable(), length);
|
||||||
|
delete fr;
|
||||||
fr = new MemoryArrayReader(data);
|
fr = new MemoryArrayReader(data);
|
||||||
}
|
}
|
||||||
else if ((flags & DCF_SEEKABLE))
|
else if ((flags & DCF_SEEKABLE))
|
||||||
|
|
|
@ -36,6 +36,18 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -63,14 +75,6 @@ enum
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fnmatch.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
struct findstate_t
|
struct findstate_t
|
||||||
{
|
{
|
||||||
std::string path;
|
std::string path;
|
||||||
|
|
|
@ -43,8 +43,6 @@
|
||||||
#include "texturemanager.h"
|
#include "texturemanager.h"
|
||||||
#include "modelrenderer.h"
|
#include "modelrenderer.h"
|
||||||
|
|
||||||
|
|
||||||
TArray<FString> savedModelFiles;
|
|
||||||
TDeletingArray<FModel*> Models;
|
TDeletingArray<FModel*> Models;
|
||||||
TArray<FSpriteModelFrame> SpriteModelFrames;
|
TArray<FSpriteModelFrame> SpriteModelFrames;
|
||||||
TMap<void*, FSpriteModelFrame> BaseSpriteModelFrames;
|
TMap<void*, FSpriteModelFrame> BaseSpriteModelFrames;
|
||||||
|
@ -160,7 +158,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent)
|
||||||
|
|
||||||
for(unsigned i = 0; i< Models.Size(); i++)
|
for(unsigned i = 0; i< Models.Size(); i++)
|
||||||
{
|
{
|
||||||
if (!Models[i]->mFileName.CompareNoCase(fullname)) return i;
|
if (Models[i]->mFileName.CompareNoCase(fullname) == 0) return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto len = fileSystem.FileLength(lump);
|
auto len = fileSystem.FileLength(lump);
|
||||||
|
@ -236,6 +234,7 @@ unsigned FindModel(const char * path, const char * modelfile, bool silent)
|
||||||
}
|
}
|
||||||
// The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized
|
// The vertex buffer cannot be initialized here because this gets called before OpenGL is initialized
|
||||||
model->mFileName = fullname;
|
model->mFileName = fullname;
|
||||||
|
model->mFilePath = {path, modelfile};
|
||||||
return Models.Push(model);
|
return Models.Push(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct FSpriteModelFrame;
|
||||||
|
|
||||||
FTextureID LoadSkin(const char* path, const char* fn);
|
FTextureID LoadSkin(const char* path, const char* fn);
|
||||||
void FlushModels();
|
void FlushModels();
|
||||||
extern TArray<FString> savedModelFiles;
|
|
||||||
extern TDeletingArray<FModel*> Models;
|
extern TDeletingArray<FModel*> Models;
|
||||||
extern TArray<FSpriteModelFrame> SpriteModelFrames;
|
extern TArray<FSpriteModelFrame> SpriteModelFrames;
|
||||||
extern TMap<void*, FSpriteModelFrame> BaseSpriteModelFrames;
|
extern TMap<void*, FSpriteModelFrame> BaseSpriteModelFrames;
|
||||||
|
@ -76,6 +76,7 @@ enum EFrameError
|
||||||
class FModel
|
class FModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FModel();
|
FModel();
|
||||||
virtual ~FModel();
|
virtual ~FModel();
|
||||||
|
|
||||||
|
@ -100,7 +101,9 @@ public:
|
||||||
void DestroyVertexBuffer();
|
void DestroyVertexBuffer();
|
||||||
|
|
||||||
bool hasSurfaces = false;
|
bool hasSurfaces = false;
|
||||||
|
|
||||||
FString mFileName;
|
FString mFileName;
|
||||||
|
std::pair<FString, FString> mFilePath;
|
||||||
|
|
||||||
FSpriteModelFrame *baseFrame;
|
FSpriteModelFrame *baseFrame;
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -164,6 +164,7 @@ FVoxel *R_LoadKVX(int lumpnum)
|
||||||
auto lump = fileSystem.ReadFile(lumpnum); // FileData adds an extra 0 byte to the end.
|
auto lump = fileSystem.ReadFile(lumpnum); // FileData adds an extra 0 byte to the end.
|
||||||
auto rawvoxel = lump.bytes();
|
auto rawvoxel = lump.bytes();
|
||||||
int voxelsize = (int)(lump.size());
|
int voxelsize = (int)(lump.size());
|
||||||
|
if (voxelsize <= 768 + 4) return nullptr;
|
||||||
|
|
||||||
// Oh, KVX, why couldn't you have a proper header? We'll just go through
|
// Oh, KVX, why couldn't you have a proper header? We'll just go through
|
||||||
// and collect each MIP level, doing lots of range checking, and if the
|
// and collect each MIP level, doing lots of range checking, and if the
|
||||||
|
|
|
@ -359,54 +359,49 @@ size_t DObject::PropagateMark()
|
||||||
const PClass *info = GetClass();
|
const PClass *info = GetClass();
|
||||||
if (!PClass::bShutdown)
|
if (!PClass::bShutdown)
|
||||||
{
|
{
|
||||||
const size_t *offsets = info->FlatPointers;
|
if (info->FlatPointers == nullptr)
|
||||||
if (offsets == NULL)
|
|
||||||
{
|
{
|
||||||
const_cast<PClass *>(info)->BuildFlatPointers();
|
info->BuildFlatPointers();
|
||||||
offsets = info->FlatPointers;
|
assert(info->FlatPointers);
|
||||||
}
|
|
||||||
while (*offsets != ~(size_t)0)
|
|
||||||
{
|
|
||||||
GC::Mark((DObject **)((uint8_t *)this + *offsets));
|
|
||||||
offsets++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
offsets = info->ArrayPointers;
|
for(size_t i = 0; i < info->FlatPointersSize; i++)
|
||||||
if (offsets == NULL)
|
|
||||||
{
|
{
|
||||||
const_cast<PClass *>(info)->BuildArrayPointers();
|
GC::Mark((DObject **)((uint8_t *)this + info->FlatPointers[i].first));
|
||||||
offsets = info->ArrayPointers;
|
|
||||||
}
|
}
|
||||||
while (*offsets != ~(size_t)0)
|
|
||||||
|
if (info->ArrayPointers == nullptr)
|
||||||
{
|
{
|
||||||
auto aray = (TArray<DObject*>*)((uint8_t *)this + *offsets);
|
info->BuildArrayPointers();
|
||||||
|
assert(info->ArrayPointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < info->ArrayPointersSize; i++)
|
||||||
|
{
|
||||||
|
auto aray = (TArray<DObject*>*)((uint8_t *)this + info->ArrayPointers[i].first);
|
||||||
for (auto &p : *aray)
|
for (auto &p : *aray)
|
||||||
{
|
{
|
||||||
GC::Mark(&p);
|
GC::Mark(&p);
|
||||||
}
|
}
|
||||||
offsets++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->MapPointers == nullptr)
|
||||||
{
|
{
|
||||||
const std::pair<size_t,PType *> *maps = info->MapPointers;
|
info->BuildMapPointers();
|
||||||
if (maps == NULL)
|
assert(info->MapPointers);
|
||||||
{
|
|
||||||
const_cast<PClass *>(info)->BuildMapPointers();
|
|
||||||
maps = info->MapPointers;
|
|
||||||
}
|
}
|
||||||
while (maps->first != ~(size_t)0)
|
|
||||||
|
for(size_t i = 0; i < info->MapPointersSize; i++)
|
||||||
{
|
{
|
||||||
if(maps->second->RegType == REGT_STRING)
|
PMap * type = static_cast<PMap*>(info->MapPointers[i].second);
|
||||||
|
if(type->KeyType->RegType == REGT_STRING)
|
||||||
{ // FString,DObject*
|
{ // FString,DObject*
|
||||||
PropagateMarkMap((ZSMap<FString,DObject*>*)((uint8_t *)this + maps->first));
|
PropagateMarkMap((ZSMap<FString,DObject*>*)((uint8_t *)this + info->MapPointers[i].first));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // uint32_t,DObject*
|
{ // uint32_t,DObject*
|
||||||
PropagateMarkMap((ZSMap<uint32_t,DObject*>*)((uint8_t *)this + maps->first));
|
PropagateMarkMap((ZSMap<uint32_t,DObject*>*)((uint8_t *)this + info->MapPointers[i].first));
|
||||||
}
|
}
|
||||||
maps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return info->Size;
|
return info->Size;
|
||||||
}
|
}
|
||||||
|
@ -419,46 +414,116 @@ size_t DObject::PropagateMark()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
|
template<typename M>
|
||||||
|
static void MapPointerSubstitution(M *map, size_t &changed, DObject *old, DObject *notOld, const bool shouldSwap)
|
||||||
{
|
{
|
||||||
const PClass *info = GetClass();
|
TMapIterator<typename M::KeyType, DObject*> it(*map);
|
||||||
const size_t *offsets = info->FlatPointers;
|
typename M::Pair * p;
|
||||||
size_t changed = 0;
|
while(it.NextPair(p))
|
||||||
if (offsets == NULL)
|
|
||||||
{
|
{
|
||||||
const_cast<PClass *>(info)->BuildFlatPointers();
|
if (p->Value == old)
|
||||||
offsets = info->FlatPointers;
|
|
||||||
}
|
|
||||||
while (*offsets != ~(size_t)0)
|
|
||||||
{
|
{
|
||||||
if (*(DObject **)((uint8_t *)this + *offsets) == old)
|
if (shouldSwap)
|
||||||
{
|
{
|
||||||
*(DObject **)((uint8_t *)this + *offsets) = notOld;
|
p->Value = notOld;
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
offsets++;
|
else if (p->Value != nullptr)
|
||||||
|
{
|
||||||
|
p->Value = nullptr;
|
||||||
|
changed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
offsets = info->ArrayPointers;
|
size_t DObject::PointerSubstitution (DObject *old, DObject *notOld, bool nullOnFail)
|
||||||
if (offsets == NULL)
|
|
||||||
{
|
{
|
||||||
const_cast<PClass *>(info)->BuildArrayPointers();
|
const PClass *info = GetClass();
|
||||||
offsets = info->ArrayPointers;
|
size_t changed = 0;
|
||||||
|
if (info->FlatPointers == nullptr)
|
||||||
|
{
|
||||||
|
info->BuildFlatPointers();
|
||||||
|
assert(info->FlatPointers);
|
||||||
}
|
}
|
||||||
while (*offsets != ~(size_t)0)
|
|
||||||
|
for(size_t i = 0; i < info->FlatPointersSize; i++)
|
||||||
{
|
{
|
||||||
auto aray = (TArray<DObject*>*)((uint8_t *)this + *offsets);
|
size_t offset = info->FlatPointers[i].first;
|
||||||
|
auto& obj = *(DObject**)((uint8_t*)this + offset);
|
||||||
|
|
||||||
|
if (obj == old)
|
||||||
|
{
|
||||||
|
// If a pointer's type is null, that means it's native and anything native is safe to swap
|
||||||
|
// around due to its inherit type expansiveness.
|
||||||
|
if (info->FlatPointers[i].second == nullptr || notOld->IsKindOf(info->FlatPointers[i].second->PointedClass()))
|
||||||
|
{
|
||||||
|
obj = notOld;
|
||||||
|
changed++;
|
||||||
|
}
|
||||||
|
else if (nullOnFail && obj != nullptr)
|
||||||
|
{
|
||||||
|
obj = nullptr;
|
||||||
|
changed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->ArrayPointers == nullptr)
|
||||||
|
{
|
||||||
|
info->BuildArrayPointers();
|
||||||
|
assert(info->ArrayPointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < info->ArrayPointersSize; i++)
|
||||||
|
{
|
||||||
|
const bool isType = notOld->IsKindOf(static_cast<PObjectPointer*>(info->ArrayPointers[i].second->ElementType)->PointedClass());
|
||||||
|
|
||||||
|
if (!isType && !nullOnFail)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto aray = (TArray<DObject*>*)((uint8_t*)this + info->ArrayPointers[i].first);
|
||||||
for (auto &p : *aray)
|
for (auto &p : *aray)
|
||||||
{
|
{
|
||||||
if (p == old)
|
if (p == old)
|
||||||
|
{
|
||||||
|
if (isType)
|
||||||
{
|
{
|
||||||
p = notOld;
|
p = notOld;
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
|
else if (p != nullptr)
|
||||||
|
{
|
||||||
|
p = nullptr;
|
||||||
|
changed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
offsets++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->MapPointers == nullptr)
|
||||||
|
{
|
||||||
|
info->BuildMapPointers();
|
||||||
|
assert(info->MapPointers);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < info->MapPointersSize; i++)
|
||||||
|
{
|
||||||
|
PMap * type = static_cast<PMap*>(info->MapPointers[i].second);
|
||||||
|
|
||||||
|
const bool isType = notOld->IsKindOf(static_cast<PObjectPointer*>(type->ValueType)->PointedClass());
|
||||||
|
if (!isType && !nullOnFail)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(type->KeyType->RegType == REGT_STRING)
|
||||||
|
{ // FString,DObject*
|
||||||
|
MapPointerSubstitution((ZSMap<FString,DObject*>*)((uint8_t *)this + info->MapPointers[i].first), changed, old, notOld, isType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // uint32_t,DObject*
|
||||||
|
MapPointerSubstitution((ZSMap<uint32_t,DObject*>*)((uint8_t *)this + info->MapPointers[i].first), changed, old, notOld, isType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,7 @@ public:
|
||||||
inline int* IntArray(FName field);
|
inline int* IntArray(FName field);
|
||||||
|
|
||||||
// This is only needed for swapping out PlayerPawns and absolutely nothing else!
|
// This is only needed for swapping out PlayerPawns and absolutely nothing else!
|
||||||
virtual size_t PointerSubstitution (DObject *old, DObject *notOld);
|
virtual size_t PointerSubstitution (DObject *old, DObject *notOld, bool nullOnFail);
|
||||||
|
|
||||||
PClass *GetClass() const
|
PClass *GetClass() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -214,6 +214,9 @@ class TObjPtr
|
||||||
mutable DObject *o;
|
mutable DObject *o;
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
|
TObjPtr() = default;
|
||||||
|
|
||||||
|
TObjPtr(T t) : pp(t) {}
|
||||||
|
|
||||||
constexpr TObjPtr<T>& operator=(T q) noexcept
|
constexpr TObjPtr<T>& operator=(T q) noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,9 +80,7 @@ DEFINE_GLOBAL(WP_NOCHANGE);
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
// A harmless non-nullptr FlatPointer for classes without pointers.
|
// A harmless non-nullptr FlatPointer for classes without pointers.
|
||||||
static const size_t TheEnd = ~(size_t)0;
|
static const std::pair<size_t,PType *> TheEnd = {~(size_t)0 , nullptr};
|
||||||
|
|
||||||
static const std::pair<size_t,PType *> TheMapEnd = {~(size_t)0 , nullptr};
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -669,7 +667,7 @@ PClass *PClass::FindClassTentative(FName name)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType)
|
int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType, bool ignorePointerReadOnly)
|
||||||
{
|
{
|
||||||
auto proto = variant->Proto;
|
auto proto = variant->Proto;
|
||||||
for (unsigned i = 0; i < Virtuals.Size(); i++)
|
for (unsigned i = 0; i < Virtuals.Size(); i++)
|
||||||
|
@ -688,11 +686,25 @@ int PClass::FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction
|
||||||
for (unsigned a = 1; a < proto->ArgumentTypes.Size(); a++)
|
for (unsigned a = 1; a < proto->ArgumentTypes.Size(); a++)
|
||||||
{
|
{
|
||||||
if (proto->ArgumentTypes[a] != vproto->ArgumentTypes[a])
|
if (proto->ArgumentTypes[a] != vproto->ArgumentTypes[a])
|
||||||
|
{
|
||||||
|
if(ignorePointerReadOnly && proto->ArgumentTypes[a]->isPointer() && vproto->ArgumentTypes[a]->isPointer())
|
||||||
|
{
|
||||||
|
PPointer *ppa = proto->ArgumentTypes[a]->toPointer();
|
||||||
|
PPointer *ppb = vproto->ArgumentTypes[a]->toPointer();
|
||||||
|
|
||||||
|
if(ppa->PointedType != ppb->PointedType)
|
||||||
{
|
{
|
||||||
fail = true;
|
fail = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fail = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fail) continue;
|
if (fail) continue;
|
||||||
|
|
||||||
for (unsigned a = 0; a < proto->ReturnTypes.Size(); a++)
|
for (unsigned a = 0; a < proto->ReturnTypes.Size(); a++)
|
||||||
|
@ -752,28 +764,46 @@ PSymbol *PClass::FindSymbol(FName symname, bool searchparents) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PClass::BuildFlatPointers ()
|
void PClass::BuildFlatPointers() const
|
||||||
{
|
{
|
||||||
|
using pairType = std::pair<size_t, PObjectPointer *>;
|
||||||
|
|
||||||
if (FlatPointers != nullptr)
|
if (FlatPointers != nullptr)
|
||||||
{ // Already built: Do nothing.
|
{ // Already built: Do nothing.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ParentClass == nullptr)
|
else
|
||||||
{ // No parent (i.e. DObject: FlatPointers is the same as Pointers.
|
{
|
||||||
if (Pointers == nullptr)
|
TArray<pairType> NativePointers;
|
||||||
|
if (Pointers != nullptr)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; Pointers[i] != ~(size_t)0; i++)
|
||||||
|
{
|
||||||
|
NativePointers.Push({Pointers[i], nullptr}); // native pointers have a null type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParentClass == nullptr)
|
||||||
|
{ // No parent (i.e. DObject): FlatPointers is the same as Pointers.
|
||||||
|
if (NativePointers.Size() == 0)
|
||||||
{ // No pointers: Make FlatPointers a harmless non-nullptr.
|
{ // No pointers: Make FlatPointers a harmless non-nullptr.
|
||||||
FlatPointers = &TheEnd;
|
FlatPointers = (pairType*)(&TheEnd);
|
||||||
|
FlatPointersSize = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FlatPointers = Pointers;
|
pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * NativePointers.Size());
|
||||||
|
memcpy(flat, NativePointers.Data(), sizeof(pairType) * NativePointers.Size());
|
||||||
|
|
||||||
|
FlatPointers = flat;
|
||||||
|
FlatPointersSize = NativePointers.Size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParentClass->BuildFlatPointers();
|
ParentClass->BuildFlatPointers();
|
||||||
|
|
||||||
TArray<size_t> ScriptPointers;
|
TArray<pairType> ScriptPointers;
|
||||||
|
|
||||||
// Collect all pointers in scripted fields. These are not part of the Pointers list.
|
// Collect all pointers in scripted fields. These are not part of the Pointers list.
|
||||||
for (auto field : Fields)
|
for (auto field : Fields)
|
||||||
|
@ -784,43 +814,31 @@ void PClass::BuildFlatPointers ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Pointers == nullptr && ScriptPointers.Size() == 0)
|
if (NativePointers.Size() == 0 && ScriptPointers.Size() == 0)
|
||||||
{ // No new pointers: Just use the same FlatPointers as the parent.
|
{ // No new pointers: Just use the same FlatPointers as the parent.
|
||||||
FlatPointers = ParentClass->FlatPointers;
|
FlatPointers = ParentClass->FlatPointers;
|
||||||
|
FlatPointersSize = ParentClass->FlatPointersSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // New pointers: Create a new FlatPointers array and add them.
|
{ // New pointers: Create a new FlatPointers array and add them.
|
||||||
int numPointers, numSuperPointers;
|
|
||||||
|
|
||||||
if (Pointers != nullptr)
|
|
||||||
{
|
|
||||||
// Count pointers defined by this class.
|
|
||||||
for (numPointers = 0; Pointers[numPointers] != ~(size_t)0; numPointers++)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else numPointers = 0;
|
|
||||||
|
|
||||||
// Count pointers defined by superclasses.
|
|
||||||
for (numSuperPointers = 0; ParentClass->FlatPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
// Concatenate them into a new array
|
// Concatenate them into a new array
|
||||||
size_t *flat = (size_t*)ClassDataAllocator.Alloc(sizeof(size_t) * (numPointers + numSuperPointers + ScriptPointers.Size() + 1));
|
pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * (ParentClass->FlatPointersSize + NativePointers.Size() + ScriptPointers.Size()));
|
||||||
if (numSuperPointers > 0)
|
|
||||||
|
if (ParentClass->FlatPointersSize > 0)
|
||||||
{
|
{
|
||||||
memcpy (flat, ParentClass->FlatPointers, sizeof(size_t)*numSuperPointers);
|
memcpy (flat, ParentClass->FlatPointers, sizeof(pairType) * ParentClass->FlatPointersSize);
|
||||||
}
|
}
|
||||||
if (numPointers > 0)
|
if (NativePointers.Size() > 0)
|
||||||
{
|
{
|
||||||
memcpy(flat + numSuperPointers, Pointers, sizeof(size_t)*numPointers);
|
memcpy(flat + ParentClass->FlatPointersSize, NativePointers.Data(), sizeof(pairType) * NativePointers.Size());
|
||||||
}
|
}
|
||||||
if (ScriptPointers.Size() > 0)
|
if (ScriptPointers.Size() > 0)
|
||||||
{
|
{
|
||||||
memcpy(flat + numSuperPointers + numPointers, &ScriptPointers[0], sizeof(size_t) * ScriptPointers.Size());
|
memcpy(flat + ParentClass->FlatPointersSize + NativePointers.Size(), &ScriptPointers[0], sizeof(pairType) * ScriptPointers.Size());
|
||||||
}
|
}
|
||||||
flat[numSuperPointers + numPointers + ScriptPointers.Size()] = ~(size_t)0;
|
|
||||||
FlatPointers = flat;
|
FlatPointers = flat;
|
||||||
|
FlatPointersSize = ParentClass->FlatPointersSize + NativePointers.Size() + ScriptPointers.Size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -833,21 +851,24 @@ void PClass::BuildFlatPointers ()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PClass::BuildArrayPointers()
|
void PClass::BuildArrayPointers() const
|
||||||
{
|
{
|
||||||
|
using pairType = std::pair<size_t, PDynArray *>;
|
||||||
|
|
||||||
if (ArrayPointers != nullptr)
|
if (ArrayPointers != nullptr)
|
||||||
{ // Already built: Do nothing.
|
{ // Already built: Do nothing.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ParentClass == nullptr)
|
else if (ParentClass == nullptr)
|
||||||
{ // No parent (i.e. DObject: FlatPointers is the same as Pointers.
|
{ // No parent (i.e. DObject): Make ArrayPointers a harmless non-nullptr.
|
||||||
ArrayPointers = &TheEnd;
|
ArrayPointers = (pairType*)(&TheEnd);
|
||||||
|
ArrayPointersSize = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParentClass->BuildArrayPointers();
|
ParentClass->BuildArrayPointers();
|
||||||
|
|
||||||
TArray<size_t> ScriptPointers;
|
TArray<pairType> ScriptPointers;
|
||||||
|
|
||||||
// Collect all arrays to pointers in scripted fields.
|
// Collect all arrays to pointers in scripted fields.
|
||||||
for (auto field : Fields)
|
for (auto field : Fields)
|
||||||
|
@ -861,28 +882,24 @@ void PClass::BuildArrayPointers()
|
||||||
if (ScriptPointers.Size() == 0)
|
if (ScriptPointers.Size() == 0)
|
||||||
{ // No new pointers: Just use the same ArrayPointers as the parent.
|
{ // No new pointers: Just use the same ArrayPointers as the parent.
|
||||||
ArrayPointers = ParentClass->ArrayPointers;
|
ArrayPointers = ParentClass->ArrayPointers;
|
||||||
|
ArrayPointersSize = ParentClass->ArrayPointersSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // New pointers: Create a new FlatPointers array and add them.
|
{ // New pointers: Create a new ArrayPointers array and add them.
|
||||||
int numSuperPointers;
|
|
||||||
|
|
||||||
// Count pointers defined by superclasses.
|
|
||||||
for (numSuperPointers = 0; ParentClass->ArrayPointers[numSuperPointers] != ~(size_t)0; numSuperPointers++)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Concatenate them into a new array
|
// Concatenate them into a new array
|
||||||
size_t *flat = (size_t*)ClassDataAllocator.Alloc(sizeof(size_t) * (numSuperPointers + ScriptPointers.Size() + 1));
|
pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * (ParentClass->ArrayPointersSize + ScriptPointers.Size()));
|
||||||
if (numSuperPointers > 0)
|
if (ParentClass->ArrayPointersSize > 0)
|
||||||
{
|
{
|
||||||
memcpy(flat, ParentClass->ArrayPointers, sizeof(size_t)*numSuperPointers);
|
memcpy(flat, ParentClass->ArrayPointers, sizeof(pairType) * ParentClass->ArrayPointersSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ScriptPointers.Size() > 0)
|
if (ScriptPointers.Size() > 0)
|
||||||
{
|
{
|
||||||
memcpy(flat + numSuperPointers, &ScriptPointers[0], sizeof(size_t) * ScriptPointers.Size());
|
memcpy(flat + ParentClass->ArrayPointersSize, ScriptPointers.Data(), sizeof(pairType) * ScriptPointers.Size());
|
||||||
}
|
}
|
||||||
flat[numSuperPointers + ScriptPointers.Size()] = ~(size_t)0;
|
|
||||||
ArrayPointers = flat;
|
ArrayPointers = flat;
|
||||||
|
ArrayPointersSize = ParentClass->ArrayPointersSize + ScriptPointers.Size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -895,21 +912,24 @@ void PClass::BuildArrayPointers()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PClass::BuildMapPointers()
|
void PClass::BuildMapPointers() const
|
||||||
{
|
{
|
||||||
|
using pairType = std::pair<size_t, PMap *>;
|
||||||
|
|
||||||
if (MapPointers != nullptr)
|
if (MapPointers != nullptr)
|
||||||
{ // Already built: Do nothing.
|
{ // Already built: Do nothing.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (ParentClass == nullptr)
|
else if (ParentClass == nullptr)
|
||||||
{ // No parent (i.e. DObject: FlatPointers is the same as Pointers.
|
{ // No parent (i.e. DObject): Make MapPointers a harmless non-nullptr.
|
||||||
MapPointers = &TheMapEnd;
|
MapPointers = (pairType*)(&TheEnd);
|
||||||
|
MapPointersSize = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ParentClass->BuildMapPointers();
|
ParentClass->BuildMapPointers();
|
||||||
|
|
||||||
TArray<std::pair<size_t,PType *>> ScriptPointers;
|
TArray<pairType> ScriptPointers;
|
||||||
|
|
||||||
// Collect all arrays to pointers in scripted fields.
|
// Collect all arrays to pointers in scripted fields.
|
||||||
for (auto field : Fields)
|
for (auto field : Fields)
|
||||||
|
@ -923,28 +943,23 @@ void PClass::BuildMapPointers()
|
||||||
if (ScriptPointers.Size() == 0)
|
if (ScriptPointers.Size() == 0)
|
||||||
{ // No new pointers: Just use the same ArrayPointers as the parent.
|
{ // No new pointers: Just use the same ArrayPointers as the parent.
|
||||||
MapPointers = ParentClass->MapPointers;
|
MapPointers = ParentClass->MapPointers;
|
||||||
|
MapPointersSize = ParentClass->MapPointersSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // New pointers: Create a new FlatPointers array and add them.
|
{ // New pointers: Create a new FlatPointers array and add them.
|
||||||
int numSuperPointers;
|
|
||||||
|
|
||||||
// Count pointers defined by superclasses.
|
|
||||||
for (numSuperPointers = 0; ParentClass->MapPointers[numSuperPointers].first != ~(size_t)0; numSuperPointers++)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Concatenate them into a new array
|
// Concatenate them into a new array
|
||||||
std::pair<size_t,PType *> *flat = (std::pair<size_t,PType *>*)ClassDataAllocator.Alloc(sizeof(std::pair<size_t,PType *>) * (numSuperPointers + ScriptPointers.Size() + 1));
|
pairType *flat = (pairType*)ClassDataAllocator.Alloc(sizeof(pairType) * (ParentClass->MapPointersSize + ScriptPointers.Size()));
|
||||||
if (numSuperPointers > 0)
|
if (ParentClass->MapPointersSize > 0)
|
||||||
{
|
{
|
||||||
memcpy(flat, ParentClass->MapPointers, sizeof(std::pair<size_t,PType *>)*numSuperPointers);
|
memcpy(flat, ParentClass->MapPointers, sizeof(pairType) * ParentClass->MapPointersSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ScriptPointers.Size() > 0)
|
if (ScriptPointers.Size() > 0)
|
||||||
{
|
{
|
||||||
memcpy(flat + numSuperPointers, &ScriptPointers[0], sizeof(std::pair<size_t,PType *>) * ScriptPointers.Size());
|
memcpy(flat + ParentClass->MapPointersSize, ScriptPointers.Data(), sizeof(pairType) * ScriptPointers.Size());
|
||||||
}
|
}
|
||||||
flat[numSuperPointers + ScriptPointers.Size()] = TheMapEnd;
|
|
||||||
MapPointers = flat;
|
MapPointers = flat;
|
||||||
|
MapPointersSize = ParentClass->MapPointersSize + ScriptPointers.Size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ class PClassType;
|
||||||
struct FNamespaceManager;
|
struct FNamespaceManager;
|
||||||
class PSymbol;
|
class PSymbol;
|
||||||
class PField;
|
class PField;
|
||||||
|
class PObjectPointer;
|
||||||
|
class PDynArray;
|
||||||
|
class PMap;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -43,7 +46,7 @@ public:
|
||||||
void InitializeSpecials(void* addr, void* defaults, TArray<FTypeAndOffset> PClass::* Inits);
|
void InitializeSpecials(void* addr, void* defaults, TArray<FTypeAndOffset> PClass::* Inits);
|
||||||
void WriteAllFields(FSerializer &ar, const void *addr) const;
|
void WriteAllFields(FSerializer &ar, const void *addr) const;
|
||||||
bool ReadAllFields(FSerializer &ar, void *addr) const;
|
bool ReadAllFields(FSerializer &ar, void *addr) const;
|
||||||
int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType);
|
int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType, bool ignorePointerReadOnly);
|
||||||
PSymbol *FindSymbol(FName symname, bool searchparents) const;
|
PSymbol *FindSymbol(FName symname, bool searchparents) const;
|
||||||
PField *AddField(FName name, PType *type, uint32_t flags, int fileno = 0);
|
PField *AddField(FName name, PType *type, uint32_t flags, int fileno = 0);
|
||||||
void InitializeDefaults();
|
void InitializeDefaults();
|
||||||
|
@ -53,10 +56,15 @@ public:
|
||||||
|
|
||||||
// Per-class information -------------------------------------
|
// Per-class information -------------------------------------
|
||||||
PClass *ParentClass = nullptr; // the class this class derives from
|
PClass *ParentClass = nullptr; // the class this class derives from
|
||||||
const size_t *Pointers = nullptr; // object pointers defined by this class *only*
|
const size_t * Pointers = nullptr; // native object pointers defined by this class *only*
|
||||||
const size_t *FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default
|
|
||||||
const size_t *ArrayPointers = nullptr; // dynamic arrays containing object pointers.
|
mutable size_t FlatPointersSize = 0;
|
||||||
const std::pair<size_t,PType *> *MapPointers = nullptr; // maps containing object pointers.
|
mutable const std::pair<size_t, PObjectPointer*> * FlatPointers = nullptr; // object pointers defined by this class and all its superclasses; not initialized by default.
|
||||||
|
mutable size_t ArrayPointersSize = 0;
|
||||||
|
mutable const std::pair<size_t, PDynArray *> * ArrayPointers = nullptr; // dynamic arrays containing object pointers.
|
||||||
|
mutable size_t MapPointersSize = 0;
|
||||||
|
mutable const std::pair<size_t, PMap *> * MapPointers = nullptr; // maps containing object pointers.
|
||||||
|
|
||||||
uint8_t *Defaults = nullptr;
|
uint8_t *Defaults = nullptr;
|
||||||
uint8_t *Meta = nullptr; // Per-class static script data
|
uint8_t *Meta = nullptr; // Per-class static script data
|
||||||
unsigned Size = sizeof(DObject);
|
unsigned Size = sizeof(DObject);
|
||||||
|
@ -86,9 +94,11 @@ public:
|
||||||
PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr, int fileno = 0);
|
PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr, int fileno = 0);
|
||||||
|
|
||||||
void InitializeActorInfo();
|
void InitializeActorInfo();
|
||||||
void BuildFlatPointers();
|
|
||||||
void BuildArrayPointers();
|
void BuildFlatPointers() const;
|
||||||
void BuildMapPointers();
|
void BuildArrayPointers() const;
|
||||||
|
void BuildMapPointers() const;
|
||||||
|
|
||||||
void DestroySpecials(void *addr);
|
void DestroySpecials(void *addr);
|
||||||
void DestroyMeta(void *addr);
|
void DestroyMeta(void *addr);
|
||||||
const PClass *NativeClass() const;
|
const PClass *NativeClass() const;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "i_common.h"
|
#include "i_common.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
|
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
@ -40,7 +41,7 @@
|
||||||
#include "st_console.h"
|
#include "st_console.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, longsavemessages)
|
||||||
double PerfToSec, PerfToMillisec;
|
double PerfToSec, PerfToMillisec;
|
||||||
|
|
||||||
void CalculateCPUSpeed()
|
void CalculateCPUSpeed()
|
||||||
|
@ -188,6 +189,7 @@ void I_OpenShellFolder(const char* folder)
|
||||||
NSString *currentpath = [filemgr currentDirectoryPath];
|
NSString *currentpath = [filemgr currentDirectoryPath];
|
||||||
|
|
||||||
[filemgr changeCurrentDirectoryPath:[NSString stringWithUTF8String:folder]];
|
[filemgr changeCurrentDirectoryPath:[NSString stringWithUTF8String:folder]];
|
||||||
|
if (longsavemessages)
|
||||||
Printf("Opening folder: %s\n", folder);
|
Printf("Opening folder: %s\n", folder);
|
||||||
std::system("open .");
|
std::system("open .");
|
||||||
[filemgr changeCurrentDirectoryPath:currentpath];
|
[filemgr changeCurrentDirectoryPath:currentpath];
|
||||||
|
|
|
@ -77,6 +77,7 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad
|
||||||
double PerfToSec, PerfToMillisec;
|
double PerfToSec, PerfToMillisec;
|
||||||
CVAR(Bool, con_printansi, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
CVAR(Bool, con_printansi, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
||||||
CVAR(Bool, con_4bitansi, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
CVAR(Bool, con_4bitansi, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE);
|
||||||
|
EXTERN_CVAR(Bool, longsavemessages)
|
||||||
|
|
||||||
extern FStartupScreen *StartWindow;
|
extern FStartupScreen *StartWindow;
|
||||||
|
|
||||||
|
@ -372,13 +373,17 @@ void I_OpenShellFolder(const char* infolder)
|
||||||
|
|
||||||
if (!chdir(infolder))
|
if (!chdir(infolder))
|
||||||
{
|
{
|
||||||
|
if (longsavemessages)
|
||||||
Printf("Opening folder: %s\n", infolder);
|
Printf("Opening folder: %s\n", infolder);
|
||||||
std::system("xdg-open .");
|
std::system("xdg-open .");
|
||||||
chdir(curdir);
|
chdir(curdir);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (longsavemessages)
|
||||||
Printf("Unable to open directory '%s\n", infolder);
|
Printf("Unable to open directory '%s\n", infolder);
|
||||||
|
else
|
||||||
|
Printf("Unable to open requested directory\n");
|
||||||
}
|
}
|
||||||
free(curdir);
|
free(curdir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,8 +95,6 @@ CUSTOM_CVAR(Bool, gl_es, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCA
|
||||||
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CVAR (Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|
||||||
|
|
||||||
CUSTOM_CVAR(String, vid_sdl_render_driver, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
CUSTOM_CVAR(String, vid_sdl_render_driver, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
{
|
{
|
||||||
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
||||||
|
@ -120,29 +118,61 @@ namespace Priv
|
||||||
bool vulkanEnabled;
|
bool vulkanEnabled;
|
||||||
bool softpolyEnabled;
|
bool softpolyEnabled;
|
||||||
bool fullscreenSwitch;
|
bool fullscreenSwitch;
|
||||||
|
int numberOfDisplays;
|
||||||
|
SDL_Rect* displayBounds = nullptr;
|
||||||
|
|
||||||
|
void updateDisplayInfo()
|
||||||
|
{
|
||||||
|
Priv::numberOfDisplays = SDL_GetNumVideoDisplays();
|
||||||
|
if (Priv::numberOfDisplays <= 0) {
|
||||||
|
Printf("%sWrong number of displays detected.\n", TEXTCOLOR_BOLD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Printf("Number of detected displays %d .\n", Priv::numberOfDisplays);
|
||||||
|
|
||||||
|
if (Priv::displayBounds != nullptr) {
|
||||||
|
free(Priv::displayBounds);
|
||||||
|
}
|
||||||
|
Priv::displayBounds = (SDL_Rect*) calloc(Priv::numberOfDisplays, sizeof(SDL_Rect));
|
||||||
|
|
||||||
|
for (int i=0; i < Priv::numberOfDisplays; i++) {
|
||||||
|
if (0 != SDL_GetDisplayBounds(i, &Priv::displayBounds[i])) {
|
||||||
|
Printf("%sError getting display %d size: %s\n", TEXTCOLOR_BOLD, i, SDL_GetError());
|
||||||
|
if (i == 0) {
|
||||||
|
free(Priv::displayBounds);
|
||||||
|
displayBounds = nullptr;
|
||||||
|
}
|
||||||
|
Priv::numberOfDisplays = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CreateWindow(uint32_t extraFlags)
|
void CreateWindow(uint32_t extraFlags)
|
||||||
{
|
{
|
||||||
assert(Priv::window == nullptr);
|
assert(Priv::window == nullptr);
|
||||||
|
|
||||||
// Set default size
|
// Get displays and default display size
|
||||||
SDL_Rect bounds;
|
updateDisplayInfo();
|
||||||
SDL_GetDisplayBounds(vid_adapter, &bounds);
|
|
||||||
|
// TODO control better when updateDisplayInfo fails
|
||||||
|
SDL_Rect* bounds = &displayBounds[vid_adapter % numberOfDisplays];
|
||||||
|
|
||||||
if (win_w <= 0 || win_h <= 0)
|
if (win_w <= 0 || win_h <= 0)
|
||||||
{
|
{
|
||||||
win_w = bounds.w * 8 / 10;
|
win_w = bounds->w * 8 / 10;
|
||||||
win_h = bounds.h * 8 / 10;
|
win_h = bounds->h * 8 / 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xWindowPos = (win_x <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_x;
|
||||||
|
int yWindowPos = (win_y <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_y;
|
||||||
|
Printf("Creating window [%dx%d] on adapter %d\n", (*win_w), (*win_h), (*vid_adapter));
|
||||||
|
|
||||||
FString caption;
|
FString caption;
|
||||||
caption.Format(GAMENAME " %s (%s)", GetVersionString(), GetGitTime());
|
caption.Format(GAMENAME " %s (%s)", GetVersionString(), GetGitTime());
|
||||||
|
|
||||||
const uint32_t windowFlags = (win_maximized ? SDL_WINDOW_MAXIMIZED : 0) | SDL_WINDOW_RESIZABLE | extraFlags;
|
const uint32_t windowFlags = (win_maximized ? SDL_WINDOW_MAXIMIZED : 0) | SDL_WINDOW_RESIZABLE | extraFlags;
|
||||||
Priv::window = SDL_CreateWindow(caption.GetChars(),
|
Priv::window = SDL_CreateWindow(caption.GetChars(), xWindowPos, yWindowPos, win_w, win_h, windowFlags);
|
||||||
(win_x <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_x,
|
|
||||||
(win_y <= 0) ? SDL_WINDOWPOS_CENTERED_DISPLAY(vid_adapter) : win_y,
|
|
||||||
win_w, win_h, windowFlags);
|
|
||||||
|
|
||||||
if (Priv::window != nullptr)
|
if (Priv::window != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -159,6 +189,11 @@ namespace Priv
|
||||||
|
|
||||||
SDL_DestroyWindow(Priv::window);
|
SDL_DestroyWindow(Priv::window);
|
||||||
Priv::window = nullptr;
|
Priv::window = nullptr;
|
||||||
|
|
||||||
|
if (Priv::displayBounds != nullptr) {
|
||||||
|
free(Priv::displayBounds);
|
||||||
|
Priv::displayBounds = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupPixelFormat(int multisample, const int *glver)
|
void SetupPixelFormat(int multisample, const int *glver)
|
||||||
|
@ -194,12 +229,70 @@ namespace Priv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
{
|
||||||
|
if (Priv::window != nullptr) {
|
||||||
|
// Get displays and default display size
|
||||||
|
Priv::updateDisplayInfo();
|
||||||
|
|
||||||
|
int display = (*self) % Priv::numberOfDisplays;
|
||||||
|
|
||||||
|
// TODO control better when updateDisplayInfo fails
|
||||||
|
SDL_Rect* bounds = &Priv::displayBounds[vid_adapter % Priv::numberOfDisplays];
|
||||||
|
|
||||||
|
if (win_w <= 0 || win_h <= 0)
|
||||||
|
{
|
||||||
|
win_w = bounds->w * 8 / 10;
|
||||||
|
win_h = bounds->h * 8 / 10;
|
||||||
|
}
|
||||||
|
// Forces to set to the ini this vars to -1, so +vid_adapter keeps working the next time that the game it's launched
|
||||||
|
win_x = -1;
|
||||||
|
win_y = -1;
|
||||||
|
|
||||||
|
if ((SDL_GetWindowFlags(Priv::window) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0) {
|
||||||
|
|
||||||
|
// TODO This not works. For some reason keeps stuck on the previus screen
|
||||||
|
/*
|
||||||
|
SDL_DisplayMode currentDisplayMode;
|
||||||
|
SDL_GetWindowDisplayMode(Priv::window, ¤tDisplayMode);
|
||||||
|
currentDisplayMode.w = win_w;
|
||||||
|
currentDisplayMode.h = win_h;
|
||||||
|
if ( 0 != SDL_SetWindowDisplayMode(Priv::window, ¤tDisplayMode)) {
|
||||||
|
Printf("A problem occured trying to change of display %s\n", SDL_GetError());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO This workaround also isn't working
|
||||||
|
/*
|
||||||
|
SDL_SetWindowFullscreen(Priv::window, 0);
|
||||||
|
SDL_SetWindowSize(Priv::window, win_w, win_h);
|
||||||
|
SDL_SetWindowPosition(Priv::window, bounds->x , bounds->y);
|
||||||
|
SDL_SetWindowFullscreen(Priv::window, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||||
|
*/
|
||||||
|
Printf("Changing adapter on fullscreen, isn't full supported by SDL. Instead try to switch to windowed mode, change the adapter and then switch again to fullscreen.\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
SDL_SetWindowSize(Priv::window, win_w, win_h);
|
||||||
|
SDL_SetWindowPosition(Priv::window, SDL_WINDOWPOS_CENTERED_DISPLAY(display), SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
||||||
|
}
|
||||||
|
|
||||||
|
display = SDL_GetWindowDisplayIndex(Priv::window);
|
||||||
|
if (display >= 0) {
|
||||||
|
Printf("New display is %d\n", display );
|
||||||
|
} else {
|
||||||
|
Printf("A problem occured trying to change of display %s\n", SDL_GetError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SDLVideo : public IVideo
|
class SDLVideo : public IVideo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SDLVideo ();
|
SDLVideo ();
|
||||||
~SDLVideo ();
|
~SDLVideo ();
|
||||||
|
|
||||||
|
void DumpAdapters();
|
||||||
|
|
||||||
DFrameBuffer *CreateFrameBuffer ();
|
DFrameBuffer *CreateFrameBuffer ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -270,6 +363,22 @@ SDLVideo::~SDLVideo ()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLVideo::DumpAdapters()
|
||||||
|
{
|
||||||
|
Priv::updateDisplayInfo();
|
||||||
|
for (int i=0; i < Priv::numberOfDisplays; i++) {
|
||||||
|
Printf("%s%d. [%dx%d @ (%d,%d)]\n",
|
||||||
|
vid_adapter == i ? TEXTCOLOR_BOLD : "",
|
||||||
|
i,
|
||||||
|
Priv::displayBounds[i].w,
|
||||||
|
Priv::displayBounds[i].h,
|
||||||
|
Priv::displayBounds[i].x,
|
||||||
|
Priv::displayBounds[i].y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DFrameBuffer *SDLVideo::CreateFrameBuffer ()
|
DFrameBuffer *SDLVideo::CreateFrameBuffer ()
|
||||||
{
|
{
|
||||||
SystemBaseFrameBuffer *fb = nullptr;
|
SystemBaseFrameBuffer *fb = nullptr;
|
||||||
|
@ -415,6 +524,7 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h)
|
||||||
SDL_GetWindowPosition(Priv::window, &x, &y);
|
SDL_GetWindowPosition(Priv::window, &x, &y);
|
||||||
win_x = x;
|
win_x = x;
|
||||||
win_y = y;
|
win_y = y;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,8 @@ EXTERN_CVAR (Bool, use_mouse)
|
||||||
static int WheelDelta;
|
static int WheelDelta;
|
||||||
extern bool CursorState;
|
extern bool CursorState;
|
||||||
|
|
||||||
|
void SetCursorState(bool visible);
|
||||||
|
|
||||||
extern BOOL paused;
|
extern BOOL paused;
|
||||||
static bool noidle = false;
|
static bool noidle = false;
|
||||||
|
|
||||||
|
@ -415,7 +417,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
case WM_SETCURSOR:
|
case WM_SETCURSOR:
|
||||||
if (!CursorState)
|
if (!CursorState)
|
||||||
{
|
{
|
||||||
SetCursor(NULL); // turn off window cursor
|
SetCursorState(false); // turn off window cursor
|
||||||
return TRUE; // Prevent Windows from setting cursor to window class cursor
|
return TRUE; // Prevent Windows from setting cursor to window class cursor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -131,7 +131,7 @@ enum EMouseMode
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
static void SetCursorState(bool visible);
|
void SetCursorState(bool visible);
|
||||||
static FMouse *CreateWin32Mouse();
|
static FMouse *CreateWin32Mouse();
|
||||||
static FMouse *CreateDInputMouse();
|
static FMouse *CreateDInputMouse();
|
||||||
static FMouse *CreateRawMouse();
|
static FMouse *CreateRawMouse();
|
||||||
|
@ -191,7 +191,7 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||||
|
|
||||||
static bool mouse_shown = true;
|
static bool mouse_shown = true;
|
||||||
|
|
||||||
static void SetCursorState(bool visible)
|
void SetCursorState(bool visible)
|
||||||
{
|
{
|
||||||
CursorState = visible || !m_hidepointer;
|
CursorState = visible || !m_hidepointer;
|
||||||
if (GetForegroundWindow() == mainwindow.GetHandle())
|
if (GetForegroundWindow() == mainwindow.GetHandle())
|
||||||
|
@ -297,6 +297,12 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult)
|
||||||
{
|
{
|
||||||
BlockMouseMove = 3;
|
BlockMouseMove = 3;
|
||||||
Mouse->Ungrab();
|
Mouse->Ungrab();
|
||||||
|
|
||||||
|
if(!mouse_shown)
|
||||||
|
{
|
||||||
|
ShowCursor(true);
|
||||||
|
mouse_shown = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -114,6 +114,7 @@ static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP
|
||||||
EXTERN_CVAR (Bool, queryiwad);
|
EXTERN_CVAR (Bool, queryiwad);
|
||||||
// Used on welcome/IWAD screen.
|
// Used on welcome/IWAD screen.
|
||||||
EXTERN_CVAR (Int, vid_preferbackend)
|
EXTERN_CVAR (Int, vid_preferbackend)
|
||||||
|
EXTERN_CVAR(Bool, longsavemessages)
|
||||||
|
|
||||||
extern HANDLE StdOut;
|
extern HANDLE StdOut;
|
||||||
extern bool FancyStdOut;
|
extern bool FancyStdOut;
|
||||||
|
@ -824,13 +825,17 @@ void I_OpenShellFolder(const char* infolder)
|
||||||
}
|
}
|
||||||
else if (SetCurrentDirectoryW(WideString(infolder).c_str()))
|
else if (SetCurrentDirectoryW(WideString(infolder).c_str()))
|
||||||
{
|
{
|
||||||
|
if (longsavemessages)
|
||||||
Printf("Opening folder: %s\n", infolder);
|
Printf("Opening folder: %s\n", infolder);
|
||||||
ShellExecuteW(NULL, L"open", L"explorer.exe", L".", NULL, SW_SHOWNORMAL);
|
ShellExecuteW(NULL, L"open", L"explorer.exe", L".", NULL, SW_SHOWNORMAL);
|
||||||
SetCurrentDirectoryW(curdir.Data());
|
SetCurrentDirectoryW(curdir.Data());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (longsavemessages)
|
||||||
Printf("Unable to open directory '%s\n", infolder);
|
Printf("Unable to open directory '%s\n", infolder);
|
||||||
|
else
|
||||||
|
Printf("Unable to open requested directory\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ CUSTOM_CVAR(Int, gl_pipeline_depth, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N
|
||||||
Printf("Changing the pipeline depth requires a restart for " GAMENAME ".\n");
|
Printf("Changing the pipeline depth requires a restart for " GAMENAME ".\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CUSTOM_CVAR(Int, vid_maxfps, 500, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
{
|
{
|
||||||
if (self < GameTicRate && self != 0)
|
if (self < GameTicRate && self != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -173,6 +173,7 @@ void VkCommandBufferManager::WaitForCommands(bool finish, bool uploadOnly)
|
||||||
|
|
||||||
if (finish)
|
if (finish)
|
||||||
{
|
{
|
||||||
|
if (!fb->GetVSync())
|
||||||
fb->FPSLimit();
|
fb->FPSLimit();
|
||||||
fb->GetFramebufferManager()->QueuePresent();
|
fb->GetFramebufferManager()->QueuePresent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,23 +291,21 @@ bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare)
|
||||||
if (!forcompare && fromtype->IsConst && !totype->IsConst) return false;
|
if (!forcompare && fromtype->IsConst && !totype->IsConst) return false;
|
||||||
// A type is always compatible to itself.
|
// A type is always compatible to itself.
|
||||||
if (fromtype == totype) return true;
|
if (fromtype == totype) return true;
|
||||||
// Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type.
|
|
||||||
if (source->isObjectPointer() && dest->isObjectPointer())
|
if (source->isObjectPointer() && dest->isObjectPointer())
|
||||||
{
|
{ // Pointers to different types are only compatible if both point to an object and the source type is a child of the destination type.
|
||||||
auto fromcls = static_cast<PObjectPointer*>(source)->PointedClass();
|
auto fromcls = static_cast<PObjectPointer*>(source)->PointedClass();
|
||||||
auto tocls = static_cast<PObjectPointer*>(dest)->PointedClass();
|
auto tocls = static_cast<PObjectPointer*>(dest)->PointedClass();
|
||||||
if (forcompare && tocls->IsDescendantOf(fromcls)) return true;
|
if (forcompare && tocls->IsDescendantOf(fromcls)) return true;
|
||||||
return (fromcls->IsDescendantOf(tocls));
|
return (fromcls->IsDescendantOf(tocls));
|
||||||
}
|
}
|
||||||
// The same rules apply to class pointers. A child type can be assigned to a variable of a parent type.
|
else if (source->isClassPointer() && dest->isClassPointer())
|
||||||
if (source->isClassPointer() && dest->isClassPointer())
|
{ // The same rules apply to class pointers. A child type can be assigned to a variable of a parent type.
|
||||||
{
|
|
||||||
auto fromcls = static_cast<PClassPointer*>(source)->ClassRestriction;
|
auto fromcls = static_cast<PClassPointer*>(source)->ClassRestriction;
|
||||||
auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction;
|
auto tocls = static_cast<PClassPointer*>(dest)->ClassRestriction;
|
||||||
if (forcompare && tocls->IsDescendantOf(fromcls)) return true;
|
if (forcompare && tocls->IsDescendantOf(fromcls)) return true;
|
||||||
return (fromcls->IsDescendantOf(tocls));
|
return (fromcls->IsDescendantOf(tocls));
|
||||||
}
|
}
|
||||||
if(source->isFunctionPointer() && dest->isFunctionPointer())
|
else if(source->isFunctionPointer() && dest->isFunctionPointer())
|
||||||
{
|
{
|
||||||
auto from = static_cast<PFunctionPointer*>(source);
|
auto from = static_cast<PFunctionPointer*>(source);
|
||||||
auto to = static_cast<PFunctionPointer*>(dest);
|
auto to = static_cast<PFunctionPointer*>(dest);
|
||||||
|
@ -315,6 +313,10 @@ bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare)
|
||||||
|
|
||||||
return to->PointedType == TypeVoid || (AreCompatibleFnPtrTypes((PPrototype *)to->PointedType, (PPrototype *)from->PointedType) && from->ArgFlags == to->ArgFlags && FScopeBarrier::CheckSidesForFunctionPointer(from->Scope, to->Scope));
|
return to->PointedType == TypeVoid || (AreCompatibleFnPtrTypes((PPrototype *)to->PointedType, (PPrototype *)from->PointedType) && from->ArgFlags == to->ArgFlags && FScopeBarrier::CheckSidesForFunctionPointer(from->Scope, to->Scope));
|
||||||
}
|
}
|
||||||
|
else if(source->isRealPointer() && dest->isRealPointer())
|
||||||
|
{
|
||||||
|
return fromtype->PointedType == totype->PointedType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1940,6 +1942,12 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
bool writable;
|
bool writable;
|
||||||
basex->RequestAddress(ctx, &writable);
|
basex->RequestAddress(ctx, &writable);
|
||||||
|
|
||||||
|
if(!writable && !ValueType->toPointer()->IsConst && ctx.Version >= MakeVersion(4, 12))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Trying to assign readonly value to writable type.");
|
||||||
|
}
|
||||||
|
|
||||||
basex->ValueType = ValueType;
|
basex->ValueType = ValueType;
|
||||||
auto x = basex;
|
auto x = basex;
|
||||||
basex = nullptr;
|
basex = nullptr;
|
||||||
|
@ -8739,6 +8747,12 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
if (Self->ValueType->isRealPointer())
|
if (Self->ValueType->isRealPointer())
|
||||||
{
|
{
|
||||||
auto pointedType = Self->ValueType->toPointer()->PointedType;
|
auto pointedType = Self->ValueType->toPointer()->PointedType;
|
||||||
|
|
||||||
|
if(pointedType && pointedType->isStruct() && Self->ValueType->toPointer()->IsConst && ctx.Version >= MakeVersion(4, 12))
|
||||||
|
{
|
||||||
|
isreadonly = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
if (pointedType && (pointedType->isDynArray() || pointedType->isMap() || pointedType->isMapIterator()))
|
||||||
{
|
{
|
||||||
Self = new FxOutVarDereference(Self, Self->ScriptPosition);
|
Self = new FxOutVarDereference(Self, Self->ScriptPosition);
|
||||||
|
@ -9268,7 +9282,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Self->ValueType->isStruct())
|
else if (Self->ValueType->isStruct() && !isreadonly)
|
||||||
{
|
{
|
||||||
bool writable;
|
bool writable;
|
||||||
|
|
||||||
|
@ -9528,6 +9542,8 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
auto &argflags = Function->Variants[0].ArgFlags;
|
auto &argflags = Function->Variants[0].ArgFlags;
|
||||||
auto *defaults = FnPtrCall ? nullptr : &Function->Variants[0].Implementation->DefaultArgs;
|
auto *defaults = FnPtrCall ? nullptr : &Function->Variants[0].Implementation->DefaultArgs;
|
||||||
|
|
||||||
|
if(FnPtrCall) static_cast<VMScriptFunction*>(ctx.Function->Variants[0].Implementation)->blockJit = true;
|
||||||
|
|
||||||
int implicit = Function->GetImplicitArgs();
|
int implicit = Function->GetImplicitArgs();
|
||||||
|
|
||||||
if (!CheckAccessibility(ctx.Version))
|
if (!CheckAccessibility(ctx.Version))
|
||||||
|
|
|
@ -196,15 +196,15 @@ void PType::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset>
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PType::SetPointer(void *base, unsigned offset, TArray<size_t> *stroffs)
|
void PType::SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *stroffs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void PType::SetPointerArray(void *base, unsigned offset, TArray<size_t> *stroffs)
|
void PType::SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *stroffs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void PType::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs)
|
void PType::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *ptrofs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1575,10 +1575,10 @@ PObjectPointer::PObjectPointer(PClass *cls, bool isconst)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PObjectPointer::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
void PObjectPointer::SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *special)
|
||||||
{
|
{
|
||||||
// Add to the list of pointers for this class.
|
// Add to the list of pointers for this class.
|
||||||
special->Push(offset);
|
special->Push({offset, this});
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1706,7 +1706,7 @@ bool PClassPointer::isCompatible(PType *type)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PClassPointer::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
void PClassPointer::SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *special)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1908,7 +1908,7 @@ void PArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset>
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PArray::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
void PArray::SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *special)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < ElementCount; ++i)
|
for (unsigned i = 0; i < ElementCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -1922,7 +1922,7 @@ void PArray::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special)
|
void PArray::SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *special)
|
||||||
{
|
{
|
||||||
if (ElementType->isStruct() || ElementType->isDynArray())
|
if (ElementType->isStruct() || ElementType->isDynArray())
|
||||||
{
|
{
|
||||||
|
@ -1939,7 +1939,7 @@ void PArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *specia
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PArray::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
void PArray::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *special)
|
||||||
{
|
{
|
||||||
if(ElementType->isStruct() || ElementType->isMap())
|
if(ElementType->isStruct() || ElementType->isMap())
|
||||||
{
|
{
|
||||||
|
@ -2254,12 +2254,12 @@ void PDynArray::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffs
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PDynArray::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special)
|
void PDynArray::SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *special)
|
||||||
{
|
{
|
||||||
if (ElementType->isObjectPointer())
|
if (ElementType->isObjectPointer())
|
||||||
{
|
{
|
||||||
// Add to the list of pointer arrays for this class.
|
// Add to the list of pointer arrays for this class.
|
||||||
special->Push(offset);
|
special->Push({offset, this});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2524,12 +2524,12 @@ void PMap::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PMap::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
void PMap::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *special)
|
||||||
{
|
{
|
||||||
if (ValueType->isObjectPointer())
|
if (ValueType->isObjectPointer())
|
||||||
{
|
{
|
||||||
// Add to the list of pointer arrays for this class.
|
// Add to the list of pointer arrays for this class.
|
||||||
special->Push(std::make_pair(offset,KeyType));
|
special->Push(std::make_pair(offset, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3264,7 +3264,7 @@ void PStruct::SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PStruct::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
void PStruct::SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *special)
|
||||||
{
|
{
|
||||||
auto it = Symbols.GetIterator();
|
auto it = Symbols.GetIterator();
|
||||||
PSymbolTable::MapType::Pair *pair;
|
PSymbolTable::MapType::Pair *pair;
|
||||||
|
@ -3284,7 +3284,7 @@ void PStruct::SetPointer(void *base, unsigned offset, TArray<size_t> *special)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PStruct::SetPointerArray(void *base, unsigned offset, TArray<size_t> *special)
|
void PStruct::SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *special)
|
||||||
{
|
{
|
||||||
auto it = Symbols.GetIterator();
|
auto it = Symbols.GetIterator();
|
||||||
PSymbolTable::MapType::Pair *pair;
|
PSymbolTable::MapType::Pair *pair;
|
||||||
|
@ -3304,7 +3304,7 @@ void PStruct::SetPointerArray(void *base, unsigned offset, TArray<size_t> *speci
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void PStruct::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *special)
|
void PStruct::SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *special)
|
||||||
{
|
{
|
||||||
auto it = Symbols.GetIterator();
|
auto it = Symbols.GetIterator();
|
||||||
PSymbolTable::MapType::Pair *pair;
|
PSymbolTable::MapType::Pair *pair;
|
||||||
|
|
|
@ -68,8 +68,11 @@ class PPointer;
|
||||||
class PClassPointer;
|
class PClassPointer;
|
||||||
class PFunctionPointer;
|
class PFunctionPointer;
|
||||||
class PArray;
|
class PArray;
|
||||||
|
class PDynArray;
|
||||||
|
class PMap;
|
||||||
class PStruct;
|
class PStruct;
|
||||||
class PClassType;
|
class PClassType;
|
||||||
|
class PObjectPointer;
|
||||||
|
|
||||||
struct ZCC_ExprConstant;
|
struct ZCC_ExprConstant;
|
||||||
class PType : public PTypeBase
|
class PType : public PTypeBase
|
||||||
|
@ -129,9 +132,9 @@ public:
|
||||||
// initialization when the object is created and destruction when the
|
// initialization when the object is created and destruction when the
|
||||||
// object is destroyed.
|
// object is destroyed.
|
||||||
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL);
|
virtual void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special=NULL);
|
||||||
virtual void SetPointer(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
virtual void SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *ptrofs = NULL);
|
||||||
virtual void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL);
|
virtual void SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *ptrofs = NULL);
|
||||||
virtual void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL);
|
virtual void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *ptrofs = NULL);
|
||||||
|
|
||||||
// Initialize the value, if needed (e.g. strings)
|
// Initialize the value, if needed (e.g. strings)
|
||||||
virtual void InitializeValue(void *addr, const void *def) const;
|
virtual void InitializeValue(void *addr, const void *def) const;
|
||||||
|
@ -455,7 +458,7 @@ 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;
|
||||||
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) override;
|
void SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *special = NULL) override;
|
||||||
PClass *PointedClass() const;
|
PClass *PointedClass() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -471,7 +474,7 @@ 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;
|
||||||
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
bool ReadValue(FSerializer &ar, const char *key, void *addr) const override;
|
||||||
|
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special = NULL) override;
|
void SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *special = NULL) override;
|
||||||
bool IsMatch(intptr_t id1, intptr_t id2) const override;
|
bool IsMatch(intptr_t id1, intptr_t id2) const override;
|
||||||
void GetTypeIDs(intptr_t &id1, intptr_t &id2) const override;
|
void GetTypeIDs(intptr_t &id1, intptr_t &id2) const override;
|
||||||
};
|
};
|
||||||
|
@ -503,9 +506,9 @@ public:
|
||||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||||
|
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *special) override;
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *special) override;
|
void SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *special) override;
|
||||||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) override;
|
void SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *ptrofs = NULL) override;
|
||||||
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs = NULL) override;
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *ptrofs = NULL) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PStaticArray : public PArray
|
class PStaticArray : public PArray
|
||||||
|
@ -535,7 +538,7 @@ public:
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
void InitializeValue(void *addr, const void *def) const override;
|
void InitializeValue(void *addr, const void *def) const override;
|
||||||
void DestroyValue(void *addr) const override;
|
void DestroyValue(void *addr) const override;
|
||||||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *ptrofs = NULL) override;
|
void SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *ptrofs = NULL) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PMap : public PCompoundType
|
class PMap : public PCompoundType
|
||||||
|
@ -579,7 +582,7 @@ public:
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
void InitializeValue(void *addr, const void *def) const override;
|
void InitializeValue(void *addr, const void *def) const override;
|
||||||
void DestroyValue(void *addr) const override;
|
void DestroyValue(void *addr) const override;
|
||||||
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *ptrofs) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -653,9 +656,9 @@ 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;
|
||||||
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
bool ReadValue(FSerializer &ar, const char *key,void *addr) const override;
|
||||||
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
void SetDefaultValue(void *base, unsigned offset, TArray<FTypeAndOffset> *specials) override;
|
||||||
void SetPointer(void *base, unsigned offset, TArray<size_t> *specials) override;
|
void SetPointer(void *base, unsigned offset, TArray<std::pair<size_t, PObjectPointer *>> *specials) override;
|
||||||
void SetPointerArray(void *base, unsigned offset, TArray<size_t> *special) override;
|
void SetPointerArray(void *base, unsigned offset, TArray<std::pair<size_t, PDynArray *>> *special) override;
|
||||||
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t,PType *>> *ptrofs) override;
|
void SetPointerMap(void *base, unsigned offset, TArray<std::pair<size_t, PMap *>> *ptrofs) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPrototype : public PCompoundType
|
class PPrototype : public PCompoundType
|
||||||
|
|
|
@ -43,6 +43,11 @@
|
||||||
FSharedStringArena VMStringConstants;
|
FSharedStringArena VMStringConstants;
|
||||||
|
|
||||||
|
|
||||||
|
static bool ShouldWrapPointer(PType * type)
|
||||||
|
{
|
||||||
|
return ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray() || type->isMap() || type->isMapIterator());
|
||||||
|
}
|
||||||
|
|
||||||
int GetIntConst(FxExpression *ex, FCompileContext &ctx)
|
int GetIntConst(FxExpression *ex, FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
ex = new FxIntCast(ex, false);
|
ex = new FxIntCast(ex, false);
|
||||||
|
@ -2049,8 +2054,17 @@ PType *ZCCCompiler::DetermineType(PType *outertype, ZCC_TreeNode *field, FName n
|
||||||
} while( (t = (ZCC_Type *)t->SiblingNext) != fn->RetType);
|
} while( (t = (ZCC_Type *)t->SiblingNext) != fn->RetType);
|
||||||
|
|
||||||
if(auto *t = fn->Params; t != nullptr) do {
|
if(auto *t = fn->Params; t != nullptr) do {
|
||||||
args.Push(DetermineType(outertype, field, name, t->Type, false, false));
|
PType * tt = DetermineType(outertype, field, name, t->Type, false, false);
|
||||||
argflags.Push(t->Flags == ZCC_Out ? VARF_Out : 0);
|
int flags = 0;
|
||||||
|
|
||||||
|
if (ShouldWrapPointer(tt))
|
||||||
|
{
|
||||||
|
tt = NewPointer(tt);
|
||||||
|
flags = VARF_Ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Push(tt);
|
||||||
|
argflags.Push(t->Flags == ZCC_Out ? VARF_Out|flags : flags);
|
||||||
} while( (t = (ZCC_FuncPtrParamDecl *) t->SiblingNext) != fn->Params);
|
} while( (t = (ZCC_FuncPtrParamDecl *) t->SiblingNext) != fn->Params);
|
||||||
|
|
||||||
auto proto = NewPrototype(returns,args);
|
auto proto = NewPrototype(returns,args);
|
||||||
|
@ -2550,7 +2564,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
{
|
{
|
||||||
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false);
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
if ((type->isStruct() && type != TypeVector2 && type != TypeVector3 && type != TypeVector4 && type != TypeQuaternion && type != TypeFVector2 && type != TypeFVector3 && type != TypeFVector4 && type != TypeFQuaternion) || type->isDynArray() || type->isMap() || type->isMapIterator())
|
if (ShouldWrapPointer(type))
|
||||||
{
|
{
|
||||||
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
// Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly.
|
||||||
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/);
|
||||||
|
@ -2785,7 +2799,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
|
|
||||||
auto parentfunc = clstype->ParentClass? dyn_cast<PFunction>(clstype->ParentClass->VMType->Symbols.FindSymbol(sym->SymbolName, true)) : nullptr;
|
auto parentfunc = clstype->ParentClass? dyn_cast<PFunction>(clstype->ParentClass->VMType->Symbols.FindSymbol(sym->SymbolName, true)) : nullptr;
|
||||||
|
|
||||||
int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType);
|
int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], parentfunc, exactReturnType, sym->SymbolName == FName("SpecialBounceHit") && mVersion < MakeVersion(4, 12));
|
||||||
// specifying 'override' is necessary to prevent one of the biggest problem spots with virtual inheritance: Mismatching argument types.
|
// specifying 'override' is necessary to prevent one of the biggest problem spots with virtual inheritance: Mismatching argument types.
|
||||||
if (varflags & VARF_Override)
|
if (varflags & VARF_Override)
|
||||||
{
|
{
|
||||||
|
@ -2867,7 +2881,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
}
|
}
|
||||||
else if (forclass)
|
else if (forclass)
|
||||||
{
|
{
|
||||||
int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType);
|
int virtindex = clstype->FindVirtualIndex(sym->SymbolName, &sym->Variants[0], nullptr, exactReturnType, sym->SymbolName == FName("SpecialBounceHit") && mVersion < MakeVersion(4, 12));
|
||||||
if (virtindex != -1)
|
if (virtindex != -1)
|
||||||
{
|
{
|
||||||
Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars());
|
Error(f, "Function %s attempts to override parent function without 'override' qualifier", FName(f->Name).GetChars());
|
||||||
|
|
|
@ -279,6 +279,8 @@ static bool CanJit(VMScriptFunction *func)
|
||||||
// Asmjit has a 256 register limit. Stay safely away from it as the jit compiler uses a few for temporaries as well.
|
// Asmjit has a 256 register limit. Stay safely away from it as the jit compiler uses a few for temporaries as well.
|
||||||
// Any function exceeding the limit will use the VM - a fair punishment to someone for writing a function so bloated ;)
|
// Any function exceeding the limit will use the VM - a fair punishment to someone for writing a function so bloated ;)
|
||||||
|
|
||||||
|
if(func->blockJit) return false;
|
||||||
|
|
||||||
int maxregs = 200;
|
int maxregs = 200;
|
||||||
if (func->NumRegA + func->NumRegD + func->NumRegF + func->NumRegS < maxregs)
|
if (func->NumRegA + func->NumRegD + func->NumRegF + func->NumRegS < maxregs)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -474,6 +474,8 @@ public:
|
||||||
VM_UBYTE NumArgs; // Number of arguments this function takes
|
VM_UBYTE NumArgs; // Number of arguments this function takes
|
||||||
TArray<FTypeAndOffset> SpecialInits; // list of all contents on the extra stack which require construction and destruction
|
TArray<FTypeAndOffset> SpecialInits; // list of all contents on the extra stack which require construction and destruction
|
||||||
|
|
||||||
|
bool blockJit = false; // function triggers Jit bugs, block compilation until bugs are fixed
|
||||||
|
|
||||||
void InitExtra(void *addr);
|
void InitExtra(void *addr);
|
||||||
void DestroyExtra(void *addr);
|
void DestroyExtra(void *addr);
|
||||||
int AllocExtraStack(PType *type);
|
int AllocExtraStack(PType *type);
|
||||||
|
|
|
@ -654,9 +654,11 @@ void FStartScreen::NetProgress(int count)
|
||||||
|
|
||||||
void FStartScreen::Render(bool force)
|
void FStartScreen::Render(bool force)
|
||||||
{
|
{
|
||||||
|
static uint64_t minwaittime = 30;
|
||||||
|
|
||||||
auto nowtime = I_msTime();
|
auto nowtime = I_msTime();
|
||||||
// Do not refresh too often. This function gets called a lot more frequently than the screen can update.
|
// Do not refresh too often. This function gets called a lot more frequently than the screen can update.
|
||||||
if (nowtime - screen->FrameTime > 30 || force)
|
if (nowtime - screen->FrameTime > minwaittime || force)
|
||||||
{
|
{
|
||||||
screen->FrameTime = nowtime;
|
screen->FrameTime = nowtime;
|
||||||
screen->BeginFrame();
|
screen->BeginFrame();
|
||||||
|
@ -689,6 +691,9 @@ void FStartScreen::Render(bool force)
|
||||||
screen->Update();
|
screen->Update();
|
||||||
twod->OnFrameDone();
|
twod->OnFrameDone();
|
||||||
}
|
}
|
||||||
|
auto newtime = I_msTime();
|
||||||
|
if ((newtime - nowtime) * 2.0 > minwaittime) // slow down drawing the start screen if we're on a slow GPU!
|
||||||
|
minwaittime = (newtime - nowtime) * 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FImageSource* CreateStartScreenTexture(FBitmap& srcdata);
|
FImageSource* CreateStartScreenTexture(FBitmap& srcdata);
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
#include "hw_ihwtexture.h"
|
#include "hw_ihwtexture.h"
|
||||||
#include "palettecontainer.h"
|
#include "palettecontainer.h"
|
||||||
|
#include "hw_ihwtexture.h" // Note: this cannot be a forward declaration due to the inlined delete statement below.
|
||||||
|
|
||||||
struct FTextureBuffer;
|
struct FTextureBuffer;
|
||||||
class IHardwareTexture;
|
|
||||||
|
|
||||||
enum ECreateTexBufferFlags
|
enum ECreateTexBufferFlags
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ private:
|
||||||
|
|
||||||
void Delete()
|
void Delete()
|
||||||
{
|
{
|
||||||
if (hwTexture) delete hwTexture;
|
delete hwTexture;
|
||||||
hwTexture = nullptr;
|
hwTexture = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +148,11 @@ public:
|
||||||
{
|
{
|
||||||
for (auto& tt : hwDefTex)
|
for (auto& tt : hwDefTex)
|
||||||
{
|
{
|
||||||
if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false);
|
tt.MarkForPrecache(false);
|
||||||
}
|
}
|
||||||
for (auto& tt : hwTex_Translated)
|
for (auto& tt : hwTex_Translated)
|
||||||
{
|
{
|
||||||
if (!tt.isMarkedForPreache()) tt.MarkForPrecache(false);
|
tt.MarkForPrecache(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
#include <inttypes.h> // for intptr_t
|
#include <inttypes.h> // for intptr_t
|
||||||
|
@ -355,6 +356,105 @@ public:
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// !!! THIS REQUIRES AN ELEMENT TYPE THAT'S COMPARABLE WITH THE LT OPERATOR !!!
|
||||||
|
bool IsSorted()
|
||||||
|
{
|
||||||
|
for(unsigned i = 1; i < Count; i++)
|
||||||
|
{
|
||||||
|
if(Array[i] < Array[i-1]) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Func>
|
||||||
|
bool IsSorted(Func &<)
|
||||||
|
{
|
||||||
|
for(unsigned i = 1; i < Count; i++)
|
||||||
|
{
|
||||||
|
if(std::invoke(lt, Array[i], Array[i-1])) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! THIS REQUIRES A SORTED OR EMPTY ARRAY !!!
|
||||||
|
// !!! AND AN ELEMENT TYPE THAT'S COMPARABLE WITH THE LT OPERATOR !!!
|
||||||
|
//
|
||||||
|
// exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does
|
||||||
|
unsigned int SortedFind(const T& item, bool exact = true) const
|
||||||
|
{
|
||||||
|
if(Count == 0) return 0;
|
||||||
|
if(Count == 1) return (item < Array[0]) ? 0 : 1;
|
||||||
|
|
||||||
|
unsigned int lo = 0;
|
||||||
|
unsigned int hi = Count - 1;
|
||||||
|
|
||||||
|
while(lo <= hi)
|
||||||
|
{
|
||||||
|
int mid = lo + ((hi - lo) / 2);
|
||||||
|
|
||||||
|
if(Array[mid] < item)
|
||||||
|
{
|
||||||
|
lo = mid + 1;
|
||||||
|
}
|
||||||
|
else if(item < Array[mid])
|
||||||
|
{
|
||||||
|
hi = mid - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(exact)
|
||||||
|
{
|
||||||
|
return Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (lo == Count || (item < Array[lo])) ? lo : lo + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! THIS REQUIRES A SORTED OR EMPTY ARRAY !!!
|
||||||
|
//
|
||||||
|
// exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does
|
||||||
|
template<typename Func>
|
||||||
|
unsigned int SortedFind(const T& item, Func &<, bool exact = true) const
|
||||||
|
{
|
||||||
|
if(Count == 0) return 0;
|
||||||
|
if(Count == 1) return lt(item, Array[0]) ? 0 : 1;
|
||||||
|
|
||||||
|
unsigned int lo = 0;
|
||||||
|
unsigned int hi = Count - 1;
|
||||||
|
|
||||||
|
while(lo <= hi)
|
||||||
|
{
|
||||||
|
int mid = lo + ((hi - lo) / 2);
|
||||||
|
|
||||||
|
if(std::invoke(lt, Array[mid], item))
|
||||||
|
{
|
||||||
|
lo = mid + 1;
|
||||||
|
}
|
||||||
|
else if(std::invoke(lt, item, Array[mid]))
|
||||||
|
{
|
||||||
|
if(mid == 0) break; // prevent negative overflow due to unsigned numbers
|
||||||
|
hi = mid - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(exact)
|
||||||
|
{
|
||||||
|
return Count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (lo == Count || std::invoke(lt, item, Array[lo])) ? lo : lo + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Contains(const T& item) const
|
bool Contains(const T& item) const
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
@ -367,12 +467,24 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Func>
|
template<class Func>
|
||||||
unsigned int FindEx(Func compare) const
|
bool Contains(const T& item, Func &&compare) const
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for(i = 0;i < Count;++i)
|
for(i = 0;i < Count;++i)
|
||||||
{
|
{
|
||||||
if (compare(Array[i]))
|
if(std::invoke(compare, Array[i], item))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Func>
|
||||||
|
unsigned int FindEx(Func &&compare) const
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = 0; i < Count; ++i)
|
||||||
|
{
|
||||||
|
if (std::invoke(compare, Array[i]))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
|
@ -462,6 +574,50 @@ public:
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned SortedAddUnique(const T& obj)
|
||||||
|
{
|
||||||
|
auto f = SortedFind(obj, true);
|
||||||
|
if (f == Size()) Push(obj);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Func>
|
||||||
|
unsigned SortedAddUnique(const T& obj, Func &<)
|
||||||
|
{
|
||||||
|
auto f = SortedFind(obj, std::forward<Func>(lt), true);
|
||||||
|
if (f == Size()) Push(obj);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SortedDelete(const T& obj)
|
||||||
|
{
|
||||||
|
auto f = SortedFind(obj, true);
|
||||||
|
if (f == Size())
|
||||||
|
{
|
||||||
|
Delete(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Func>
|
||||||
|
bool SortedDelete(const T& obj, Func &<)
|
||||||
|
{
|
||||||
|
auto f = SortedFind(obj, std::forward<Func>(lt), true);
|
||||||
|
if (f == Size())
|
||||||
|
{
|
||||||
|
Delete(f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Pop ()
|
bool Pop ()
|
||||||
{
|
{
|
||||||
if (Count > 0)
|
if (Count > 0)
|
||||||
|
@ -542,6 +698,17 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SortedInsert (const T &item)
|
||||||
|
{
|
||||||
|
Insert (SortedFind (item, false), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Func>
|
||||||
|
void SortedInsert (const T &item, Func &<)
|
||||||
|
{
|
||||||
|
Insert (SortedFind (item, std::forward<Func>(lt), false), item);
|
||||||
|
}
|
||||||
|
|
||||||
void ShrinkToFit ()
|
void ShrinkToFit ()
|
||||||
{
|
{
|
||||||
if (Most > Count)
|
if (Most > Count)
|
||||||
|
|
Loading…
Reference in a new issue