From 42886f0e4b572f6047018060b1ea5dea7162164d Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Fri, 4 Jan 2019 20:18:07 +0100 Subject: [PATCH] Modify check for Demo version to not break Game DLL ABI Changing idSession would break the interface for Game DLLs, making the existing ports of Mods incompatible. Luckily we have idCommon::GetAdditionalFunction() for cases like this.. Also added a check for WEAPON_NETFIRING in idWeapon::EnterCinematic(), I got an Assert() there in Debug builds. Running the Demo seems to work now, at least I could finish it without any problems (ignoring some warnings in the console) --- neo/framework/Common.cpp | 21 +++++++++++++++++---- neo/framework/Common.h | 11 +++++------ neo/framework/Session.cpp | 2 +- neo/framework/Session.h | 3 --- neo/framework/Session_local.h | 8 ++++++++ neo/game/Game_local.cpp | 18 ++++++++++++++++++ neo/game/Weapon.cpp | 11 +++++++---- 7 files changed, 56 insertions(+), 18 deletions(-) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index ad3a1865..842c81e7 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -52,6 +52,7 @@ If you have questions concerning this license or the applicable additional terms #include "framework/Common.h" #include "GameCallbacks_local.h" +#include "Session_local.h" // DG: For FT_IsDemo/isDemo() hack #define MAX_PRINT_MSG_SIZE 4096 #define MAX_WARNING_LIST 256 @@ -3238,6 +3239,11 @@ bool idCommonLocal::SetCallback(idCommon::CallbackType cbt, idCommon::FunctionPo } } +static bool isDemo(void) +{ + return sessLocal.IsDemoVersion(); +} + // returns true if that function is available in this version of dhewm3 // *out_fnptr will be the function (you'll have to cast it probably) // *out_userArg will be an argument you have to pass to the function, if appropriate (else NULL) @@ -3251,11 +3257,18 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F Warning("Called idCommon::GetAdditionalFunction() with out_fnptr == NULL!\n"); return false; } - *out_fnptr = NULL; + switch(ft) + { + case idCommon::FT_IsDemo: + *out_fnptr = (idCommon::FunctionPointer)isDemo; + // don't set *out_userArg, this function takes no arguments + return true; - // NOTE: this doesn't do anything yet, but allows to later add ugly mod-specific hacks without breaking the Game interface - - return false; + default: + *out_fnptr = NULL; + Warning("Called idCommon::SetCallback() with unknown FunctionType %d!\n", ft); + return false; + } } diff --git a/neo/framework/Common.h b/neo/framework/Common.h index b556e4bd..c0400bb4 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -243,10 +243,7 @@ public: * * Similar to SetCallback() I've also added GetAdditionalFunction() to get a function pointer * from dhewm3 that Mods can call (and that's not exported via the normal interface classes). - * Right now GetAdditionalFunction() will always just return false and do nothing, but if - * some Mod needs some specific function in the future, it could be implemented with - * GetAdditionalFunction() - again without breaking the game API and ABI for all the other - * Mods that don't need that function. + * Right now it's only used for a Doom3 Demo specific hack only relevant for base.dll (not for Mods) */ typedef void* (*FunctionPointer)(void*); // needs to be cast to/from real type! @@ -264,13 +261,15 @@ public: virtual bool SetCallback(CallbackType cbt, FunctionPointer cb, void* userArg) = 0; enum FunctionType { - // None yet.. + // the function's signature is bool fn(void) - no arguments. + // it returns true if we're currently running the doom3 demo + // not relevant for mods, only for game/ aka base.dll/base.so/... + FT_IsDemo = 1, }; // returns true if that function is available in this version of dhewm3 // *out_fnptr will be the function (you'll have to cast it probably) // *out_userArg will be an argument you have to pass to the function, if appropriate (else NULL) - // NOTE: this doesn't do anything yet, but allows to add ugly mod-specific hacks without breaking the Game interface virtual bool GetAdditionalFunction(FunctionType ft, FunctionPointer* out_fnptr, void** out_userArg) = 0; }; diff --git a/neo/framework/Session.cpp b/neo/framework/Session.cpp index e60f9e85..73585a2e 100644 --- a/neo/framework/Session.cpp +++ b/neo/framework/Session.cpp @@ -2895,7 +2895,7 @@ void idSessionLocal::Init() { guiMainMenu = uiManager->FindGui( "guis/mainmenu.gui", true, false, true ); if (!guiMainMenu) { guiMainMenu = uiManager->FindGui( "guis/demo_mainmenu.gui", true, false, true ); - demoversion = true; + demoversion = (guiMainMenu != NULL); } guiMainMenu_MapList = uiManager->AllocListGUI(); guiMainMenu_MapList->Config( guiMainMenu, "mapList" ); diff --git a/neo/framework/Session.h b/neo/framework/Session.h index c6f86ab3..f94081a9 100644 --- a/neo/framework/Session.h +++ b/neo/framework/Session.h @@ -165,9 +165,6 @@ public: idDemoFile * readDemo; idDemoFile * writeDemo; int renderdemoVersion; - -public: - bool demoversion; }; extern idSession * session; diff --git a/neo/framework/Session_local.h b/neo/framework/Session_local.h index 0273af2b..c96aa763 100644 --- a/neo/framework/Session_local.h +++ b/neo/framework/Session_local.h @@ -343,6 +343,12 @@ public: void SetMainMenuSkin( void ); void SetPbMenuGuiVars( void ); + // DG: true if running the Demo version of Doom3 (for FT_IsDemo, see Common.h) + bool IsDemoVersion() + { + return demoversion; + } + private: bool BoxDialogSanityCheck( void ); void EmitGameAuth( void ); @@ -366,6 +372,8 @@ private: bool authWaitBox; idStr authMsg; + + bool demoversion; // DG: true if running the Demo version of Doom3, for FT_IsDemo (see Common.h) }; extern idSessionLocal sessLocal; diff --git a/neo/game/Game_local.cpp b/neo/game/Game_local.cpp index 524bc5d8..41f11767 100644 --- a/neo/game/Game_local.cpp +++ b/neo/game/Game_local.cpp @@ -254,6 +254,20 @@ void idGameLocal::Clear( void ) { memset( lagometer, 0, sizeof( lagometer ) ); } + +// DG: hack to support the Demo version of Doom3 +// NOTE: I couldn't just make this a global bool variable that's initialized +// in idGameLocal::Init(), because we decide whether it's the demo +// after loading and initializing the game DLL (when loading the main menu) +static bool (*isDemoFnPtr)(void) = NULL; +bool IsDoom3DemoVersion() +{ + bool ret = isDemoFnPtr ? isDemoFnPtr() : false; + return ret; +} + + + /* =========== idGameLocal::Init @@ -330,6 +344,10 @@ void idGameLocal::Init( void ) { gamestate = GAMESTATE_NOMAP; Printf( "...%d aas types\n", aasList.Num() ); + + + // DG: hack to support the Demo version of Doom3 + common->GetAdditionalFunction(idCommon::FT_IsDemo, (idCommon::FunctionPointer*)&isDemoFnPtr, NULL); } /* diff --git a/neo/game/Weapon.cpp b/neo/game/Weapon.cpp index d3f2e9b6..f21a2fe9 100644 --- a/neo/game/Weapon.cpp +++ b/neo/game/Weapon.cpp @@ -40,6 +40,8 @@ If you have questions concerning this license or the applicable additional terms #include "Weapon.h" +extern bool IsDoom3DemoVersion(); // DG: hack to support the Demo version of Doom3 + /*********************************************************************** idWeapon @@ -399,7 +401,7 @@ void idWeapon::Restore( idRestoreGame *savefile ) { WEAPON_RELOAD.LinkTo( scriptObject, "WEAPON_RELOAD" ); WEAPON_NETRELOAD.LinkTo( scriptObject, "WEAPON_NETRELOAD" ); WEAPON_NETENDRELOAD.LinkTo( scriptObject, "WEAPON_NETENDRELOAD" ); - if (!session->demoversion) + if (!IsDoom3DemoVersion()) // the demo assets don't support WEAPON_NETFIRING WEAPON_NETFIRING.LinkTo( scriptObject, "WEAPON_NETFIRING" ); WEAPON_RAISEWEAPON.LinkTo( scriptObject, "WEAPON_RAISEWEAPON" ); WEAPON_LOWERWEAPON.LinkTo( scriptObject, "WEAPON_LOWERWEAPON" ); @@ -554,7 +556,7 @@ void idWeapon::Clear( void ) { WEAPON_RELOAD.Unlink(); WEAPON_NETRELOAD.Unlink(); WEAPON_NETENDRELOAD.Unlink(); - if (!session->demoversion) + if (WEAPON_NETFIRING.IsLinked()) WEAPON_NETFIRING.Unlink(); WEAPON_RAISEWEAPON.Unlink(); WEAPON_LOWERWEAPON.Unlink(); @@ -998,7 +1000,7 @@ void idWeapon::GetWeaponDef( const char *objectname, int ammoinclip ) { WEAPON_RELOAD.LinkTo( scriptObject, "WEAPON_RELOAD" ); WEAPON_NETRELOAD.LinkTo( scriptObject, "WEAPON_NETRELOAD" ); WEAPON_NETENDRELOAD.LinkTo( scriptObject, "WEAPON_NETENDRELOAD" ); - if (!session->demoversion) + if (!IsDoom3DemoVersion()) // the demo assets don't support WEAPON_NETFIRING WEAPON_NETFIRING.LinkTo( scriptObject, "WEAPON_NETFIRING" ); WEAPON_RAISEWEAPON.LinkTo( scriptObject, "WEAPON_RAISEWEAPON" ); WEAPON_LOWERWEAPON.LinkTo( scriptObject, "WEAPON_LOWERWEAPON" ); @@ -2023,7 +2025,8 @@ void idWeapon::EnterCinematic( void ) { WEAPON_RELOAD = false; WEAPON_NETRELOAD = false; WEAPON_NETENDRELOAD = false; - WEAPON_NETFIRING = false; + if(WEAPON_NETFIRING.IsLinked()) + WEAPON_NETFIRING = false; WEAPON_RAISEWEAPON = false; WEAPON_LOWERWEAPON = false; }