diff --git a/neo/d3xp/GameEdit.cpp b/neo/d3xp/GameEdit.cpp index 45c89d71..5d68b80f 100644 --- a/neo/d3xp/GameEdit.cpp +++ b/neo/d3xp/GameEdit.cpp @@ -670,7 +670,7 @@ void idEditEntities::DisplayEntities( void ) { =============================================================================== */ -idGameEdit gameEditLocal; +idGameEditExt gameEditLocal; idGameEdit * gameEdit = &gameEditLocal; @@ -1154,7 +1154,7 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const { ***********************************************************************/ -bool idGameEdit::IsLineCode( const char *filename, int linenumber ) const { +bool idGameEditExt::IsLineCode( const char *filename, int linenumber ) const { idStr fileStr; idProgram *program = &gameLocal.program; for ( int i = 0; i < program->NumStatements( ); i++ ) { @@ -1170,7 +1170,7 @@ bool idGameEdit::IsLineCode( const char *filename, int linenumber ) const { return false; } -void idGameEdit::GetLoadedScripts(idStrList** result) +void idGameEditExt::GetLoadedScripts(idStrList** result) { (*result)->Clear(); idProgram* program = &gameLocal.program; @@ -1181,7 +1181,7 @@ void idGameEdit::GetLoadedScripts(idStrList** result) } } -void idGameEdit::MSG_WriteScriptList(idBitMsg* msg) +void idGameEditExt::MSG_WriteScriptList(idBitMsg* msg) { idProgram* program = &gameLocal.program; @@ -1196,12 +1196,12 @@ void idGameEdit::MSG_WriteScriptList(idBitMsg* msg) } } -const char* idGameEdit::GetFilenameForStatement(idProgram* program, int index) const +const char* idGameEditExt::GetFilenameForStatement(idProgram* program, int index) const { return program->GetFilenameForStatement(index); } -int idGameEdit::GetLineNumberForStatement(idProgram* program, int index) const +int idGameEditExt::GetLineNumberForStatement(idProgram* program, int index) const { return program->GetLineNumberForStatement(index); } diff --git a/neo/d3xp/Game_local.cpp b/neo/d3xp/Game_local.cpp index fccc4947..38fa15bb 100644 --- a/neo/d3xp/Game_local.cpp +++ b/neo/d3xp/Game_local.cpp @@ -302,6 +302,21 @@ void idGameLocal::Clear( void ) { #endif } +static DebuggerArgs_t * userDebuggerArgs; +static bool ( *checkDebuggerBreakpointFnPtr )( void ) = NULL; +bool IsGameDebuggerActive( idInterpreter *interpreter, idProgram *program, int instructionPointer ) { + bool ret = false; + + if ( interpreter != nullptr && program != nullptr ) { + userDebuggerArgs->interpreter = interpreter; + userDebuggerArgs->program = program; + userDebuggerArgs->instructionPointer = instructionPointer; + ret = checkDebuggerBreakpointFnPtr ? checkDebuggerBreakpointFnPtr( ) : false; + } + return ret; +} + + /* =========== idGameLocal::Init @@ -410,6 +425,11 @@ void idGameLocal::Init( void ) { gamestate = GAMESTATE_NOMAP; Printf( "...%d aas types\n", aasList.Num() ); + + //debugger support + common->GetAdditionalFunction( idCommon::FT_CheckDebuggerBreakpoint, + ( idCommon::FunctionPointer * ) &checkDebuggerBreakpointFnPtr, ( void ** ) &userDebuggerArgs ); + } /* @@ -1312,7 +1332,7 @@ void idGameLocal::MapPopulate( void ) { idGameLocal::InitFromNewMap =================== */ -void idGameLocal::InitFromNewMap(const char* mapName, idRenderWorld* renderWorld, idSoundWorld* soundWorld, bool isServer, bool isClient, int randseed, int activeEditors) { +void idGameLocal::InitFromNewMap(const char* mapName, idRenderWorld* renderWorld, idSoundWorld* soundWorld, bool isServer, bool isClient, int randseed) { this->isServer = isServer; this->isClient = isClient; @@ -1323,9 +1343,6 @@ void idGameLocal::InitFromNewMap(const char* mapName, idRenderWorld* renderWorld } Printf( "----- Game Map Init -----\n" ); - - //exposing editor flag so debugger does not miss any script calls during load/startup - editors = activeEditors; gamestate = GAMESTATE_STARTUP; @@ -2439,7 +2456,7 @@ void idGameLocal::RunTimeGroup2() { idGameLocal::RunFrame ================ */ -gameReturn_t idGameLocal::RunFrame(const usercmd_t* clientCmds, int activeEditors) { +gameReturn_t idGameLocal::RunFrame(const usercmd_t* clientCmds) { idEntity* ent; int num; float ms; @@ -2448,9 +2465,6 @@ gameReturn_t idGameLocal::RunFrame(const usercmd_t* clientCmds, int activeEditor idPlayer* player; const renderView_t* view; - //exposing editor flag so debugger does not miss any script calls during load/startup - editors = activeEditors; - #ifdef _DEBUG if ( isMultiplayer ) { assert( !isClient ); diff --git a/neo/d3xp/Game_local.h b/neo/d3xp/Game_local.h index 4451b559..f9a96935 100644 --- a/neo/d3xp/Game_local.h +++ b/neo/d3xp/Game_local.h @@ -319,7 +319,6 @@ public: idEntityPtr<idEntity> lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f int lastGUI; // last GUI on the lastGUIEnt - int editors; #ifdef _D3XP idEntityPtr<idEntity> portalSkyEnt; @@ -366,13 +365,13 @@ public: virtual const idDict & GetPersistentPlayerInfo( int clientNum ); virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo ); - virtual void InitFromNewMap(const char* mapName, idRenderWorld* renderWorld, idSoundWorld* soundWorld, bool isServer, bool isClient, int randSeed, int activeEditors); - virtual bool InitFromSaveGame(const char* mapName, idRenderWorld* renderWorld, idSoundWorld* soundWorld, idFile* saveGameFile, int activeEditors); + virtual void InitFromNewMap(const char* mapName, idRenderWorld* renderWorld, idSoundWorld* soundWorld, bool isServer, bool isClient, int randSeed ); + virtual bool InitFromSaveGame(const char* mapName, idRenderWorld* renderWorld, idSoundWorld* soundWorld, idFile* saveGameFile ); virtual void SaveGame( idFile *saveGameFile ); virtual void MapShutdown( void ); virtual void CacheDictionaryMedia( const idDict *dict ); virtual void SpawnPlayer( int clientNum ); - virtual gameReturn_t RunFrame(const usercmd_t* clientCmds, int activeEditors); + virtual gameReturn_t RunFrame(const usercmd_t* clientCmds ); virtual bool Draw( int clientNum ); virtual escReply_t HandleESC( idUserInterface **gui ); virtual idUserInterface *StartMenu( void ); diff --git a/neo/d3xp/script/Script_Interpreter.cpp b/neo/d3xp/script/Script_Interpreter.cpp index 58fc69ee..69828d08 100644 --- a/neo/d3xp/script/Script_Interpreter.cpp +++ b/neo/d3xp/script/Script_Interpreter.cpp @@ -35,6 +35,9 @@ If you have questions concerning this license or the applicable additional terms #include "framework/FileSystem.h" +// HvG: Debugger support +extern bool IsGameDebuggerActive( idInterpreter *interpreter, idProgram *program, int instructionPointer ); + /* ================ idInterpreter::idInterpreter() @@ -1001,10 +1004,9 @@ bool idInterpreter::Execute( void ) { // next statement st = &gameLocal.program.GetStatement( instructionPointer ); - if (gameLocal.editors & EDITOR_DEBUGGER) { - common->DebuggerCheckBreakpoint(this, &gameLocal.program, instructionPointer); - } - else if (g_debugScript.GetBool()) { + if ( !IsGameDebuggerActive( this, &gameLocal.program, instructionPointer ) + && g_debugScript.GetBool( ) ) + { static int lastLineNumber = -1; if (lastLineNumber != gameLocal.program.GetStatement(instructionPointer).linenumber) { gameLocal.Printf("%s (%d)\n", @@ -1881,30 +1883,30 @@ bool idInterpreter::Execute( void ) { } -bool idGameEdit::CheckForBreakPointHit(const idInterpreter* interpreter, const function_t* function1, const function_t* function2, int depth) const +bool idGameEditExt::CheckForBreakPointHit(const idInterpreter* interpreter, const function_t* function1, const function_t* function2, int depth) const { return ((interpreter->GetCurrentFunction() == function1 || interpreter->GetCurrentFunction() == function2) && (interpreter->GetCallstackDepth() <= depth)); } -bool idGameEdit::ReturnedFromFunction(const idProgram* program, const idInterpreter* interpreter, int index) const +bool idGameEditExt::ReturnedFromFunction(const idProgram* program, const idInterpreter* interpreter, int index) const { return (const_cast<idProgram*>(program)->GetStatement(index).op == OP_RETURN && interpreter->GetCallstackDepth() <= 1); } -bool idGameEdit::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const +bool idGameEditExt::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const { return const_cast<idInterpreter*>(interpreter)->GetRegisterValue(name, out, scopeDepth); } -const idThread* idGameEdit::GetThread(const idInterpreter* interpreter) const +const idThread* idGameEditExt::GetThread(const idInterpreter* interpreter) const { return interpreter->GetThread(); } -void idGameEdit::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, const idProgram* program, int instructionPtr) +void idGameEditExt::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, const idProgram* program, int instructionPtr) { const statement_t* st; const function_t* func; @@ -1945,7 +1947,7 @@ void idGameEdit::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, c } } -void idGameEdit::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr) +void idGameEditExt::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr) { int i; prstack_s temp; @@ -1966,12 +1968,12 @@ void idGameEdit::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* in } -int idGameEdit::GetInterpreterCallStackDepth(const idInterpreter* interpreter) +int idGameEditExt::GetInterpreterCallStackDepth(const idInterpreter* interpreter) { return interpreter->GetCallstackDepth(); } -const function_t* idGameEdit::GetInterpreterCallStackFunction(const idInterpreter* interpreter, int stackDepth/* = -1*/) +const function_t* idGameEditExt::GetInterpreterCallStackFunction(const idInterpreter* interpreter, int stackDepth/* = -1*/) { return interpreter->GetCallstack()[stackDepth > -1 ? stackDepth : interpreter->GetCallstackDepth()].f; } \ No newline at end of file diff --git a/neo/d3xp/script/Script_Thread.cpp b/neo/d3xp/script/Script_Thread.cpp index e320ec69..ef0b8ed9 100644 --- a/neo/d3xp/script/Script_Thread.cpp +++ b/neo/d3xp/script/Script_Thread.cpp @@ -1922,42 +1922,42 @@ void idThread::Event_InfluenceActive( void ) { } } -int idGameEdit::ThreadGetNum(const idThread* thread) const +int idGameEditExt::ThreadGetNum(const idThread* thread) const { return const_cast<idThread*>(thread)->GetThreadNum(); } -const char* idGameEdit::ThreadGetName(const idThread* thread) const +const char* idGameEditExt::ThreadGetName(const idThread* thread) const { return const_cast<idThread*>(thread)->GetThreadName(); } -int idGameEdit::GetTotalScriptThreads() const +int idGameEditExt::GetTotalScriptThreads() const { return idThread::GetThreads().Num(); } -const idThread* idGameEdit::GetThreadByIndex(int index) const +const idThread* idGameEditExt::GetThreadByIndex(int index) const { return idThread::GetThreads()[index]; } -bool idGameEdit::ThreadIsDoneProcessing(const idThread* thread) const +bool idGameEditExt::ThreadIsDoneProcessing(const idThread* thread) const { return const_cast<idThread*>(thread)->IsDoneProcessing(); } -bool idGameEdit::ThreadIsWaiting(const idThread* thread) const +bool idGameEditExt::ThreadIsWaiting(const idThread* thread) const { return const_cast<idThread*>(thread)->IsWaiting(); } -bool idGameEdit::ThreadIsDying(const idThread* thread) const +bool idGameEditExt::ThreadIsDying(const idThread* thread) const { return const_cast<idThread*>(thread)->IsDying(); } -void idGameEdit::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter) +void idGameEditExt::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter) { msg->WriteString(const_cast<idThread*>(thread)->GetThreadName()); msg->WriteInt(const_cast<idThread*>(thread)->GetThreadNum()); diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index b2e67327..03f8bb1f 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -146,7 +146,6 @@ public: virtual void ActivateTool( bool active ); virtual void WriteConfigToFile( const char *filename ); virtual void WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd ); - virtual void DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer); virtual void BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) ); virtual void EndRedirect( void ); virtual void SetRefreshOnPrint( bool set ); @@ -3222,7 +3221,7 @@ void idCommonLocal::ShutdownGame( bool reloading ) { } // shutdown the script debugger - if ( com_enableDebuggerServer.GetBool( ) ) + if ( com_enableDebuggerServer.GetBool() ) DebuggerServerShutdown(); idAsyncNetwork::client.Shutdown(); @@ -3286,11 +3285,23 @@ bool idCommonLocal::SetCallback(idCommon::CallbackType cbt, idCommon::FunctionPo } } -static bool isDemo(void) +static bool isDemo( void ) { return sessLocal.IsDemoVersion(); } +static DebuggerArgs_t userDebuggerArgs; + +static bool checkForDebuggerBreakPoint( void ) +{ + if (com_editors & EDITOR_DEBUGGER) + { + DebuggerServerCheckBreakpoint( userDebuggerArgs.interpreter, userDebuggerArgs.program, userDebuggerArgs.instructionPointer ); + return true; + } + return false; +} + // 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) @@ -3311,6 +3322,12 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F // don't set *out_userArg, this function takes no arguments return true; + case idCommon::FT_CheckDebuggerBreakpoint: + *out_fnptr = (idCommon::FunctionPointer)checkForDebuggerBreakPoint; + if (out_userArg != NULL ) + *out_userArg = &userDebuggerArgs; + return true; + default: *out_fnptr = NULL; Warning("Called idCommon::SetCallback() with unknown FunctionType %d!\n", ft); @@ -3318,20 +3335,17 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F } } -void idCommonLocal::DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer) -{ - if ( com_enableDebuggerServer.GetBool( ) ) - DebuggerServerCheckBreakpoint(interpreter, program, instructionPointer); -} - idGameCallbacks gameCallbacks; idGameCallbacks::idGameCallbacks() : reloadImagesCB(NULL), reloadImagesUserArg(NULL) +, checkBreakPointCB(NULL), checkBreakPointUserArg(NULL) {} void idGameCallbacks::Reset() { reloadImagesCB = NULL; reloadImagesUserArg = NULL; + checkBreakPointCB = NULL; + checkBreakPointUserArg = NULL; } diff --git a/neo/framework/Common.h b/neo/framework/Common.h index a471d4a5..8857a773 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -117,6 +117,12 @@ class idLangDict; class idInterpreter; class idProgram; +struct DebuggerArgs_t { + idInterpreter *interpreter; + idProgram *program; + int instructionPointer; +}; + class idCommon { public: virtual ~idCommon( void ) {} @@ -163,8 +169,6 @@ public: // Writes cvars with the given flags to a file. virtual void WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd ) = 0; - // Debbugger hook to check if a breakpoint has been hit - virtual void DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer) = 0; // Begins redirection of console output to the given buffer. virtual void BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) ) = 0; @@ -273,6 +277,7 @@ public: // 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, + FT_CheckDebuggerBreakpoint, }; // returns true if that function is available in this version of dhewm3 diff --git a/neo/framework/Game.h b/neo/framework/Game.h index 6af69967..af64d2c8 100644 --- a/neo/framework/Game.h +++ b/neo/framework/Game.h @@ -110,10 +110,10 @@ public: virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo ) = 0; // Loads a map and spawns all the entities. - virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed, int activeEditors ) = 0; + virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed ) = 0; // Loads a map from a savegame file. - virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors ) = 0; + virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) = 0; // Saves the current game state, the session may have written some data to the file already. virtual void SaveGame( idFile *saveGameFile ) = 0; @@ -128,7 +128,7 @@ public: virtual void SpawnPlayer( int clientNum ) = 0; // Runs a game frame, may return a session command for level changing, etc - virtual gameReturn_t RunFrame( const usercmd_t *clientCmds , int activeEditors) = 0; + virtual gameReturn_t RunFrame( const usercmd_t *clientCmds ) = 0; // Makes rendering and sound system calls to display for a given clientNum. virtual bool Draw( int clientNum ) = 0; @@ -316,8 +316,14 @@ public: virtual int MapGetEntitiesMatchingClassWithString( const char *classname, const char *match, const char *list[], const int max ) const; virtual void MapRemoveEntity( const char *name ) const; virtual void MapEntityTranslate( const char *name, const idVec3 &v ) const; +}; - // In game script Debugging Support +extern idGameEdit * gameEdit; + +// In game script Debugging Support +class idGameEditExt : public idGameEdit { +public: + virtual ~idGameEditExt( void ) { } // IdProgram virtual void GetLoadedScripts( idStrList ** result ); virtual bool IsLineCode( const char* filename, int linenumber) const; @@ -348,8 +354,6 @@ public: virtual void MSG_WriteScriptList( idBitMsg* msg ); }; -extern idGameEdit * gameEdit; - /* =============================================================================== diff --git a/neo/framework/GameCallbacks_local.h b/neo/framework/GameCallbacks_local.h index 51d9763a..60f781a5 100644 --- a/neo/framework/GameCallbacks_local.h +++ b/neo/framework/GameCallbacks_local.h @@ -40,9 +40,12 @@ If you have questions concerning this license or the applicable additional terms struct idGameCallbacks { typedef void (*ReloadImagesCallback)(void* userArg, const idCmdArgs &args); - ReloadImagesCallback reloadImagesCB; - void* reloadImagesUserArg; + ReloadImagesCallback reloadImagesCB; + void* reloadImagesUserArg; + typedef void ( *CheckBreakpointCallback )( void *userArg, idInterpreter *interpreter, idProgram *program, int instructionPointer ); + CheckBreakpointCallback checkBreakPointCB; + void* checkBreakPointUserArg; idGameCallbacks(); diff --git a/neo/framework/Session.cpp b/neo/framework/Session.cpp index 74d6b19f..697591e4 100644 --- a/neo/framework/Session.cpp +++ b/neo/framework/Session.cpp @@ -1646,7 +1646,7 @@ void idSessionLocal::ExecuteMapChange( bool noFadeWipe ) { // load and spawn all other entities ( from a savegame possibly ) if ( loadingSaveGame && savegameFile ) { - if ( game->InitFromSaveGame( fullMapName + ".map", rw, sw, savegameFile, com_editors ) == false ) { + if ( game->InitFromSaveGame( fullMapName + ".map", rw, sw, savegameFile ) == false ) { // If the loadgame failed, restart the map with the player persistent data loadingSaveGame = false; fileSystem->CloseFile( savegameFile ); @@ -1655,11 +1655,11 @@ void idSessionLocal::ExecuteMapChange( bool noFadeWipe ) { common->Warning( "WARNING: Loading savegame failed, will restart the map with the player persistent data!" ); game->SetServerInfo( mapSpawnData.serverInfo ); - game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds(),com_editors ); + game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds() ); } } else { game->SetServerInfo( mapSpawnData.serverInfo ); - game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds(), com_editors); + game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds() ); } if ( !idAsyncNetwork::IsActive() && !loadingSaveGame ) { @@ -1681,7 +1681,7 @@ void idSessionLocal::ExecuteMapChange( bool noFadeWipe ) { if ( !idAsyncNetwork::IsActive() && !loadingSaveGame ) { // run a few frames to allow everything to settle for ( i = 0; i < 10; i++ ) { - game->RunFrame( mapSpawnData.mapSpawnUsercmd, com_editors); + game->RunFrame( mapSpawnData.mapSpawnUsercmd ); } } @@ -2785,7 +2785,7 @@ void idSessionLocal::RunGameTic() { // run the game logic every player move int start = Sys_Milliseconds(); - gameReturn_t ret = game->RunFrame( &cmd, com_editors); + gameReturn_t ret = game->RunFrame( &cmd ); int end = Sys_Milliseconds(); time_gameFrame += end - start; // note time used for com_speeds diff --git a/neo/framework/async/AsyncServer.cpp b/neo/framework/async/AsyncServer.cpp index e2b5a97b..9f6981fc 100644 --- a/neo/framework/async/AsyncServer.cpp +++ b/neo/framework/async/AsyncServer.cpp @@ -2442,7 +2442,7 @@ void idAsyncServer::RunFrame( void ) { DuplicateUsercmds( gameFrame, gameTime ); // advance game - gameReturn_t ret = game->RunFrame( userCmds[gameFrame & ( MAX_USERCMD_BACKUP - 1 ) ], com_editors ); + gameReturn_t ret = game->RunFrame( userCmds[gameFrame & ( MAX_USERCMD_BACKUP - 1 ) ] ); idAsyncNetwork::ExecuteSessionCommand( ret.sessionCommand ); diff --git a/neo/game/GameEdit.cpp b/neo/game/GameEdit.cpp index ba495d7c..57e7eb28 100644 --- a/neo/game/GameEdit.cpp +++ b/neo/game/GameEdit.cpp @@ -670,7 +670,7 @@ void idEditEntities::DisplayEntities( void ) { =============================================================================== */ -idGameEdit gameEditLocal; +idGameEditExt gameEditLocal; idGameEdit * gameEdit = &gameEditLocal; @@ -1153,7 +1153,7 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const { ***********************************************************************/ -bool idGameEdit::IsLineCode(const char* filename, int linenumber) const +bool idGameEditExt::IsLineCode(const char* filename, int linenumber) const { idStr fileStr; idProgram* program = &gameLocal.program; @@ -1172,7 +1172,7 @@ bool idGameEdit::IsLineCode(const char* filename, int linenumber) const return false; } -void idGameEdit::GetLoadedScripts( idStrList** result ) +void idGameEditExt::GetLoadedScripts( idStrList** result ) { (*result)->Clear(); idProgram* program = &gameLocal.program; @@ -1183,7 +1183,7 @@ void idGameEdit::GetLoadedScripts( idStrList** result ) } } -void idGameEdit::MSG_WriteScriptList( idBitMsg* msg) +void idGameEditExt::MSG_WriteScriptList( idBitMsg* msg) { idProgram* program = &gameLocal.program; @@ -1198,12 +1198,12 @@ void idGameEdit::MSG_WriteScriptList( idBitMsg* msg) } } -const char* idGameEdit::GetFilenameForStatement(idProgram* program, int index) const +const char*idGameEditExt::GetFilenameForStatement(idProgram* program, int index) const { return program->GetFilenameForStatement(index); } -int idGameEdit::GetLineNumberForStatement(idProgram* program, int index) const +int idGameEditExt::GetLineNumberForStatement(idProgram* program, int index) const { return program->GetLineNumberForStatement(index); -} +} \ No newline at end of file diff --git a/neo/game/Game_local.cpp b/neo/game/Game_local.cpp index ba6d4554..110cda2e 100644 --- a/neo/game/Game_local.cpp +++ b/neo/game/Game_local.cpp @@ -270,6 +270,21 @@ bool IsDoom3DemoVersion() return ret; } +static DebuggerArgs_t * userDebuggerArgs; +static bool ( *checkDebuggerBreakpointFnPtr )( void ) = NULL; +bool IsGameDebuggerActive( idInterpreter *interpreter, idProgram *program, int instructionPointer ) +{ + bool ret = false; + + if (interpreter != nullptr && program != nullptr ) + { + userDebuggerArgs->interpreter = interpreter; + userDebuggerArgs->program = program; + userDebuggerArgs->instructionPointer = instructionPointer; + ret = checkDebuggerBreakpointFnPtr ? checkDebuggerBreakpointFnPtr( ) : false; + } + return ret; +} /* @@ -352,6 +367,9 @@ void idGameLocal::Init( void ) { // DG: hack to support the Demo version of Doom3 common->GetAdditionalFunction(idCommon::FT_IsDemo, (idCommon::FunctionPointer*)&isDemoFnPtr, NULL); + //debugger support + common->GetAdditionalFunction( idCommon::FT_CheckDebuggerBreakpoint, + ( idCommon::FunctionPointer * ) &checkDebuggerBreakpointFnPtr, (void**)&userDebuggerArgs ); } /* @@ -1192,7 +1210,7 @@ void idGameLocal::MapPopulate( void ) { idGameLocal::InitFromNewMap =================== */ -void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed, int activeEditors) { +void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed) { this->isServer = isServer; this->isClient = isClient; @@ -1204,8 +1222,6 @@ void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorl Printf( "----- Game Map Init -----\n" ); - //exposing editor flag so debugger does not miss any script calls during load/startup - editors = activeEditors; gamestate = GAMESTATE_STARTUP; gameRenderWorld = renderWorld; @@ -1232,7 +1248,7 @@ void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorl idGameLocal::InitFromSaveGame ================= */ -bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors ) { +bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) { int i; int num; idEntity *ent; @@ -1244,8 +1260,6 @@ bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWo Printf( "----- Game Map Init SaveGame -----\n" ); - //exposing editor flag so debugger does not miss any script calls during load/startup - editors = activeEditors; gamestate = GAMESTATE_STARTUP; gameRenderWorld = renderWorld; @@ -2219,7 +2233,7 @@ void idGameLocal::SortActiveEntityList( void ) { idGameLocal::RunFrame ================ */ -gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds, int activeEditors ) { +gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds ) { idEntity * ent; int num; float ms; @@ -2227,9 +2241,6 @@ gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds, int activeEdito gameReturn_t ret; idPlayer *player; const renderView_t *view; - - //exposing editor flag so debugger does not miss any script calls during load/startup - editors = activeEditors; #ifdef _DEBUG if ( isMultiplayer ) { diff --git a/neo/game/Game_local.h b/neo/game/Game_local.h index 44cf515d..6a346b43 100644 --- a/neo/game/Game_local.h +++ b/neo/game/Game_local.h @@ -308,13 +308,13 @@ public: virtual const idDict & GetPersistentPlayerInfo( int clientNum ); virtual void SetPersistentPlayerInfo( int clientNum, const idDict &playerInfo ); - virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randSeed, int activeEditors); - virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors); + virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randSeed ); + virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ); virtual void SaveGame( idFile *saveGameFile ); virtual void MapShutdown( void ); virtual void CacheDictionaryMedia( const idDict *dict ); virtual void SpawnPlayer( int clientNum ); - virtual gameReturn_t RunFrame( const usercmd_t *clientCmds , int activeEditors); + virtual gameReturn_t RunFrame( const usercmd_t *clientCmds ); virtual bool Draw( int clientNum ); virtual escReply_t HandleESC( idUserInterface **gui ); virtual idUserInterface *StartMenu( void ); diff --git a/neo/game/script/Script_Interpreter.cpp b/neo/game/script/Script_Interpreter.cpp index dd5b3f3d..e6608d39 100644 --- a/neo/game/script/Script_Interpreter.cpp +++ b/neo/game/script/Script_Interpreter.cpp @@ -35,6 +35,9 @@ If you have questions concerning this license or the applicable additional terms #include "framework/FileSystem.h" +// HvG: Debugger support +extern bool IsGameDebuggerActive( idInterpreter *interpreter, idProgram *program, int instructionPointer ); + /* ================ idInterpreter::idInterpreter() @@ -1004,9 +1007,9 @@ bool idInterpreter::Execute( void ) { // next statement st = &gameLocal.program.GetStatement( instructionPointer ); - if (gameLocal.editors & EDITOR_DEBUGGER ) { - common->DebuggerCheckBreakpoint ( this, &gameLocal.program, instructionPointer ); - } else if ( g_debugScript.GetBool ( ) ) { + if ( !IsGameDebuggerActive( this, &gameLocal.program, instructionPointer ) + && g_debugScript.GetBool( ) ) + { static int lastLineNumber = -1; if ( lastLineNumber != gameLocal.program.GetStatement ( instructionPointer ).linenumber ) { gameLocal.Printf ( "%s (%d)\n", @@ -1882,30 +1885,30 @@ bool idInterpreter::Execute( void ) { return threadDying; } -bool idGameEdit::CheckForBreakPointHit(const idInterpreter* interpreter, const function_t* function1, const function_t* function2, int depth) const +bool idGameEditExt::CheckForBreakPointHit(const idInterpreter* interpreter, const function_t* function1, const function_t* function2, int depth) const { return ( ( interpreter->GetCurrentFunction ( ) == function1 || interpreter->GetCurrentFunction ( ) == function2)&& ( interpreter->GetCallstackDepth ( ) <= depth) ); } -bool idGameEdit::ReturnedFromFunction(const idProgram* program, const idInterpreter* interpreter, int index) const +bool idGameEditExt::ReturnedFromFunction(const idProgram* program, const idInterpreter* interpreter, int index) const { return ( const_cast<idProgram*>(program)->GetStatement(index).op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 ); } -bool idGameEdit::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const +bool idGameEditExt::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const { return const_cast<idInterpreter*>(interpreter)->GetRegisterValue(name, out, scopeDepth); } -const idThread* idGameEdit::GetThread(const idInterpreter* interpreter) const +const idThread*idGameEditExt::GetThread(const idInterpreter* interpreter) const { return interpreter->GetThread(); } -void idGameEdit::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, const idProgram * program, int instructionPtr) +void idGameEditExt::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, const idProgram * program, int instructionPtr) { const statement_t* st; const function_t* func; @@ -1946,7 +1949,7 @@ void idGameEdit::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, c } } -void idGameEdit::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr) +void idGameEditExt::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr) { int i; prstack_s temp; @@ -1967,12 +1970,12 @@ void idGameEdit::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* in } -int idGameEdit::GetInterpreterCallStackDepth(const idInterpreter* interpreter) +int idGameEditExt::GetInterpreterCallStackDepth(const idInterpreter* interpreter) { return interpreter->GetCallstackDepth(); } -const function_t* idGameEdit::GetInterpreterCallStackFunction( const idInterpreter* interpreter, int stackDepth/* = -1*/) +const function_t*idGameEditExt::GetInterpreterCallStackFunction( const idInterpreter* interpreter, int stackDepth/* = -1*/) { return interpreter->GetCallstack( )[ stackDepth > -1 ? stackDepth :interpreter->GetCallstackDepth( ) ].f; } \ No newline at end of file diff --git a/neo/game/script/Script_Thread.cpp b/neo/game/script/Script_Thread.cpp index ce6ed271..546ede9e 100644 --- a/neo/game/script/Script_Thread.cpp +++ b/neo/game/script/Script_Thread.cpp @@ -1842,42 +1842,42 @@ void idThread::Event_InfluenceActive( void ) { } } -int idGameEdit::ThreadGetNum(const idThread* thread) const +int idGameEditExt::ThreadGetNum(const idThread* thread) const { return const_cast<idThread*>(thread)->GetThreadNum(); } -const char* idGameEdit::ThreadGetName(const idThread* thread) const +const char*idGameEditExt::ThreadGetName(const idThread* thread) const { return const_cast<idThread*>(thread)->GetThreadName(); } -int idGameEdit::GetTotalScriptThreads() const +int idGameEditExt::GetTotalScriptThreads() const { return idThread::GetThreads().Num(); } -const idThread* idGameEdit::GetThreadByIndex(int index) const +const idThread*idGameEditExt::GetThreadByIndex(int index) const { return idThread::GetThreads()[index]; } -bool idGameEdit::ThreadIsDoneProcessing(const idThread* thread) const +bool idGameEditExt::ThreadIsDoneProcessing(const idThread* thread) const { return const_cast<idThread*>(thread)->IsDoneProcessing(); } -bool idGameEdit::ThreadIsWaiting(const idThread* thread) const +bool idGameEditExt::ThreadIsWaiting(const idThread* thread) const { return const_cast<idThread*>(thread)->IsWaiting(); } -bool idGameEdit::ThreadIsDying(const idThread* thread) const +bool idGameEditExt::ThreadIsDying(const idThread* thread) const { return const_cast<idThread*>(thread)->IsDying(); } -void idGameEdit::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter) +void idGameEditExt::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter) { msg->WriteString(const_cast<idThread*>(thread)->GetThreadName()); msg->WriteInt(const_cast<idThread*>(thread)->GetThreadNum()); diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 3eebfa8d..d3f05d02 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -3,6 +3,8 @@ Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. +Copyright (C) 1999-2011 Raven Software +Copyright (C) 2021 Harrie van Ginneken This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code"). @@ -218,11 +220,11 @@ bool rvDebuggerServer::ProcessMessages ( void ) case DBMSG_STEPOVER: mBreakStepOver = true; - mBreakStepOverDepth = gameEdit->GetInterpreterCallStackDepth(mBreakInterpreter); - mBreakStepOverFunc1 = gameEdit->GetInterpreterCallStackFunction(mBreakInterpreter); + mBreakStepOverDepth = ((idGameEditExt*) gameEdit)->GetInterpreterCallStackDepth(mBreakInterpreter); + mBreakStepOverFunc1 = ((idGameEditExt*) gameEdit)->GetInterpreterCallStackFunction(mBreakInterpreter); if (mBreakStepOverDepth) { - mBreakStepOverFunc2 = gameEdit->GetInterpreterCallStackFunction(mBreakInterpreter,mBreakStepOverDepth - 1); + mBreakStepOverFunc2 = ((idGameEditExt*) gameEdit)->GetInterpreterCallStackFunction(mBreakInterpreter,mBreakStepOverDepth - 1); } else { @@ -305,7 +307,7 @@ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg ) msg->ReadString ( filename, sizeof(filename) ); //check for statement on requested breakpoint location - if (!gameEdit->IsLineCode(filename, lineNumber)) + if (!((idGameEditExt*) gameEdit)->IsLineCode(filename, lineNumber)) { idBitMsg msgOut; byte buffer[MAX_MSGLEN]; @@ -391,7 +393,7 @@ void rvDebuggerServer::HandleInspectCallstack ( idBitMsg* msg ) msgOut.BeginWriting(); msgOut.WriteShort ( (short)DBMSG_INSPECTCALLSTACK ); - gameEdit->MSG_WriteInterpreterInfo(&msgOut, mBreakInterpreter, mBreakProgram, mBreakInstructionPointer); + ((idGameEditExt*) gameEdit)->MSG_WriteInterpreterInfo(&msgOut, mBreakInterpreter, mBreakProgram, mBreakInstructionPointer); SendPacket (msgOut.GetData(), msgOut.GetSize() ); } @@ -416,12 +418,12 @@ void rvDebuggerServer::HandleInspectThreads ( idBitMsg* msg ) msgOut.WriteShort ( (short)DBMSG_INSPECTTHREADS ); // Write the number of threads to the message - msgOut.WriteShort ((short)gameEdit->GetTotalScriptThreads() ); + msgOut.WriteShort ((short)((idGameEditExt*) gameEdit)->GetTotalScriptThreads() ); // Loop through all of the threads and write their name and number to the message - for ( i = 0; i < gameEdit->GetTotalScriptThreads(); i ++ ) + for ( i = 0; i < ((idGameEditExt*) gameEdit)->GetTotalScriptThreads(); i ++ ) { - gameEdit->MSG_WriteThreadInfo(&msgOut,gameEdit->GetThreadByIndex(i), mBreakInterpreter); + ((idGameEditExt*) gameEdit)->MSG_WriteThreadInfo(&msgOut,((idGameEditExt*) gameEdit)->GetThreadByIndex(i), mBreakInterpreter); } // Send off the inspect threads packet to the debugger client @@ -461,7 +463,7 @@ void rvDebuggerServer::HandleInspectScripts( idBitMsg* msg ) msgOut.BeginWriting(); msgOut.WriteShort((short)DBMSG_INSPECTSCRIPTS); - gameEdit->MSG_WriteScriptList( &msgOut ); + ((idGameEditExt*) gameEdit)->MSG_WriteScriptList( &msgOut ); SendPacket(msgOut.GetData(), msgOut.GetSize()); } @@ -496,7 +498,7 @@ void rvDebuggerServer::HandleInspectVariable ( idBitMsg* msg ) msgOut.BeginWriting(); msgOut.WriteShort ( (short)DBMSG_INSPECTVARIABLE ); - if (!gameEdit->GetRegisterValue(mBreakInterpreter, varname, varvalue, scopeDepth ) ) + if (!((idGameEditExt*) gameEdit)->GetRegisterValue(mBreakInterpreter, varname, varvalue, scopeDepth ) ) { varvalue = "???"; } @@ -527,8 +529,8 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* // Grab the current statement and the filename that it came from - filename = gameEdit->GetFilenameForStatement(program, instructionPointer); - int linenumber = gameEdit->GetLineNumberForStatement(program, instructionPointer); + filename = ((idGameEditExt*) gameEdit)->GetFilenameForStatement(program, instructionPointer); + int linenumber = ((idGameEditExt*) gameEdit)->GetLineNumberForStatement(program, instructionPointer); // Operate on lines, not statements if ( mLastStatementLine == linenumber && mLastStatementFile == filename) @@ -542,7 +544,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* mLastStatementLine = linenumber; // Reset stepping when the last function on the callstack is returned from - if (gameEdit->ReturnedFromFunction(program, interpreter,instructionPointer)) + if ( ((idGameEditExt*) gameEdit)->ReturnedFromFunction(program, interpreter,instructionPointer)) { mBreakStepOver = false; mBreakStepInto = false; @@ -560,7 +562,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* if ( mBreakStepOver ) { //virtual bool CheckForBreakpointHit(interpreter,function1,function2,depth) - if (gameEdit->CheckForBreakPointHit(interpreter, mBreakStepOverFunc1, mBreakStepOverFunc2, mBreakStepOverDepth)) + if (((idGameEditExt*) gameEdit)->CheckForBreakPointHit(interpreter, mBreakStepOverFunc1, mBreakStepOverFunc2, mBreakStepOverDepth)) { Break ( interpreter, program, instructionPointer ); return; @@ -635,8 +637,8 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i mBreakNext = false; // Grab the current statement and the filename that it came from - filename = gameEdit->GetFilenameForStatement(program,instructionPointer); - int linenumber = gameEdit->GetLineNumberForStatement(program, instructionPointer); + filename = ((idGameEditExt*) gameEdit)->GetFilenameForStatement(program,instructionPointer); + int linenumber = ((idGameEditExt*) gameEdit)->GetLineNumberForStatement(program, instructionPointer); idStr fileStr = filename; fileStr.BackSlashesToSlashes();