From a188a8839a6b16bed705d10d9ed47dec50b2f1d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 31 Jan 2017 10:09:44 +0100 Subject: [PATCH 01/11] - fixed a typo in Hexen's light definitions. --- wadsrc_lights/static/filter/hexen/gldefs.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc_lights/static/filter/hexen/gldefs.txt b/wadsrc_lights/static/filter/hexen/gldefs.txt index d72b9c76f..cc9513d97 100644 --- a/wadsrc_lights/static/filter/hexen/gldefs.txt +++ b/wadsrc_lights/static/filter/hexen/gldefs.txt @@ -1345,7 +1345,7 @@ flickerlight2 FIREBULL attenuate 1 color 1.0 0.7 0.0 size 96 - secondarysize - 105 + secondarysize 130 interval 0.1 offset 0 40 0 } From f0a325a904fc8bb2c6ae26cf16cbd52778d75e7a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 31 Jan 2017 13:22:05 +0100 Subject: [PATCH 02/11] - fixed: The restart CCMD needs to clear the global FraggleScript before taking down the class system. This is a soft root and would never be deleted otherwise. --- src/d_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index 6041af9b4..aa90d6c46 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2707,6 +2707,7 @@ void D_DoomMain (void) S_Shutdown(); // free all channels and delete playlist C_ClearAliases(); // CCMDs won't be reinitialized so these need to be deleted here DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods + FS_Close(); // destroy the global FraggleScript. GC::FullGC(); // clean up before taking down the object list. From 3131c08640c4e9831cdd9f190bb9b4099ed22b4e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 31 Jan 2017 13:41:23 +0100 Subject: [PATCH 03/11] - fixed: the restart CCMD must clear out all statically stored pointers to VM functions because they do not survive the shutdown that is needed before loading new data. --- src/dobjtype.cpp | 17 +++++++++++++++++ src/dobjtype.h | 2 ++ src/g_inventory/a_pickups.cpp | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 4 ++-- src/m_cheat.cpp | 2 +- src/p_acs.cpp | 4 ++-- 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 313ee7389..7468b6dab 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -69,6 +69,7 @@ FNamespaceManager Namespaces; FTypeTable TypeTable; TArray PClass::AllClasses; +TArray PClass::FunctionPtrList; bool PClass::bShutdown; bool PClass::bVMOperational; @@ -2840,6 +2841,12 @@ void PClass::StaticShutdown () TArray uniqueFPs(64); unsigned int i, j; + // delete all variables containing pointers to script functions. + for (auto p : FunctionPtrList) + { + *p = nullptr; + } + FunctionPtrList.Clear(); // Make a full garbage collection here so that all destroyed but uncollected higher level objects that still exist can be properly taken down. GC::FullGC(); @@ -3547,6 +3554,16 @@ VMFunction *PClass::FindFunction(FName clsname, FName funcname) return func->Variants[0].Implementation; } +void PClass::FindFunction(VMFunction **pptr, FName clsname, FName funcname) +{ + auto cls = PClass::FindActor(clsname); + if (!cls) return; + auto func = dyn_cast(cls->Symbols.FindSymbol(funcname, true)); + if (!func) return; + *pptr = func->Variants[0].Implementation; + FunctionPtrList.Push(pptr); +} + /* FTypeTable **************************************************************/ diff --git a/src/dobjtype.h b/src/dobjtype.h index 632ef96bb..2726ebff1 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -848,9 +848,11 @@ public: static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); } static PClassActor *FindActor(FName name); static VMFunction *FindFunction(FName cls, FName func); + static void FindFunction(VMFunction **pptr, FName cls, FName func); PClass *FindClassTentative(FName name); static TArray AllClasses; + static TArray FunctionPtrList; static bool bShutdown; static bool bVMOperational; diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index cd4d02f04..fc35d2da4 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -522,7 +522,7 @@ DEFINE_ACTION_FUNCTION(AInventory, DoRespawn) bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return) { static VMFunction *func = nullptr; - if (func == nullptr) func = PClass::FindFunction(NAME_Inventory, NAME_CallTryPickup); + if (func == nullptr) PClass::FindFunction(&func, NAME_Inventory, NAME_CallTryPickup); VMValue params[2] = { (DObject*)this, toucher }; VMReturn ret[2]; int res; diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 5e12bf9d0..c3950571f 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -1437,7 +1437,7 @@ class CommandDrawNumber : public CommandDrawString { // num = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem) / TICRATE + 1; static VMFunction *func = nullptr; - if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem"); + if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem"); VMValue params[] = { statusBar->CPlayer->mo, inventoryItem }; int retv; VMReturn ret(&retv); @@ -2830,7 +2830,7 @@ class CommandDrawBar : public SBarInfoCommand // [value, max] = statusBar.CPlayer.mo.GetEffectTicsForItem(inventoryItem); // value++; max++; static VMFunction *func = nullptr; - if (func == nullptr) func = PClass::FindFunction(NAME_PlayerPawn, "GetEffectTicsForItem"); + if (func == nullptr) PClass::FindFunction(&func, NAME_PlayerPawn, "GetEffectTicsForItem"); VMValue params[] = { statusBar->CPlayer->mo, data.inventoryItem }; VMReturn ret[2]; int ival; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 2f99ea61c..23c2f1ded 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -478,7 +478,7 @@ void cht_DoCheat (player_t *player, int cheat) if (player->mo != NULL && player->health >= 0) { static VMFunction *gsp = nullptr; - if (gsp == nullptr) gsp = PClass::FindFunction(NAME_Sigil, NAME_GiveSigilPiece); + if (gsp == nullptr) PClass::FindFunction(&gsp, NAME_Sigil, NAME_GiveSigilPiece); if (gsp) { VMValue params[1] = { player->mo }; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 24142e0ec..e346579c4 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -6203,7 +6203,7 @@ static bool CharArrayParms(int &capacity, int &offset, int &a, int *Stack, int & static void SetMarineWeapon(AActor *marine, int weapon) { static VMFunction *smw = nullptr; - if (smw == nullptr) smw = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetWeapon); + if (smw == nullptr) PClass::FindFunction(&smw, NAME_ScriptedMarine, NAME_SetWeapon); if (smw) { VMValue params[2] = { marine, weapon }; @@ -6214,7 +6214,7 @@ static void SetMarineWeapon(AActor *marine, int weapon) static void SetMarineSprite(AActor *marine, PClassActor *source) { static VMFunction *sms = nullptr; - if (sms == nullptr) sms = PClass::FindFunction(NAME_ScriptedMarine, NAME_SetSprite); + if (sms == nullptr) PClass::FindFunction(&sms, NAME_ScriptedMarine, NAME_SetSprite); if (sms) { VMValue params[2] = { marine, source }; From 94d5d6848e696f45075aafd047fd0ca8a9cea0fe Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 31 Jan 2017 13:46:35 +0100 Subject: [PATCH 04/11] - moved all code that deletes some data from P_SetupLevel to P_FreeLevelData so that P_Shutdown can also call it. This is particularly important for camera textures which otherwise would not be taken down before a restart. --- src/p_setup.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index df41345f4..a4e4ef1b9 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3423,6 +3423,17 @@ extern polyblock_t **PolyBlockMap; void P_FreeLevelData () { + MapThingsConverted.Clear(); + MapThingsUserDataIndex.Clear(); + MapThingsUserData.Clear(); + linemap.Clear(); + FCanvasTextureInfo::EmptyList(); + R_FreePastViewers(); + P_ClearUDMFKeys(); + + // [RH] Clear all ThingID hash chains. + AActor::ClearTIDHashes(); + P_FreeMapDataBackup(); interpolator.ClearInterpolations(); // [RH] Nothing to interpolate on a fresh level. Renderer->CleanLevelData(); @@ -3575,14 +3586,6 @@ void P_SetupLevel (const char *lumpname, int position) level.maptype = MAPTYPE_UNKNOWN; wminfo.partime = 180; - MapThingsConverted.Clear(); - MapThingsUserDataIndex.Clear(); - MapThingsUserData.Clear(); - linemap.Clear(); - FCanvasTextureInfo::EmptyList (); - R_FreePastViewers (); - P_ClearUDMFKeys(); - if (!savegamerestore) { for (i = 0; i < MAXPLAYERS; ++i) @@ -3612,8 +3615,6 @@ void P_SetupLevel (const char *lumpname, int position) // Make sure all sounds are stopped before Z_FreeTags. S_Start (); - // [RH] Clear all ThingID hash chains. - AActor::ClearTIDHashes (); // [RH] clear out the mid-screen message C_MidPrint (NULL, NULL); From 6225f60eb210fcdf3341b7233854a6715b241ac0 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 31 Jan 2017 11:05:29 +0200 Subject: [PATCH 05/11] Added cheat flag for console variables CVAR with this flag can be set in console or from command line when sv_cheats is enabled There is no such restriction for changing its value from ACS, via SetCVar() and related functions 'cheat' modifier can be used in CVARINFO lump to create variable of this kind --- src/c_cvars.cpp | 8 ++++++++ src/c_cvars.h | 1 + src/d_main.cpp | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index fe859cb49..11ebf5574 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -1617,8 +1617,16 @@ void C_ArchiveCVars (FConfigFile *f, uint32 filter) } } +EXTERN_CVAR(Bool, sv_cheats); + void FBaseCVar::CmdSet (const char *newval) { + if ((GetFlags() & CVAR_CHEAT) && !sv_cheats) + { + Printf("sv_cheats must be true to set this console variable.\n"); + return; + } + UCVarValue val; // Casting away the const is safe in this case. diff --git a/src/c_cvars.h b/src/c_cvars.h index cf6975b86..98dc71915 100644 --- a/src/c_cvars.h +++ b/src/c_cvars.h @@ -63,6 +63,7 @@ enum CVAR_NOSAVE = 4096, // when used with CVAR_SERVERINFO, do not save var to savegame CVAR_MOD = 8192, // cvar was defined by a mod CVAR_IGNORE = 16384,// do not send cvar across the network/inaccesible from ACS (dummy mod cvar) + CVAR_CHEAT = 32768,// can be set only when sv_cheats is enabled }; union UCVarValue diff --git a/src/d_main.cpp b/src/d_main.cpp index aa90d6c46..e0676b751 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1398,6 +1398,10 @@ void ParseCVarInfo() { cvarflags &= ~CVAR_ARCHIVE; } + else if (stricmp(sc.String, "cheat") == 0) + { + cvarflags |= CVAR_CHEAT; + } else { sc.ScriptError("Unknown cvar attribute '%s'", sc.String); From 1cdfcb4935f2cdbc28cefb6ef1c716088643f030 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 31 Jan 2017 15:56:58 +0200 Subject: [PATCH 06/11] RDTSC-based cycle_t for macOS Windows and macOS now share most of related code Old implementation using mach_absolute_time() was more precise (at least in theory) but too costly --- src/posix/cocoa/i_system.mm | 21 +++++++++++ src/stats.cpp | 9 ----- src/stats.h | 75 +------------------------------------ 3 files changed, 22 insertions(+), 83 deletions(-) diff --git a/src/posix/cocoa/i_system.mm b/src/posix/cocoa/i_system.mm index 2e27a8002..35b71c64b 100644 --- a/src/posix/cocoa/i_system.mm +++ b/src/posix/cocoa/i_system.mm @@ -36,6 +36,7 @@ #include #include #include +#include #include "d_ticcmd.h" #include "doomdef.h" @@ -98,9 +99,29 @@ void SetLanguageIDs() void I_InitTimer(); void I_ShutdownTimer(); +double PerfToSec, PerfToMillisec; + +static void CalculateCPUSpeed() +{ + long long frequency; + size_t size = sizeof frequency; + + if (0 == sysctlbyname("machdep.tsc.frequency", &frequency, &size, nullptr, 0) && 0 != frequency) + { + PerfToSec = 1.0 / frequency; + PerfToMillisec = 1000.0 / frequency; + + if (!batchrun) + { + Printf("CPU speed: %.0f MHz\n", 0.001 / PerfToMillisec); + } + } +} + void I_Init(void) { CheckCPUID(&CPU); + CalculateCPUSpeed(); DumpCPUInfo(&CPU); atterm(I_ShutdownSound); diff --git a/src/stats.cpp b/src/stats.cpp index c57b32640..237436c41 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -42,15 +42,6 @@ #include "m_swap.h" #include "sbar.h" - -#if defined (__APPLE__) - -mach_timebase_info_data_t cycle_t::s_info; -bool cycle_t::s_initialized; - -#endif // __APPLE__ - - FStat *FStat::FirstStat; FStat::FStat (const char *name) diff --git a/src/stats.h b/src/stats.h index d90efa7e4..316633983 100644 --- a/src/stats.h +++ b/src/stats.h @@ -36,78 +36,7 @@ #include "zstring.h" -#ifndef _WIN32 - -#if defined (__APPLE__) - - -#include - - -class cycle_t -{ -public: - cycle_t() - { - if ( !s_initialized ) - { - mach_timebase_info( &s_info ); - s_initialized = true; - } - - Reset(); - } - - cycle_t &operator=( const cycle_t &other ) - { - if ( &other != this ) - { - m_seconds = other.m_seconds; - - } - - return *this; - } - - void Reset() - { - m_seconds = 0; - } - - void Clock() - { - m_seconds -= Nanoseconds() * 1e-9; - } - - void Unclock() - { - m_seconds += Nanoseconds() * 1e-9; - } - - double Time() - { - return m_seconds; - } - - double TimeMS() - { - return m_seconds * 1e3; - } - -private: - double m_seconds; - - static mach_timebase_info_data_t s_info; - static bool s_initialized; - - uint64_t Nanoseconds() const - { - return mach_absolute_time() * s_info.numer / s_info.denom; - } - -}; - -#else // !__APPLE__ +#if !defined _WIN32 && !defined __APPLE__ #ifdef NO_CLOCK_GETTIME class cycle_t @@ -171,8 +100,6 @@ private: #endif -#endif // __APPLE__ - #else // Windows From b12c8a8f791b9b16d8532b9da613e6759f7c7105 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 31 Jan 2017 16:00:14 +0200 Subject: [PATCH 07/11] RDTSC-based glcycle_t for macOS Time profiler implementation is now closer to Windows version --- src/gl/utility/gl_clock.cpp | 11 +++++++++++ src/gl/utility/gl_clock.h | 27 ++++++++++----------------- src/posix/cocoa/i_video.mm | 3 +++ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/gl/utility/gl_clock.cpp b/src/gl/utility/gl_clock.cpp index 68a2b06e5..2377029c2 100644 --- a/src/gl/utility/gl_clock.cpp +++ b/src/gl/utility/gl_clock.cpp @@ -40,6 +40,8 @@ #include #define USE_WINDOWS_DWORD +#elif defined __APPLE__ +#include #endif #include "i_system.h" @@ -114,6 +116,15 @@ void gl_CalculateCPUSpeed () gl_SecondsPerCycle = 1.0 / CyclesPerSecond; gl_MillisecPerCycle = 1000.0 / CyclesPerSecond; } + #elif defined __APPLE__ + long long frequency; + size_t size = sizeof frequency; + + if (0 == sysctlbyname("machdep.tsc.frequency", &frequency, &size, nullptr, 0) && 0 != frequency) + { + gl_SecondsPerCycle = 1.0 / frequency; + gl_MillisecPerCycle = 1000.0 / frequency; + } #endif } diff --git a/src/gl/utility/gl_clock.h b/src/gl/utility/gl_clock.h index 4d5163d86..2ccda639a 100644 --- a/src/gl/utility/gl_clock.h +++ b/src/gl/utility/gl_clock.h @@ -7,11 +7,11 @@ extern bool gl_benching; -#ifdef _MSC_VER - extern double gl_SecondsPerCycle; extern double gl_MillisecPerCycle; +#ifdef _MSC_VER + __forceinline long long GetClockCycle () { #if _M_X64 @@ -21,10 +21,14 @@ __forceinline long long GetClockCycle () #endif } -#elif defined(__GNUG__) && defined(__i386__) +#elif defined __APPLE__ && (defined __i386__ || defined __x86_64__) -extern double gl_SecondsPerCycle; -extern double gl_MillisecPerCycle; +inline long long GetClockCycle() +{ + return __builtin_ia32_rdtsc(); +} + +#elif defined(__GNUG__) && defined(__i386__) inline long long GetClockCycle() { @@ -42,21 +46,12 @@ inline long long GetClockCycle() #else -extern double gl_SecondsPerCycle; -extern double gl_MillisecPerCycle; - inline long long GetClockCycle () { return 0; } #endif -#if defined (__APPLE__) - -typedef cycle_t glcycle_t; - -#else // !__APPLE__ - class glcycle_t { public: @@ -100,8 +95,6 @@ private: long long Counter; }; -#endif // __APPLE__ - extern glcycle_t RenderWall,SetupWall,ClipWall; extern glcycle_t RenderFlat,SetupFlat; extern glcycle_t RenderSprite,SetupSprite; @@ -122,4 +115,4 @@ void CheckBench(); void checkBenchActive(); -#endif \ No newline at end of file +#endif diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 2ee7458a8..637ca0d7f 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -534,6 +534,9 @@ CocoaVideo::CocoaVideo() { memset(&m_modeIterator, 0, sizeof m_modeIterator); + extern void gl_CalculateCPUSpeed(); + gl_CalculateCPUSpeed(); + // Create OpenGL pixel format NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat(OpenGLProfile::Core); From 47faaa87fcc7a497cd138041ed6c13a742dd671c Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 31 Jan 2017 17:41:44 +0200 Subject: [PATCH 08/11] Fixed deprecation warning reported by Clang warning: 'register' storage class specifier is deprecated and incompatible with C++1z [-Wdeprecated-register] --- src/stats.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stats.h b/src/stats.h index 316633983..8ac1e978a 100644 --- a/src/stats.h +++ b/src/stats.h @@ -130,7 +130,7 @@ inline unsigned long long rdtsc() if (CPU.bRDTSC) #endif { - register unsigned long long tsc; + unsigned long long tsc; asm volatile ("\trdtsc\n" : "=A" (tsc)); return tsc; } From 3d147a032c688342dfa681d9f82e157f9ef42682 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Tue, 31 Jan 2017 17:51:12 +0200 Subject: [PATCH 09/11] Proper RDTSC implementation for x86_64 targets Higher 32 bits of Time Stamp Counter were ignored in non-MSVC Windows and macOS builds --- src/stats.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/stats.h b/src/stats.h index 8ac1e978a..f18159616 100644 --- a/src/stats.h +++ b/src/stats.h @@ -102,7 +102,7 @@ private: #else -// Windows +// Windows and macOS #include "x86.h" extern double PerfToSec, PerfToMillisec; @@ -126,15 +126,19 @@ inline unsigned __int64 rdtsc() #else inline unsigned long long rdtsc() { -#ifndef __amd64__ +#ifdef __amd64__ + unsigned long long tsc; + asm volatile ("rdtsc; shlq $32, %%rdx; orq %%rdx, %%rax" : "=a" (tsc) :: "%rdx"); + return tsc; +#else // i386 if (CPU.bRDTSC) -#endif { unsigned long long tsc; asm volatile ("\trdtsc\n" : "=A" (tsc)); return tsc; } return 0; +#endif // __amd64__ } #endif From ccacc2390504a695daa28f49aba3d0c2c9fc639b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Feb 2017 00:20:08 +0100 Subject: [PATCH 10/11] - fixed division by 0 in ActorMover code. --- wadsrc/static/zscript/shared/movingcamera.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/shared/movingcamera.txt b/wadsrc/static/zscript/shared/movingcamera.txt index 0fc50f3e2..15fdd0836 100644 --- a/wadsrc/static/zscript/shared/movingcamera.txt +++ b/wadsrc/static/zscript/shared/movingcamera.txt @@ -287,7 +287,7 @@ class PathFollower : Actor if (Interpolate ()) { - Time += (8. / (CurrNode.args[1] * TICRATE)); + Time += (8. / (max(1, CurrNode.args[1]) * TICRATE)); if (Time > 1.) { Time -= 1.; From 90ee22b76067d98c14fa6e39af286376aefa5a6f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Feb 2017 01:13:26 +0100 Subject: [PATCH 11/11] - don't let monsters without a See state disappear if they try to enter it. --- src/p_enemy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index e93f41ce5..2926e4e8c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2049,7 +2049,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } } - if (self->target) + if (self->target && self->SeeState) { self->SetState (self->SeeState); }