diff --git a/src/actor.h b/src/actor.h index 6f5ba46a3..833cd2c0a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1419,10 +1419,6 @@ public: }; -VMEXPORT_NATIVES_START(AActor, DThinker) - VMEXPORT_NATIVES_FUNC(DropInventory) -VMEXPORT_NATIVES_END(AActor) - class FActorIterator { public: diff --git a/src/dobject.cpp b/src/dobject.cpp index 6fa7d5317..ad575bebc 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -48,6 +48,7 @@ #include "a_sharedglobal.h" #include "dsectoreffect.h" #include "serializer.h" +#include "virtual.h" //========================================================================== // diff --git a/src/dobject.h b/src/dobject.h index d5e11a04c..d858e577f 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -153,34 +153,6 @@ protected: \ #define HAS_FIELDS \ static void InitNativeFields(); -// Templates really are powerful -#define VMEXPORTED_NATIVES_START \ - template class ExportedNatives : public ExportedNatives {}; \ - template<> class ExportedNatives { \ - protected: ExportedNatives() {} \ - public: \ - static ExportedNatives *Get() { static ExportedNatives *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives; return Instance; } \ - ExportedNatives(const ExportedNatives&) = delete; \ - ExportedNatives(ExportedNatives&&) = delete; - -#define VMEXPORTED_NATIVES_FUNC(func) \ - template ret func(void *ptr, args ... arglist) { return ret(); } - -#define VMEXPORTED_NATIVES_END }; - -#define VMEXPORT_NATIVES_START(cls, parent) \ - template<> class ExportedNatives : public ExportedNatives { \ - protected: ExportedNatives() {} \ - public: \ - static ExportedNatives *Get() { static ExportedNatives *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives; return Instance; } \ - ExportedNatives(const ExportedNatives&) = delete; \ - ExportedNatives(ExportedNatives&&) = delete; - -#define VMEXPORT_NATIVES_FUNC(func) \ - template ret func(void *ptr, args ... arglist) { return static_cast(ptr)->object::func(arglist...); } - -#define VMEXPORT_NATIVES_END(cls) }; - #if defined(_MSC_VER) # pragma section(".creg$u",read) # define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo; @@ -615,100 +587,8 @@ protected: } }; -//Initial list -VMEXPORTED_NATIVES_START - VMEXPORTED_NATIVES_FUNC(Destroy) - VMEXPORTED_NATIVES_FUNC(Tick) - VMEXPORTED_NATIVES_FUNC(DropInventory) -VMEXPORTED_NATIVES_END - class AInventory;// -template -class DVMObject : public T -{ -public: - static char *FormatClassName() - { - static char *name = nullptr; - if (name == nullptr) - { - name = new char[64]; - mysnprintf(name, 64, "DVMObject<%s>", Super::RegistrationInfo.Name); - atterm([]{ delete[] DVMObject::RegistrationInfo.Name; }); - } - return name; - } - - virtual PClass *StaticType() const - { - return RegistrationInfo.MyClass; - } - static ClassReg RegistrationInfo; - static ClassReg * const RegistrationInfoPtr; - typedef T Super; - -private: - typedef DVMObject ThisClass; - static void InPlaceConstructor(void *mem) - { - new((EInPlace *)mem) DVMObject; - } - -public: - void Destroy() - { - if (ObjectFlags & OF_SuperCall) - { - ObjectFlags &= OF_SuperCall; - ExportedNatives::Get()->template Destroy(this); - } - else - { - static int VIndex = -1; - if (VIndex < 0) - { - // Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override. - auto sym = dyn_cast(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false)); - assert(sym != nullptr); - VIndex = sym->Variants[0].Implementation->VirtualIndex; - assert(VIndex >= 0); - } - // Without the type cast this picks the 'void *' assignment... - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); - } - } - void Tick() - { - ExportedNatives::Get()->template Tick(this); - } - AInventory *DropInventory(AInventory *item) - { - return ExportedNatives::Get()->template DropInventory(this, item); - } -}; - -template -ClassReg DVMObject::RegistrationInfo = -{ - nullptr, - DVMObject::FormatClassName(), - &DVMObject::Super::RegistrationInfo, - nullptr, - nullptr, - DVMObject::InPlaceConstructor, - nullptr, - sizeof(DVMObject), - DVMObject::MetaClassNum -}; -template _DECLARE_TI(DVMObject) - -VMEXPORT_NATIVES_START(DObject, void) - VMEXPORT_NATIVES_FUNC(Destroy) -VMEXPORT_NATIVES_END(DObject) - // When you write to a pointer to an Object, you must call this for // proper bookkeeping in case the Object holding this pointer has // already been processed by the GC. diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 912b5642e..06cd5dbfa 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -40,6 +40,7 @@ #include "doomerrors.h" #include "serializer.h" #include "d_player.h" +#include "virtual.h" static cycle_t ThinkCycles; diff --git a/src/dthinker.h b/src/dthinker.h index e1020544c..95985c2fb 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -108,10 +108,6 @@ private: DThinker *NextThinker, *PrevThinker; }; -VMEXPORT_NATIVES_START(DThinker, DObject) - VMEXPORT_NATIVES_FUNC(Tick) -VMEXPORT_NATIVES_END(DThinker) - class FThinkerIterator { protected: diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index c6192b8e2..35b24eb93 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -26,7 +26,6 @@ #include "a_hereticartifacts.cpp" #include "a_hereticweaps.cpp" #include "a_ironlich.cpp" -#include "a_wizard.cpp" static FRandom pr_podpain ("PodPain"); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 94b739135..65fd1ad34 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -72,6 +72,7 @@ #include "serializer.h" #include "r_utility.h" #include "thingdef.h" +#include "virtual.h" // MACROS ------------------------------------------------------------------ diff --git a/src/p_user.cpp b/src/p_user.cpp index f4e52ac2f..6b0b2cfe6 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -59,6 +59,7 @@ #include "p_blockmap.h" #include "a_morph.h" #include "p_spec.h" +#include "virtual.h" static FRandom pr_skullpop ("SkullPop"); diff --git a/src/virtual.h b/src/virtual.h new file mode 100644 index 000000000..377ec2ce8 --- /dev/null +++ b/src/virtual.h @@ -0,0 +1,132 @@ + + + +// Templates really are powerful +#define VMEXPORTED_NATIVES_START \ + template class ExportedNatives : public ExportedNatives {}; \ + template<> class ExportedNatives { \ + protected: ExportedNatives() {} \ + public: \ + static ExportedNatives *Get() { static ExportedNatives *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives; return Instance; } \ + ExportedNatives(const ExportedNatives&) = delete; \ + ExportedNatives(ExportedNatives&&) = delete; + +#define VMEXPORTED_NATIVES_FUNC(func) \ + template ret func(void *ptr, args ... arglist) { return ret(); } + +#define VMEXPORTED_NATIVES_END }; + +#define VMEXPORT_NATIVES_START(cls, parent) \ + template<> class ExportedNatives : public ExportedNatives { \ + protected: ExportedNatives() {} \ + public: \ + static ExportedNatives *Get() { static ExportedNatives *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives; return Instance; } \ + ExportedNatives(const ExportedNatives&) = delete; \ + ExportedNatives(ExportedNatives&&) = delete; + +#define VMEXPORT_NATIVES_FUNC(func) \ + template ret func(void *ptr, args ... arglist) { return static_cast(ptr)->object::func(arglist...); } + +#define VMEXPORT_NATIVES_END(cls) }; + + +//Initial list +VMEXPORTED_NATIVES_START + VMEXPORTED_NATIVES_FUNC(Destroy) + VMEXPORTED_NATIVES_FUNC(Tick) + VMEXPORTED_NATIVES_FUNC(DropInventory) +VMEXPORTED_NATIVES_END + +template +class DVMObject : public T +{ +public: + static char *FormatClassName() + { + static char *name = nullptr; + if (name == nullptr) + { + name = new char[64]; + mysnprintf(name, 64, "DVMObject<%s>", Super::RegistrationInfo.Name); + atterm([]{ delete[] DVMObject::RegistrationInfo.Name; }); + } + return name; + } + + virtual PClass *StaticType() const + { + return RegistrationInfo.MyClass; + } + static ClassReg RegistrationInfo; + static ClassReg * const RegistrationInfoPtr; + typedef T Super; + +private: + typedef DVMObject ThisClass; + static void InPlaceConstructor(void *mem) + { + new((EInPlace *)mem) DVMObject; + } + +public: + void Destroy() + { + if (ObjectFlags & OF_SuperCall) + { + ObjectFlags &= OF_SuperCall; + ExportedNatives::Get()->template Destroy(this); + } + else + { + static int VIndex = -1; + if (VIndex < 0) + { + // Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override. + auto sym = dyn_cast(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false)); + assert(sym != nullptr); + VIndex = sym->Variants[0].Implementation->VirtualIndex; + assert(VIndex >= 0); + } + // Without the type cast this picks the 'void *' assignment... + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr); + } + } + void Tick() + { + ExportedNatives::Get()->template Tick(this); + } + AInventory *DropInventory(AInventory *item) + { + return ExportedNatives::Get()->template DropInventory(this, item); + } +}; + +template +ClassReg DVMObject::RegistrationInfo = +{ + nullptr, + DVMObject::FormatClassName(), + &DVMObject::Super::RegistrationInfo, + nullptr, + nullptr, + DVMObject::InPlaceConstructor, + nullptr, + sizeof(DVMObject), + DVMObject::MetaClassNum +}; +template _DECLARE_TI(DVMObject) + +VMEXPORT_NATIVES_START(DObject, void) + VMEXPORT_NATIVES_FUNC(Destroy) +VMEXPORT_NATIVES_END(DObject) + +VMEXPORT_NATIVES_START(DThinker, DObject) + VMEXPORT_NATIVES_FUNC(Tick) +VMEXPORT_NATIVES_END(DThinker) + +VMEXPORT_NATIVES_START(AActor, DThinker) + VMEXPORT_NATIVES_FUNC(DropInventory) +VMEXPORT_NATIVES_END(AActor) +