From 1eb7912bd835b460a62fb89ac937d6dc26c76c09 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 17 Sep 2009 01:36:14 +0000 Subject: [PATCH] - Make the autosegs read-only. - Derive PClass from dobject.cpp. This has one major ramification: Since the PClass is not allocated until runtime, you cannot initialize any static/global data structures with pointers to PClasses using RUNTIME_CLASS. Attempting to do so will just initialize with a NULL pointer. Instead, you can initialize using the address of the pointer returned by RUNTIME_CLASS and dereference that. By the time you have an opportunity to dereference it, it will no longer be NULL. - Sync CmakeLists.txt. - Random fixes for problems GCC spotted. SVN r1852 (scripting) --- src/CMakeLists.txt | 4 + src/autosegs.h | 2 +- src/autostart.cpp | 44 ++++++----- src/autozend.cpp | 33 ++++---- src/d_dehacked.cpp | 20 ++--- src/d_main.cpp | 6 -- src/decallib.h | 2 +- src/dobject.cpp | 6 +- src/dobject.h | 37 +++++---- src/dobjgc.cpp | 13 ++-- src/dobjtype.cpp | 109 +++++++++++++++++++-------- src/dobjtype.h | 10 ++- src/g_level.h | 4 +- src/g_shared/a_decals.cpp | 6 +- src/g_shared/a_morph.h | 2 +- src/info.cpp | 18 ++++- src/info.h | 18 ++--- src/m_cheat.cpp | 22 +++--- src/m_cheat.h | 2 +- src/p_buildmap.cpp | 4 +- src/p_enemy.h | 2 +- src/p_lnspec.cpp | 26 +++---- src/p_map.cpp | 2 +- src/p_spec.cpp | 2 +- src/p_terrain.h | 2 +- src/sdl/i_main.cpp | 1 + src/textures/textures.h | 2 +- src/thingdef/thingdef.h | 23 +++--- src/thingdef/thingdef_data.cpp | 22 +++--- src/thingdef/thingdef_expression.cpp | 3 - src/thingdef/thingdef_parse.cpp | 4 +- src/win32/i_main.cpp | 1 + src/zscript/vm.h | 7 +- src/zscript/vmexec.h | 2 +- wadsrc/static/actors/constants.txt | 4 - 35 files changed, 258 insertions(+), 207 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f7b8dd1ae..824d764a6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -771,6 +771,9 @@ add_executable( zdoom WIN32 timidity/resample.cpp timidity/timidity.cpp xlat/parse_xlat.cpp + zscript/vmdisasm.cpp + zscript/vmexec.cpp + zscript/vmframe.cpp autozend.cpp ) set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" ) @@ -790,6 +793,7 @@ include_directories( . thingdef timidity xlat + zscript ../game-music-emu/gme ../gdtoa ../dumb/include diff --git a/src/autosegs.h b/src/autosegs.h index fb3c0d3ee..b4f825879 100644 --- a/src/autosegs.h +++ b/src/autosegs.h @@ -36,7 +36,7 @@ #define AUTOSEGS_H #define REGMARKER(x) (x) -typedef void *REGINFO; +typedef void * const REGINFO; // List of Action functons extern REGINFO ARegHead; diff --git a/src/autostart.cpp b/src/autostart.cpp index 6ed85ae15..3822bafc1 100644 --- a/src/autostart.cpp +++ b/src/autostart.cpp @@ -46,24 +46,29 @@ #if defined(_MSC_VER) -#pragma comment(linker, "/merge:.areg=.data /merge:.creg=.data /merge:.greg=.data /merge:.mreg=.data /merge:.yreg=.data") +// The various reg sections are used to group pointers spread across multiple +// source files into cohesive arrays in the final executable. We don't +// actually care about these sections themselves and merge them all into +// a single section during the final link. (.rdata is the standard section +// for initialized read-only data.) -#pragma data_seg(".areg$a") -void *ARegHead = 0; +#pragma comment(linker, "/merge:.areg=.rdata /merge:.creg=.rdata /merge:.greg=.rdata") +#pragma comment(linker, "/merge:.mreg=.rdata /merge:.yreg=.rdata") -#pragma data_seg(".creg$a") -void *CRegHead = 0; +#pragma section(".areg$a",read) +__declspec(allocate(".areg$a")) void *const ARegHead = 0; -#pragma data_seg(".greg$a") -void *GRegHead = 0; +#pragma section(".creg$a",read) +__declspec(allocate(".creg$a")) void *const CRegHead = 0; -#pragma data_seg(".mreg$a") -void *MRegHead = 0; +#pragma section(".greg$a",read) +__declspec(allocate(".greg$a")) void *const GRegHead = 0; -#pragma data_seg(".yreg$a") -void *YRegHead = 0; +#pragma section(".mreg$a",read) +__declspec(allocate(".mreg$a")) void *const MRegHead = 0; -#pragma data_seg() +#pragma section(".yreg$a",read) +__declspec(allocate(".yreg$a")) void *const YRegHead = 0; // We want visual styles support under XP #if defined _M_IX86 @@ -88,11 +93,16 @@ void *YRegHead = 0; #include "doomtype.h" -void *ARegHead __attribute__((section(SECTION_AREG))) = 0; -void *CRegHead __attribute__((section(SECTION_CREG))) = 0; -void *GRegHead __attribute__((section(SECTION_GREG))) = 0; -void *MRegHead __attribute__((section(SECTION_MREG))) = 0; -void *YRegHead __attribute__((section(SECTION_YREG))) = 0; +// I don't know of an easy way to merge sections together with the GNU linker, +// so GCC users will see all of these sections appear in the final executable. +// (There are linker scripts, but that apparently involves extracting the +// default script from ld and then modifying it.) + +void *ARegHead const __attribute__((section(SECTION_AREG))) = 0; +void *CRegHead const __attribute__((section(SECTION_CREG))) = 0; +void *GRegHead const __attribute__((section(SECTION_GREG))) = 0; +void *MRegHead const __attribute__((section(SECTION_MREG))) = 0; +void *YRegHead const __attribute__((section(SECTION_YREG))) = 0; #else diff --git a/src/autozend.cpp b/src/autozend.cpp index 023f8c733..ab61bc92c 100644 --- a/src/autozend.cpp +++ b/src/autozend.cpp @@ -37,34 +37,31 @@ #if defined(_MSC_VER) -#pragma data_seg(".areg$z") -void *ARegTail = 0; +#pragma section(".areg$z",read) +__declspec(allocate(".areg$z")) void *const ARegTail = 0; -#pragma data_seg(".creg$z") -void *CRegTail = 0; +#pragma section(".creg$z",read) +__declspec(allocate(".creg$z")) void *const CRegTail = 0; -#pragma data_seg(".greg$z") -void *GRegTail = 0; +#pragma section(".greg$z",read) +__declspec(allocate(".greg$z")) void *const GRegTail = 0; -#pragma data_seg(".mreg$z") -void *MRegTail = 0; - -#pragma data_seg(".yreg$z") -void *YRegTail = 0; - -#pragma data_seg() +#pragma section(".mreg$z",read) +__declspec(allocate(".mreg$z")) void *const MRegTail = 0; +#pragma section(".yreg$z",read) +__declspec(allocate(".yreg$z")) void *const YRegTail = 0; #elif defined(__GNUC__) #include "doomtype.h" -void *ARegTail __attribute__((section(SECTION_AREG))) = 0; -void *CRegTail __attribute__((section(SECTION_CREG))) = 0; -void *GRegTail __attribute__((section(SECTION_GREG))) = 0; -void *MRegTail __attribute__((section(SECTION_MREG))) = 0; -void *YRegTail __attribute__((section(SECTION_YREG))) = 0; +void *const ARegTail __attribute__((section(SECTION_AREG))) = 0; +void *const CRegTail __attribute__((section(SECTION_CREG))) = 0; +void *const GRegTail __attribute__((section(SECTION_GREG))) = 0; +void *const MRegTail __attribute__((section(SECTION_MREG))) = 0; +void *const YRegTail __attribute__((section(SECTION_YREG))) = 0; #else diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 1ac3ff287..09fd3ba18 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1760,16 +1760,16 @@ static int PatchMisc (int dummy) "Minotaur", NULL }; - static const PClass * const types[] = + static const PClass * const *types[] = { - RUNTIME_CLASS(APowerInvulnerable), - RUNTIME_CLASS(APowerStrength), - RUNTIME_CLASS(APowerInvisibility), - RUNTIME_CLASS(APowerIronFeet), - RUNTIME_CLASS(APowerLightAmp), - RUNTIME_CLASS(APowerWeaponLevel2), - RUNTIME_CLASS(APowerSpeed), - RUNTIME_CLASS(APowerMinotaur) + &RUNTIME_CLASS(APowerInvulnerable), + &RUNTIME_CLASS(APowerStrength), + &RUNTIME_CLASS(APowerInvisibility), + &RUNTIME_CLASS(APowerIronFeet), + &RUNTIME_CLASS(APowerLightAmp), + &RUNTIME_CLASS(APowerWeaponLevel2), + &RUNTIME_CLASS(APowerSpeed), + &RUNTIME_CLASS(APowerMinotaur) }; int i; @@ -1795,7 +1795,7 @@ static int PatchMisc (int dummy) } else { - static_cast(GetDefaultByType (types[i]))->BlendColor = PalEntry( + static_cast(GetDefaultByType (*types[i]))->BlendColor = PalEntry( BYTE(clamp(a,0.f,1.f)*255.f), clamp(r,0,255), clamp(g,0,255), diff --git a/src/d_main.cpp b/src/d_main.cpp index 7c0a13aca..9ade69c8e 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1691,12 +1691,10 @@ void D_DoomMain (void) execFiles = new DArgs; GameConfig->AddAutoexec (execFiles, GameNames[gameinfo.gametype]); D_MultiExec (execFiles, true); - execFiles->Destroy(); // Run .cfg files at the start of the command line. execFiles = Args->GatherFiles (NULL, ".cfg", false); D_MultiExec (execFiles, true); - execFiles->Destroy(); C_ExecCmdLineParams (); // [RH] do all +set commands on the command line @@ -1730,10 +1728,6 @@ void D_DoomMain (void) D_AddWildFile (files3->GetArg (i)); } } - files->Destroy(); - files1->Destroy(); - files2->Destroy(); - files3->Destroy(); Printf ("W_Init: Init WADfiles.\n"); Wads.InitMultipleFiles (&wadfiles); diff --git a/src/decallib.h b/src/decallib.h index 70804b0e5..61b97fc94 100644 --- a/src/decallib.h +++ b/src/decallib.h @@ -43,7 +43,7 @@ class FScanner; class FDecalTemplate; struct FDecalAnimator; -struct PClass; +class PClass; class DBaseDecal; struct side_t; diff --git a/src/dobject.cpp b/src/dobject.cpp index d71f87ed7..00ae9ee50 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -48,10 +48,9 @@ #include "a_sharedglobal.h" #include "dsectoreffect.h" -PClass DObject::_StaticType; ClassReg DObject::RegistrationInfo = { - &DObject::_StaticType, // MyClass + NULL, // MyClass "DObject", // Name NULL, // ParentType sizeof(DObject), // SizeOf @@ -458,9 +457,12 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld) int i; // Go through all objects. + i = 0;DObject *last=0; for (probe = GC::Root; probe != NULL; probe = probe->ObjNext) { + i++; changed += probe->PointerSubstitution(old, notOld); + last = probe; } // Go through the bodyque. diff --git a/src/dobject.h b/src/dobject.h index 39ccbc576..8ed1f2352 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -37,7 +37,7 @@ #include #include "doomtype.h" -struct PClass; +class PClass; class FArchive; @@ -130,29 +130,28 @@ private: void CopyMeta (const FMetaTable *other); }; -#define RUNTIME_TYPE(object) (object->GetClass()) // Passed an object, returns the type of that object -#define RUNTIME_CLASS(cls) (&cls::_StaticType) // Passed a class name, returns a PClass representing that class -#define NATIVE_TYPE(object) (object->StaticType()) // Passed an object, returns the type of the C++ class representing the object +#define RUNTIME_TYPE(object) (object->GetClass()) // Passed an object, returns the type of that object +#define RUNTIME_CLASS(cls) (cls::RegistrationInfo.MyClass) // Passed a native class name, returns a PClass representing that class +#define NATIVE_TYPE(object) (object->StaticType()) // Passed an object, returns the type of the C++ class representing the object struct ClassReg { PClass *MyClass; const char *Name; - PClass *ParentType; + ClassReg *ParentType; unsigned int SizeOf; const size_t *Pointers; void (*ConstructNative)(void *); - void RegisterClass() const; + PClass *RegisterClass(); }; enum EInPlace { EC_InPlace }; #define DECLARE_ABSTRACT_CLASS(cls,parent) \ public: \ - static PClass _StaticType; \ - virtual PClass *StaticType() const { return &_StaticType; } \ - static ClassReg RegistrationInfo, *RegistrationInfoPtr; \ + virtual PClass *StaticType() const { return RegistrationInfo.MyClass; } \ + static ClassReg RegistrationInfo, * const RegistrationInfoPtr; \ private: \ typedef parent Super; \ typedef cls ThisClass; @@ -170,19 +169,17 @@ private: \ #define END_POINTERS ~(size_t)0 }; #if defined(_MSC_VER) -# pragma data_seg(".creg$u") -# pragma data_seg() -# define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg *cls::RegistrationInfoPtr = &cls::RegistrationInfo; +# pragma section(".creg$u",read) +# define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo; #else -# define _DECLARE_TI(cls) ClassReg *cls::RegistrationInfoPtr __attribute__((section(SECTION_CREG))) = &cls::RegistrationInfo; +# define _DECLARE_TI(cls) ClassReg * const cls::RegistrationInfoPtr __attribute__((section(SECTION_CREG))) = &cls::RegistrationInfo; #endif #define _IMP_PCLASS(cls,ptrs,create) \ - PClass cls::_StaticType; \ ClassReg cls::RegistrationInfo = {\ - RUNTIME_CLASS(cls), \ + NULL, \ #cls, \ - RUNTIME_CLASS(cls::Super), \ + &cls::Super::RegistrationInfo, \ sizeof(cls), \ ptrs, \ create }; \ @@ -263,6 +260,9 @@ namespace GC // Size of GC steps. extern int StepMul; + // Is this the final collection just before exit? + extern bool FinalGC; + // Current white value for known-dead objects. static inline uint32 OtherWhite() { @@ -433,9 +433,8 @@ template inline void GC::Mark(TObjPtr &obj) class DObject { public: - static PClass _StaticType; - virtual PClass *StaticType() const { return &_StaticType; } - static ClassReg RegistrationInfo, *RegistrationInfoPtr; + virtual PClass *StaticType() const { return RegistrationInfo.MyClass; } + static ClassReg RegistrationInfo, * const RegistrationInfoPtr; static void InPlaceConstructor (void *mem); private: typedef DObject ThisClass; diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 0ba5d7c81..101729037 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -147,6 +147,7 @@ int Pause = DEFAULT_GCPAUSE; int StepMul = DEFAULT_GCMUL; int StepCount; size_t Dept; +bool FinalGC; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -239,8 +240,8 @@ static DObject **SweepList(DObject **p, size_t count, size_t *finalize_count) // be in a thinker list, then I need to add write barriers for every time a // thinker pointer is changed. This seems easier and perfectly reasonable, since // a live thinker that isn't on a thinker list isn't much of a thinker. - assert(!curr->IsKindOf(RUNTIME_CLASS(DThinker)) || (curr->ObjectFlags & OF_Sentinel)); - assert(!curr->IsKindOf(RUNTIME_CLASS(DInterpolation))); + assert(FinalGC || !curr->IsKindOf(RUNTIME_CLASS(DThinker)) || (curr->ObjectFlags & OF_Sentinel)); + assert(FinalGC || !curr->IsKindOf(RUNTIME_CLASS(DInterpolation))); curr->Destroy(); } curr->ObjectFlags |= OF_Cleanup; @@ -327,14 +328,10 @@ static void MarkRoot() SectorMarker->SecNum = 0; } Mark(SectorMarker); - // Mark symbol tables + // Mark classes for (unsigned j = 0; j < PClass::m_Types.Size(); ++j) { - PClass *cls = PClass::m_Types[j]; - if (cls != NULL) - { - cls->Symbols.MarkSymbols(); - } + Mark(PClass::m_Types[j]); } // Mark bot stuff. Mark(bglobal.firstthing); diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 93586bcbf..d0e26b8ba 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -38,6 +38,10 @@ #include "templates.h" #include "autosegs.h" +IMPLEMENT_POINTY_CLASS(PClass) + DECLARE_POINTER(ParentClass) +END_POINTERS + TArray PClass::m_RuntimeActors; TArray PClass::m_Types; PClass *PClass::TypeHash[PClass::HASH_SIZE]; @@ -48,35 +52,29 @@ static const size_t TheEnd = ~(size_t)0; static int STACK_ARGS cregcmp (const void *a, const void *b) { - // VC++ introduces NULLs in the sequence. GCC seems to work as expected and not do it. - const ClassReg *class1 = *(const ClassReg **)a; - const ClassReg *class2 = *(const ClassReg **)b; - if (class1 == NULL) return 1; - if (class2 == NULL) return -1; - return strcmp (class1->Name, class2->Name); + const PClass *class1 = *(const PClass **)a; + const PClass *class2 = *(const PClass **)b; + return strcmp(class1->TypeName, class2->TypeName); } void PClass::StaticInit () { atterm (StaticShutdown); - // Sort classes by name to remove dependance on how the compiler ordered them. - REGINFO *head = &CRegHead; - REGINFO *tail = &CRegTail; - - // MinGW's linker is linking the object files backwards for me now... - if (head > tail) - { - swap (head, tail); - } - qsort (head + 1, tail - head - 1, sizeof(REGINFO), cregcmp); - FAutoSegIterator probe(CRegHead, CRegTail); while (*++probe != NULL) { ((ClassReg *)*probe)->RegisterClass (); } + + // Keep actors in consistant order. I did this before, though I'm not + // sure if this is really necessary to maintain any sort of sync. + qsort(&m_Types[0], m_Types.Size(), sizeof(m_Types[0]), cregcmp); + for (unsigned int i = 0; i < m_Types.Size(); ++i) + { + m_Types[i]->ClassIndex = i; + } } void PClass::StaticShutdown () @@ -114,6 +112,24 @@ void PClass::StaticShutdown () bShutdown = true; } +PClass::PClass() +{ + Size = sizeof(DObject); + ParentClass = NULL; + Pointers = NULL; + FlatPointers = NULL; + ActorInfo = NULL; + HashNext = NULL; + Defaults = NULL; + bRuntimeClass = false; + ClassIndex = ~0; +} + +PClass::~PClass() +{ + Symbols.ReleaseSymbols(); +} + void PClass::StaticFreeData (PClass *type) { if (type->Defaults != NULL) @@ -142,7 +158,7 @@ void PClass::StaticFreeData (PClass *type) } delete type->ActorInfo; type->ActorInfo = NULL; - } + }/* if (type->bRuntimeClass) { delete type; @@ -150,22 +166,32 @@ void PClass::StaticFreeData (PClass *type) else { type->Symbols.ReleaseSymbols(); - } + }*/ } -void ClassReg::RegisterClass () const +PClass *ClassReg::RegisterClass() { - assert (MyClass != NULL); + // MyClass may have already been created by a previous recursive call. + // Or this may be a recursive call for a previously created class. + if (MyClass != NULL) + { + return MyClass; + } // Add type to list - MyClass->ClassIndex = PClass::m_Types.Push (MyClass); - - MyClass->TypeName = FName(Name+1); - MyClass->ParentClass = ParentType; - MyClass->Size = SizeOf; - MyClass->Pointers = Pointers; - MyClass->ConstructNative = ConstructNative; - MyClass->InsertIntoHash (); + PClass *cls = new PClass; + MyClass = cls; + PClass::m_Types.Push(cls); + cls->TypeName = FName(Name+1); + if (ParentType != NULL) + { + cls->ParentClass = ParentType->RegisterClass(); + } + cls->Size = SizeOf; + cls->Pointers = Pointers; + cls->ConstructNative = ConstructNative; + cls->InsertIntoHash(); + return cls; } void PClass::InsertIntoHash () @@ -465,6 +491,28 @@ const PClass *PClass::NativeClass() const return cls; } +size_t PClass::PropagateMark() +{ + size_t marked; + + // Mark symbols + marked = Symbols.MarkSymbols(); + + // Mark state functions + if (ActorInfo != NULL) + { + for (int i = 0; i < ActorInfo->NumOwnedStates; ++i) + { + if (ActorInfo->OwnedStates[i].ActionFunc != NULL) + { + GC::Mark(ActorInfo->OwnedStates[i].ActionFunc); + } + } +// marked += ActorInfo->NumOwnedStates * sizeof(FState); + } + return marked + Super::PropagateMark(); +} + // Symbol tables ------------------------------------------------------------ IMPLEMENT_ABSTRACT_CLASS(PSymbol); @@ -486,12 +534,13 @@ PSymbolTable::~PSymbolTable () ReleaseSymbols(); } -void PSymbolTable::MarkSymbols() +size_t PSymbolTable::MarkSymbols() { for (unsigned int i = 0; i < Symbols.Size(); ++i) { GC::Mark(Symbols[i]); } + return Symbols.Size() * sizeof(Symbols[0]); } void PSymbolTable::ReleaseSymbols() diff --git a/src/dobjtype.h b/src/dobjtype.h index d58ce2f00..518f076c6 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -101,7 +101,7 @@ struct PSymbolTable PSymbolTable(); ~PSymbolTable(); - void MarkSymbols(); + size_t MarkSymbols(); // Sets the table to use for searches if this one doesn't contain the // requested symbol. @@ -126,8 +126,11 @@ private: // Meta-info for every class derived from DObject --------------------------- -struct PClass +class PClass : public DObject { + DECLARE_CLASS(PClass, DObject); + HAS_OBJECT_POINTERS; +public: static void StaticInit (); static void StaticShutdown (); static void StaticFreeData (PClass *type); @@ -149,6 +152,8 @@ struct PClass void (*ConstructNative)(void *); // The rest are all functions and static data ---------------- + PClass(); + ~PClass(); void InsertIntoHash (); DObject *CreateNew () const; PClass *CreateDerivedClass (FName name, unsigned int size); @@ -156,6 +161,7 @@ struct PClass void BuildFlatPointers (); void FreeStateList(); const PClass *NativeClass() const; + size_t PropagateMark(); // Returns true if this type is an ancestor of (or same as) the passed type. bool IsAncestorOf (const PClass *ti) const diff --git a/src/g_level.h b/src/g_level.h index 3b0851636..3f5186b1e 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -44,9 +44,7 @@ struct cluster_info_t; class FScanner; #if defined(_MSC_VER) -#pragma data_seg(".yreg$u") -#pragma data_seg() - +#pragma section(".yreg$u",read) #define MSVC_YSEG __declspec(allocate(".yreg$u")) #define GCC_YSEG #else diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 77c036ba8..e1184c40c 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -357,7 +357,7 @@ fixed_t DBaseDecal::GetRealZ (const side_t *wall) const void DBaseDecal::CalcFracPos (side_t *wall, fixed_t x, fixed_t y) { - line_t *line = line = wall->linedef; + line_t *line = wall->linedef; vertex_t *v1, *v2; if (line->sidedef[0] == wall) @@ -390,7 +390,7 @@ void DBaseDecal::CalcFracPos (side_t *wall, fixed_t x, fixed_t y) static void GetWallStuff (side_t *wall, vertex_t *&v1, fixed_t &ldx, fixed_t &ldy) { - line_t *line = line = wall->linedef; + line_t *line = wall->linedef; if (line->sidedef[0] == wall) { v1 = line->v1; @@ -412,7 +412,7 @@ static fixed_t Length (fixed_t dx, fixed_t dy) static side_t *NextWall (const side_t *wall) { - line_t *line = line = wall->linedef;; + line_t *line = wall->linedef;; if (line->sidedef[0] == wall) { diff --git a/src/g_shared/a_morph.h b/src/g_shared/a_morph.h index 7ae83aed4..338b5f549 100644 --- a/src/g_shared/a_morph.h +++ b/src/g_shared/a_morph.h @@ -25,7 +25,7 @@ enum MORPH_UNDOBYDEATHSAVES = 0x00000800, // Actor (if unmorphed when killed) regains their health and doesn't die }; -struct PClass; +class PClass; class AActor; class player_t; class AMorphedMonster; diff --git a/src/info.cpp b/src/info.cpp index aeb89e8c9..cf12086ea 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -39,9 +39,8 @@ #include "m_fixed.h" #include "c_dispatch.h" #include "d_net.h" - #include "gi.h" - +#include "vm.h" #include "actor.h" #include "r_state.h" #include "i_system.h" @@ -52,6 +51,21 @@ extern void LoadActors (); +bool FState::CallAction(AActor *self, AActor *stateowner, StateCallData *statecall) +{ + if (ActionFunc != NULL) + { + //ActionFunc(self, stateowner, this, ParameterIndex-1, statecall); + VMFrameStack stack; + VMValue params[5] = { self, stateowner, this, ParameterIndex - 1, VMValue(statecall, ATAG_STATE) }; + stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL); + return true; + } + else + { + return false; + } +} //========================================================================== // diff --git a/src/info.h b/src/info.h index 5e06bcc10..e4e73a5f8 100644 --- a/src/info.h +++ b/src/info.h @@ -43,6 +43,7 @@ #include "dobject.h" #include "doomdef.h" +#include "vm.h" const BYTE SF_FULLBRIGHT = 0x40; @@ -60,7 +61,7 @@ struct FState BYTE Frame; BYTE DefineFlags; // Unused byte so let's use it during state creation. FState *NextState; - actionf_p ActionFunc; + VMFunction *ActionFunc; int ParameterIndex; inline int GetFrame() const @@ -93,29 +94,20 @@ struct FState } void SetAction(PSymbolActionFunction *func, bool setdefaultparams = true) { +#if 0 if (func != NULL) { ActionFunc = func->Function; if (setdefaultparams) ParameterIndex = func->defaultparameterindex+1; } else +#endif { ActionFunc = NULL; if (setdefaultparams) ParameterIndex = 0; } } - inline bool CallAction(AActor *self, AActor *stateowner, StateCallData *statecall = NULL) - { - if (ActionFunc != NULL) - { - ActionFunc(self, stateowner, this, ParameterIndex-1, statecall); - return true; - } - else - { - return false; - } - } + bool CallAction(AActor *self, AActor *stateowner, StateCallData *statecall = NULL); static const PClass *StaticFindStateOwner (const FState *state); static const PClass *StaticFindStateOwner (const FState *state, const FActorInfo *info); }; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index bcf36d45d..a4ffd5950 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -52,17 +52,17 @@ void cht_DoCheat (player_t *player, int cheat) { - static const PClass *BeholdPowers[9] = + static const PClass *const *BeholdPowers[9] = { - RUNTIME_CLASS(APowerInvulnerable), - RUNTIME_CLASS(APowerStrength), - RUNTIME_CLASS(APowerInvisibility), - RUNTIME_CLASS(APowerIronFeet), + &RUNTIME_CLASS(APowerInvulnerable), + &RUNTIME_CLASS(APowerStrength), + &RUNTIME_CLASS(APowerInvisibility), + &RUNTIME_CLASS(APowerIronFeet), NULL, // MapRevealer - RUNTIME_CLASS(APowerLightAmp), - RUNTIME_CLASS(APowerShadow), - RUNTIME_CLASS(APowerMask), - RUNTIME_CLASS(APowerTargeter) + &RUNTIME_CLASS(APowerLightAmp), + &RUNTIME_CLASS(APowerShadow), + &RUNTIME_CLASS(APowerMask), + &RUNTIME_CLASS(APowerTargeter) }; const PClass *type; AInventory *item; @@ -248,12 +248,12 @@ void cht_DoCheat (player_t *player, int cheat) } else if (player->mo != NULL && player->health >= 0) { - item = player->mo->FindInventory (BeholdPowers[i]); + item = player->mo->FindInventory (*BeholdPowers[i]); if (item == NULL) { if (i != 0) { - player->mo->GiveInventoryType (BeholdPowers[i]); + player->mo->GiveInventoryType (*BeholdPowers[i]); if (cheat == CHT_BEHOLDS) { P_GiveBody (player->mo, -100); diff --git a/src/m_cheat.h b/src/m_cheat.h index d273965ae..e56c69198 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -29,7 +29,7 @@ // [RH] Functions that actually perform the cheating class player_t; -struct PClass; +class PClass; void cht_DoCheat (player_t *player, int cheat); void cht_Give (player_t *player, const char *item, int amount=1); void cht_Take (player_t *player, const char *item, int amount=1); diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 4e44e1c26..8cf3273e1 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -624,11 +624,11 @@ static void LoadWalls (walltype *walls, int numwalls, sectortype *bsec) int sidenum = int(intptr_t(lines[linenum].sidedef[1])); if (bsec->floorstat & 64) { // floor is aligned to first wall - R_AlignFlat (linenum, sidenum == (DWORD)bsec->wallptr, 0); + R_AlignFlat (linenum, (DWORD)sidenum == (DWORD)bsec->wallptr, 0); } if (bsec->ceilingstat & 64) { // ceiling is aligned to first wall - R_AlignFlat (linenum, sidenum == (DWORD)bsec->wallptr, 0); + R_AlignFlat (linenum, (DWORD)sidenum == (DWORD)bsec->wallptr, 0); } } for(i = 0; i < numsides; i++) diff --git a/src/p_enemy.h b/src/p_enemy.h index f111f9d08..73fe06e3d 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -6,7 +6,7 @@ struct sector_t; class AActor; class AInventory; -struct PClass; +class PClass; enum dirtype_t diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index b34ed4878..8615ffcac 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2504,19 +2504,19 @@ FUNC(LS_SetPlayerProperty) // Add or remove a power if (arg2 >= PROP_INVULNERABILITY && arg2 <= PROP_SPEED) { - static const PClass *powers[11] = + static const PClass * const *powers[11] = { - RUNTIME_CLASS(APowerInvulnerable), - RUNTIME_CLASS(APowerStrength), - RUNTIME_CLASS(APowerInvisibility), - RUNTIME_CLASS(APowerIronFeet), + &RUNTIME_CLASS(APowerInvulnerable), + &RUNTIME_CLASS(APowerStrength), + &RUNTIME_CLASS(APowerInvisibility), + &RUNTIME_CLASS(APowerIronFeet), NULL, // MapRevealer - RUNTIME_CLASS(APowerLightAmp), - RUNTIME_CLASS(APowerWeaponLevel2), - RUNTIME_CLASS(APowerFlight), + &RUNTIME_CLASS(APowerLightAmp), + &RUNTIME_CLASS(APowerWeaponLevel2), + &RUNTIME_CLASS(APowerFlight), NULL, NULL, - RUNTIME_CLASS(APowerSpeed) + &RUNTIME_CLASS(APowerSpeed) }; int power = arg2 - PROP_INVULNERABILITY; @@ -2531,7 +2531,7 @@ FUNC(LS_SetPlayerProperty) { // Give power to activator if (power != 4) { - APowerup *item = static_cast(it->GiveInventoryType (powers[power])); + APowerup *item = static_cast(it->GiveInventoryType (*powers[power])); if (item != NULL && power == 0) item->BlendColor = INVERSECOLOR; } else if (it->player - players == consoleplayer) @@ -2543,7 +2543,7 @@ FUNC(LS_SetPlayerProperty) { // Take power from activator if (power != 4) { - AInventory *item = it->FindInventory (powers[power]); + AInventory *item = it->FindInventory (*powers[power]); if (item != NULL) { item->Destroy (); @@ -2568,7 +2568,7 @@ FUNC(LS_SetPlayerProperty) { // Give power if (power != 4) { - players[i].mo->GiveInventoryType (powers[power]); + players[i].mo->GiveInventoryType (*powers[power]); } else if (i == consoleplayer) { @@ -2579,7 +2579,7 @@ FUNC(LS_SetPlayerProperty) { // Take power if (power != 4) { - AInventory *item = players[i].mo->FindInventory (powers[power]); + AInventory *item = players[i].mo->FindInventory (*powers[power]); if (item != NULL) { item->Destroy (); diff --git a/src/p_map.cpp b/src/p_map.cpp index 09dbf076b..b32c9e3ad 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4906,7 +4906,7 @@ msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode) if (s == 0) { - I_FatalError ("AddSecnode of 0 for %s\n", thing->_StaticType.TypeName.GetChars()); + I_FatalError ("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars()); } node = nextnode; diff --git a/src/p_spec.cpp b/src/p_spec.cpp index e1d486869..c7e792908 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -1332,7 +1332,7 @@ static void P_SpawnScrollers(void) if (special != 0) { int max = LineSpecialsInfo[special] != NULL ? LineSpecialsInfo[special]->map_args : countof(l->args); - for (int arg = max; arg < countof(l->args); ++arg) + for (int arg = max; arg < (int)countof(l->args); ++arg) { if (l->args[arg] != 0) { diff --git a/src/p_terrain.h b/src/p_terrain.h index 087087afe..e5a98ccf8 100644 --- a/src/p_terrain.h +++ b/src/p_terrain.h @@ -37,7 +37,7 @@ #include "s_sound.h" #include "textures/textures.h" -struct PClass; +class PClass; // This is just a wrapper class so that I don't have to expose FTextureID's implementation // to anything that doesn't really need it. diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index 5650c0781..7a80d9fc2 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -140,6 +140,7 @@ void STACK_ARGS call_terms () static void FinalGC() { + GC::FinalGC = true; Args = NULL; GC::FullGC(); } diff --git a/src/textures/textures.h b/src/textures/textures.h index c96da0648..195295a5c 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -7,7 +7,7 @@ class FBitmap; struct FRemapTable; struct FCopyInfo; class FScanner; -struct PClass; +class PClass; class FArchive; // Texture IDs diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index df4bc78ab..2f573f8e9 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -243,10 +243,9 @@ enum EDefinitionType }; #if defined(_MSC_VER) -#pragma data_seg(".areg$u") -#pragma data_seg(".greg$u") -#pragma data_seg(".mreg$u") -#pragma data_seg() +#pragma section(".areg$u",read) +#pragma section(".greg$u",read) +#pragma section(".mreg$u",read) #define MSVC_ASEG __declspec(allocate(".areg$u")) #define GCC_ASEG @@ -283,7 +282,7 @@ struct FPropertyInfo { const char *name; const char *params; - const PClass *cls; + const PClass * const *cls; PropHandler Handler; int category; }; @@ -292,7 +291,7 @@ struct FVariableInfo { const char *name; intptr_t address; - const PClass *owner; + const PClass * const *owner; }; @@ -304,14 +303,14 @@ int MatchString (const char *in, const char **strings); #define DEFINE_PROPERTY_BASE(name, paramlist, clas, cat) \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params); \ static FPropertyInfo Prop_##name##_##paramlist##_##clas = \ - { #name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ + { #name, #paramlist, &RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params) #define DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, cat) \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params); \ static FPropertyInfo Prop_##name##_##paramlist##_##clas = \ -{ #prefix"."#name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ +{ #prefix"."#name, #paramlist, &RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params) @@ -340,16 +339,12 @@ int MatchString (const char *in, const char **strings); int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(NULL, params[(no)+2].s); -#define DEFINE_GLOBAL_VARIABLE(name) \ - static FVariableInfo GlobalDef__##name = { #name, intptr_t(&name), NULL }; \ - MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; - #define DEFINE_MEMBER_VARIABLE(name, cls) \ - static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, name), RUNTIME_CLASS(cls) }; \ + static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, name), &RUNTIME_CLASS(cls) }; \ MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; #define DEFINE_MEMBER_VARIABLE_ALIAS(name, alias, cls) \ - static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, alias), RUNTIME_CLASS(cls) }; \ + static FVariableInfo GlobalDef__##name = { #name, myoffsetof(cls, alias), &RUNTIME_CLASS(cls) }; \ MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name; diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index c65cb5d21..b23852365 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -311,12 +311,12 @@ static FFlagDef PlayerPawnFlags[] = DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags), }; -static const struct FFlagList { const PClass *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] = +static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] = { - { RUNTIME_CLASS(AActor), ActorFlags, countof(ActorFlags) }, - { RUNTIME_CLASS(AInventory), InventoryFlags, countof(InventoryFlags) }, - { RUNTIME_CLASS(AWeapon), WeaponFlags, countof(WeaponFlags) }, - { RUNTIME_CLASS(APlayerPawn), PlayerPawnFlags,countof(PlayerPawnFlags) }, + { &RUNTIME_CLASS(AActor), ActorFlags, countof(ActorFlags) }, + { &RUNTIME_CLASS(AInventory), InventoryFlags, countof(InventoryFlags) }, + { &RUNTIME_CLASS(AWeapon), WeaponFlags, countof(WeaponFlags) }, + { &RUNTIME_CLASS(APlayerPawn), PlayerPawnFlags,countof(PlayerPawnFlags) }, }; #define NUM_FLAG_LISTS (countof(FlagLists)) @@ -364,7 +364,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2) { // Search all lists for (i = 0; i < NUM_FLAG_LISTS; ++i) { - if (type->IsDescendantOf (FlagLists[i].Type)) + if (type->IsDescendantOf (*FlagLists[i].Type)) { def = FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part1); if (def != NULL) @@ -378,9 +378,9 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2) { // Search just the named list for (i = 0; i < NUM_FLAG_LISTS; ++i) { - if (stricmp (FlagLists[i].Type->TypeName.GetChars(), part1) == 0) + if (stricmp ((*FlagLists[i].Type)->TypeName.GetChars(), part1) == 0) { - if (type->IsDescendantOf (FlagLists[i].Type)) + if (type->IsDescendantOf (*FlagLists[i].Type)) { return FindFlag (FlagLists[i].Defs, FlagLists[i].NumDefs, part2); } @@ -403,7 +403,7 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2) const char *GetFlagName(int flagnum, int flagoffset) { - for(int i=0; iowner) lexval = -1; - else if (cls > variables[mid]->owner) lexval = 1; + if (cls < *variables[mid]->owner) lexval = -1; + else if (cls > *variables[mid]->owner) lexval = 1; else lexval = stricmp (string, variables[mid]->name); if (lexval == 0) diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index d68ecfcd6..60a01586b 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -50,9 +50,6 @@ #include "doomstat.h" #include "thingdef_exp.h" -int testglobalvar = 1337; // just for having one global variable to test with -DEFINE_GLOBAL_VARIABLE(testglobalvar) - // Accessible actor member variables DEFINE_MEMBER_VARIABLE(alpha, AActor) DEFINE_MEMBER_VARIABLE(angle, AActor) diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 039d578b4..160555f46 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -733,13 +733,13 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) if (prop != NULL) { - if (bag.Info->Class->IsDescendantOf(prop->cls)) + if (bag.Info->Class->IsDescendantOf(*prop->cls)) { ParsePropertyParams(sc, prop, (AActor *)bag.Info->Class->Defaults, bag); } else { - sc.ScriptMessage("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), prop->cls->TypeName.GetChars()); + sc.ScriptMessage("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), (*prop->cls)->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } } diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 6bc9e2f5f..5f2383fee 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -262,6 +262,7 @@ static void UnWTS (void) static void FinalGC() { + GC::FinalGC = true; Args = NULL; GC::FullGC(); } diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 6755290c7..61207e862 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -409,13 +409,12 @@ struct VMValue Type = REGT_POINTER; return *this; } - VMValue &operator=(void *v) + void SetPointer(void *v, VM_UBYTE atag=ATAG_GENERIC) { Kill(); a = v; - atag = ATAG_GENERIC; - Type = REGT_POINTER; - return *this; + atag = atag; + Type = atag; } void SetNil() { diff --git a/src/zscript/vmexec.h b/src/zscript/vmexec.h index 6bb2ae3eb..ec41b3ac8 100644 --- a/src/zscript/vmexec.h +++ b/src/zscript/vmexec.h @@ -540,7 +540,7 @@ begin: } if (B & REGT_FINAL) { - return MIN(numret, a + 1); + return a < numret ? a + 1 : numret; } NEXTOP; OP(RESULT): diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index f69771f25..c3a65e025 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -99,7 +99,3 @@ const float ATTN_NONE = 0; const float ATTN_NORM = 1; const float ATTN_IDLE = 1.001; const float ATTN_STATIC = 3; - - -// This is only here to provide one global variable for testing. -native int testglobalvar;