- Unbreaking Game and GameEdit API / ABI for game debugger use

This commit is contained in:
HarrievG 2021-06-28 23:38:38 +02:00
parent 7e367a0e62
commit d4db77b9ed
17 changed files with 175 additions and 118 deletions

View file

@ -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);
}

View file

@ -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 );

View file

@ -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 );

View file

@ -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;
}

View file

@ -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());

View file

@ -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;
}

View file

@ -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

View file

@ -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;
/*
===============================================================================

View file

@ -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();

View file

@ -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

View file

@ -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 );

View file

@ -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);
}
}

View file

@ -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 ) {

View file

@ -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 );

View file

@ -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;
}

View file

@ -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());

View file

@ -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();