From 7a2ccee3309d971471e477f926978ab2bee804b2 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Tue, 11 May 2021 22:45:24 +0200 Subject: [PATCH 01/42] debugger --- .gitignore | 1 + neo/CMakeLists.txt | 4 + neo/framework/CVarSystem.cpp | 2 +- neo/framework/Common.cpp | 32 ++- neo/framework/Common.h | 5 + neo/framework/Game.h | 43 +++- neo/framework/Session.cpp | 10 +- neo/framework/async/AsyncServer.cpp | 2 +- neo/game/GameEdit.cpp | 61 +++++ neo/game/Game_local.cpp | 27 ++- neo/game/Game_local.h | 8 +- neo/game/script/Script_Interpreter.cpp | 217 +++++++++++++++--- neo/game/script/Script_Program.h | 2 +- neo/game/script/Script_Thread.cpp | 54 ++++- neo/idlib/Lib.cpp | 2 +- neo/sys/win32/rc/Debugger.rc | 9 +- neo/sys/win32/rc/GuiEd.rc | 2 - neo/sys/win32/win_main.cpp | 27 ++- neo/tools/common/OpenFileDialog.cpp | 3 +- neo/tools/debugger/DebuggerApp.cpp | 4 +- neo/tools/debugger/DebuggerApp.h | 6 +- neo/tools/debugger/DebuggerBreakpoint.h | 3 +- neo/tools/debugger/DebuggerClient.cpp | 190 ++++++++++----- neo/tools/debugger/DebuggerClient.h | 45 +++- neo/tools/debugger/DebuggerMessages.h | 1 + neo/tools/debugger/DebuggerScript.cpp | 80 +------ neo/tools/debugger/DebuggerScript.h | 12 +- neo/tools/debugger/DebuggerServer.cpp | 293 ++++++++++++------------ neo/tools/debugger/DebuggerServer.h | 83 +++---- neo/tools/debugger/DebuggerWindow.cpp | 228 +++++++++++++++--- neo/tools/debugger/DebuggerWindow.h | 81 +++---- 31 files changed, 1038 insertions(+), 499 deletions(-) diff --git a/.gitignore b/.gitignore index 258b4d5a..48071768 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ /neo/out* /neo/build* +/neo/CMakeSettings.json diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt index a57d47be..11ec8394 100644 --- a/neo/CMakeLists.txt +++ b/neo/CMakeLists.txt @@ -862,6 +862,9 @@ if (TOOLS AND MFC_FOUND AND MSVC) # Script editor file(GLOB src_script_editor "tools/script/*.cpp") add_globbed_headers(src_script_editor "tools/script") + # Script Debugger + file(GLOB src_script_debugger "tools/debugger/*.cpp") + add_globbed_headers(src_script_debugger "tools/debugger") # sound editor? file(GLOB src_sound_editor "tools/sound/*.cpp") add_globbed_headers(src_sound_editor "tools/sound") @@ -881,6 +884,7 @@ if (TOOLS AND MFC_FOUND AND MSVC) ${src_map_editor} ${src_script_editor} ${src_sound_editor} + ${src_script_debugger} "tools/edit_public.h" "tools/edit_gui_common.h" ) diff --git a/neo/framework/CVarSystem.cpp b/neo/framework/CVarSystem.cpp index 413e3d5d..a10860ee 100644 --- a/neo/framework/CVarSystem.cpp +++ b/neo/framework/CVarSystem.cpp @@ -244,7 +244,7 @@ void idInternalCVar::UpdateValue( void ) { clamped = true; } } - if ( clamped || !idStr::IsNumeric( value ) || idStr::FindChar( value, '.' ) ) { + if ( clamped || !idStr::IsNumeric( value ) || (idStr::FindChar( value, '.' )!=-1) ) { valueString = idStr( integerValue ); value = valueString.c_str(); } diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index d0bda134..6edfb00a 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -142,6 +142,7 @@ 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 ); @@ -382,12 +383,17 @@ void idCommonLocal::VPrintf( const char *fmt, va_list args ) { // remove any color codes idStr::RemoveColors( msg ); - // echo to dedicated console and early console - Sys_Printf( "%s", msg ); + +#ifdef ID_ALLOW_TOOLS // print to script debugger server - // DebuggerServerPrint( msg ); - + if (com_editors & EDITOR_DEBUGGER) + DebuggerServerPrint(msg); + else +#endif + // only echo to dedicated console and early console when debugger is not running so no + // deadlocks occur if engine functions called from the debuggerthread trace stuff.. + Sys_Printf("%s", msg); #if 0 // !@# #if defined(_DEBUG) && defined(WIN32) if ( strlen( msg ) < 512 ) { @@ -1134,8 +1140,7 @@ Com_ScriptDebugger_f static void Com_ScriptDebugger_f( const idCmdArgs &args ) { // Make sure it wasnt on the command line if ( !( com_editors & EDITOR_DEBUGGER ) ) { - common->Printf( "Script debugger is currently disabled\n" ); - // DebuggerClientLaunch(); + DebuggerClientLaunch(); } } @@ -2020,6 +2025,7 @@ void Com_LocalizeMaps_f( const idCmdArgs &args ) { strCount += LocalizeMap(args.Argv(2), strTable, listHash, excludeList, write); } else { idStrList files; + //wow, what now? a hardcoded path? GetFileList("z:/d3xp/d3xp/maps/game", "*.map", files); for ( int i = 0; i < files.Num(); i++ ) { idStr file = fileSystem->OSPathToRelativePath(files[i]); @@ -2666,7 +2672,7 @@ void idCommonLocal::LoadGameDLL( void ) { gameImport.AASFileManager = ::AASFileManager; gameImport.collisionModelManager = ::collisionModelManager; - gameExport = *GetGameAPI( &gameImport ); + gameExport = *GetGameAPI( &gameImport); if ( gameExport.version != GAME_API_VERSION ) { Sys_DLL_Unload( gameDLL ); @@ -3164,8 +3170,10 @@ void idCommonLocal::InitGame( void ) { // initialize the user interfaces uiManager->Init(); +#if defined(ID_ALLOW_TOOLS) // startup the script debugger - // DebuggerServerInit(); + DebuggerServerInit(); +#endif; PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04350" ) ); @@ -3202,8 +3210,10 @@ void idCommonLocal::ShutdownGame( bool reloading ) { sw->StopAllSounds(); } +#if defined(ID_ALLOW_TOOLS) // shutdown the script debugger - // DebuggerServerShutdown(); + DebuggerServerShutdown(); +#endif idAsyncNetwork::client.Shutdown(); @@ -3298,6 +3308,10 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F } } +void idCommonLocal::DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer) +{ + DebuggerServerCheckBreakpoint(interpreter, program, instructionPointer); +} idGameCallbacks gameCallbacks; diff --git a/neo/framework/Common.h b/neo/framework/Common.h index c0400bb4..ec44ee66 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -111,6 +111,8 @@ struct MemInfo_t { }; class idLangDict; +class idInterpreter; +class idProgram; class idCommon { public: @@ -158,6 +160,9 @@ 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; diff --git a/neo/framework/Game.h b/neo/framework/Game.h index 8a4c4e1c..6af69967 100644 --- a/neo/framework/Game.h +++ b/neo/framework/Game.h @@ -31,6 +31,7 @@ If you have questions concerning this license or the applicable additional terms #include "idlib/BitMsg.h" #include "idlib/Dict.h" +#include "idlib/containers/StrList.h" #include "framework/UsercmdGen.h" #include "renderer/RenderWorld.h" #include "sound/sound.h" @@ -109,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 ) = 0; + virtual void InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed, int activeEditors ) = 0; // Loads a map from a savegame file. - virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) = 0; + virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors ) = 0; // Saves the current game state, the session may have written some data to the file already. virtual void SaveGame( idFile *saveGameFile ) = 0; @@ -127,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 ) = 0; + virtual gameReturn_t RunFrame( const usercmd_t *clientCmds , int activeEditors) = 0; // Makes rendering and sound system calls to display for a given clientNum. virtual bool Draw( int clientNum ) = 0; @@ -232,6 +233,11 @@ enum { class idEntity; class idMD5Anim; +class idThread; +class function_t; +class idProgram; +class idInterpreter; +typedef struct prstack_s prstack_t; // FIXME: this interface needs to be reworked but it properly separates code for the time being class idGameEdit { @@ -294,7 +300,7 @@ public: virtual void EntitySetColor( idEntity *ent, const idVec3 color ); // Player methods. - virtual bool PlayerIsValid() const; + virtual bool PlayerIsValid( ) const; virtual void PlayerGetOrigin( idVec3 &org ) const; virtual void PlayerGetAxis( idMat3 &axis ) const; virtual void PlayerGetViewAngles( idAngles &angles ) const; @@ -311,6 +317,35 @@ public: virtual void MapRemoveEntity( const char *name ) const; virtual void MapEntityTranslate( const char *name, const idVec3 &v ) const; + // In game script Debugging Support + // IdProgram + virtual void GetLoadedScripts( idStrList ** result ); + virtual bool IsLineCode( const char* filename, int linenumber) const; + virtual const char * GetFilenameForStatement( idProgram* program, int index ) const; + virtual int GetLineNumberForStatement( idProgram* program, int index ) const; + + // idInterpreter + virtual bool CheckForBreakPointHit( const idInterpreter* interpreter, const function_t* function1, const function_t* function2, int depth ) const; + virtual bool ReturnedFromFunction( const idProgram* program, const idInterpreter* interpreter, int index ) const; + virtual bool GetRegisterValue( const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth ) const; + virtual const idThread* GetThread( const idInterpreter* interpreter ) const; + virtual int GetInterpreterCallStackDepth( const idInterpreter* interpreter ); + virtual const function_t* GetInterpreterCallStackFunction( const idInterpreter* interpreter, int stackDepth = -1 ); + + // IdThread + virtual const char * ThreadGetName( const idThread* thread ) const; + virtual int ThreadGetNum( const idThread* thread ) const; + virtual bool ThreadIsDoneProcessing( const idThread* thread ) const; + virtual bool ThreadIsWaiting( const idThread* thread ) const; + virtual bool ThreadIsDying( const idThread* thread ) const; + virtual int GetTotalScriptThreads( ) const; + virtual const idThread* GetThreadByIndex( int index ) const; + + // MSG helpers + virtual void MSG_WriteThreadInfo( idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter ); + virtual void MSG_WriteCallstackFunc( idBitMsg* msg, const prstack_t* stack, const idProgram* program, int instructionPtr ); + virtual void MSG_WriteInterpreterInfo( idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr ); + virtual void MSG_WriteScriptList( idBitMsg* msg ); }; extern idGameEdit * gameEdit; diff --git a/neo/framework/Session.cpp b/neo/framework/Session.cpp index 697591e4..74d6b19f 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 ) == false ) { + if ( game->InitFromSaveGame( fullMapName + ".map", rw, sw, savegameFile, com_editors ) == 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() ); + game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds(),com_editors ); } } else { game->SetServerInfo( mapSpawnData.serverInfo ); - game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds() ); + game->InitFromNewMap( fullMapName + ".map", rw, sw, idAsyncNetwork::server.IsActive(), idAsyncNetwork::client.IsActive(), Sys_Milliseconds(), com_editors); } 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 ); + game->RunFrame( mapSpawnData.mapSpawnUsercmd, com_editors); } } @@ -2785,7 +2785,7 @@ void idSessionLocal::RunGameTic() { // run the game logic every player move int start = Sys_Milliseconds(); - gameReturn_t ret = game->RunFrame( &cmd ); + gameReturn_t ret = game->RunFrame( &cmd, com_editors); 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 9f6981fc..e2b5a97b 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 ) ] ); + gameReturn_t ret = game->RunFrame( userCmds[gameFrame & ( MAX_USERCMD_BACKUP - 1 ) ], com_editors ); idAsyncNetwork::ExecuteSessionCommand( ret.sessionCommand ); diff --git a/neo/game/GameEdit.cpp b/neo/game/GameEdit.cpp index 0c637bdb..769df2a0 100644 --- a/neo/game/GameEdit.cpp +++ b/neo/game/GameEdit.cpp @@ -1146,3 +1146,64 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const { } } } + +/*********************************************************************** + + Debugger + +***********************************************************************/ + +bool idGameEdit::IsLineCode(const char* filename, int linenumber) const +{ + static idStr fileStr = idStr(MAX_PATH); + idProgram* program = &gameLocal.program; + for (int i = 0; i < program->NumStatements(); i++) + { + fileStr = program->GetFilename(program->GetStatement(i).file); + fileStr.BackSlashesToSlashes(); + + if (strcmp(filename, fileStr.c_str()) == 0 + && program->GetStatement(i).linenumber == linenumber + ) + { + return true; + } + } + return false; +} + +void idGameEdit::GetLoadedScripts( idStrList** result ) +{ + (*result)->Clear(); + idProgram* program = &gameLocal.program; + + for (int i = 0; i < program->NumFilenames(); i++) + { + (*result)->AddUnique( idStr(program->GetFilename( i )) ); + } +} + +void idGameEdit::MSG_WriteScriptList( idBitMsg* msg) +{ + idProgram* program = &gameLocal.program; + + msg->WriteInt( program->NumFilenames() ); + for (int i = 0; i < program->NumFilenames(); i++) + { + idStr file = program->GetFilename(i); + //fix this. it seams that scripts triggered by the runtime are stored with a wrong path + //the use // instead of '\' + file.BackSlashesToSlashes(); + msg->WriteString(file); + } +} + +const char* idGameEdit::GetFilenameForStatement(idProgram* program, int index) const +{ + return program->GetFilenameForStatement(index); +} + +int idGameEdit::GetLineNumberForStatement(idProgram* program, int index) const +{ + return program->GetLineNumberForStatement(index); +} diff --git a/neo/game/Game_local.cpp b/neo/game/Game_local.cpp index ef820d66..ba6d4554 100644 --- a/neo/game/Game_local.cpp +++ b/neo/game/Game_local.cpp @@ -1192,7 +1192,7 @@ void idGameLocal::MapPopulate( void ) { idGameLocal::InitFromNewMap =================== */ -void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed ) { +void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed, int activeEditors) { this->isServer = isServer; this->isClient = isClient; @@ -1204,6 +1204,8 @@ 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; @@ -1230,7 +1232,7 @@ void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorl idGameLocal::InitFromSaveGame ================= */ -bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) { +bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors ) { int i; int num; idEntity *ent; @@ -1242,6 +1244,8 @@ 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; @@ -2215,14 +2219,17 @@ void idGameLocal::SortActiveEntityList( void ) { idGameLocal::RunFrame ================ */ -gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds ) { - idEntity * ent; - int num; - float ms; - idTimer timer_think, timer_events, timer_singlethink; - gameReturn_t ret; - idPlayer *player; - const renderView_t *view; +gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds, int activeEditors ) { + idEntity * ent; + int num; + float ms; + idTimer timer_think, timer_events, timer_singlethink; + 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 df7456d1..44cf515d 100644 --- a/neo/game/Game_local.h +++ b/neo/game/Game_local.h @@ -293,7 +293,7 @@ public: idEntityPtr lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f int lastGUI; // last GUI on the lastGUIEnt - + int editors; // Mirrored editors flags from common to determine which editors are running // ---------------------- Public idGame Interface ------------------- idGameLocal(); @@ -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 ); - virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ); + 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 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 ); + virtual gameReturn_t RunFrame( const usercmd_t *clientCmds , int activeEditors); 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 b6d044cf..dd5b3f3d 100644 --- a/neo/game/script/Script_Interpreter.cpp +++ b/neo/game/script/Script_Interpreter.cpp @@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms #include "script/Script_Interpreter.h" +#include "framework/FileSystem.h" + /* ================ idInterpreter::idInterpreter() @@ -183,7 +185,6 @@ idInterpreter::GetRegisterValue Returns a string representation of the value of the register. This is used primarily for the debugger and debugging -//FIXME: This is pretty much wrong. won't access data in most situations. ================ */ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDepth ) { @@ -191,17 +192,17 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep idVarDef *d; char funcObject[ 1024 ]; char *funcName; - const idVarDef *scope; + const idVarDef *scope = NULL; + const idVarDef *scopeObj; const idTypeDef *field; - const idScriptObject *obj; const function_t *func; out.Empty(); - + if ( scopeDepth == -1 ) { scopeDepth = callStackDepth; - } - + } + if ( scopeDepth == callStackDepth ) { func = currentFunction; } else { @@ -215,35 +216,44 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep funcName = strstr( funcObject, "::" ); if ( funcName ) { *funcName = '\0'; - scope = gameLocal.program.GetDef( NULL, funcObject, &def_namespace ); - funcName += 2; + scopeObj = gameLocal.program.GetDef( NULL, funcObject, &def_namespace ); + funcName += 2; + if ( scopeObj ) + { + scope = gameLocal.program.GetDef( NULL, funcName, scopeObj ); + } } else { funcName = funcObject; - scope = &def_namespace; + scope = gameLocal.program.GetDef( NULL, func->Name(), &def_namespace ); + scopeObj = NULL; } - // Get the function from the object - d = gameLocal.program.GetDef( NULL, funcName, scope ); - if ( !d ) { + if ( !scope ) + { return false; } - // Get the variable itself and check various namespaces - d = gameLocal.program.GetDef( NULL, name, d ); - if ( !d ) { - if ( scope == &def_namespace ) { - return false; - } - - d = gameLocal.program.GetDef( NULL, name, scope ); - if ( !d ) { - d = gameLocal.program.GetDef( NULL, name, &def_namespace ); - if ( !d ) { - return false; + d = gameLocal.program.GetDef( NULL, name, scope ); + + // Check the objects for it if it wasnt local to the function + if ( !d ) + { + for ( ; scopeObj && scopeObj->TypeDef()->SuperClass(); scopeObj = scopeObj->TypeDef()->SuperClass()->def ) + { + d = gameLocal.program.GetDef( NULL, name, scopeObj ); + if ( d ) + { + break; } } - } + } + if ( !d ) + { + out = "???"; + return false; + } + reg = GetVariable( d ); switch( d->Type() ) { case ev_float: @@ -256,7 +266,7 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep break; case ev_vector: - if ( reg.vectorPtr ) { + if ( reg.vectorPtr ) { out = va( "%g,%g,%g", reg.vectorPtr->x, reg.vectorPtr->y, reg.vectorPtr->z ); } else { out = "0,0,0"; @@ -274,30 +284,55 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep break; case ev_field: + { + idEntity* entity; + idScriptObject* obj; + if ( scope == &def_namespace ) { // should never happen, but handle it safely anyway return false; } - field = scope->TypeDef()->GetParmType( reg.ptrOffset )->FieldType(); - obj = *reinterpret_cast( &localstack[ callStack[ callStackDepth ].stackbase ] ); - if ( !field || !obj ) { + field = d->TypeDef()->FieldType(); + entity = GetEntity ( *((int*)&localstack[ localstackBase ]) ); + if ( !entity || !field ) + { return false; } + obj = &entity->scriptObject; + if ( !obj ) { + return false; + } + switch ( field->Type() ) { - case ev_boolean: - out = va( "%d", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); - return true; + case ev_boolean: + out = va( "%d", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); + return true; - case ev_float: - out = va( "%g", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); - return true; + case ev_float: + out = va( "%g", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); + return true; + + case ev_string: { + const char* str; + str = reinterpret_cast( &obj->data[ reg.ptrOffset ] ); + if ( !str ) { + out = "\"\""; + } else { + out = "\""; + out += str; + out += "\""; + } + return true; + } - default: - return false; + default: + return false; } + break; + } case ev_string: if ( reg.stringPtr ) { @@ -969,6 +1004,19 @@ 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 ( ) ) { + static int lastLineNumber = -1; + if ( lastLineNumber != gameLocal.program.GetStatement ( instructionPointer ).linenumber ) { + gameLocal.Printf ( "%s (%d)\n", + gameLocal.program.GetFilename ( gameLocal.program.GetStatement ( instructionPointer ).file ), + gameLocal.program.GetStatement ( instructionPointer ).linenumber + ); + lastLineNumber = gameLocal.program.GetStatement ( instructionPointer ).linenumber; + } + } + switch( st->op ) { case OP_RETURN: LeaveFunction( st->a ); @@ -1833,3 +1881,98 @@ bool idInterpreter::Execute( void ) { return threadDying; } + +bool idGameEdit::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 +{ + + return ( const_cast(program)->GetStatement(index).op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 ); +} + +bool idGameEdit::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const +{ + return const_cast(interpreter)->GetRegisterValue(name, out, scopeDepth); +} + +const idThread* idGameEdit::GetThread(const idInterpreter* interpreter) const +{ + return interpreter->GetThread(); +} + +void idGameEdit::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, const idProgram * program, int instructionPtr) +{ + const statement_t* st; + const function_t* func; + + func = stack->f; + + // If the function is unknown then just fill in with default data. + if ( !func ) + { + msg->WriteString ( "" ); + msg->WriteString ( "" ); + msg->WriteInt ( 0 ); + return; + } + else + { + msg->WriteString ( va("%s( )", func->Name() ) ); + } + + if (stack->s == -1) //this is a fake stack created by debugger, use intruction pointer for retrieval. + st = &const_cast( program )->GetStatement( instructionPtr ); + else // Use the calling statement as the filename and linenumber where the call was made from + st = &const_cast( program )->GetStatement ( stack->s ); + + if ( st ) + { + idStr qpath = const_cast( program )->GetFilename( st->file ); + if (idStr::FindChar( qpath, ':' ) != -1) + qpath = fileSystem->OSPathToRelativePath( qpath.c_str() ); + qpath.BackSlashesToSlashes ( ); + msg->WriteString( qpath ); + msg->WriteInt( st->linenumber ); + } + else + { + msg->WriteString ( "" ); + msg->WriteInt ( 0 ); + } +} + +void idGameEdit::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr) +{ + int i; + prstack_s temp; + + msg->WriteShort((int)interpreter->GetCallstackDepth( ) ); + + // write out the current function + temp.f = interpreter->GetCurrentFunction( ); + temp.s = -1; + temp.stackbase = 0; + MSG_WriteCallstackFunc( msg, &temp, program, instructionPtr); + + // Run through all of the callstack and write each to the msg + for (i = interpreter->GetCallstackDepth() - 1; i > 0; i--) + { + MSG_WriteCallstackFunc( msg, interpreter->GetCallstack( ) + i, program, instructionPtr); + } +} + + +int idGameEdit::GetInterpreterCallStackDepth(const idInterpreter* interpreter) +{ + return interpreter->GetCallstackDepth(); +} + +const function_t* idGameEdit::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_Program.h b/neo/game/script/Script_Program.h index 68230c1f..cd129e34 100644 --- a/neo/game/script/Script_Program.h +++ b/neo/game/script/Script_Program.h @@ -34,7 +34,7 @@ If you have questions concerning this license or the applicable additional terms #include "idlib/containers/HashIndex.h" #include "idlib/math/Vector.h" -#include "GameBase.h" +//#include "GameBase.h" class idEventDef; class idVarDef; diff --git a/neo/game/script/Script_Thread.cpp b/neo/game/script/Script_Thread.cpp index 58daa5d9..ce6ed271 100644 --- a/neo/game/script/Script_Thread.cpp +++ b/neo/game/script/Script_Thread.cpp @@ -28,11 +28,11 @@ If you have questions concerning this license or the applicable additional terms #include "sys/platform.h" -#include "gamesys/SysCvar.h" -#include "Player.h" -#include "Camera.h" +#include "game/gamesys/SysCvar.h" +#include "game/Player.h" +#include "game/Camera.h" -#include "script/Script_Thread.h" +#include "Script_Thread.h" const idEventDef EV_Thread_Execute( "", NULL ); const idEventDef EV_Thread_SetCallback( "", NULL ); @@ -1841,3 +1841,49 @@ void idThread::Event_InfluenceActive( void ) { idThread::ReturnInt( false ); } } + +int idGameEdit::ThreadGetNum(const idThread* thread) const +{ + return const_cast(thread)->GetThreadNum(); +} + +const char* idGameEdit::ThreadGetName(const idThread* thread) const +{ + return const_cast(thread)->GetThreadName(); +} + +int idGameEdit::GetTotalScriptThreads() const +{ + return idThread::GetThreads().Num(); +} + +const idThread* idGameEdit::GetThreadByIndex(int index) const +{ + return idThread::GetThreads()[index]; +} + +bool idGameEdit::ThreadIsDoneProcessing(const idThread* thread) const +{ + return const_cast(thread)->IsDoneProcessing(); +} + +bool idGameEdit::ThreadIsWaiting(const idThread* thread) const +{ + return const_cast(thread)->IsWaiting(); +} + +bool idGameEdit::ThreadIsDying(const idThread* thread) const +{ + return const_cast(thread)->IsDying(); +} + +void idGameEdit::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter) +{ + msg->WriteString(const_cast(thread)->GetThreadName()); + msg->WriteInt(const_cast(thread)->GetThreadNum()); + + msg->WriteBits((int)(thread == interpreter->GetThread()), 1); + msg->WriteBits((int)const_cast(thread)->IsDoneProcessing(), 1); + msg->WriteBits((int)const_cast(thread)->IsWaiting(), 1); + msg->WriteBits((int)const_cast(thread)->IsDying(), 1); +} \ No newline at end of file diff --git a/neo/idlib/Lib.cpp b/neo/idlib/Lib.cpp index 0976c85e..7f2a37d6 100644 --- a/neo/idlib/Lib.cpp +++ b/neo/idlib/Lib.cpp @@ -35,7 +35,7 @@ If you have questions concerning this license or the applicable additional terms #include #endif -#include +#include #include "sys/platform.h" #include "idlib/math/Vector.h" diff --git a/neo/sys/win32/rc/Debugger.rc b/neo/sys/win32/rc/Debugger.rc index bee22e2f..8aad0722 100644 --- a/neo/sys/win32/rc/Debugger.rc +++ b/neo/sys/win32/rc/Debugger.rc @@ -149,17 +149,16 @@ END // Dialog // -IDD_DBG_ABOUT DIALOGEX 0, 0, 222, 71 +IDD_DBG_ABOUT DIALOGEX 0, 0, 250, 80 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Script Debugger" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Script Debugger",IDC_STATIC,35,7,81,8 - LTEXT "Version 0.01",IDC_STATIC,35,17,41,8 - LTEXT "Original version by Raven",IDC_STATIC,35, - 28,134,8 - DEFPUSHBUTTON "OK",IDOK,165,50,50,14 + LTEXT "Version 1.0",IDC_STATIC,35,17,41,8 + LTEXT "Dhewm3 version by Harrie van Ginneken", IDC_STATIC, 35, 38, 134, 8 + DEFPUSHBUTTON "OK",IDOK,165,60,50,14 ICON 5098,IDC_STATIC,7,7,20,20 END diff --git a/neo/sys/win32/rc/GuiEd.rc b/neo/sys/win32/rc/GuiEd.rc index 6de83dc7..46f6bba1 100644 --- a/neo/sys/win32/rc/GuiEd.rc +++ b/neo/sys/win32/rc/GuiEd.rc @@ -269,8 +269,6 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "GUI Editor",IDC_STATIC,35,7,62,8 LTEXT "Version 0.15",IDC_STATIC,35,17,41,8 - LTEXT "Original version by Raven",IDC_STATIC,35, - 28,134,8 DEFPUSHBUTTON "OK",IDOK,165,50,50,14 ICON IDI_GUIED,IDC_STATIC,7,7,20,20 END diff --git a/neo/sys/win32/win_main.cpp b/neo/sys/win32/win_main.cpp index 7d7c8cc7..96a9a66a 100644 --- a/neo/sys/win32/win_main.cpp +++ b/neo/sys/win32/win_main.cpp @@ -629,7 +629,30 @@ Sys_DLL_GetProcAddress ===================== */ void *Sys_DLL_GetProcAddress( uintptr_t dllHandle, const char *procName ) { - return (void *)GetProcAddress( (HINSTANCE)dllHandle, procName ); + void * adr = (void*)GetProcAddress((HINSTANCE)dllHandle, procName); + if (!adr) + { + DWORD e = GetLastError(); + LPVOID msgBuf = nullptr; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + e, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&msgBuf, + 0, NULL); + + idStr errorStr = va("[%i (0x%X)]\t%s", e, e, msgBuf); + + if (errorStr.Length()) + common->Warning("GetProcAddress( %i %s) Failed ! %s", dllHandle, procName, errorStr.c_str()); + + ::LocalFree(msgBuf); + } + return adr; } /* @@ -969,7 +992,7 @@ int main(int argc, char *argv[]) { // Launch the script debugger if ( strstr( GetCommandLine(), "+debugger" ) ) { - // DebuggerClientInit( lpCmdLine ); + DebuggerClientInit(GetCommandLine()); return 0; } diff --git a/neo/tools/common/OpenFileDialog.cpp b/neo/tools/common/OpenFileDialog.cpp index 6da65c8f..405d48f9 100644 --- a/neo/tools/common/OpenFileDialog.cpp +++ b/neo/tools/common/OpenFileDialog.cpp @@ -392,7 +392,8 @@ void rvOpenFileDialog::SetFilter ( const char* s ) if ( semi != -1 ) { filter = filters.Left ( semi ); - filters = filters.Right ( filters.Length ( ) - semi ); + filters = filters.Right ( filters.Length ( ) - (semi + 1)); + filters.Strip(' '); } else { diff --git a/neo/tools/debugger/DebuggerApp.cpp b/neo/tools/debugger/DebuggerApp.cpp index 82aacaa1..1176d84a 100644 --- a/neo/tools/debugger/DebuggerApp.cpp +++ b/neo/tools/debugger/DebuggerApp.cpp @@ -37,8 +37,8 @@ If you have questions concerning this license or the applicable additional terms rvDebuggerApp::rvDebuggerApp ================ */ -rvDebuggerApp::rvDebuggerApp ( ) : - mOptions ( "Software\\id Software\\DOOM3\\Tools\\Debugger" ) +rvDebuggerApp::rvDebuggerApp ( ) //: + //mOptions ( "Software\\id Software\\DOOM3\\Tools\\Debugger" ) { mInstance = NULL; mDebuggerWindow = NULL; diff --git a/neo/tools/debugger/DebuggerApp.h b/neo/tools/debugger/DebuggerApp.h index d659b1d4..4438e97d 100644 --- a/neo/tools/debugger/DebuggerApp.h +++ b/neo/tools/debugger/DebuggerApp.h @@ -29,7 +29,7 @@ If you have questions concerning this license or the applicable additional terms #define DEBUGGERAPP_H_ #include "../../sys/win32/win_local.h" -#include "../../framework/sync/Msg.h" +//#include "../../framework/sync/Msg.h" #ifndef REGISTRYOPTIONS_H_ #include "../common/RegistryOptions.h" @@ -49,13 +49,15 @@ If you have questions concerning this license or the applicable additional terms // These were changed to static by ID so to make it easy we just throw them // in this header -const int MAX_MSGLEN = 1400; +// we need a lot to be able to list all threads in mars_city1 +const int MAX_MSGLEN = 8600; class rvDebuggerApp { public: rvDebuggerApp ( ); + ~rvDebuggerApp(); bool Initialize ( HINSTANCE hInstance ); int Run ( void ); diff --git a/neo/tools/debugger/DebuggerBreakpoint.h b/neo/tools/debugger/DebuggerBreakpoint.h index a1f07a68..da0ab5c4 100644 --- a/neo/tools/debugger/DebuggerBreakpoint.h +++ b/neo/tools/debugger/DebuggerBreakpoint.h @@ -28,6 +28,8 @@ If you have questions concerning this license or the applicable additional terms #ifndef DEBUGGERBREAKPOINT_H_ #define DEBUGGERBREAKPOINT_H_ +class idProgram; + class rvDebuggerBreakpoint { public: @@ -46,7 +48,6 @@ protected: int mID; int mLineNumber; idStr mFilename; - private: static int mNextID; diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index 6ce67255..982029f3 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -73,7 +73,7 @@ bool rvDebuggerClient::Initialize ( void ) } // Server must be running on the local host on port 28980 - Sys_StringToNetAdr ( "localhost", &mServerAdrt, true ); + Sys_StringToNetAdr ( "localhost", &mServerAdr, true ); mServerAdr.port = 27980; // Attempt to let the server know we are here. The server may not be running so this @@ -110,25 +110,29 @@ Process all incomding messages from the debugger server bool rvDebuggerClient::ProcessMessages ( void ) { netadr_t adrFrom; - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; - MSG_Init( &msg, buffer, sizeof( buffer ) ); + msg.SetSize(MAX_MSGLEN); + msg.BeginReading(); + int msgSize; // Check for pending udp packets on the debugger port - while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) ) + while ( mPort.GetPacket ( adrFrom, buffer,msgSize, MAX_MSGLEN) ) { - unsigned short command; + short command; + msg.Init(buffer, sizeof(buffer)); + msg.SetSize(msgSize); + msg.BeginReading(); // Only accept packets from the debugger server for security reasons if ( !Sys_CompareNetAdrBase ( adrFrom, mServerAdr ) ) { continue; } + command = msg.ReadShort ( ); - command = (unsigned short) MSG_ReadShort ( &msg ); - - // Is this what we are waiting for? + // Is this what we are waiting for? if ( command == mWaitFor ) { mWaitFor = DBMSG_UNKNOWN; @@ -168,17 +172,39 @@ bool rvDebuggerClient::ProcessMessages ( void ) case DBMSG_INSPECTVARIABLE: HandleInspectVariable ( &msg ); break; + + case DBMSG_REMOVEBREAKPOINT: + HandleRemoveBreakpoint( &msg ); + break; + case DBMSG_INSPECTSCRIPTS: + HandleInspectScripts( &msg ); + break; } // Give the window a chance to process the message - msg.readcount = 0; - msg.bit = 0; + msg.SetReadCount(0); + msg.SetReadBit(0); gDebuggerApp.GetWindow().ProcessNetMessage ( &msg ); } return true; } +void rvDebuggerClient::HandleRemoveBreakpoint(idBitMsg* msg) +{ + long lineNumber; + char filename[MAX_PATH]; + + // Read the breakpoint info + + lineNumber = msg->ReadInt(); + msg->ReadString(filename, MAX_PATH); + + rvDebuggerBreakpoint* bp = FindBreakpoint(filename, lineNumber); + if(bp) + RemoveBreakpoint(bp->GetID()); +} + /* ================ rvDebuggerClient::HandleBreak @@ -187,19 +213,22 @@ Handle the DBMSG_BREAK message send from the server. This message is handled by caching the file and linenumber where the break occured. ================ */ -void rvDebuggerClient::HandleBreak ( msg_t* msg ) +void rvDebuggerClient::HandleBreak ( idBitMsg* msg ) { char filename[MAX_PATH]; mBreak = true; // Line number - mBreakLineNumber = MSG_ReadInt ( msg ); + mBreakLineNumber = msg->ReadInt ( ); // Filename - MSG_ReadString ( msg, filename, MAX_PATH ); + msg->ReadString ( filename, MAX_PATH ); mBreakFilename = filename; + int ptr32b = msg->ReadInt(); + mBreakProgram = (idProgram*)ptr32b; + // Clear the variables mVariables.Clear ( ); @@ -211,6 +240,26 @@ void rvDebuggerClient::HandleBreak ( msg_t* msg ) WaitFor ( DBMSG_INSPECTTHREADS, 2000 ); } + +/* +================ +rvDebuggerClient::InspectScripts + +Instructs the client to inspect the loaded scripts +================ +*/ +void rvDebuggerClient::InspectScripts ( void ) +{ + idBitMsg msg; + byte buffer[MAX_MSGLEN]; + + msg.Init(buffer, sizeof(buffer)); + msg.BeginWriting(); + msg.WriteShort((short)DBMSG_INSPECTSCRIPTS); + SendPacket(msg.GetData(), msg.GetSize()); +} + + /* ================ rvDebuggerClient::InspectVariable @@ -222,15 +271,41 @@ will in turn respond back to the client with the variable value */ void rvDebuggerClient::InspectVariable ( const char* name, int callstackDepth ) { - msg_t msg; - byte buffer[MAX_MSGLEN]; + idBitMsg msg; + byte buffer[MAX_MSGLEN]; - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE ); - MSG_WriteShort ( &msg, (short)(mCallstack.Num()-callstackDepth) ); - MSG_WriteString ( &msg, name ); + msg.Init( buffer, sizeof( buffer ) ); + msg.BeginWriting(); + msg.WriteShort ( (short)DBMSG_INSPECTVARIABLE ); + msg.WriteShort ( (short)(mCallstack.Num()-callstackDepth) ); + msg.WriteString ( name ); - SendPacket ( msg.data, msg.cursize ); + SendPacket ( msg.GetData(), msg.GetSize()); +} + +/* +================ +rvDebuggerClient::HandleInspectScripts + +Handle the message DBMSG_INSPECTSCRIPTS being sent from the server. This message +is handled by adding the script entries to a list for later lookup. +================ +*/ +void rvDebuggerClient::HandleInspectScripts( idBitMsg* msg ) +{ + int totalScripts; + + mServerScripts.Clear(); + + // Read all of the callstack entries specfied in the message + for (totalScripts = msg->ReadInt(); totalScripts > 0; totalScripts--) + { + char temp[1024]; + + // Script Name + msg->ReadString(temp, 1024); + mServerScripts.Append(temp); + } } /* @@ -241,29 +316,29 @@ Handle the message DBMSG_INSPECTCALLSTACK being sent from the server. This mess is handled by adding the callstack entries to a list for later lookup. ================ */ -void rvDebuggerClient::HandleInspectCallstack ( msg_t* msg ) +void rvDebuggerClient::HandleInspectCallstack ( idBitMsg* msg ) { int depth; ClearCallstack ( ); // Read all of the callstack entries specfied in the message - for ( depth = (short)MSG_ReadShort ( msg ) ; depth > 0; depth -- ) + for ( depth = (short)msg->ReadShort ( ) ; depth > 0; depth -- ) { rvDebuggerCallstack* entry = new rvDebuggerCallstack; char temp[1024]; // Function name - MSG_ReadString ( msg, temp, 1024 ); - entry->mFunction = temp; + msg->ReadString ( temp, 1024 ); + entry->mFunction = idStr(temp); // Filename - MSG_ReadString ( msg, temp, 1024 ); - entry->mFilename = temp; + msg->ReadString ( temp, 1024 ); + entry->mFilename = idStr(temp); // Line Number - entry->mLineNumber = MSG_ReadInt ( msg ); + entry->mLineNumber = msg->ReadInt ( ); // Add to list mCallstack.Append ( entry ); @@ -278,31 +353,31 @@ Handle the message DBMSG_INSPECTTHREADS being sent from the server. This messag is handled by adding the list of threads to a list for later lookup. ================ */ -void rvDebuggerClient::HandleInspectThreads ( msg_t* msg ) +void rvDebuggerClient::HandleInspectThreads ( idBitMsg* msg ) { int count; ClearThreads ( ); // Loop over the number of threads in the message - for ( count = (short)MSG_ReadShort ( msg ) ; count > 0; count -- ) + for ( count = (short)msg->ReadShort ( ) ; count > 0; count -- ) { rvDebuggerThread* entry = new rvDebuggerThread; char temp[1024]; // Thread name - MSG_ReadString ( msg, temp, 1024 ); + msg->ReadString ( temp, 1024 ); entry->mName = temp; // Thread ID - entry->mID = MSG_ReadInt ( msg ); + entry->mID = msg->ReadInt ( ); // Thread state - entry->mCurrent = MSG_ReadBits ( msg, 1 ) ? true : false; - entry->mDoneProcessing = MSG_ReadBits ( msg, 1 ) ? true : false; - entry->mWaiting = MSG_ReadBits ( msg, 1 ) ? true : false; - entry->mDying = MSG_ReadBits ( msg, 1 ) ? true : false; + entry->mCurrent = msg->ReadBits ( 1 ) ? true : false; + entry->mDoneProcessing = msg->ReadBits ( 1 ) ? true : false; + entry->mWaiting = msg->ReadBits ( 1 ) ? true : false; + entry->mDying = msg->ReadBits ( 1 ) ? true : false; // Add thread to list mThreads.Append ( entry ); @@ -317,15 +392,15 @@ Handle the message DBMSG_INSPECTVARIABLE being sent from the server. This messa is handled by adding the inspected variable to a dictionary for later lookup ================ */ -void rvDebuggerClient::HandleInspectVariable ( msg_t* msg ) +void rvDebuggerClient::HandleInspectVariable ( idBitMsg* msg ) { char var[1024]; char value[1024]; int callDepth; - callDepth = (short)MSG_ReadShort ( msg ); - MSG_ReadString ( msg, var, 1024 ); - MSG_ReadString ( msg, value, 1024 ); + callDepth = (short)msg->ReadShort ( ); + msg->ReadString ( var, 1024 ); + msg->ReadString ( value, 1024 ); mVariables.Set ( va("%d:%s", mCallstack.Num()-callDepth, var), value ); } @@ -463,13 +538,14 @@ Send a message with no data to the debugger server */ void rvDebuggerClient::SendMessage ( EDebuggerMessage dbmsg ) { - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)dbmsg ); + msg.Init ( buffer, sizeof( buffer ) ); + msg.BeginWriting ( ); + msg.WriteShort ( (short)dbmsg ); - SendPacket ( msg.data, msg.cursize ); + SendPacket ( msg.GetData(), msg.GetSize() ); } /* @@ -504,7 +580,7 @@ Send an individual breakpoint over to the debugger server */ void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly ) { - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; if ( !mConnected ) @@ -512,14 +588,15 @@ void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOn return; } - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_ADDBREAKPOINT ); - MSG_WriteBits ( &msg, onceOnly?1:0, 1 ); - MSG_WriteInt ( &msg, (unsigned long) bp.GetLineNumber ( ) ); - MSG_WriteInt ( &msg, bp.GetID ( ) ); - MSG_WriteString ( &msg, bp.GetFilename() ); + msg.Init( buffer, sizeof( buffer ) ); + msg.BeginWriting(); + msg.WriteShort ( (short)DBMSG_ADDBREAKPOINT ); + msg.WriteBits ( onceOnly?1:0, 1 ); + msg.WriteInt ( (unsigned long) bp.GetLineNumber ( ) ); + msg.WriteInt ( bp.GetID ( ) ); + msg.WriteString ( bp.GetFilename() ); - SendPacket ( msg.data, msg.cursize ); + SendPacket ( msg.GetData(), msg.GetSize() ); } /* @@ -531,7 +608,7 @@ Sends a remove breakpoint message to the debugger server */ void rvDebuggerClient::SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp ) { - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; if ( !mConnected ) @@ -539,11 +616,12 @@ void rvDebuggerClient::SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp ) return; } - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_REMOVEBREAKPOINT ); - MSG_WriteInt ( &msg, bp.GetID() ); + msg.Init ( buffer, sizeof( buffer ) ); + msg.BeginWriting( ); + msg.WriteShort ( (short)DBMSG_REMOVEBREAKPOINT ); + msg.WriteInt ( bp.GetID() ); - SendPacket ( msg.data, msg.cursize ); + SendPacket ( msg.GetData(), msg.GetSize() ); } /* diff --git a/neo/tools/debugger/DebuggerClient.h b/neo/tools/debugger/DebuggerClient.h index dfc67717..9d02da1c 100644 --- a/neo/tools/debugger/DebuggerClient.h +++ b/neo/tools/debugger/DebuggerClient.h @@ -28,6 +28,9 @@ If you have questions concerning this license or the applicable additional terms #ifndef DEBUGGERCLIENT_H_ #define DEBUGGERCLIENT_H_ +#include "DebuggerBreakpoint.h" +#include "idlib/containers/StrList.h" + class rvDebuggerCallstack { public: @@ -49,9 +52,6 @@ public: bool mDoneProcessing; }; -#ifndef DEBUGGERBREAKPOINT_H_ -#include "DebuggerBreakpoint.h" -#endif typedef idList rvDebuggerCallstackList; typedef idList rvDebuggerThreadList; @@ -75,12 +75,14 @@ public: int GetActiveBreakpointID ( void ); const char* GetBreakFilename ( void ); int GetBreakLineNumber ( void ); + idProgram* GetBreakProgram ( void ); rvDebuggerCallstackList& GetCallstack ( void ); rvDebuggerThreadList& GetThreads ( void ); const char* GetVariableValue ( const char* name, int stackDepth ); + idStrList& GetServerScripts ( void ); void InspectVariable ( const char* name, int callstackDepth ); - + void InspectScripts ( void ); void Break ( void ); void Resume ( void ); void StepInto ( void ); @@ -110,6 +112,7 @@ protected: int mBreakID; int mBreakLineNumber; idStr mBreakFilename; + idProgram* mBreakProgram; idDict mVariables; @@ -119,6 +122,8 @@ protected: EDebuggerMessage mWaitFor; + idStrList mServerScripts; + private: void ClearCallstack ( void ); @@ -127,10 +132,13 @@ private: void UpdateWatches ( void ); // Network message handlers - void HandleBreak ( msg_t* msg ); - void HandleInspectCallstack ( msg_t* msg ); - void HandleInspectThreads ( msg_t* msg ); - void HandleInspectVariable ( msg_t* msg ); + void HandleBreak ( idBitMsg* msg ); + void HandleInspectScripts ( idBitMsg* msg ); + void HandleInspectCallstack ( idBitMsg* msg ); + void HandleInspectThreads ( idBitMsg* msg ); + void HandleInspectVariable ( idBitMsg* msg ); + void HandleGameDLLHandle ( idBitMsg* msg ); + void HandleRemoveBreakpoint ( idBitMsg* msg ); }; /* @@ -183,6 +191,17 @@ ID_INLINE int rvDebuggerClient::GetBreakLineNumber ( void ) return mBreakLineNumber; } +/* +================ +rvDebuggerClient::GetBreakProgram +================ +*/ +ID_INLINE idProgram* rvDebuggerClient::GetBreakProgram(void) +{ + return mBreakProgram; +} + + /* ================ rvDebuggerClient::GetCallstack @@ -286,4 +305,14 @@ ID_INLINE void rvDebuggerClient::SendPacket ( void* data, int size ) mPort.SendPacket ( mServerAdr, data, size ); } + +/* +================ +rvDebuggerClient::GetServerScripts +================ +*/ +ID_INLINE idStrList& rvDebuggerClient::GetServerScripts( void ) +{ + return mServerScripts; +} #endif // DEBUGGERCLIENT_H_ diff --git a/neo/tools/debugger/DebuggerMessages.h b/neo/tools/debugger/DebuggerMessages.h index 6e0cba43..f5eff0cd 100644 --- a/neo/tools/debugger/DebuggerMessages.h +++ b/neo/tools/debugger/DebuggerMessages.h @@ -46,6 +46,7 @@ enum EDebuggerMessage DBMSG_INSPECTTHREADS, DBMSG_STEPOVER, DBMSG_STEPINTO, + DBMSG_INSPECTSCRIPTS }; #endif // DEBUGGER_MESSAGES_H_ \ No newline at end of file diff --git a/neo/tools/debugger/DebuggerScript.cpp b/neo/tools/debugger/DebuggerScript.cpp index fc15dfac..bea021d5 100644 --- a/neo/tools/debugger/DebuggerScript.cpp +++ b/neo/tools/debugger/DebuggerScript.cpp @@ -31,7 +31,6 @@ If you have questions concerning this license or the applicable additional terms #include "DebuggerApp.h" #include "DebuggerScript.h" -#include "../../game/script/Script_Program.h" #include "../../ui/Window.h" #include "../../ui/UserInterfaceLocal.h" @@ -57,6 +56,7 @@ rvDebuggerScript::~rvDebuggerScript ( void ) Unload ( ); } + /* ================ rvDebuggerScript::Unload @@ -72,10 +72,6 @@ void rvDebuggerScript::Unload ( void ) { delete mInterface; } - else - { - delete mProgram; - } mContents = NULL; mProgram = NULL; @@ -91,7 +87,7 @@ appropriate for the file being loaded. If the script cant be compiled the loading of the script fails ================ */ -bool rvDebuggerScript::Load ( const char* filename ) +bool rvDebuggerScript::Load ( const char* filename) { void* buffer; int size; @@ -116,60 +112,7 @@ bool rvDebuggerScript::Load ( const char* filename ) // Cleanup fileSystem->FreeFile ( buffer ); - - // Now compile the script so we can tell what a valid line is, etc.. If its - // a gui file then we need to parse it using the userinterface system rather - // than the normal script compiler. - try - { - // Parse the script using the script compiler - mProgram = new idProgram; - mProgram->BeginCompilation ( ); - mProgram->CompileFile ( SCRIPT_DEFAULT ); - - //BSM Nerve: Loads a game specific main script file - idStr gamedir = cvarSystem->GetCVarString( "fs_game" ); - if(gamedir.Length() > 0) { - - idStr scriptFile = va("script/%s_main.script", gamedir.c_str()); - if(fileSystem->ReadFile(scriptFile.c_str(), NULL) > 0) { - mProgram.CompileFile(scriptFile.c_str()); - } - - } - - // Make sure the file isnt already compiled before trying to compile it again - for ( int f = mProgram->NumFilenames() - 1; f >= 0; f -- ) - { - idStr qpath; - qpath = fileSystem->OSPathToRelativePath ( mProgram->GetFilename ( f ) ); - qpath.BackSlashesToSlashes ( ); - if ( !qpath.Cmp ( filename ) ) - { - break; - } - } - - if ( f < 0 ) - { - mProgram->CompileText ( filename, mContents, false ); - } - - mProgram->FinishCompilation ( ); - } - catch ( idException& ) - { - // Failed to parse the script so fail to load the file - delete mProgram; - mProgram = NULL; - delete[] mContents; - mContents = NULL; - - // TODO: Should cache the error for the dialog box - - return false; - } - + return true; } @@ -194,21 +137,8 @@ Determines whether or not the given line number within the script is a valid lin */ bool rvDebuggerScript::IsLineCode ( int linenumber ) { - int i; - - assert ( mProgram ); - - // Run through all the statements in the program and see if any match the - // linenumber that we are checking. - for ( i = 0; i < mProgram->NumStatements ( ); i ++ ) - { - if ( mProgram->GetStatement ( i ).linenumber == linenumber ) - { - return true; - } - } - - return false; + //we let server decide. + return true; } /* diff --git a/neo/tools/debugger/DebuggerScript.h b/neo/tools/debugger/DebuggerScript.h index d60086a3..ae090f8d 100644 --- a/neo/tools/debugger/DebuggerScript.h +++ b/neo/tools/debugger/DebuggerScript.h @@ -43,21 +43,22 @@ public: const char* GetFilename ( void ); const char* GetContents ( void ); - + idProgram* GetProgram ( void ); +#if 0// Test code idProgram& GetProgram ( void ); +#endif bool IsLineCode ( int linenumber ); bool IsFileModified ( bool updateTime = false ); protected: - void Unload ( void ); idProgram* mProgram; idUserInterfaceLocal* mInterface; char* mContents; idStr mFilename; - ID_TIME_T mModifiedTime; + ID_TIME_T mModifiedTime; }; ID_INLINE const char* rvDebuggerScript::GetFilename ( void ) @@ -70,9 +71,10 @@ ID_INLINE const char* rvDebuggerScript::GetContents ( void ) return mContents?mContents:""; } -ID_INLINE idProgram& rvDebuggerScript::GetProgram ( void ) +ID_INLINE idProgram* rvDebuggerScript::GetProgram ( void ) { - return *mProgram; + return mProgram; } + #endif // DEBUGGERSCRIPT_H_ \ No newline at end of file diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 9606b19a..b2711f59 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -28,14 +28,6 @@ If you have questions concerning this license or the applicable additional terms #include "tools/edit_gui_common.h" - -#include "../../game/gamesys/Event.h" -#include "../../game/gamesys/Class.h" -#include "../../game/script/Script_Program.h" -#include "../../game/script/Script_Interpreter.h" -#include "../../game/script/Script_Thread.h" -#include "../../game/script/Script_Compiler.h" -#include "../../framework/sync/Msg.h" #include "DebuggerApp.h" #include "DebuggerServer.h" @@ -144,15 +136,17 @@ Process all incoming network messages from the debugger client bool rvDebuggerServer::ProcessMessages ( void ) { netadr_t adrFrom; - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; - MSG_Init( &msg, buffer, sizeof( buffer ) ); - // Check for pending udp packets on the debugger port - while ( mPort.GetPacket ( adrFrom, msg.data, msg.cursize, msg.maxsize ) ) + int msgSize; + while ( mPort.GetPacket ( adrFrom, buffer, msgSize, MAX_MSGLEN) ) { - unsigned short command; + short command; + msg.Init(buffer, sizeof(buffer)); + msg.SetSize(msgSize); + msg.BeginReading(); // Only accept packets from the debugger server for security reasons if ( !Sys_CompareNetAdrBase ( adrFrom, mClientAdr ) ) @@ -160,23 +154,26 @@ bool rvDebuggerServer::ProcessMessages ( void ) continue; } - command = (unsigned short) MSG_ReadShort ( &msg ); + command = msg.ReadShort( ); switch ( command ) { case DBMSG_CONNECT: mConnected = true; SendMessage ( DBMSG_CONNECTED ); + break; case DBMSG_CONNECTED: mConnected = true; + com_editors |= EDITOR_DEBUGGER; break; case DBMSG_DISCONNECT: ClearBreakpoints ( ); Resume ( ); mConnected = false; + com_editors &= ~EDITOR_DEBUGGER; break; case DBMSG_ADDBREAKPOINT: @@ -188,7 +185,7 @@ bool rvDebuggerServer::ProcessMessages ( void ) break; case DBMSG_RESUME: - Resume ( ); + HandleResume ( &msg ); break; case DBMSG_BREAK: @@ -197,11 +194,11 @@ bool rvDebuggerServer::ProcessMessages ( void ) case DBMSG_STEPOVER: mBreakStepOver = true; - mBreakStepOverDepth = mBreakInterpreter->GetCallstackDepth ( ); - mBreakStepOverFunc1 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()].f; - if ( mBreakInterpreter->GetCallstackDepth() > 0 ) + mBreakStepOverDepth = gameEdit->GetInterpreterCallStackDepth(mBreakInterpreter); + mBreakStepOverFunc1 = gameEdit->GetInterpreterCallStackFunction(mBreakInterpreter); + if (mBreakStepOverDepth) { - mBreakStepOverFunc2 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()-1].f; + mBreakStepOverFunc2 = gameEdit->GetInterpreterCallStackFunction(mBreakInterpreter,mBreakStepOverDepth - 1); } else { @@ -226,6 +223,10 @@ bool rvDebuggerServer::ProcessMessages ( void ) case DBMSG_INSPECTTHREADS: HandleInspectThreads ( &msg ); break; + + case DBMSG_INSPECTSCRIPTS: + HandleInspectScripts( &msg ); + break; } } @@ -241,13 +242,14 @@ Send a message with no data to the debugger server. */ void rvDebuggerServer::SendMessage ( EDebuggerMessage dbmsg ) { - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)dbmsg ); + msg.Init( buffer, sizeof( buffer ) ); + msg.BeginWriting(); + msg.WriteShort ( (short)dbmsg ); - SendPacket ( msg.data, msg.cursize ); + SendPacket ( msg.GetData(), msg.GetSize() ); } /* @@ -255,11 +257,12 @@ void rvDebuggerServer::SendMessage ( EDebuggerMessage dbmsg ) rvDebuggerServer::HandleAddBreakpoint Handle the DBMSG_ADDBREAKPOINT message being sent by the debugger client. This -message is handled by adding a new breakpoint to the breakpoint list with the +message is handled by first checking if it is valid +and is added as a new breakpoint to the breakpoint list with the data supplied in the message. ================ */ -void rvDebuggerServer::HandleAddBreakpoint ( msg_t* msg ) +void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg ) { bool onceOnly = false; long lineNumber; @@ -267,14 +270,28 @@ void rvDebuggerServer::HandleAddBreakpoint ( msg_t* msg ) char filename[MAX_PATH]; // Read the breakpoint info - onceOnly = MSG_ReadBits ( msg, 1 ) ? true : false; - lineNumber = MSG_ReadInt ( msg ); - id = MSG_ReadInt ( msg ); + onceOnly = msg->ReadBits ( 1 ) ? true : false; + lineNumber = msg->ReadInt ( ); + id = msg->ReadInt ( ); + + msg->ReadString ( filename, MAX_PATH ); + + //check for statement on requested breakpoint location + if (!gameEdit->IsLineCode(filename, lineNumber)) + { + idBitMsg msgOut; + byte buffer[MAX_MSGLEN]; + + msgOut.Init(buffer, sizeof(buffer)); + msgOut.BeginWriting(); + msgOut.WriteShort((short)DBMSG_REMOVEBREAKPOINT); + msgOut.WriteInt(lineNumber); + msgOut.WriteString(filename); + SendPacket(msgOut.GetData(), msgOut.GetSize()); + return; + } - MSG_ReadString ( msg, filename, MAX_PATH ); - // Since breakpoints are used by both threads we need to - // protect them with a crit section EnterCriticalSection ( &mCriticalSection ); mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id ) ); LeaveCriticalSection ( &mCriticalSection ); @@ -289,13 +306,13 @@ message is handled by removing the breakpoint that matches the given id from the list. ================ */ -void rvDebuggerServer::HandleRemoveBreakpoint ( msg_t* msg ) +void rvDebuggerServer::HandleRemoveBreakpoint ( idBitMsg* msg ) { int i; int id; // ID that we are to remove - id = MSG_ReadInt ( msg ); + id = msg->ReadInt ( ); // Since breakpoints are used by both threads we need to // protect them with a crit section @@ -317,47 +334,16 @@ void rvDebuggerServer::HandleRemoveBreakpoint ( msg_t* msg ) /* ================ -rvDebuggerServer::MSG_WriteCallstackFunc +rvDebuggerServer::HandleResume -Writes a single callstack entry to the given message +Resume the game thread. ================ + */ -void rvDebuggerServer::MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack ) +void rvDebuggerServer::HandleResume(idBitMsg* msg) { - const statement_t* st; - const function_t* func; - - func = stack->f; - - // If the function is unknown then just fill in with default data. - if ( !func ) - { - MSG_WriteString ( msg, "" ); - MSG_WriteString ( msg, "" ); - MSG_WriteInt ( msg, 0 ); - return; - } - else - { - MSG_WriteString ( msg, va("%s( ??? )", func->Name() ) ); - } - - // Use the calling statement as the filename and linenumber where - // the call was made from - st = &mBreakProgram->GetStatement ( stack->s ); - if ( st ) - { - idStr qpath; - OSPathToRelativePath(mBreakProgram->GetFilename( st->file ), qpath); - qpath.BackSlashesToSlashes ( ); - MSG_WriteString ( msg, qpath ); - MSG_WriteInt ( msg, st->linenumber ); - } - else - { - MSG_WriteString ( msg, "" ); - MSG_WriteInt ( msg, 0 ); - } + //Empty msg + Resume(); } /* @@ -368,31 +354,18 @@ Handle an incoming inspect callstack message by sending a message back to the client with the callstack data. ================ */ -void rvDebuggerServer::HandleInspectCallstack ( msg_t* in_msg ) +void rvDebuggerServer::HandleInspectCallstack ( idBitMsg* msg ) { - msg_t msg; + idBitMsg msgOut; byte buffer[MAX_MSGLEN]; - int i; - prstack_t temp; - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_INSPECTCALLSTACK ); + msgOut.Init(buffer, sizeof( buffer ) ); + msgOut.BeginWriting(); + msgOut.WriteShort ( (short)DBMSG_INSPECTCALLSTACK ); - MSG_WriteShort ( &msg, (int)mBreakInterpreter->GetCallstackDepth ( ) ); + gameEdit->MSG_WriteInterpreterInfo(&msgOut, mBreakInterpreter, mBreakProgram, mBreakInstructionPointer); - // write out the current function - temp.f = mBreakInterpreter->GetCurrentFunction ( ); - temp.s = 0; - temp.stackbase = 0; - MSG_WriteCallstackFunc ( &msg, &temp ); - - // Run through all of the callstack and write each to the msg - for ( i = mBreakInterpreter->GetCallstackDepth ( ) - 1; i > 0; i -- ) - { - MSG_WriteCallstackFunc ( &msg, mBreakInterpreter->GetCallstack ( ) + i ); - } - - SendPacket ( msg.data, msg.cursize ); + SendPacket (msgOut.GetData(), msgOut.GetSize() ); } /* @@ -402,35 +375,51 @@ rvDebuggerServer::HandleInspectThreads Send the list of the current threads in the interpreter back to the debugger client ================ */ -void rvDebuggerServer::HandleInspectThreads ( msg_t* in_msg ) +void rvDebuggerServer::HandleInspectThreads ( idBitMsg* msg ) { - msg_t msg; - byte buffer[MAX_MSGLEN]; - int i; + idBitMsg msgOut; + byte buffer[MAX_MSGLEN]; + int i; // Initialize the message - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_INSPECTTHREADS ); + msgOut.Init( buffer, sizeof( buffer ) ); + msgOut.SetAllowOverflow(true); + msgOut.BeginWriting(); + msgOut.WriteShort ( (short)DBMSG_INSPECTTHREADS ); // Write the number of threads to the message - MSG_WriteShort ( &msg, (int)idThread::GetThreads().Num() ); + msgOut.WriteShort ((short)gameEdit->GetTotalScriptThreads() ); // Loop through all of the threads and write their name and number to the message - for ( i = 0; i < idThread::GetThreads().Num(); i ++ ) + for ( i = 0; i < gameEdit->GetTotalScriptThreads(); i ++ ) { - idThread* thread = idThread::GetThreads()[i]; - - MSG_WriteString ( &msg, thread->GetThreadName ( ) ); - MSG_WriteInt ( &msg, thread->GetThreadNum ( ) ); - - MSG_WriteBits ( &msg, (int)(thread == mBreakInterpreter->GetThread ( )), 1 ); - MSG_WriteBits ( &msg, (int)thread->IsDoneProcessing(), 1 ); - MSG_WriteBits ( &msg, (int)thread->IsWaiting(), 1 ); - MSG_WriteBits ( &msg, (int)thread->IsDying(), 1 ); + gameEdit->MSG_WriteThreadInfo(&msgOut,gameEdit->GetThreadByIndex(i), mBreakInterpreter); } // Send off the inspect threads packet to the debugger client - SendPacket ( msg.data, msg.cursize ); + SendPacket (msgOut.GetData(), msgOut.GetSize() ); +} + +/* +================ +rvDebuggerServer::HandleInspectScripts + +Send the list of the current loaded scripts in the interpreter back to the debugger client +================ +*/ +void rvDebuggerServer::HandleInspectScripts( idBitMsg* msg ) +{ + idBitMsg msgOut; + byte buffer[MAX_MSGLEN]; + + // Initialize the message + msgOut.Init(buffer, sizeof(buffer)); + msgOut.BeginWriting(); + msgOut.WriteShort((short)DBMSG_INSPECTSCRIPTS); + + gameEdit->MSG_WriteScriptList( &msgOut ); + + SendPacket(msgOut.GetData(), msgOut.GetSize()); } /* @@ -440,7 +429,7 @@ rvDebuggerServer::HandleInspectVariable Respondes to a request from the debugger client to inspect the value of a given variable ================ */ -void rvDebuggerServer::HandleInspectVariable ( msg_t* in_msg ) +void rvDebuggerServer::HandleInspectVariable ( idBitMsg* msg ) { char varname[256]; int scopeDepth; @@ -450,28 +439,29 @@ void rvDebuggerServer::HandleInspectVariable ( msg_t* in_msg ) return; } - scopeDepth = (short)MSG_ReadShort ( in_msg ); - MSG_ReadString ( in_msg, varname, 256 ); + scopeDepth = (short)msg->ReadShort ( ); + msg->ReadString ( varname, 256 ); idStr varvalue; - msg_t msg; + idBitMsg msgOut; byte buffer[MAX_MSGLEN]; // Initialize the message - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_INSPECTVARIABLE ); + msgOut.Init( buffer, sizeof( buffer ) ); + msgOut.BeginWriting(); + msgOut.WriteShort ( (short)DBMSG_INSPECTVARIABLE ); - if ( !mBreakInterpreter->GetRegisterValue ( varname, varvalue, scopeDepth ) ) + if (!gameEdit->GetRegisterValue(mBreakInterpreter, varname, varvalue, scopeDepth ) ) { varvalue = "???"; } - MSG_WriteShort ( &msg, (short)scopeDepth ); - MSG_WriteString ( &msg, varname ); - MSG_WriteString ( &msg, varvalue ); + msgOut.WriteShort ( (short)scopeDepth ); + msgOut.WriteString ( varname ); + msgOut.WriteString ( varvalue ); - SendPacket ( msg.data, msg.cursize ); + SendPacket (msgOut.GetData(), msgOut.GetSize() ); } /* @@ -484,7 +474,6 @@ Check to see if any breakpoints have been hit. This includes "break next", */ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer ) { - const statement_t* st; const char* filename; int i; @@ -492,23 +481,24 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* return; } + // Grab the current statement and the filename that it came from - st = &program->GetStatement ( instructionPointer ); - filename = program->GetFilename ( st->file ); + filename = gameEdit->GetFilenameForStatement(program, instructionPointer); + int linenumber = gameEdit->GetLineNumberForStatement(program, instructionPointer); // Operate on lines, not statements - if ( mLastStatementLine == st->linenumber && mLastStatementFile == st->file ) + if ( mLastStatementLine == linenumber && mLastStatementFile == filename) { return; } - + // Save the last visited line and file so we can prevent // double breaks on lines with more than one statement - mLastStatementFile = idStr( st->file ); - mLastStatementLine = st->linenumber; + mLastStatementFile = idStr(filename); + mLastStatementLine = linenumber; // Reset stepping when the last function on the callstack is returned from - if ( st->op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 ) + if (gameEdit->ReturnedFromFunction(program, interpreter,instructionPointer)) { mBreakStepOver = false; mBreakStepInto = false; @@ -517,6 +507,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* // See if we are supposed to break on the next script line if ( mBreakNext ) { + HandleInspectScripts(nullptr); Break ( interpreter, program, instructionPointer ); return; } @@ -524,9 +515,8 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* // Only break on the same callstack depth and thread as the break over if ( mBreakStepOver ) { - if ( ( interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc1 || - interpreter->GetCurrentFunction ( ) == mBreakStepOverFunc2 )&& - ( interpreter->GetCallstackDepth ( ) <= mBreakStepOverDepth ) ) + //virtual bool CheckForBreakpointHit(interpreter,function1,function2,depth) + if (gameEdit->CheckForBreakPointHit(interpreter, mBreakStepOverFunc1, mBreakStepOverFunc2, mBreakStepOverDepth)) { Break ( interpreter, program, instructionPointer ); return; @@ -536,6 +526,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* // See if we are supposed to break on the next line if ( mBreakStepInto ) { + HandleInspectScripts(nullptr); // Break Break ( interpreter, program, instructionPointer ); return; @@ -553,13 +544,13 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* rvDebuggerBreakpoint* bp = mBreakpoints[i]; // Skip if not match of the line number - if ( st->linenumber != bp->GetLineNumber ( ) ) + if ( linenumber != bp->GetLineNumber ( ) ) { continue; } // Skip if no match of the filename - if ( idStr::Icmp ( bp->GetFilename(), qpath ) ) + if ( idStr::Icmp ( bp->GetFilename(), qpath.c_str() ) ) { continue; } @@ -567,6 +558,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* // Pop out of the critical section so we dont get stuck LeaveCriticalSection ( &mCriticalSection ); + HandleInspectScripts(nullptr); // We hit a breakpoint, so break Break ( interpreter, program, instructionPointer ); @@ -589,9 +581,8 @@ the game has been halted */ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer ) { - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; - const statement_t* st; const char* filename; // Clear all the break types @@ -600,12 +591,10 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i mBreakNext = false; // Grab the current statement and the filename that it came from - st = &program->GetStatement ( instructionPointer ); - filename = program->GetFilename ( st->file ); - - idStr qpath; - OSPathToRelativePath(filename, qpath); - qpath.BackSlashesToSlashes ( ); + filename = gameEdit->GetFilenameForStatement(program,instructionPointer); + int linenumber = gameEdit->GetLineNumberForStatement(program, instructionPointer); + idStr fileStr = filename; + fileStr.BackSlashesToSlashes(); // Give the mouse cursor back to the world Sys_GrabMouseCursor( false ); @@ -617,11 +606,13 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i mBreakInstructionPointer = instructionPointer; // Inform the debugger of the breakpoint hit - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_BREAK ); - MSG_WriteInt ( &msg, st->linenumber ); - MSG_WriteString ( &msg, qpath ); - SendPacket ( msg.data, msg.cursize ); + msg.Init( buffer, sizeof( buffer ) ); + msg.BeginWriting(); + msg.WriteShort ( (short)DBMSG_BREAK ); + msg.WriteInt ( linenumber ); + msg.WriteString ( fileStr.c_str() ); + msg.WriteInt( (int)mBreakProgram ); + SendPacket ( msg.GetData(), msg.GetSize() ); // Suspend the game thread. Since this will be called from within the main game thread // execution wont return until after the thread is resumed @@ -642,6 +633,7 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i SetFocus ( win32.hWnd ); // Give the mouse cursor back to the game + // HVG_Note : there be dragons here. somewhere. Sys_GrabMouseCursor( true ); // Clear all commands that were generated before we went into suspended mode. This is @@ -703,12 +695,13 @@ void rvDebuggerServer::Print ( const char* text ) return; } - msg_t msg; + idBitMsg msg; byte buffer[MAX_MSGLEN]; - MSG_Init( &msg, buffer, sizeof( buffer ) ); - MSG_WriteShort ( &msg, (int)DBMSG_PRINT ); - MSG_WriteString ( &msg, text ); + msg.Init( buffer, sizeof( buffer ) ); + msg.BeginWriting(); + msg.WriteShort ( (short)DBMSG_PRINT ); + msg.WriteString ( text ); - SendPacket ( msg.data, msg.cursize ); + SendPacket ( msg.GetData(), msg.GetSize() ); } diff --git a/neo/tools/debugger/DebuggerServer.h b/neo/tools/debugger/DebuggerServer.h index 04b9782d..0473b9ed 100644 --- a/neo/tools/debugger/DebuggerServer.h +++ b/neo/tools/debugger/DebuggerServer.h @@ -28,20 +28,15 @@ If you have questions concerning this license or the applicable additional terms #ifndef DEBUGGERSERVER_H_ #define DEBUGGERSERVER_H_ -#ifndef DEBUGGERMESSAGES_H_ + #include "DebuggerMessages.h" -#endif - -#ifndef DEBUGGERBREAKPOINT_H_ #include "DebuggerBreakpoint.h" -#endif +#include "framework/Game.h" -#ifndef __GAME_LOCAL_H__ -#include "../../game/Game.h" -#endif -class idInterpreter; -class idProgram; + +class function_t; +typedef struct prstack_s prstack_t; class rvDebuggerServer { @@ -50,22 +45,40 @@ public: rvDebuggerServer ( ); ~rvDebuggerServer ( ); - bool Initialize ( void ); - void Shutdown ( void ); + bool Initialize ( void ); + void Shutdown ( void ); - bool ProcessMessages ( void ); + bool ProcessMessages ( void ); - bool IsConnected ( void ); + bool IsConnected ( void ); - void CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer ); + void CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer ); - void Print ( const char* text ); + void Print ( const char* text ); - void OSPathToRelativePath( const char *osPath, idStr &qpath ); + void OSPathToRelativePath ( const char *osPath, idStr &qpath ); -protected: + bool GameSuspended ( void ); +private: + + void ClearBreakpoints ( void ); + + void Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer ); + void Resume ( void ); + + void SendMessage ( EDebuggerMessage dbmsg ); + void SendPacket ( void* data, int datasize ); + + // Message handlers + void HandleAddBreakpoint ( idBitMsg * msg ); + void HandleRemoveBreakpoint ( idBitMsg * msg ); + void HandleResume ( idBitMsg * msg ); + void HandleInspectVariable ( idBitMsg * msg ); + void HandleInspectCallstack ( idBitMsg * msg ); + void HandleInspectThreads ( idBitMsg * msg ); + void HandleInspectScripts ( idBitMsg * msg ); + //// - // protected member variables bool mConnected; netadr_t mClientAdr; idPort mPort; @@ -87,27 +100,9 @@ protected: idStr mLastStatementFile; int mLastStatementLine; + uintptr_t mGameDLLHandle; + idStrList mScriptFileList; -private: - - void ClearBreakpoints ( void ); - - void Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer ); - void Resume ( void ); - - void SendMessage ( EDebuggerMessage dbmsg ); - void SendPacket ( void* data, int datasize ); - - // Message handlers - void HandleAddBreakpoint ( msg_t* msg ); - void HandleRemoveBreakpoint ( msg_t* msg ); - void HandleResume ( msg_t* msg ); - void HandleInspectVariable ( msg_t* msg ); - void HandleInspectCallstack ( msg_t* msg ); - void HandleInspectThreads ( msg_t* msg ); - - // MSG helper routines - void MSG_WriteCallstackFunc ( msg_t* msg, const prstack_t* stack ); }; /* @@ -130,4 +125,14 @@ ID_INLINE void rvDebuggerServer::SendPacket ( void* data, int size ) mPort.SendPacket ( mClientAdr, data, size ); } +/* +================ +rvDebuggerServer::GameSuspended +================ +*/ +ID_INLINE bool rvDebuggerServer::GameSuspended( void ) +{ + return mBreak; +} + #endif // DEBUGGERSERVER_H_ diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index fbf33e79..ca0b95c3 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -35,7 +35,7 @@ If you have questions concerning this license or the applicable additional terms #include "DebuggerQuickWatchDlg.h" #include "DebuggerFindDlg.h" -#define DEBUGGERWINDOWCLASS "QUAKE4_DEBUGGER_WINDOW" +#define DEBUGGERWINDOWCLASS "DHEWM3_DEBUGGER_WINDOW" #define ID_DBG_WINDOWMIN 18900 #define ID_DBG_WINDOWMAX 19900 @@ -49,6 +49,7 @@ If you have questions concerning this license or the applicable additional terms #define IDC_DBG_WATCH 31007 #define IDC_DBG_THREADS 31008 #define IDC_DBG_TOOLBAR 31009 +#define IDC_DBG_SCRIPTLIST 31010 #define ID_DBG_FILE_MRU1 10000 @@ -167,7 +168,7 @@ bool rvDebuggerWindow::Create ( HINSTANCE instance ) UpdateTitle ( ); - Printf ( "Quake 4 Script Debugger v0.1\n\n" ); + Printf ( "Dhewm3 Script Debugger v1.0\n\n" ); ShowWindow ( mWnd, SW_SHOW ); UpdateWindow ( mWnd ); @@ -347,6 +348,20 @@ LRESULT CALLBACK rvDebuggerWindow::ScriptWndProc ( HWND wnd, UINT msg, WPARAM wp break; } + case WM_SIZE: + { + float scaling_factor = Win_GetWindowScalingFactor(wnd); + int s18 = int(18 * scaling_factor); + int s10 = int(10 * scaling_factor); + + RECT rect; + window->mMarginSize = window->mZoomScaleDem ? ((long)(s18 * (float)window->mZoomScaleNum / (float)window->mZoomScaleDem)) : s18; + + GetWindowRect(window->mWndToolbar, &rect); + MoveWindow(window->mWndMargin, 0, 0, window->mMarginSize, window->mSplitterRect.top - (rect.bottom - rect.top), TRUE); + SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + + } } return CallWindowProc ( wndproc, wnd, msg, wparam, lparam ); @@ -384,14 +399,20 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp case WM_PAINT: { HDC dc; + float scaling_factor = Win_GetWindowScalingFactor(wnd); + int s2 = int(2 * scaling_factor); + int s4 = int(4 * scaling_factor); + int s22 = int(22 * scaling_factor); + int width,height; - int size = window->mMarginSize - 2; + window->ResizeImageList(width,height); PAINTSTRUCT ps; RECT rect; GetClientRect ( wnd, &rect ); + dc = BeginPaint ( wnd, &ps ); - FillRect ( dc, &rect, GetSysColorBrush ( COLOR_3DFACE ) ); + FillRect ( dc, &rect, GetSysColorBrush ( COLOR_3DSHADOW ) ); if ( window->mScripts.Num ( ) ) { @@ -407,7 +428,7 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp c = SendMessage ( window->mWndScript, EM_LINEINDEX, bp->GetLineNumber ( ) - 1, 0 ); SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c ); - ImageList_DrawEx ( window->mImageList, 2, dc, rect.left, pos.y, size, size, CLR_NONE, CLR_NONE, ILD_NORMAL ); + ImageList_DrawEx ( window->mTmpImageList, 2, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL ); } } @@ -421,7 +442,7 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp c = SendMessage ( window->mWndScript, EM_LINEINDEX, window->mClient->GetBreakLineNumber() - 1, 0 ); SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c ); - ImageList_DrawEx ( window->mImageList, 3, dc, rect.left, pos.y, size, size, CLR_NONE, CLR_NONE, ILD_NORMAL ); + ImageList_DrawEx ( window->mTmpImageList, 3, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL ); } } @@ -434,17 +455,19 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp c = SendMessage ( window->mWndScript, EM_LINEINDEX, window->mClient->GetCallstack()[window->mCurrentStackDepth]->mLineNumber - 1, 0 ); SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c ); - ImageList_DrawEx ( window->mImageList, 1, dc, rect.left, pos.y, size, size, CLR_NONE, CLR_NONE, ILD_NORMAL ); + ImageList_DrawEx ( window->mTmpImageList, 1, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL ); } } } + RECT tmp = rect; - rect.right-=2; - rect.left = rect.right + 1; - HPEN pen = CreatePen ( PS_SOLID, 1, GetSysColor ( COLOR_3DSHADOW ) ); + rect.right -= s2; + rect.left = rect.right + s2; + HPEN pen = CreatePen ( PS_SOLID, s2, GetSysColor ( COLOR_BACKGROUND ) ); HPEN old = (HPEN)SelectObject ( dc, pen ); MoveToEx ( dc, rect.right, rect.top, NULL ); LineTo ( dc, rect.right, rect.bottom ); + SelectObject ( dc, old ); DeleteObject ( pen ); EndPaint ( wnd, &ps ); @@ -466,7 +489,7 @@ void rvDebuggerWindow::UpdateTitle ( void ) { idStr title; - title = "Quake 4 Script Debugger - "; + title = "Dhewm3 Script Debugger - "; if ( mClient->IsConnected ( ) ) { @@ -487,7 +510,10 @@ void rvDebuggerWindow::UpdateTitle ( void ) if ( mScripts.Num ( ) ) { title += " - ["; - title += idStr( mScripts[mActiveScript]->GetFilename() ).StripPath ( ); + if (mActiveScript != -1) + title += idStr( mScripts[mActiveScript]->GetFilename() ).StripPath ( ); + else + title += "Load Error"; title += "]"; } @@ -590,6 +616,33 @@ void rvDebuggerWindow::UpdateCallstack ( void ) } } +void rvDebuggerWindow::UpdateScriptList(void) +{ + LVITEM item; + ListView_DeleteAllItems(mWndScriptList); + ZeroMemory(&item, sizeof(item)); + item.mask = LVIF_TEXT | LVIF_IMAGE; + + idStrList& scripts = mClient->GetServerScripts(); + for (int i = 0; i < scripts.Num(); i++) + { + item.iItem = ListView_GetItemCount(mWndScriptList); + item.pszText = ""; + //find in activeScripts + item.iImage = 0; + for (int j = 0; j < mScripts.Num(); j++) + { + if (!idStr::Icmp(mScripts[j]->GetFilename(), scripts[i])) + { + item.iImage = 1; + break; + } + } + ListView_InsertItem(mWndScriptList, &item); + ListView_SetItemText(mWndScriptList, item.iItem, 1, (LPSTR)scripts[i].c_str()); + } +} + /* ================ rvDebuggerWindow::UpdateWatch @@ -737,6 +790,32 @@ int rvDebuggerWindow::HandleInitMenu ( WPARAM wParam, LPARAM lParam ) return 0; } + +void rvDebuggerWindow::ResizeImageList(int& widthOut, int& heightOut) +{ + //mTmpImageList + float scaling_factor = Win_GetWindowScalingFactor(mWnd); + int s16 = int(16 * scaling_factor); + + TEXTMETRIC tm; + HDC dc; + dc = GetDC(mWndScript); + + GetTextMetrics(dc, &tm); + int height = mZoomScaleDem ? (tm.tmHeight * (float)mZoomScaleNum / (float)mZoomScaleDem) : 16; + int width = mZoomScaleDem ? (s16 * (float)mZoomScaleNum / (float)mZoomScaleDem) : 16; + + ImageList_Destroy(mTmpImageList); + mTmpImageList = ImageList_Create(width, height, ILC_COLOR | ILC_MASK , 0, 2); + ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_EMPTY), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR)); + ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENT), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR)); + ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_BREAKPOINT), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR)); + ImageList_AddIcon(mTmpImageList, (HICON)LoadImage(mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENTLINE), IMAGE_ICON, width, height, LR_DEFAULTSIZE | LR_DEFAULTCOLOR)); + + widthOut = width; + heightOut = height; +} + /* ================ rvDebuggerWindow::HandleCreate @@ -760,7 +839,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) // Create the script window LoadLibrary ( "Riched20.dll" ); mWndScript = CreateWindow ( "RichEdit20A", "", WS_CHILD|WS_BORDER|ES_NOHIDESEL|ES_READONLY|ES_MULTILINE|ES_WANTRETURN|ES_AUTOVSCROLL|ES_AUTOHSCROLL|WS_VSCROLL|WS_HSCROLL, 0, 0, 100, 100, mWnd, (HMENU) IDC_DBG_SCRIPT, mInstance, 0 ); - SendMessage ( mWndScript, EM_SETEVENTMASK, 0, ENM_SCROLL|ENM_CHANGE ); + SendMessage ( mWndScript, EM_SETEVENTMASK, 0, ENM_SCROLL | ENM_CHANGE | ENM_UPDATE | ENM_SCROLLEVENTS | ENM_REQUESTRESIZE) ; SendMessage ( mWndScript, EM_SETWORDBREAKPROC, 0, (LPARAM) ScriptWordBreakProc ); mOldScriptProc = (WNDPROC)GetWindowLong ( mWndScript, GWL_WNDPROC ); SetWindowLong ( mWndScript, GWL_USERDATA, (LONG)this ); @@ -782,6 +861,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) SendMessage ( mWndOutput, WM_SETFONT, (WPARAM)CreateFontIndirect ( &lf ), 0 ); SendMessage ( mWndOutput, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(18,10) ); SendMessage ( mWndOutput, EM_SETBKGNDCOLOR, 0, GetSysColor ( COLOR_3DFACE ) ); + SendMessage ( mWndOutput, EM_SETEVENTMASK, 0, ENM_SCROLL | ENM_CHANGE | ENM_UPDATE | ENM_SCROLLEVENTS); mWndConsole = CreateWindow ( "RichEdit20A", "", WS_CHILD|ES_READONLY|ES_MULTILINE|ES_WANTRETURN|ES_AUTOVSCROLL|ES_AUTOHSCROLL|WS_VSCROLL|WS_HSCROLL, 0, 0, 100, 100, mWnd, (HMENU) IDC_DBG_CONSOLE, mInstance, 0 ); SendMessage ( mWndConsole, WM_SETFONT, (WPARAM)CreateFontIndirect ( &lf ), 0 ); @@ -816,13 +896,24 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) TabCtrl_InsertItem ( mWndTabs, 3, &item ); item.pszText = "Threads"; TabCtrl_InsertItem ( mWndTabs, 4, &item ); + item.pszText = "Scripts"; + TabCtrl_InsertItem ( mWndTabs, 5, &item ); mWndCallstack = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_CALLSTACK, mInstance, NULL ); mWndWatch = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_EDITLABELS|LVS_OWNERDRAWFIXED, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_WATCH, mInstance, NULL ); mWndThreads = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_THREADS, mInstance, NULL ); + mWndScriptList = CreateWindow( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_SCRIPTLIST, mInstance, NULL ); LVCOLUMN col; col.mask = LVCF_WIDTH|LVCF_TEXT; + + col.cx = 20; + col.pszText = ""; + ListView_InsertColumn ( mWndScriptList, 0, &col); + col.cx = 150; + col.pszText = "Filename"; + ListView_InsertColumn ( mWndScriptList, 1, &col ); + col.cx = 20; col.pszText = ""; ListView_InsertColumn ( mWndCallstack, 0, &col ); @@ -863,13 +954,19 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) ImageList_AddIcon ( mImageList, (HICON)LoadImage ( mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENT), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE|LR_DEFAULTCOLOR) ); ImageList_AddIcon ( mImageList, (HICON)LoadImage ( mInstance, MAKEINTRESOURCE(IDI_DBG_BREAKPOINT), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE|LR_DEFAULTCOLOR) ); ImageList_AddIcon ( mImageList, (HICON)LoadImage ( mInstance, MAKEINTRESOURCE(IDI_DBG_CURRENTLINE), IMAGE_ICON, 16, 16, LR_DEFAULTSIZE|LR_DEFAULTCOLOR) ); + + int w, h; + ResizeImageList(w, h); + ListView_SetImageList ( mWndScriptList, mTmpImageList, LVSIL_SMALL ); ListView_SetImageList ( mWndThreads, mImageList, LVSIL_SMALL ); ListView_SetImageList ( mWndCallstack, mImageList, LVSIL_SMALL ); EnableWindows ( FALSE ); - + EnableWindow ( mWndScriptList, true ); + ListView_SetExtendedListViewStyle ( mWndCallstack, LVS_EX_FULLROWSELECT ); ListView_SetExtendedListViewStyle ( mWndThreads, LVS_EX_FULLROWSELECT ); + ListView_SetExtendedListViewStyle ( mWndScriptList, LVS_EX_FULLROWSELECT ); gDebuggerApp.GetOptions().GetColumnWidths ( "cw_callstack", mWndCallstack ); gDebuggerApp.GetOptions().GetColumnWidths ( "cw_threads", mWndThreads ); @@ -920,6 +1017,10 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) AddWatch ( s ); } + RECT t; + GetClientRect(mWndScript, &t); + SendMessage(mWndScript, WM_SIZE, 0, MAKELPARAM(t.right - t.left, t.bottom - t.top)); + return 0; } @@ -1055,7 +1156,7 @@ int rvDebuggerWindow::HandleCommand ( WPARAM wparam, LPARAM lparam ) mZoomScaleNum = num; mZoomScaleDem = dem; GetClientRect ( mWndScript, &t ); - SendMessage ( mWnd, WM_SIZE, 0, MAKELPARAM(t.right-t.left,t.bottom-t.top) ); + SendMessage ( mWndScript, WM_SIZE, 0, MAKELPARAM(t.right-t.left ,t.bottom-t.top) ); } else { @@ -1202,8 +1303,13 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, case WM_SIZE: { + float scaling_factor = Win_GetWindowScalingFactor(wnd); + int s18 = int(18 * scaling_factor); + int s4 = int(4 * scaling_factor); + int s10 = int(10 * scaling_factor); + RECT rect; - window->mMarginSize = window->mZoomScaleDem ? ((long)(18.0f * (float)window->mZoomScaleNum / (float)window->mZoomScaleDem)):18; + window->mMarginSize = window->mZoomScaleDem ? ((long)(s18 * (float)window->mZoomScaleNum / (float)window->mZoomScaleDem)): s18; window->mSplitterRect.left = 0; window->mSplitterRect.right = LOWORD(lparam); @@ -1215,7 +1321,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, SetRect ( &rect, 0, window->mSplitterRect.bottom, LOWORD(lparam), HIWORD(lparam) ); MoveWindow ( window->mWndTabs, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); SendMessage ( window->mWndTabs, TCM_ADJUSTRECT, FALSE, (LPARAM)&rect ); - rect.bottom -= 4 ; + rect.bottom -= s4; MoveWindow ( window->mWndBorder, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); InflateRect ( &rect, -1, -1 ); MoveWindow ( window->mWndOutput, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); @@ -1223,6 +1329,13 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, MoveWindow ( window->mWndCallstack, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndWatch, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndThreads, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); + MoveWindow ( window->mWndScriptList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); + + SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + SendMessage(window->mWndCallstack, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + SendMessage(window->mWndOutput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + SendMessage(window->mWndConsole, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + break; } @@ -1258,7 +1371,17 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, } break; } + case WM_MOUSEWHEEL: + { + HDC dc = GetDC(wnd); + DrawFocusRect(dc, &window->mSplitterRect); + ReleaseDC(wnd, dc); + RECT client; + GetClientRect(wnd, &client); + SendMessage(wnd, WM_SIZE, 0, MAKELPARAM(client.right - client.left, client.bottom - client.top)); + + } case WM_LBUTTONUP: if ( window->mSplitterDrag ) { @@ -1454,6 +1577,31 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, } } break; + case IDC_DBG_SCRIPTLIST: + if ( hdr->code == NM_DBLCLK ) + { + int sel = ListView_GetNextItem(hdr->hwndFrom, -1, LVNI_SELECTED); + + if (sel != -1) + { + LVITEM item = { 0 }; + char temp[1024] = { 0 }; + item.mask = LVIF_TEXT; + item.pszText = temp; + item.cchTextMax = sizeof(temp) - 1; + item.iSubItem = 1; + item.iItem = sel; + + ListView_GetItem(hdr->hwndFrom, &item); + + if (strlen(item.pszText) > 0) + { + window->OpenScript(item.pszText); + window->UpdateScriptList(); + } + } + } + break; case IDC_DBG_TABS: if ( hdr->code == TCN_SELCHANGE ) { @@ -1462,6 +1610,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, ShowWindow ( window->mWndCallstack, SW_HIDE ); ShowWindow ( window->mWndWatch, SW_HIDE ); ShowWindow ( window->mWndThreads, SW_HIDE ); + ShowWindow ( window->mWndScriptList, SW_HIDE ); switch ( TabCtrl_GetCurSel ( hdr->hwndFrom ) ) { case 0: @@ -1483,6 +1632,9 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, case 4: ShowWindow ( window->mWndThreads, SW_SHOW ); break; + case 5: + ShowWindow(window->mWndScriptList, SW_SHOW); + break; } } break; @@ -1535,14 +1687,19 @@ rvDebuggerWindow::ProcessNetMessage Process an incoming network message ================ */ -void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg ) +void rvDebuggerWindow::ProcessNetMessage ( idBitMsg* msg ) { - unsigned short command; + short command; - command = (unsigned short)MSG_ReadShort ( msg ); + command = msg->ReadShort( ); switch ( command ) { + case DBMSG_REMOVEBREAKPOINT: + MessageBeep(MB_ICONEXCLAMATION); + InvalidateRect(mWndScript, NULL, FALSE); + break; + case DBMSG_RESUMED: UpdateTitle ( ); UpdateToolbar ( ); @@ -1554,9 +1711,9 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg ) char temp2[1024]; int i; - MSG_ReadShort ( msg ); - MSG_ReadString ( msg, temp, 1024 ); - MSG_ReadString ( msg, temp2, 1024 ); + msg->ReadShort ( ); + msg->ReadString ( temp, 1024 ); + msg->ReadString ( temp2, 1024 ); if ( mTooltipVar.Icmp ( temp ) == 0 ) { mTooltipValue = temp2; @@ -1625,7 +1782,7 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg ) case DBMSG_PRINT: SendMessage ( mWndConsole, EM_SETSEL, -1, -1 ); - SendMessage ( mWndConsole, EM_REPLACESEL, 0, (LPARAM)(const char*)(msg->data) + msg->readcount ); + SendMessage ( mWndConsole, EM_REPLACESEL, 0, (LPARAM)(const char*)(msg->GetData()) + msg->GetReadCount() ); SendMessage ( mWndConsole, EM_SCROLLCARET, 0, 0 ); break; @@ -1637,13 +1794,17 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg ) mClient->InspectVariable ( mTooltipVar, mCurrentStackDepth ); UpdateWatch ( ); EnableWindows ( TRUE ); - OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1 ); + OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1, mClient->GetBreakProgram()); UpdateTitle ( ); UpdateToolbar ( ); SetForegroundWindow ( mWnd ); break; } - + case DBMSG_INSPECTSCRIPTS: + { + UpdateScriptList ( ); + break; + } case DBMSG_INSPECTCALLSTACK: { UpdateCallstack ( ); @@ -1719,7 +1880,7 @@ Opens the script with the given filename and will scroll to the given line number if one is specified ================ */ -bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber ) +bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber, idProgram* program ) { int i; @@ -1748,7 +1909,6 @@ bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber ) // Load the script if ( !script->Load ( filename ) ) { - delete script; SetCursor ( LoadCursor ( NULL, IDC_ARROW ) ); return false; } @@ -1777,7 +1937,7 @@ bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber ) // Move to a specific line number? if ( lineNumber != -1 ) { - int c; + long c; // Put the caret on the line number specified and scroll it into position. // This is a bit of a hack since we set the selection twice, but setting the @@ -1785,10 +1945,10 @@ bool rvDebuggerWindow::OpenScript ( const char* filename, int lineNumber ) // and then scroll before going back to (c,c). // NOTE: We scroll to the line before the one we want so its more visible SetFocus ( mWndScript ); - c = SendMessage ( mWndScript, EM_LINEINDEX, lineNumber - 1, 0 ); + c = SendMessage ( mWndScript, EM_LINEINDEX, (long)lineNumber - 1, 0 ); SendMessage ( mWndScript, EM_SETSEL, c, c + 1 ); SendMessage ( mWndScript, EM_SCROLLCARET, 0, 0 ); - c = SendMessage ( mWndScript, EM_LINEINDEX, lineNumber, 0 ); + c = SendMessage ( mWndScript, EM_LINEINDEX, (long)lineNumber, 0 ); SendMessage ( mWndScript, EM_SETSEL, c, c ); } else @@ -2193,7 +2353,7 @@ then the last text used will be searched for. */ bool rvDebuggerWindow::FindNext ( const char* text ) { - int start; + long start; FINDTEXT ft; if ( text ) @@ -2230,7 +2390,7 @@ bool rvDebuggerWindow::FindNext ( const char* text ) } } - SendMessage ( mWndScript, EM_SETSEL, start, start + mFind.Length() ); + SendMessage ( mWndScript, EM_SETSEL, start, start + (long)mFind.Length() ); SendMessage ( mWndScript, EM_SCROLLCARET, 0, 0 ); return true; @@ -2247,7 +2407,7 @@ then the last text used will be searched for. */ bool rvDebuggerWindow::FindPrev ( const char* text ) { - int start; + long start; FINDTEXT ft; if ( text ) diff --git a/neo/tools/debugger/DebuggerWindow.h b/neo/tools/debugger/DebuggerWindow.h index d1e57476..cc86fe9d 100644 --- a/neo/tools/debugger/DebuggerWindow.h +++ b/neo/tools/debugger/DebuggerWindow.h @@ -52,38 +52,56 @@ public: rvDebuggerWindow ( ); ~rvDebuggerWindow ( ); - bool Create ( HINSTANCE hInstance ); + bool Create ( HINSTANCE hInstance ); - static bool Activate ( void ); + static bool Activate ( void ); - void ProcessNetMessage ( msg_t* msg ); + void ProcessNetMessage ( idBitMsg * msg ); - void Printf ( const char* format, ... ); + void Printf ( const char* format, ... ); - HWND GetWindow ( void ); + HWND GetWindow ( void ); - void AddWatch ( const char* name, bool update = true ); + void AddWatch ( const char* name, bool update = true ); - HINSTANCE GetInstance ( void ); + HINSTANCE GetInstance ( void ); -protected: +private: + bool RegisterClass ( void ); + void CreateToolbar ( void ); + bool InitRecentFiles ( void ); - bool FindPrev ( const char* text = NULL ); - bool FindNext ( const char* text = NULL ); + int HandleInitMenu ( WPARAM wParam, LPARAM lParam ); + int HandleCommand ( WPARAM wParam, LPARAM lParam ); + int HandleCreate ( WPARAM wparam, LPARAM lparam ); + int HandleActivate ( WPARAM wparam, LPARAM lparam ); + int HandleDrawItem ( WPARAM wparam, LPARAM lparam ); + void HandleTooltipGetDispInfo( WPARAM wparam, LPARAM lparam ); - void UpdateWatch ( void ); - void UpdateWindowMenu ( void ); - void UpdateScript ( void ); - void UpdateToolbar ( void ); - void UpdateTitle ( void ); - void UpdateCallstack ( void ); - void UpdateRecentFiles ( void ); - bool OpenScript ( const char* filename, int lineNumber = -1 ); - void EnableWindows ( bool state ); + void ResizeImageList ( int& widthOut, int& heightOut); + static LRESULT CALLBACK WndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); + static LRESULT CALLBACK MarginWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); + static LRESULT CALLBACK ScriptWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); + static INT_PTR CALLBACK AboutDlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); + static int CALLBACK ScriptWordBreakProc( LPTSTR text, int current, int max, int action ); - int GetSelectedText ( idStr& text ); + bool FindPrev ( const char* text = NULL ); + bool FindNext ( const char* text = NULL ); - void ToggleBreakpoint ( void ); + void UpdateScriptList ( void ); + void UpdateWatch ( void ); + void UpdateWindowMenu ( void ); + void UpdateScript ( void ); + void UpdateToolbar ( void ); + void UpdateTitle ( void ); + void UpdateCallstack ( void ); + void UpdateRecentFiles ( void ); + bool OpenScript ( const char* filename, int lineNumber = -1, idProgram* program = nullptr ); + void EnableWindows ( bool state ); + + int GetSelectedText ( idStr& text ); + + void ToggleBreakpoint ( void ); HWND mWnd; HWND mWndScript; @@ -93,6 +111,7 @@ protected: HWND mWndBorder; HWND mWndConsole; HWND mWndCallstack; + HWND mWndScriptList; HWND mWndWatch; HWND mWndThreads; HWND mWndToolTips; @@ -108,6 +127,7 @@ protected: HINSTANCE mInstance; HIMAGELIST mImageList; + HIMAGELIST mTmpImageList; RECT mSplitterRect; bool mSplitterDrag; @@ -129,25 +149,6 @@ protected: rvDebuggerClient* mClient; rvDebuggerWatchList mWatches; - -private: - - bool RegisterClass ( void ); - void CreateToolbar ( void ); - bool InitRecentFiles ( void ); - - int HandleInitMenu ( WPARAM wParam, LPARAM lParam ); - int HandleCommand ( WPARAM wParam, LPARAM lParam ); - int HandleCreate ( WPARAM wparam, LPARAM lparam ); - int HandleActivate ( WPARAM wparam, LPARAM lparam ); - int HandleDrawItem ( WPARAM wparam, LPARAM lparam ); - void HandleTooltipGetDispInfo ( WPARAM wparam, LPARAM lparam ); - - static LRESULT CALLBACK WndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); - static LRESULT CALLBACK MarginWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); - static LRESULT CALLBACK ScriptWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); - static INT_PTR CALLBACK AboutDlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ); - static int CALLBACK ScriptWordBreakProc ( LPTSTR text, int current, int max, int action ); }; /* From 5e273302337dab81661662363c97c8d348b5d5ab Mon Sep 17 00:00:00 2001 From: HarrievG Date: Wed, 12 May 2021 00:21:25 +0200 Subject: [PATCH 02/42] - 64bit debugger fixes --- neo/idlib/BitMsg.h | 20 +++++++++++++++++- neo/tools/debugger/DebuggerClient.cpp | 5 +++++ neo/tools/debugger/DebuggerFindDlg.cpp | 7 ++++--- neo/tools/debugger/DebuggerQuickWatchDlg.cpp | 6 +++--- neo/tools/debugger/DebuggerServer.cpp | 6 ++++++ neo/tools/debugger/DebuggerWindow.cpp | 22 ++++++++++---------- 6 files changed, 48 insertions(+), 18 deletions(-) diff --git a/neo/idlib/BitMsg.h b/neo/idlib/BitMsg.h index e853bf7c..2733b4a5 100644 --- a/neo/idlib/BitMsg.h +++ b/neo/idlib/BitMsg.h @@ -85,7 +85,8 @@ public: void WriteShort( int c ); void WriteUShort( int c ); void WriteInt( int c ); - void WriteFloat( float f ); + void WriteInt64(int64_t c); + void WriteFloat( float f ); void WriteFloat( float f, int exponentBits, int mantissaBits ); void WriteAngle8( float f ); void WriteAngle16( float f ); @@ -114,6 +115,7 @@ public: int ReadShort( void ) const; int ReadUShort( void ) const; int ReadInt( void ) const; + int64_t ReadInt64( void ) const; float ReadFloat( void ) const; float ReadFloat( int exponentBits, int mantissaBits ) const; float ReadAngle8( void ) const; @@ -300,6 +302,13 @@ ID_INLINE void idBitMsg::WriteInt( int c ) { WriteBits( c, 32 ); } +ID_INLINE void idBitMsg::WriteInt64(int64_t c) { + uint64_t uc = c; + + WriteBits(uc & 0xFFFFFFFF, 32); + WriteBits((uc >> 32) & 0xFFFFFFFF, 32); +} + ID_INLINE void idBitMsg::WriteFloat( float f ) { WriteBits( *reinterpret_cast(&f), 32 ); } @@ -380,6 +389,15 @@ ID_INLINE int idBitMsg::ReadInt( void ) const { return ReadBits( 32 ); } +ID_INLINE int64_t idBitMsg::ReadInt64(void) const { + uint32_t uc1, uc2; + + uc1 = ReadBits(32); + uc2 = ReadBits(32); + + return (uint64_t)uc1 | (uint64_t)uc2 << 32; +} + ID_INLINE float idBitMsg::ReadFloat( void ) const { float value; *reinterpret_cast(&value) = ReadBits( 32 ); diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index 982029f3..3d50d523 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -226,8 +226,13 @@ void rvDebuggerClient::HandleBreak ( idBitMsg* msg ) msg->ReadString ( filename, MAX_PATH ); mBreakFilename = filename; +#if D3_SIZEOFPTR == 4 // 32 bit int ptr32b = msg->ReadInt(); mBreakProgram = (idProgram*)ptr32b; +#else + int64_t ptr64b = msg->ReadInt64(); + mBreakProgram = (idProgram*)ptr64b; +#endif // Clear the variables mVariables.Clear ( ); diff --git a/neo/tools/debugger/DebuggerFindDlg.cpp b/neo/tools/debugger/DebuggerFindDlg.cpp index 59ce96c6..cf5dd28f 100644 --- a/neo/tools/debugger/DebuggerFindDlg.cpp +++ b/neo/tools/debugger/DebuggerFindDlg.cpp @@ -53,7 +53,7 @@ Launch the dialog */ bool rvDebuggerFindDlg::DoModal ( rvDebuggerWindow* parent ) { - if ( DialogBoxParam ( parent->GetInstance(), MAKEINTRESOURCE(IDD_DBG_FIND), parent->GetWindow(), DlgProc, (LONG)this ) ) + if ( DialogBoxParam ( parent->GetInstance(), MAKEINTRESOURCE(IDD_DBG_FIND), parent->GetWindow(), DlgProc, (LPARAM)this ) ) { return true; } @@ -70,7 +70,7 @@ Dialog Procedure for the find dialog */ INT_PTR CALLBACK rvDebuggerFindDlg::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - rvDebuggerFindDlg* dlg = (rvDebuggerFindDlg*) GetWindowLong ( wnd, GWL_USERDATA ); + rvDebuggerFindDlg* dlg = (rvDebuggerFindDlg*) GetWindowLongPtr ( wnd, GWLP_USERDATA); switch ( msg ) { @@ -80,7 +80,8 @@ INT_PTR CALLBACK rvDebuggerFindDlg::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, case WM_INITDIALOG: dlg = (rvDebuggerFindDlg*) lparam; - SetWindowLong ( wnd, GWL_USERDATA, (LONG) dlg ); + + SetWindowLongPtr ( wnd, GWLP_USERDATA, (LONG_PTR) dlg ); dlg->mWnd = wnd; SetWindowText ( GetDlgItem ( dlg->mWnd, IDC_DBG_FIND ), dlg->mFindText ); return TRUE; diff --git a/neo/tools/debugger/DebuggerQuickWatchDlg.cpp b/neo/tools/debugger/DebuggerQuickWatchDlg.cpp index 7cf18fe3..cee73a8f 100644 --- a/neo/tools/debugger/DebuggerQuickWatchDlg.cpp +++ b/neo/tools/debugger/DebuggerQuickWatchDlg.cpp @@ -55,7 +55,7 @@ bool rvDebuggerQuickWatchDlg::DoModal ( rvDebuggerWindow* window, int callstackD mDebuggerWindow = window; mVariable = variable?variable:""; - DialogBoxParam ( window->GetInstance(), MAKEINTRESOURCE(IDD_DBG_QUICKWATCH), window->GetWindow(), DlgProc, (LONG)this ); + DialogBoxParam ( window->GetInstance(), MAKEINTRESOURCE(IDD_DBG_QUICKWATCH), window->GetWindow(), DlgProc, (LPARAM)this ); return true; } @@ -69,7 +69,7 @@ Dialog Procedure for the quick watch dialog */ INT_PTR CALLBACK rvDebuggerQuickWatchDlg::DlgProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - rvDebuggerQuickWatchDlg* dlg = (rvDebuggerQuickWatchDlg*) GetWindowLong ( wnd, GWL_USERDATA ); + rvDebuggerQuickWatchDlg* dlg = (rvDebuggerQuickWatchDlg*) GetWindowLongPtr ( wnd, GWLP_USERDATA); switch ( msg ) { @@ -128,7 +128,7 @@ INT_PTR CALLBACK rvDebuggerQuickWatchDlg::DlgProc ( HWND wnd, UINT msg, WPARAM w // Attach the dialog class pointer to the window dlg = (rvDebuggerQuickWatchDlg*) lparam; - SetWindowLong ( wnd, GWL_USERDATA, lparam ); + SetWindowLongPtr ( wnd, GWLP_USERDATA, lparam ); dlg->mWnd = wnd; GetClientRect ( wnd, &client ); diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index b2711f59..1bf191d6 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -611,7 +611,13 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i msg.WriteShort ( (short)DBMSG_BREAK ); msg.WriteInt ( linenumber ); msg.WriteString ( fileStr.c_str() ); + +#if D3_SIZEOFPTR == 4 // 32 bit msg.WriteInt( (int)mBreakProgram ); +#else + msg.WriteInt64( (int64_t)mBreakProgram ); +#endif + SendPacket ( msg.GetData(), msg.GetSize() ); // Suspend the game thread. Since this will be called from within the main game thread diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index ca0b95c3..84f6cd0f 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -249,7 +249,7 @@ LRESULT CALLBACK rvDebuggerWindow::ScriptWndProc ( HWND wnd, UINT msg, WPARAM wp { static int lastStart = -1; static int lastEnd = -1; - rvDebuggerWindow* window = (rvDebuggerWindow*)GetWindowLong ( wnd, GWL_USERDATA ); + rvDebuggerWindow* window = (rvDebuggerWindow*)GetWindowLongPtr ( wnd, GWLP_USERDATA ); WNDPROC wndproc = window->mOldScriptProc; switch ( msg ) @@ -369,7 +369,7 @@ LRESULT CALLBACK rvDebuggerWindow::ScriptWndProc ( HWND wnd, UINT msg, WPARAM wp LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - rvDebuggerWindow* window = (rvDebuggerWindow*) GetWindowLong ( wnd, GWL_USERDATA ); + rvDebuggerWindow* window = (rvDebuggerWindow*) GetWindowLongPtr ( wnd, GWLP_USERDATA ); switch ( msg ) { @@ -841,9 +841,9 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) mWndScript = CreateWindow ( "RichEdit20A", "", WS_CHILD|WS_BORDER|ES_NOHIDESEL|ES_READONLY|ES_MULTILINE|ES_WANTRETURN|ES_AUTOVSCROLL|ES_AUTOHSCROLL|WS_VSCROLL|WS_HSCROLL, 0, 0, 100, 100, mWnd, (HMENU) IDC_DBG_SCRIPT, mInstance, 0 ); SendMessage ( mWndScript, EM_SETEVENTMASK, 0, ENM_SCROLL | ENM_CHANGE | ENM_UPDATE | ENM_SCROLLEVENTS | ENM_REQUESTRESIZE) ; SendMessage ( mWndScript, EM_SETWORDBREAKPROC, 0, (LPARAM) ScriptWordBreakProc ); - mOldScriptProc = (WNDPROC)GetWindowLong ( mWndScript, GWL_WNDPROC ); - SetWindowLong ( mWndScript, GWL_USERDATA, (LONG)this ); - SetWindowLong ( mWndScript, GWL_WNDPROC, (LONG)ScriptWndProc ); + mOldScriptProc = (WNDPROC)GetWindowLongPtr ( mWndScript, GWLP_WNDPROC ); + SetWindowLongPtr ( mWndScript, GWLP_USERDATA, (LONG_PTR)this ); + SetWindowLongPtr ( mWndScript, GWLP_WNDPROC, (LONG_PTR)ScriptWndProc ); SendMessage ( mWndScript, EM_SETTABSTOPS, 1, (LPARAM)&tabsize ); @@ -869,8 +869,8 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) SendMessage ( mWndConsole, EM_SETBKGNDCOLOR, 0, GetSysColor ( COLOR_3DFACE ) ); mWndMargin = CreateWindow ( "STATIC", "", WS_VISIBLE|WS_CHILD, 0, 0, 0, 0, mWndScript, (HMENU)IDC_DBG_SPLITTER, mInstance, NULL ); - SetWindowLong ( mWndMargin, GWL_USERDATA, (LONG)this ); - SetWindowLong ( mWndMargin, GWL_WNDPROC, (LONG)MarginWndProc ); + SetWindowLongPtr ( mWndMargin, GWLP_USERDATA, (LONG_PTR)this ); + SetWindowLongPtr ( mWndMargin, GWLP_WNDPROC, (LONG_PTR)MarginWndProc ); mWndBorder = CreateWindow ( "STATIC", "", WS_VISIBLE|WS_CHILD|SS_GRAYFRAME, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_BORDER, mInstance, NULL ); @@ -1150,7 +1150,7 @@ int rvDebuggerWindow::HandleCommand ( WPARAM wparam, LPARAM lparam ) LONG num; LONG dem; - SendMessage ( mWndScript, EM_GETZOOM, (LONG)&num, (LONG)&dem ); + SendMessage ( mWndScript, EM_GETZOOM, (WPARAM)&num, (LPARAM)&dem ); if ( num != mZoomScaleNum || dem != mZoomScaleDem ) { mZoomScaleNum = num; @@ -1254,7 +1254,7 @@ Window procedure for the deubgger window */ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - rvDebuggerWindow* window = (rvDebuggerWindow*) GetWindowLong ( wnd, GWL_USERDATA ); + rvDebuggerWindow* window = (rvDebuggerWindow*) GetWindowLongPtr ( wnd, GWLP_USERDATA ); switch ( msg ) { @@ -1277,7 +1277,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, gDebuggerApp.GetOptions().SetString ( va("watch%d", i ), "" ); window->mWnd = NULL; - SetWindowLong ( wnd, GWL_USERDATA, 0 ); + SetWindowLongPtr ( wnd, GWLP_USERDATA, 0 ); break; } @@ -1443,7 +1443,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, { CREATESTRUCT* cs = (CREATESTRUCT*) lparam; window = (rvDebuggerWindow*) cs->lpCreateParams; - SetWindowLong ( wnd, GWL_USERDATA, (LONG)cs->lpCreateParams ); + SetWindowLongPtr ( wnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams ); window->mWnd = wnd; window->HandleCreate ( wparam, lparam ); From af5f3952560a8a13fe124435c8ba813bc1848dad Mon Sep 17 00:00:00 2001 From: HarrievG Date: Wed, 12 May 2021 09:04:00 +0200 Subject: [PATCH 03/42] - Putting back the "Original by Raven" texts --- neo/sys/win32/rc/Debugger.rc | 1 + neo/sys/win32/rc/GuiEd.rc | 1 + 2 files changed, 2 insertions(+) diff --git a/neo/sys/win32/rc/Debugger.rc b/neo/sys/win32/rc/Debugger.rc index 8aad0722..726848b4 100644 --- a/neo/sys/win32/rc/Debugger.rc +++ b/neo/sys/win32/rc/Debugger.rc @@ -157,6 +157,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Script Debugger",IDC_STATIC,35,7,81,8 LTEXT "Version 1.0",IDC_STATIC,35,17,41,8 + LTEXT "Original version by Raven", IDC_STATIC, 35,28, 134, 8 LTEXT "Dhewm3 version by Harrie van Ginneken", IDC_STATIC, 35, 38, 134, 8 DEFPUSHBUTTON "OK",IDOK,165,60,50,14 ICON 5098,IDC_STATIC,7,7,20,20 diff --git a/neo/sys/win32/rc/GuiEd.rc b/neo/sys/win32/rc/GuiEd.rc index 46f6bba1..cd33f829 100644 --- a/neo/sys/win32/rc/GuiEd.rc +++ b/neo/sys/win32/rc/GuiEd.rc @@ -269,6 +269,7 @@ FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "GUI Editor",IDC_STATIC,35,7,62,8 LTEXT "Version 0.15",IDC_STATIC,35,17,41,8 + LTEXT "Original version by Raven", IDC_STATIC, 35,28, 134, 8 DEFPUSHBUTTON "OK",IDOK,165,50,50,14 ICON IDI_GUIED,IDC_STATIC,7,7,20,20 END From 7f7ed7e45f5fa72ee625877521a7fdeb419b79fa Mon Sep 17 00:00:00 2001 From: HarrievG Date: Wed, 12 May 2021 09:11:29 +0200 Subject: [PATCH 04/42] - Removing ugly (and wrong) include hack for SDL on MSCV+VCPKG. This has been resolved anyway, and should never been submitted. --- neo/idlib/Lib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/idlib/Lib.cpp b/neo/idlib/Lib.cpp index 7f2a37d6..0976c85e 100644 --- a/neo/idlib/Lib.cpp +++ b/neo/idlib/Lib.cpp @@ -35,7 +35,7 @@ If you have questions concerning this license or the applicable additional terms #include #endif -#include +#include #include "sys/platform.h" #include "idlib/math/Vector.h" From 46157857b50ec9a6c9c1c561ff2a6e0aafac8dfb Mon Sep 17 00:00:00 2001 From: HarrievG Date: Thu, 13 May 2021 09:12:27 +0200 Subject: [PATCH 05/42] - Always write 64b program pointer --- neo/tools/debugger/DebuggerClient.cpp | 5 ----- neo/tools/debugger/DebuggerServer.cpp | 4 ---- 2 files changed, 9 deletions(-) diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index 3d50d523..b3e6c97b 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -226,13 +226,8 @@ void rvDebuggerClient::HandleBreak ( idBitMsg* msg ) msg->ReadString ( filename, MAX_PATH ); mBreakFilename = filename; -#if D3_SIZEOFPTR == 4 // 32 bit - int ptr32b = msg->ReadInt(); - mBreakProgram = (idProgram*)ptr32b; -#else int64_t ptr64b = msg->ReadInt64(); mBreakProgram = (idProgram*)ptr64b; -#endif // Clear the variables mVariables.Clear ( ); diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 1bf191d6..1a92abca 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -612,11 +612,7 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i msg.WriteInt ( linenumber ); msg.WriteString ( fileStr.c_str() ); -#if D3_SIZEOFPTR == 4 // 32 bit - msg.WriteInt( (int)mBreakProgram ); -#else msg.WriteInt64( (int64_t)mBreakProgram ); -#endif SendPacket ( msg.GetData(), msg.GetSize() ); From a8709206d872fe586ab36be4b8f254558bc64a93 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Thu, 13 May 2021 09:16:39 +0200 Subject: [PATCH 06/42] - Whitespace fix --- neo/tools/debugger/DebuggerScript.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/tools/debugger/DebuggerScript.cpp b/neo/tools/debugger/DebuggerScript.cpp index bea021d5..2b88a4fd 100644 --- a/neo/tools/debugger/DebuggerScript.cpp +++ b/neo/tools/debugger/DebuggerScript.cpp @@ -87,7 +87,7 @@ appropriate for the file being loaded. If the script cant be compiled the loading of the script fails ================ */ -bool rvDebuggerScript::Load ( const char* filename) +bool rvDebuggerScript::Load ( const char* filename ) { void* buffer; int size; From cd9284d8762840750926b22a7b78badfcd666031 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Thu, 13 May 2021 09:26:16 +0200 Subject: [PATCH 07/42] - Debugger is guarded behind tools. --- neo/framework/Common.cpp | 2 ++ neo/sys/win32/win_main.cpp | 3 +++ 2 files changed, 5 insertions(+) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 6edfb00a..f0844b68 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -3310,7 +3310,9 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F void idCommonLocal::DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer) { +#ifdef ID_ALLOW_TOOLS DebuggerServerCheckBreakpoint(interpreter, program, instructionPointer); +#endif } idGameCallbacks gameCallbacks; diff --git a/neo/sys/win32/win_main.cpp b/neo/sys/win32/win_main.cpp index 96a9a66a..cbb235bb 100644 --- a/neo/sys/win32/win_main.cpp +++ b/neo/sys/win32/win_main.cpp @@ -992,7 +992,10 @@ int main(int argc, char *argv[]) { // Launch the script debugger if ( strstr( GetCommandLine(), "+debugger" ) ) { + +#ifdef ID_ALLOW_TOOLS DebuggerClientInit(GetCommandLine()); +#endif return 0; } From 5ebda5eab5ae12613f6dd786c1ff7c70148795a3 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Thu, 13 May 2021 09:56:46 +0200 Subject: [PATCH 08/42] - removed clientside use of mBreakprogram ptr --- neo/tools/debugger/DebuggerClient.cpp | 4 ++-- neo/tools/debugger/DebuggerClient.h | 12 ------------ neo/tools/debugger/DebuggerServer.cpp | 2 +- neo/tools/debugger/DebuggerWindow.cpp | 2 +- 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index b3e6c97b..038dd5ac 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -226,8 +226,8 @@ void rvDebuggerClient::HandleBreak ( idBitMsg* msg ) msg->ReadString ( filename, MAX_PATH ); mBreakFilename = filename; - int64_t ptr64b = msg->ReadInt64(); - mBreakProgram = (idProgram*)ptr64b; + //int64_t ptr64b = msg->ReadInt64(); + //mBreakProgram = (idProgram*)ptr64b; // Clear the variables mVariables.Clear ( ); diff --git a/neo/tools/debugger/DebuggerClient.h b/neo/tools/debugger/DebuggerClient.h index 9d02da1c..9a21b600 100644 --- a/neo/tools/debugger/DebuggerClient.h +++ b/neo/tools/debugger/DebuggerClient.h @@ -112,7 +112,6 @@ protected: int mBreakID; int mBreakLineNumber; idStr mBreakFilename; - idProgram* mBreakProgram; idDict mVariables; @@ -191,17 +190,6 @@ ID_INLINE int rvDebuggerClient::GetBreakLineNumber ( void ) return mBreakLineNumber; } -/* -================ -rvDebuggerClient::GetBreakProgram -================ -*/ -ID_INLINE idProgram* rvDebuggerClient::GetBreakProgram(void) -{ - return mBreakProgram; -} - - /* ================ rvDebuggerClient::GetCallstack diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 1a92abca..7244edc5 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -612,7 +612,7 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i msg.WriteInt ( linenumber ); msg.WriteString ( fileStr.c_str() ); - msg.WriteInt64( (int64_t)mBreakProgram ); + //msg.WriteInt64( (int64_t)mBreakProgram ); SendPacket ( msg.GetData(), msg.GetSize() ); diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 84f6cd0f..83b8e895 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -1794,7 +1794,7 @@ void rvDebuggerWindow::ProcessNetMessage ( idBitMsg* msg ) mClient->InspectVariable ( mTooltipVar, mCurrentStackDepth ); UpdateWatch ( ); EnableWindows ( TRUE ); - OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1, mClient->GetBreakProgram()); + OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1 ); UpdateTitle ( ); UpdateToolbar ( ); SetForegroundWindow ( mWnd ); From 99ca9f054328abca4f67a323afd72b5f114139ef Mon Sep 17 00:00:00 2001 From: HarrievG Date: Thu, 13 May 2021 10:23:36 +0200 Subject: [PATCH 09/42] - D3XP debugger fixes --- neo/d3xp/GameEdit.cpp | 62 ++++++ neo/d3xp/Game_local.cpp | 26 ++- neo/d3xp/Game_local.h | 7 +- neo/d3xp/script/Script_Interpreter.cpp | 270 +++++++++++++++++++------ neo/d3xp/script/Script_Thread.cpp | 46 +++++ 5 files changed, 334 insertions(+), 77 deletions(-) diff --git a/neo/d3xp/GameEdit.cpp b/neo/d3xp/GameEdit.cpp index 0c637bdb..71907bb4 100644 --- a/neo/d3xp/GameEdit.cpp +++ b/neo/d3xp/GameEdit.cpp @@ -1146,3 +1146,65 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const { } } } + + +/*********************************************************************** + + Debugger + +***********************************************************************/ + +bool idGameEdit::IsLineCode(const char* filename, int linenumber) const +{ + static idStr fileStr = idStr(MAX_PATH); + idProgram* program = &gameLocal.program; + for (int i = 0; i < program->NumStatements(); i++) + { + fileStr = program->GetFilename(program->GetStatement(i).file); + fileStr.BackSlashesToSlashes(); + + if (strcmp(filename, fileStr.c_str()) == 0 + && program->GetStatement(i).linenumber == linenumber + ) + { + return true; + } + } + return false; +} + +void idGameEdit::GetLoadedScripts(idStrList** result) +{ + (*result)->Clear(); + idProgram* program = &gameLocal.program; + + for (int i = 0; i < program->NumFilenames(); i++) + { + (*result)->AddUnique(idStr(program->GetFilename(i))); + } +} + +void idGameEdit::MSG_WriteScriptList(idBitMsg* msg) +{ + idProgram* program = &gameLocal.program; + + msg->WriteInt(program->NumFilenames()); + for (int i = 0; i < program->NumFilenames(); i++) + { + idStr file = program->GetFilename(i); + //fix this. it seams that scripts triggered by the runtime are stored with a wrong path + //the use // instead of '\' + file.BackSlashesToSlashes(); + msg->WriteString(file); + } +} + +const char* idGameEdit::GetFilenameForStatement(idProgram* program, int index) const +{ + return program->GetFilenameForStatement(index); +} + +int idGameEdit::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 08aaf9bf..fccc4947 100644 --- a/neo/d3xp/Game_local.cpp +++ b/neo/d3xp/Game_local.cpp @@ -1312,7 +1312,7 @@ void idGameLocal::MapPopulate( void ) { idGameLocal::InitFromNewMap =================== */ -void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randseed ) { +void idGameLocal::InitFromNewMap(const char* mapName, idRenderWorld* renderWorld, idSoundWorld* soundWorld, bool isServer, bool isClient, int randseed, int activeEditors) { this->isServer = isServer; this->isClient = isClient; @@ -1323,6 +1323,9 @@ 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; @@ -1350,7 +1353,7 @@ void idGameLocal::InitFromNewMap( const char *mapName, idRenderWorld *renderWorl idGameLocal::InitFromSaveGame ================= */ -bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ) { +bool idGameLocal::InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile, int activeEditors) { int i; int num; idEntity *ent; @@ -2436,14 +2439,17 @@ void idGameLocal::RunTimeGroup2() { idGameLocal::RunFrame ================ */ -gameReturn_t idGameLocal::RunFrame( const usercmd_t *clientCmds ) { - idEntity * ent; - int num; - float ms; - idTimer timer_think, timer_events, timer_singlethink; - gameReturn_t ret; - idPlayer *player; - const renderView_t *view; +gameReturn_t idGameLocal::RunFrame(const usercmd_t* clientCmds, int activeEditors) { + idEntity* ent; + int num; + float ms; + idTimer timer_think, timer_events, timer_singlethink; + 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/d3xp/Game_local.h b/neo/d3xp/Game_local.h index acd4fff0..4451b559 100644 --- a/neo/d3xp/Game_local.h +++ b/neo/d3xp/Game_local.h @@ -319,6 +319,7 @@ public: idEntityPtr lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f int lastGUI; // last GUI on the lastGUIEnt + int editors; #ifdef _D3XP idEntityPtr portalSkyEnt; @@ -365,13 +366,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 ); - virtual bool InitFromSaveGame( const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, idFile *saveGameFile ); + 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 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 ); + virtual gameReturn_t RunFrame(const usercmd_t* clientCmds, int activeEditors); 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 c8e0cc45..58fc69ee 100644 --- a/neo/d3xp/script/Script_Interpreter.cpp +++ b/neo/d3xp/script/Script_Interpreter.cpp @@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms #include "script/Script_Interpreter.h" +#include "framework/FileSystem.h" + /* ================ idInterpreter::idInterpreter() @@ -176,135 +178,166 @@ void idInterpreter::Reset( void ) { doneProcessing = true; } -/* -================ -idInterpreter::GetRegisterValue - -Returns a string representation of the value of the register. This is -used primarily for the debugger and debugging - -//FIXME: This is pretty much wrong. won't access data in most situations. -================ -*/ -bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDepth ) { +bool idInterpreter::GetRegisterValue(const char* name, idStr& out, int scopeDepth) { varEval_t reg; - idVarDef *d; - char funcObject[ 1024 ]; - char *funcName; - const idVarDef *scope; - const idTypeDef *field; - const idScriptObject *obj; - const function_t *func; + idVarDef* d; + char funcObject[1024]; + char* funcName; + const idVarDef* scope = NULL; + const idVarDef* scopeObj; + const idTypeDef* field; + const function_t* func; out.Empty(); - if ( scopeDepth == -1 ) { + if (scopeDepth == -1) { scopeDepth = callStackDepth; } - if ( scopeDepth == callStackDepth ) { + if (scopeDepth == callStackDepth) { func = currentFunction; - } else { - func = callStack[ scopeDepth ].f; } - if ( !func ) { + else { + func = callStack[scopeDepth].f; + } + if (!func) { return false; } - idStr::Copynz( funcObject, func->Name(), sizeof( funcObject ) ); - funcName = strstr( funcObject, "::" ); - if ( funcName ) { + idStr::Copynz(funcObject, func->Name(), sizeof(funcObject)); + funcName = strstr(funcObject, "::"); + if (funcName) { *funcName = '\0'; - scope = gameLocal.program.GetDef( NULL, funcObject, &def_namespace ); + scopeObj = gameLocal.program.GetDef(NULL, funcObject, &def_namespace); funcName += 2; - } else { + if (scopeObj) + { + scope = gameLocal.program.GetDef(NULL, funcName, scopeObj); + } + } + else { funcName = funcObject; - scope = &def_namespace; + scope = gameLocal.program.GetDef(NULL, func->Name(), &def_namespace); + scopeObj = NULL; } - // Get the function from the object - d = gameLocal.program.GetDef( NULL, funcName, scope ); - if ( !d ) { + if (!scope) + { return false; } - // Get the variable itself and check various namespaces - d = gameLocal.program.GetDef( NULL, name, d ); - if ( !d ) { - if ( scope == &def_namespace ) { - return false; - } + d = gameLocal.program.GetDef(NULL, name, scope); - d = gameLocal.program.GetDef( NULL, name, scope ); - if ( !d ) { - d = gameLocal.program.GetDef( NULL, name, &def_namespace ); - if ( !d ) { - return false; + // Check the objects for it if it wasnt local to the function + if (!d) + { + for (; scopeObj && scopeObj->TypeDef()->SuperClass(); scopeObj = scopeObj->TypeDef()->SuperClass()->def) + { + d = gameLocal.program.GetDef(NULL, name, scopeObj); + if (d) + { + break; } } } - reg = GetVariable( d ); - switch( d->Type() ) { + if (!d) + { + out = "???"; + return false; + } + + reg = GetVariable(d); + switch (d->Type()) { case ev_float: - if ( reg.floatPtr ) { - out = va("%g", *reg.floatPtr ); - } else { + if (reg.floatPtr) { + out = va("%g", *reg.floatPtr); + } + else { out = "0"; } return true; break; case ev_vector: - if ( reg.vectorPtr ) { - out = va( "%g,%g,%g", reg.vectorPtr->x, reg.vectorPtr->y, reg.vectorPtr->z ); - } else { + if (reg.vectorPtr) { + out = va("%g,%g,%g", reg.vectorPtr->x, reg.vectorPtr->y, reg.vectorPtr->z); + } + else { out = "0,0,0"; } return true; break; case ev_boolean: - if ( reg.intPtr ) { - out = va( "%d", *reg.intPtr ); - } else { + if (reg.intPtr) { + out = va("%d", *reg.intPtr); + } + else { out = "0"; } return true; break; case ev_field: - if ( scope == &def_namespace ) { + { + idEntity* entity; + idScriptObject* obj; + + if (scope == &def_namespace) { // should never happen, but handle it safely anyway return false; } - field = scope->TypeDef()->GetParmType( reg.ptrOffset )->FieldType(); - obj = *reinterpret_cast( &localstack[ callStack[ callStackDepth ].stackbase ] ); - if ( !field || !obj ) { + field = d->TypeDef()->FieldType(); + entity = GetEntity(*((int*)&localstack[localstackBase])); + if (!entity || !field) + { return false; } - switch ( field->Type() ) { + obj = &entity->scriptObject; + if (!obj) { + return false; + } + + switch (field->Type()) { case ev_boolean: - out = va( "%d", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); + out = va("%d", *(reinterpret_cast(&obj->data[reg.ptrOffset]))); return true; case ev_float: - out = va( "%g", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); + out = va("%g", *(reinterpret_cast(&obj->data[reg.ptrOffset]))); return true; + case ev_string: { + const char* str; + str = reinterpret_cast(&obj->data[reg.ptrOffset]); + if (!str) { + out = "\"\""; + } + else { + out = "\""; + out += str; + out += "\""; + } + return true; + } + default: return false; } + break; + } case ev_string: - if ( reg.stringPtr ) { + if (reg.stringPtr) { out = "\""; out += reg.stringPtr; out += "\""; - } else { + } + else { out = "\"\""; } return true; @@ -313,7 +346,6 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep return false; } } - /* ================ idInterpreter::GetCallstackDepth @@ -969,6 +1001,20 @@ 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()) { + static int lastLineNumber = -1; + if (lastLineNumber != gameLocal.program.GetStatement(instructionPointer).linenumber) { + gameLocal.Printf("%s (%d)\n", + gameLocal.program.GetFilename(gameLocal.program.GetStatement(instructionPointer).file), + gameLocal.program.GetStatement(instructionPointer).linenumber + ); + lastLineNumber = gameLocal.program.GetStatement(instructionPointer).linenumber; + } + } + switch( st->op ) { case OP_RETURN: LeaveFunction( st->a ); @@ -1833,3 +1879,99 @@ bool idInterpreter::Execute( void ) { return threadDying; } + + +bool idGameEdit::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 +{ + + return (const_cast(program)->GetStatement(index).op == OP_RETURN && interpreter->GetCallstackDepth() <= 1); +} + +bool idGameEdit::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const +{ + return const_cast(interpreter)->GetRegisterValue(name, out, scopeDepth); +} + +const idThread* idGameEdit::GetThread(const idInterpreter* interpreter) const +{ + return interpreter->GetThread(); +} + +void idGameEdit::MSG_WriteCallstackFunc(idBitMsg* msg, const prstack_t* stack, const idProgram* program, int instructionPtr) +{ + const statement_t* st; + const function_t* func; + + func = stack->f; + + // If the function is unknown then just fill in with default data. + if (!func) + { + msg->WriteString(""); + msg->WriteString(""); + msg->WriteInt(0); + return; + } + else + { + msg->WriteString(va("%s( )", func->Name())); + } + + if (stack->s == -1) //this is a fake stack created by debugger, use intruction pointer for retrieval. + st = &const_cast(program)->GetStatement(instructionPtr); + else // Use the calling statement as the filename and linenumber where the call was made from + st = &const_cast(program)->GetStatement(stack->s); + + if (st) + { + idStr qpath = const_cast(program)->GetFilename(st->file); + if (idStr::FindChar(qpath, ':') != -1) + qpath = fileSystem->OSPathToRelativePath(qpath.c_str()); + qpath.BackSlashesToSlashes(); + msg->WriteString(qpath); + msg->WriteInt(st->linenumber); + } + else + { + msg->WriteString(""); + msg->WriteInt(0); + } +} + +void idGameEdit::MSG_WriteInterpreterInfo(idBitMsg* msg, const idInterpreter* interpreter, const idProgram* program, int instructionPtr) +{ + int i; + prstack_s temp; + + msg->WriteShort((int)interpreter->GetCallstackDepth()); + + // write out the current function + temp.f = interpreter->GetCurrentFunction(); + temp.s = -1; + temp.stackbase = 0; + MSG_WriteCallstackFunc(msg, &temp, program, instructionPtr); + + // Run through all of the callstack and write each to the msg + for (i = interpreter->GetCallstackDepth() - 1; i > 0; i--) + { + MSG_WriteCallstackFunc(msg, interpreter->GetCallstack() + i, program, instructionPtr); + } +} + + +int idGameEdit::GetInterpreterCallStackDepth(const idInterpreter* interpreter) +{ + return interpreter->GetCallstackDepth(); +} + +const function_t* idGameEdit::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 cb826331..e320ec69 100644 --- a/neo/d3xp/script/Script_Thread.cpp +++ b/neo/d3xp/script/Script_Thread.cpp @@ -1921,3 +1921,49 @@ void idThread::Event_InfluenceActive( void ) { idThread::ReturnInt( false ); } } + +int idGameEdit::ThreadGetNum(const idThread* thread) const +{ + return const_cast(thread)->GetThreadNum(); +} + +const char* idGameEdit::ThreadGetName(const idThread* thread) const +{ + return const_cast(thread)->GetThreadName(); +} + +int idGameEdit::GetTotalScriptThreads() const +{ + return idThread::GetThreads().Num(); +} + +const idThread* idGameEdit::GetThreadByIndex(int index) const +{ + return idThread::GetThreads()[index]; +} + +bool idGameEdit::ThreadIsDoneProcessing(const idThread* thread) const +{ + return const_cast(thread)->IsDoneProcessing(); +} + +bool idGameEdit::ThreadIsWaiting(const idThread* thread) const +{ + return const_cast(thread)->IsWaiting(); +} + +bool idGameEdit::ThreadIsDying(const idThread* thread) const +{ + return const_cast(thread)->IsDying(); +} + +void idGameEdit::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter) +{ + msg->WriteString(const_cast(thread)->GetThreadName()); + msg->WriteInt(const_cast(thread)->GetThreadNum()); + + msg->WriteBits((int)(thread == interpreter->GetThread()), 1); + msg->WriteBits((int)const_cast(thread)->IsDoneProcessing(), 1); + msg->WriteBits((int)const_cast(thread)->IsWaiting(), 1); + msg->WriteBits((int)const_cast(thread)->IsDying(), 1); +} \ No newline at end of file From 5ff3b0b9ee9d7b074aeba7bfa6cd5505c430b4ed Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 24 May 2021 00:23:29 +0200 Subject: [PATCH 10/42] - fixed wierd bracked position --- neo/d3xp/GameEdit.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/neo/d3xp/GameEdit.cpp b/neo/d3xp/GameEdit.cpp index 71907bb4..d0aa63ce 100644 --- a/neo/d3xp/GameEdit.cpp +++ b/neo/d3xp/GameEdit.cpp @@ -1154,19 +1154,16 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const { ***********************************************************************/ -bool idGameEdit::IsLineCode(const char* filename, int linenumber) const -{ - static idStr fileStr = idStr(MAX_PATH); - idProgram* program = &gameLocal.program; - for (int i = 0; i < program->NumStatements(); i++) - { - fileStr = program->GetFilename(program->GetStatement(i).file); - fileStr.BackSlashesToSlashes(); +bool idGameEdit::IsLineCode( const char *filename, int linenumber ) const { + static idStr fileStr = idStr( MAX_PATH ); + idProgram *program = &gameLocal.program; + for ( int i = 0; i < program->NumStatements( ); i++ ) { + fileStr = program->GetFilename( program->GetStatement( i ).file ); + fileStr.BackSlashesToSlashes( ); - if (strcmp(filename, fileStr.c_str()) == 0 - && program->GetStatement(i).linenumber == linenumber - ) - { + if ( strcmp( filename, fileStr.c_str( ) ) == 0 + && program->GetStatement( i ).linenumber == linenumber + ) { return true; } } From 3ce93c7749b6ecf399bb4a2eeb4ff46a69c20245 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 24 May 2021 22:21:47 +0200 Subject: [PATCH 11/42] - Debuggersever now always builds, but is disabled by default in runtime. - use com_enableDebuggerServer=1 to enable debugger server. --- neo/CMakeLists.txt | 37 ++++- neo/d3xp/GameEdit.cpp | 2 +- neo/framework/Common.cpp | 33 ++--- neo/framework/Common.h | 1 + neo/game/GameEdit.cpp | 2 +- neo/tools/debugger/DebuggerBreakpoint.cpp | 8 +- neo/tools/debugger/DebuggerScript.cpp | 7 +- neo/tools/debugger/DebuggerServer.cpp | 12 +- neo/tools/debugger/debugger.cpp | 11 +- neo/tools/debugger/debugger_common.h | 162 ++++++++++++++++++++++ neo/tools/edit_stub.cpp | 4 - 11 files changed, 243 insertions(+), 36 deletions(-) create mode 100644 neo/tools/debugger/debugger_common.h diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt index 11ec8394..bace3073 100644 --- a/neo/CMakeLists.txt +++ b/neo/CMakeLists.txt @@ -801,6 +801,17 @@ set(src_d3xp add_globbed_headers(src_d3xp "d3xp") +set(src_debuggerServer + tools/debugger/DebuggerBreakpoint.h + tools/debugger/DebuggerBreakpoint.cpp + tools/debugger/DebuggerServer.h + tools/debugger/DebuggerServer.cpp + tools/debugger/DebuggerScript.h + tools/debugger/DebuggerScript.cpp + tools/debugger/DebuggerMessages.h + tools/debugger/debugger.cpp +) + set(src_core ${src_renderer} ${src_framework} @@ -863,8 +874,22 @@ if (TOOLS AND MFC_FOUND AND MSVC) file(GLOB src_script_editor "tools/script/*.cpp") add_globbed_headers(src_script_editor "tools/script") # Script Debugger - file(GLOB src_script_debugger "tools/debugger/*.cpp") - add_globbed_headers(src_script_debugger "tools/debugger") + set(src_debuggerClient + tools/debugger/DebuggerClient.h + tools/debugger/DebuggerClient.cpp + tools/debugger/DebuggerApp.h + tools/debugger/DebuggerApp.cpp + tools/debugger/DebuggerQuickWatchDlg.h + tools/debugger/DebuggerQuickWatchDlg.cpp + tools/debugger/DebuggerWindow.h + tools/debugger/DebuggerWindow.cpp + tools/debugger/DebuggerFindDlg.h + tools/debugger/DebuggerFindDlg.cpp + ) + set(src_script_debugger + ${src_debuggerServer} + ${src_debuggerClient} + ) # sound editor? file(GLOB src_sound_editor "tools/sound/*.cpp") add_globbed_headers(src_sound_editor "tools/sound") @@ -891,7 +916,10 @@ if (TOOLS AND MFC_FOUND AND MSVC) SET(CMAKE_MFC_FLAG 2) set(TOOLS_DEFINES "ID_ALLOW_TOOLS;_AFXDLL") else() - set(src_editor_tools "tools/edit_stub.cpp" "tools/edit_public.h") + set(src_editor_tools "tools/edit_stub.cpp" "tools/edit_public.h" "tools/debugger/debugger_common.h") + list(APPEND src_editor_tools + ${src_debuggerServer} + ) endif() @@ -1056,9 +1084,10 @@ if(DEDICATED) ${src_stub_openal} ${src_stub_gl} ${src_sys_base} + ${src_debuggerServer} ) - source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX neo FILES ${src_core} ${src_sys_base} ${src_stub_openal} ${src_stub_gl}) + source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX neo FILES ${src_core} ${src_sys_base} ${src_stub_openal} ${src_stub_gl} ${src_debuggerServer}) set_target_properties(${DHEWM3BINARY}ded PROPERTIES COMPILE_DEFINITIONS "ID_DEDICATED;__DOOM_DLL__") set_target_properties(${DHEWM3BINARY}ded PROPERTIES LINK_FLAGS "${ldflags}") diff --git a/neo/d3xp/GameEdit.cpp b/neo/d3xp/GameEdit.cpp index d0aa63ce..45c89d71 100644 --- a/neo/d3xp/GameEdit.cpp +++ b/neo/d3xp/GameEdit.cpp @@ -1155,7 +1155,7 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const { ***********************************************************************/ bool idGameEdit::IsLineCode( const char *filename, int linenumber ) const { - static idStr fileStr = idStr( MAX_PATH ); + idStr fileStr; idProgram *program = &gameLocal.program; for ( int i = 0; i < program->NumStatements( ); i++ ) { fileStr = program->GetFilename( program->GetStatement( i ).file ); diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index f0844b68..4782c3de 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -98,6 +98,8 @@ idCVar com_timescale( "timescale", "1", CVAR_SYSTEM | CVAR_FLOAT, "scales the ti idCVar com_makingBuild( "com_makingBuild", "0", CVAR_BOOL | CVAR_SYSTEM, "1 when making a build" ); idCVar com_updateLoadSize( "com_updateLoadSize", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "update the load size after loading a map" ); +idCVar com_enableDebuggerServer( "com_enableDebuggerServer", "0", CVAR_BOOL | CVAR_SYSTEM, "set to 1 on startup to enable debugging with the DHEWM3 debugger" ); + idCVar com_product_lang_ext( "com_product_lang_ext", "1", CVAR_INTEGER | CVAR_SYSTEM | CVAR_ARCHIVE, "Extension to use when creating language files." ); // com_speeds times @@ -383,17 +385,15 @@ void idCommonLocal::VPrintf( const char *fmt, va_list args ) { // remove any color codes idStr::RemoveColors( msg ); - - -#ifdef ID_ALLOW_TOOLS - // print to script debugger server - if (com_editors & EDITOR_DEBUGGER) - DebuggerServerPrint(msg); - else -#endif + if ( com_enableDebuggerServer.GetBool( ) ) { + // print to script debugger server + if ( com_editors & EDITOR_DEBUGGER ) + DebuggerServerPrint( msg ); + } else { // only echo to dedicated console and early console when debugger is not running so no // deadlocks occur if engine functions called from the debuggerthread trace stuff.. - Sys_Printf("%s", msg); + Sys_Printf( "%s", msg ); + } #if 0 // !@# #if defined(_DEBUG) && defined(WIN32) if ( strlen( msg ) < 512 ) { @@ -3170,10 +3170,9 @@ void idCommonLocal::InitGame( void ) { // initialize the user interfaces uiManager->Init(); -#if defined(ID_ALLOW_TOOLS) // startup the script debugger - DebuggerServerInit(); -#endif; + if ( com_enableDebuggerServer.GetBool( ) ) + DebuggerServerInit(); PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04350" ) ); @@ -3210,10 +3209,9 @@ void idCommonLocal::ShutdownGame( bool reloading ) { sw->StopAllSounds(); } -#if defined(ID_ALLOW_TOOLS) // shutdown the script debugger - DebuggerServerShutdown(); -#endif + if ( com_enableDebuggerServer.GetBool( ) ) + DebuggerServerShutdown(); idAsyncNetwork::client.Shutdown(); @@ -3310,9 +3308,8 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F void idCommonLocal::DebuggerCheckBreakpoint(idInterpreter* interpreter, idProgram* program, int instructionPointer) { -#ifdef ID_ALLOW_TOOLS - DebuggerServerCheckBreakpoint(interpreter, program, instructionPointer); -#endif + if ( com_enableDebuggerServer.GetBool( ) ) + DebuggerServerCheckBreakpoint(interpreter, program, instructionPointer); } idGameCallbacks gameCallbacks; diff --git a/neo/framework/Common.h b/neo/framework/Common.h index ec44ee66..d535fa7d 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -73,6 +73,7 @@ extern idCVar com_showAsyncStats; extern idCVar com_showSoundDecoders; extern idCVar com_makingBuild; extern idCVar com_updateLoadSize; +extern idCVar com_enableDebuggerServer; extern int time_gameFrame; // game logic time extern int time_gameDraw; // game present time diff --git a/neo/game/GameEdit.cpp b/neo/game/GameEdit.cpp index 769df2a0..ba495d7c 100644 --- a/neo/game/GameEdit.cpp +++ b/neo/game/GameEdit.cpp @@ -1155,7 +1155,7 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const { bool idGameEdit::IsLineCode(const char* filename, int linenumber) const { - static idStr fileStr = idStr(MAX_PATH); + idStr fileStr; idProgram* program = &gameLocal.program; for (int i = 0; i < program->NumStatements(); i++) { diff --git a/neo/tools/debugger/DebuggerBreakpoint.cpp b/neo/tools/debugger/DebuggerBreakpoint.cpp index 975f2eb2..373140ea 100644 --- a/neo/tools/debugger/DebuggerBreakpoint.cpp +++ b/neo/tools/debugger/DebuggerBreakpoint.cpp @@ -25,11 +25,13 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ - +#if defined( ID_ALLOW_TOOLS ) #include "tools/edit_gui_common.h" - - #include "DebuggerApp.h" +#else +#include "debugger_common.h" +#endif + #include "DebuggerBreakpoint.h" int rvDebuggerBreakpoint::mNextID = 1; diff --git a/neo/tools/debugger/DebuggerScript.cpp b/neo/tools/debugger/DebuggerScript.cpp index 2b88a4fd..f1d6944e 100644 --- a/neo/tools/debugger/DebuggerScript.cpp +++ b/neo/tools/debugger/DebuggerScript.cpp @@ -26,10 +26,13 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ +#if defined( ID_ALLOW_TOOLS ) #include "tools/edit_gui_common.h" - - #include "DebuggerApp.h" +#else +#include "debugger_common.h" +#endif + #include "DebuggerScript.h" #include "../../ui/Window.h" #include "../../ui/UserInterfaceLocal.h" diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 7244edc5..ed972128 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -26,9 +26,16 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ +#if defined( ID_ALLOW_TOOLS ) #include "tools/edit_gui_common.h" - #include "DebuggerApp.h" +#else +#include "debugger_common.h" +// we need a lot to be able to list all threads in mars_city1 +const int MAX_MSGLEN = 8600; +#endif + + #include "DebuggerServer.h" /* @@ -628,11 +635,14 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i // would just flash Sleep ( 150 ); +//this should be platform specific +#if defined( ID_ALLOW_TOOLS ) // Bring the window back to the foreground SetForegroundWindow ( win32.hWnd ); SetActiveWindow ( win32.hWnd ); UpdateWindow ( win32.hWnd ); SetFocus ( win32.hWnd ); +#endif // Give the mouse cursor back to the game // HVG_Note : there be dragons here. somewhere. diff --git a/neo/tools/debugger/debugger.cpp b/neo/tools/debugger/debugger.cpp index 4e5d5f6e..99d843f4 100644 --- a/neo/tools/debugger/debugger.cpp +++ b/neo/tools/debugger/debugger.cpp @@ -26,17 +26,22 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ +#if defined( ID_ALLOW_TOOLS ) #include "tools/edit_gui_common.h" - - #include "../../sys/win32/rc/debugger_resource.h" #include "DebuggerApp.h" +#else +#include "debugger_common.h" +#endif + #include "DebuggerServer.h" DWORD CALLBACK DebuggerThread ( LPVOID param ); +#if defined( ID_ALLOW_TOOLS ) rvDebuggerApp gDebuggerApp; HWND gDebuggerWindow = NULL; +#endif bool gDebuggerSuspend = false; bool gDebuggerConnnected = false; HANDLE gDebuggerGameThread = NULL; @@ -46,6 +51,7 @@ HANDLE gDebuggerServerThread = NULL; DWORD gDebuggerServerThreadID = 0; bool gDebuggerServerQuit = false; +#if defined( ID_ALLOW_TOOLS ) /* ================ DebuggerMain @@ -113,6 +119,7 @@ void DebuggerClientLaunch ( void ) CloseHandle ( process.hThread ); CloseHandle ( process.hProcess ); } +#endif // #if defined( ID_ALLOW_TOOLS ) /* ================ diff --git a/neo/tools/debugger/debugger_common.h b/neo/tools/debugger/debugger_common.h new file mode 100644 index 00000000..e98962c6 --- /dev/null +++ b/neo/tools/debugger/debugger_common.h @@ -0,0 +1,162 @@ +// header that includes all the other needed headers, replacement for precompiled.h (only used by debugger) +// this could be cleaned up more. + +#ifndef DEBUGGER_COMMON_H +#define DEBUGGER_COMMON_H + +#include "framework/Game.h" + +// non-portable system services +#include "sys/platform.h" +#include "sys/sys_public.h" + +// id lib +#include "idlib/Lib.h" + +// memory management and arrays +#include "idlib/Heap.h" +#include "idlib/containers/List.h" + +// math +#include "idlib/math/Simd.h" +#include "idlib/math/Math.h" +#include "idlib/math/Random.h" +#include "idlib/math/Complex.h" +#include "idlib/math/Vector.h" +#include "idlib/math/Matrix.h" +#include "idlib/math/Angles.h" +#include "idlib/math/Quat.h" +#include "idlib/math/Rotation.h" +#include "idlib/math/Plane.h" +#include "idlib/math/Pluecker.h" +#include "idlib/math/Polynomial.h" +#include "idlib/math/Extrapolate.h" +#include "idlib/math/Interpolate.h" +#include "idlib/math/Curve.h" +#include "idlib/math/Ode.h" +#include "idlib/math/Lcp.h" + +// bounding volumes +#include "idlib/bv/Sphere.h" +#include "idlib/bv/Bounds.h" +#include "idlib/bv/Box.h" +#include "idlib/bv/Frustum.h" + +// geometry +#include "idlib/geometry/DrawVert.h" +#include "idlib/geometry/JointTransform.h" +#include "idlib/geometry/Winding.h" +#include "idlib/geometry/Winding2D.h" +#include "idlib/geometry/Surface.h" +#include "idlib/geometry/Surface_Patch.h" +#include "idlib/geometry/Surface_Polytope.h" +#include "idlib/geometry/Surface_SweptSpline.h" +#include "idlib/geometry/TraceModel.h" + +// text manipulation +#include "idlib/Str.h" +#include "idlib/Token.h" +#include "idlib/Lexer.h" +#include "idlib/Parser.h" +#include "idlib/Base64.h" +#include "idlib/CmdArgs.h" + +// containers +#include "idlib/containers/BTree.h" +#include "idlib/containers/BinSearch.h" +#include "idlib/containers/HashIndex.h" +#include "idlib/containers/HashTable.h" +#include "idlib/containers/StaticList.h" +#include "idlib/containers/LinkList.h" +#include "idlib/containers/Hierarchy.h" +#include "idlib/containers/Queue.h" +#include "idlib/containers/Stack.h" +#include "idlib/containers/StrList.h" +#include "idlib/containers/StrPool.h" +#include "idlib/containers/VectorSet.h" +#include "idlib/containers/PlaneSet.h" + +// hashing +#include "idlib/hashing/CRC32.h" +#include "idlib/hashing/MD4.h" +#include "idlib/hashing/MD5.h" + +// misc +#include "idlib/Dict.h" +#include "idlib/LangDict.h" +#include "idlib/BitMsg.h" +#include "idlib/MapFile.h" +#include "idlib/Timer.h" + +// framework +#include "framework/BuildVersion.h" +#include "framework/Licensee.h" +#include "framework/CmdSystem.h" +#include "framework/CVarSystem.h" +#include "framework/Common.h" +#include "framework/File.h" +#include "framework/FileSystem.h" +#include "framework/UsercmdGen.h" + +// decls +#include "framework/DeclManager.h" +#include "framework/DeclTable.h" +#include "framework/DeclSkin.h" +#include "framework/DeclEntityDef.h" +#include "framework/DeclFX.h" +#include "framework/DeclParticle.h" +#include "framework/DeclAF.h" +#include "framework/DeclPDA.h" + +// We have expression parsing and evaluation code in multiple places: +// materials, sound shaders, and guis. We should unify them. + +// renderer +#include "renderer/qgl.h" +#include "renderer/Cinematic.h" +#include "renderer/Material.h" +#include "renderer/Model.h" +#include "renderer/ModelManager.h" +#include "renderer/RenderSystem.h" +#include "renderer/RenderWorld.h" + +// sound engine +#include "sound/sound.h" + +// asynchronous networking +#include "framework/async/NetworkSystem.h" + +// user interfaces +#include "ui/ListGUI.h" +#include "ui/UserInterface.h" + +// collision detection system +#include "cm/CollisionModel.h" + +// AAS files and manager +#include "tools/compilers/aas/AASFile.h" +#include "tools/compilers/aas/AASFileManager.h" + +// game interface +#include "framework/Game.h" + +//----------------------------------------------------- + +#include "framework/DemoChecksum.h" + +// framework +#include "framework/Compressor.h" +#include "framework/EventLoop.h" +#include "framework/KeyInput.h" +#include "framework/EditField.h" +#include "framework/Console.h" +#include "framework/DemoFile.h" +#include "framework/Session.h" + +// asynchronous networking +#include "framework/async/AsyncNetwork.h" + +// Compilers for map, model, video etc. processing. +#include "tools/compilers/compiler_public.h" + +#endif // DEBUGGER_COMMON_H diff --git a/neo/tools/edit_stub.cpp b/neo/tools/edit_stub.cpp index 79c2c887..34d99e14 100644 --- a/neo/tools/edit_stub.cpp +++ b/neo/tools/edit_stub.cpp @@ -67,10 +67,6 @@ bool GUIEditorHandleMessage( void *msg ) { return false; } void DebuggerClientLaunch( void ) {} void DebuggerClientInit( const char *cmdline ) { common->Printf( "The Script Debugger Client only runs on Win32\n" ); } -bool DebuggerServerInit( void ) { return false; } -void DebuggerServerShutdown( void ) {} -void DebuggerServerPrint( const char *text ) {} -void DebuggerServerCheckBreakpoint( idInterpreter *interpreter, idProgram *program, int instructionPointer ) {} void PDAEditorInit( const idDict *spawnArgs ) { common->Printf( "The PDA editor only runs on Win32\n" ); } From 85167fa1802ad667e0dd654768d3e68b9c776204 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 24 May 2021 22:27:00 +0200 Subject: [PATCH 12/42] - fixed deadlock fix for debugger server --- neo/framework/Common.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 4782c3de..7e7e5014 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -389,9 +389,11 @@ void idCommonLocal::VPrintf( const char *fmt, va_list args ) { // print to script debugger server if ( com_editors & EDITOR_DEBUGGER ) DebuggerServerPrint( msg ); + else + // only echo to dedicated console and early console when debugger is not running so no + // deadlocks occur if engine functions called from the debuggerthread trace stuff.. + Sys_Printf( "%s", msg ); } else { - // only echo to dedicated console and early console when debugger is not running so no - // deadlocks occur if engine functions called from the debuggerthread trace stuff.. Sys_Printf( "%s", msg ); } #if 0 // !@# From 6b6b28a4018ff4374f519b5008751557436131c9 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 25 May 2021 21:22:12 +0200 Subject: [PATCH 13/42] Make DebuggerServer portable (use SDL instead of WinAPI) --- neo/game/script/Script_Program.h | 2 +- neo/tools/debugger/DebuggerClient.cpp | 2 +- neo/tools/debugger/DebuggerServer.cpp | 66 +++++++++++++++++++-------- neo/tools/debugger/DebuggerServer.h | 7 ++- neo/tools/debugger/debugger.cpp | 31 +++++-------- 5 files changed, 65 insertions(+), 43 deletions(-) diff --git a/neo/game/script/Script_Program.h b/neo/game/script/Script_Program.h index cd129e34..68230c1f 100644 --- a/neo/game/script/Script_Program.h +++ b/neo/game/script/Script_Program.h @@ -34,7 +34,7 @@ If you have questions concerning this license or the applicable additional terms #include "idlib/containers/HashIndex.h" #include "idlib/math/Vector.h" -//#include "GameBase.h" +#include "GameBase.h" class idEventDef; class idVarDef; diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index 038dd5ac..30632ea1 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -594,7 +594,7 @@ void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOn msg.WriteBits ( onceOnly?1:0, 1 ); msg.WriteInt ( (unsigned long) bp.GetLineNumber ( ) ); msg.WriteInt ( bp.GetID ( ) ); - msg.WriteString ( bp.GetFilename() ); + msg.WriteString ( bp.GetFilename() ); // FIXME: this implies make7bit ?! SendPacket ( msg.GetData(), msg.GetSize() ); } diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index ed972128..b65c6d8f 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -50,10 +50,17 @@ rvDebuggerServer::rvDebuggerServer ( ) mBreak = false; mBreakStepOver = false; mBreakStepInto = false; - mGameThread = NULL; + mGameThreadBreakCond = NULL; + mGameThreadBreakLock = NULL; mLastStatementLine = -1; mBreakStepOverFunc1 = NULL; mBreakStepOverFunc2 = NULL; + mBreakInstructionPointer = 0; + mBreakInterpreter = NULL; + mBreakProgram = NULL; + mGameDLLHandle = 0; + mBreakStepOverDepth = 0; + mCriticalSection = NULL; } /* @@ -81,12 +88,14 @@ bool rvDebuggerServer::Initialize ( void ) return false; } - // Get a copy of the game thread handle so we can suspend the thread on a break - DuplicateHandle ( GetCurrentProcess(), GetCurrentThread ( ), GetCurrentProcess(), &mGameThread, 0, FALSE, DUPLICATE_SAME_ACCESS ); + // we're using a condition variable to pause the game thread in rbDebuggerServer::Break() + // until rvDebuggerServer::Resume() is called (from another thread) + mGameThreadBreakCond = SDL_CreateCond(); + mGameThreadBreakLock = SDL_CreateMutex(); // Create a critical section to ensure that the shared thread // variables are protected - InitializeCriticalSection ( &mCriticalSection ); + mCriticalSection = SDL_CreateMutex(); // Server must be running on the local host on port 28980 Sys_StringToNetAdr ( "localhost", &mClientAdr, true ); @@ -129,8 +138,16 @@ void rvDebuggerServer::Shutdown ( void ) mPort.Close(); + Resume(); // just in case we're still paused + // dont need the crit section anymore - DeleteCriticalSection ( &mCriticalSection ); + SDL_DestroyMutex( mCriticalSection ); + mCriticalSection = NULL; + + SDL_DestroyCond( mGameThreadBreakCond ); + mGameThreadBreakCond = NULL; + SDL_DestroyMutex( mGameThreadBreakLock ); + mGameThreadBreakLock = NULL; } /* @@ -274,14 +291,14 @@ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg ) bool onceOnly = false; long lineNumber; long id; - char filename[MAX_PATH]; + char filename[2048]; // DG: randomly chose this size // Read the breakpoint info onceOnly = msg->ReadBits ( 1 ) ? true : false; lineNumber = msg->ReadInt ( ); id = msg->ReadInt ( ); - msg->ReadString ( filename, MAX_PATH ); + msg->ReadString ( filename, sizeof(filename) ); //check for statement on requested breakpoint location if (!gameEdit->IsLineCode(filename, lineNumber)) @@ -299,9 +316,9 @@ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg ) } - EnterCriticalSection ( &mCriticalSection ); + SDL_LockMutex( mCriticalSection ); mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id ) ); - LeaveCriticalSection ( &mCriticalSection ); + SDL_UnlockMutex( mCriticalSection ); } /* @@ -323,7 +340,7 @@ void rvDebuggerServer::HandleRemoveBreakpoint ( idBitMsg* msg ) // Since breakpoints are used by both threads we need to // protect them with a crit section - EnterCriticalSection ( &mCriticalSection ); + SDL_LockMutex( mCriticalSection ); // Find the breakpoint that matches the given id and remove it from the list for ( i = 0; i < mBreakpoints.Num(); i ++ ) @@ -336,7 +353,7 @@ void rvDebuggerServer::HandleRemoveBreakpoint ( idBitMsg* msg ) } } - LeaveCriticalSection ( &mCriticalSection ); + SDL_UnlockMutex( mCriticalSection ); } /* @@ -543,7 +560,7 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* OSPathToRelativePath(filename,qpath); qpath.BackSlashesToSlashes ( ); - EnterCriticalSection ( &mCriticalSection ); + SDL_LockMutex( mCriticalSection ); // Check all the breakpoints for ( i = 0; i < mBreakpoints.Num ( ); i ++ ) @@ -563,19 +580,19 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* } // Pop out of the critical section so we dont get stuck - LeaveCriticalSection ( &mCriticalSection ); + SDL_UnlockMutex( mCriticalSection ); HandleInspectScripts(nullptr); // We hit a breakpoint, so break Break ( interpreter, program, instructionPointer ); // Back into the critical section since we are going to have to leave it - EnterCriticalSection ( &mCriticalSection ); + SDL_LockMutex( mCriticalSection ); break; } - LeaveCriticalSection ( &mCriticalSection ); + SDL_UnlockMutex( mCriticalSection ); } /* @@ -625,18 +642,26 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i // Suspend the game thread. Since this will be called from within the main game thread // execution wont return until after the thread is resumed - SuspendThread ( mGameThread ); + // DG: the original code used Win32 SuspendThread() here, but as there is no equivalent + // function in SDL and as this is only called within the main game thread anyway, + // just use a condition variable to put this thread to sleep until Resume() has set mBreak + SDL_LockMutex( mGameThreadBreakLock ); + while ( mBreak ) { + SDL_CondWait( mGameThreadBreakCond, mGameThreadBreakLock ); + } + SDL_UnlockMutex( mGameThreadBreakLock ); // Let the debugger client know that we have started back up again SendMessage ( DBMSG_RESUMED ); + // this should be platform specific + // TODO: maybe replace with SDL code? or does it not matter if debugger client runs on another machine? +#if defined( ID_ALLOW_TOOLS ) // This is to give some time between the keypress that // told us to resume and the setforeground window. Otherwise the quake window // would just flash Sleep ( 150 ); -//this should be platform specific -#if defined( ID_ALLOW_TOOLS ) // Bring the window back to the foreground SetForegroundWindow ( win32.hWnd ); SetActiveWindow ( win32.hWnd ); @@ -671,7 +696,10 @@ void rvDebuggerServer::Resume ( void ) mBreak = false; // Start the game thread back up - ResumeThread ( mGameThread ); + SDL_LockMutex( mGameThreadBreakLock ); + mBreak = true; + SDL_CondSignal( mGameThreadBreakCond); + SDL_UnlockMutex( mGameThreadBreakLock ); } /* diff --git a/neo/tools/debugger/DebuggerServer.h b/neo/tools/debugger/DebuggerServer.h index 0473b9ed..5111d8b0 100644 --- a/neo/tools/debugger/DebuggerServer.h +++ b/neo/tools/debugger/DebuggerServer.h @@ -32,6 +32,7 @@ If you have questions concerning this license or the applicable additional terms #include "DebuggerMessages.h" #include "DebuggerBreakpoint.h" #include "framework/Game.h" +#include @@ -83,11 +84,13 @@ private: netadr_t mClientAdr; idPort mPort; idList mBreakpoints; - CRITICAL_SECTION mCriticalSection; + SDL_mutex* mCriticalSection; - HANDLE mGameThread; + SDL_cond* mGameThreadBreakCond; + SDL_mutex* mGameThreadBreakLock; bool mBreak; + bool mBreakNext; bool mBreakStepOver; bool mBreakStepInto; diff --git a/neo/tools/debugger/debugger.cpp b/neo/tools/debugger/debugger.cpp index 99d843f4..55b2f472 100644 --- a/neo/tools/debugger/debugger.cpp +++ b/neo/tools/debugger/debugger.cpp @@ -36,20 +36,14 @@ If you have questions concerning this license or the applicable additional terms #include "DebuggerServer.h" -DWORD CALLBACK DebuggerThread ( LPVOID param ); - #if defined( ID_ALLOW_TOOLS ) -rvDebuggerApp gDebuggerApp; -HWND gDebuggerWindow = NULL; +rvDebuggerApp gDebuggerApp; // this is also used in other source files +static HWND gDebuggerWindow = NULL; #endif -bool gDebuggerSuspend = false; -bool gDebuggerConnnected = false; -HANDLE gDebuggerGameThread = NULL; -rvDebuggerServer* gDebuggerServer = NULL; -HANDLE gDebuggerServerThread = NULL; -DWORD gDebuggerServerThreadID = 0; -bool gDebuggerServerQuit = false; +static rvDebuggerServer* gDebuggerServer = NULL; +static SDL_Thread* gDebuggerServerThread = NULL; +static bool gDebuggerServerQuit = false; #if defined( ID_ALLOW_TOOLS ) /* @@ -128,14 +122,14 @@ DebuggerServerThread Thread proc for the debugger server ================ */ -DWORD CALLBACK DebuggerServerThread ( LPVOID param ) +static int SDLCALL DebuggerServerThread ( void *param ) { assert ( gDebuggerServer ); while ( !gDebuggerServerQuit ) { gDebuggerServer->ProcessMessages ( ); - Sleep ( 1 ); + SDL_Delay( 1 ); } return 0; @@ -172,7 +166,7 @@ bool DebuggerServerInit ( void ) } // Start the debugger server thread - gDebuggerServerThread = CreateThread ( NULL, 0, DebuggerServerThread, 0, 0, &gDebuggerServerThreadID ); + gDebuggerServerThread = SDL_CreateThread( DebuggerServerThread, "DebuggerServer", NULL ); return true; } @@ -186,23 +180,20 @@ Shuts down the debugger server */ void DebuggerServerShutdown ( void ) { - if ( gDebuggerServerThread ) + if ( gDebuggerServerThread != NULL ) { // Signal the debugger server to quit gDebuggerServerQuit = true; // Wait for the thread to finish - WaitForSingleObject ( gDebuggerServerThread, INFINITE ); + SDL_WaitThread( gDebuggerServerThread, NULL ); + gDebuggerServerThread = NULL; // Shutdown the server now gDebuggerServer->Shutdown(); delete gDebuggerServer; gDebuggerServer = NULL; - - // Cleanup the thread handle - CloseHandle ( gDebuggerServerThread ); - gDebuggerServerThread = NULL; } } From 2cff2ae137db42b3eb2e5719958579469e615f1a Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Thu, 27 May 2021 03:39:18 +0200 Subject: [PATCH 14/42] DebuggerServer: should now also work with SDL1.2 --- neo/tools/debugger/debugger.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/neo/tools/debugger/debugger.cpp b/neo/tools/debugger/debugger.cpp index 55b2f472..cb7afd34 100644 --- a/neo/tools/debugger/debugger.cpp +++ b/neo/tools/debugger/debugger.cpp @@ -166,7 +166,12 @@ bool DebuggerServerInit ( void ) } // Start the debugger server thread +#if SDL_VERSION_ATLEAST(2, 0, 0) gDebuggerServerThread = SDL_CreateThread( DebuggerServerThread, "DebuggerServer", NULL ); +#else // SDL 1.2 + gDebuggerServerThread = SDL_CreateThread( DebuggerServerThread, NULL ); +#endif + return true; } From 0b644a1648bceb77156eeec32cfe4cd71b31491a Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Fri, 4 Jun 2021 02:58:08 +0200 Subject: [PATCH 15/42] Fix crashes on shutdown idCommonLocal::VPrintf() wanted to call session->UpdateScreen() even though the renderer was in the process of being shut down and that caused crashes --- neo/renderer/RenderSystem_init.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index f14bb059..2a8d0f43 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -2156,6 +2156,8 @@ idRenderSystemLocal::Shutdown void idRenderSystemLocal::Shutdown( void ) { common->Printf( "idRenderSystem::Shutdown()\n" ); + common->SetRefreshOnPrint( false ); // without a renderer there's nothing to refresh + R_DoneFreeType( ); if ( glConfig.isInitialized ) { From c2b34e6fe8360377cc666ad75476da6bc6d163ac Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Fri, 4 Jun 2021 02:58:57 +0200 Subject: [PATCH 16/42] Remove idBitMsg::Read/WriteInt64() again not used anymore --- neo/idlib/BitMsg.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/neo/idlib/BitMsg.h b/neo/idlib/BitMsg.h index 2733b4a5..f27b2dab 100644 --- a/neo/idlib/BitMsg.h +++ b/neo/idlib/BitMsg.h @@ -85,7 +85,6 @@ public: void WriteShort( int c ); void WriteUShort( int c ); void WriteInt( int c ); - void WriteInt64(int64_t c); void WriteFloat( float f ); void WriteFloat( float f, int exponentBits, int mantissaBits ); void WriteAngle8( float f ); @@ -115,7 +114,6 @@ public: int ReadShort( void ) const; int ReadUShort( void ) const; int ReadInt( void ) const; - int64_t ReadInt64( void ) const; float ReadFloat( void ) const; float ReadFloat( int exponentBits, int mantissaBits ) const; float ReadAngle8( void ) const; @@ -302,13 +300,6 @@ ID_INLINE void idBitMsg::WriteInt( int c ) { WriteBits( c, 32 ); } -ID_INLINE void idBitMsg::WriteInt64(int64_t c) { - uint64_t uc = c; - - WriteBits(uc & 0xFFFFFFFF, 32); - WriteBits((uc >> 32) & 0xFFFFFFFF, 32); -} - ID_INLINE void idBitMsg::WriteFloat( float f ) { WriteBits( *reinterpret_cast(&f), 32 ); } @@ -389,15 +380,6 @@ ID_INLINE int idBitMsg::ReadInt( void ) const { return ReadBits( 32 ); } -ID_INLINE int64_t idBitMsg::ReadInt64(void) const { - uint32_t uc1, uc2; - - uc1 = ReadBits(32); - uc2 = ReadBits(32); - - return (uint64_t)uc1 | (uint64_t)uc2 << 32; -} - ID_INLINE float idBitMsg::ReadFloat( void ) const { float value; *reinterpret_cast(&value) = ReadBits( 32 ); From 8a455c3c7a413686e665ea6d933044847e43504d Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sun, 13 Jun 2021 02:35:00 +0200 Subject: [PATCH 17/42] - Debugger server can be toggled with : com_enableDebuggerServer [1 / 0] - Added com_dbgClientAdr for debugger server to connect to - Added com_dbgServerAdr for the debugger client to connect to --- neo/framework/Common.cpp | 8 +++++++- neo/framework/Common.h | 2 ++ neo/tools/debugger/DebuggerClient.cpp | 2 +- neo/tools/debugger/DebuggerServer.cpp | 2 +- neo/tools/debugger/DebuggerServer.h | 22 +++++++++++----------- neo/tools/debugger/debugger.cpp | 6 ++++++ 6 files changed, 28 insertions(+), 14 deletions(-) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 7e7e5014..5659f56f 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -98,7 +98,9 @@ idCVar com_timescale( "timescale", "1", CVAR_SYSTEM | CVAR_FLOAT, "scales the ti idCVar com_makingBuild( "com_makingBuild", "0", CVAR_BOOL | CVAR_SYSTEM, "1 when making a build" ); idCVar com_updateLoadSize( "com_updateLoadSize", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "update the load size after loading a map" ); -idCVar com_enableDebuggerServer( "com_enableDebuggerServer", "0", CVAR_BOOL | CVAR_SYSTEM, "set to 1 on startup to enable debugging with the DHEWM3 debugger" ); +idCVar com_enableDebuggerServer( "com_enableDebuggerServer", "0", CVAR_BOOL | CVAR_SYSTEM, "toggle debugger server and try to connect to com_dbgClientAdr" ); +idCVar com_dbgClientAdr( "com_dbgClientAdr", "localhost", CVAR_SYSTEM | CVAR_ARCHIVE, "debuggerApp client address" ); +idCVar com_dbgServerAdr( "com_dbgServerAdr", "localhost", CVAR_SYSTEM | CVAR_ARCHIVE, "debugger server address" ); idCVar com_product_lang_ext( "com_product_lang_ext", "1", CVAR_INTEGER | CVAR_SYSTEM | CVAR_ARCHIVE, "Extension to use when creating language files." ); @@ -2406,6 +2408,10 @@ void idCommonLocal::Frame( void ) { InitSIMD(); } + if ( com_enableDebuggerServer.IsModified( ) ) { + com_enableDebuggerServer.GetBool( ) ? DebuggerServerInit( ) : DebuggerServerShutdown( ); + } + eventLoop->RunEventLoop(); com_frameTime = com_ticNumber * USERCMD_MSEC; diff --git a/neo/framework/Common.h b/neo/framework/Common.h index d535fa7d..a471d4a5 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -74,6 +74,8 @@ extern idCVar com_showSoundDecoders; extern idCVar com_makingBuild; extern idCVar com_updateLoadSize; extern idCVar com_enableDebuggerServer; +extern idCVar com_dbgClientAdr; +extern idCVar com_dbgServerAdr; extern int time_gameFrame; // game logic time extern int time_gameDraw; // game present time diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index 30632ea1..f9eb6cc7 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -73,7 +73,7 @@ bool rvDebuggerClient::Initialize ( void ) } // Server must be running on the local host on port 28980 - Sys_StringToNetAdr ( "localhost", &mServerAdr, true ); + Sys_StringToNetAdr ( com_dbgServerAdr.GetString( ), &mServerAdr, true ); mServerAdr.port = 27980; // Attempt to let the server know we are here. The server may not be running so this diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index b65c6d8f..12fc9f6c 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -98,7 +98,7 @@ bool rvDebuggerServer::Initialize ( void ) mCriticalSection = SDL_CreateMutex(); // Server must be running on the local host on port 28980 - Sys_StringToNetAdr ( "localhost", &mClientAdr, true ); + Sys_StringToNetAdr ( com_dbgClientAdr.GetString( ), &mClientAdr, true ); mClientAdr.port = 27981; // Attempt to let the server know we are here. The server may not be running so this diff --git a/neo/tools/debugger/DebuggerServer.h b/neo/tools/debugger/DebuggerServer.h index 5111d8b0..bcd44a99 100644 --- a/neo/tools/debugger/DebuggerServer.h +++ b/neo/tools/debugger/DebuggerServer.h @@ -53,9 +53,9 @@ public: bool IsConnected ( void ); - void CheckBreakpoints ( idInterpreter* interpreter, idProgram* program, int instructionPointer ); + void CheckBreakpoints ( idInterpreter *interpreter, idProgram *program, int instructionPointer ); - void Print ( const char* text ); + void Print ( const char *text ); void OSPathToRelativePath ( const char *osPath, idStr &qpath ); @@ -64,20 +64,20 @@ private: void ClearBreakpoints ( void ); - void Break ( idInterpreter* interpreter, idProgram* program, int instructionPointer ); + void Break ( idInterpreter *interpreter, idProgram *program, int instructionPointer ); void Resume ( void ); void SendMessage ( EDebuggerMessage dbmsg ); void SendPacket ( void* data, int datasize ); // Message handlers - void HandleAddBreakpoint ( idBitMsg * msg ); - void HandleRemoveBreakpoint ( idBitMsg * msg ); - void HandleResume ( idBitMsg * msg ); - void HandleInspectVariable ( idBitMsg * msg ); - void HandleInspectCallstack ( idBitMsg * msg ); - void HandleInspectThreads ( idBitMsg * msg ); - void HandleInspectScripts ( idBitMsg * msg ); + void HandleAddBreakpoint ( idBitMsg *msg ); + void HandleRemoveBreakpoint ( idBitMsg *msg ); + void HandleResume ( idBitMsg *msg ); + void HandleInspectVariable ( idBitMsg *msg ); + void HandleInspectCallstack ( idBitMsg *msg ); + void HandleInspectThreads ( idBitMsg *msg ); + void HandleInspectScripts ( idBitMsg *msg ); //// bool mConnected; @@ -123,7 +123,7 @@ ID_INLINE bool rvDebuggerServer::IsConnected ( void ) rvDebuggerServer::SendPacket ================ */ -ID_INLINE void rvDebuggerServer::SendPacket ( void* data, int size ) +ID_INLINE void rvDebuggerServer::SendPacket ( void *data, int size ) { mPort.SendPacket ( mClientAdr, data, size ); } diff --git a/neo/tools/debugger/debugger.cpp b/neo/tools/debugger/debugger.cpp index cb7afd34..32614c8f 100644 --- a/neo/tools/debugger/debugger.cpp +++ b/neo/tools/debugger/debugger.cpp @@ -164,6 +164,8 @@ bool DebuggerServerInit ( void ) gDebuggerServer = NULL; return false; } + + com_enableDebuggerServer.ClearModified( ); // Start the debugger server thread #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -199,7 +201,11 @@ void DebuggerServerShutdown ( void ) delete gDebuggerServer; gDebuggerServer = NULL; + + com_editors &= ~EDITOR_DEBUGGER; } + + com_enableDebuggerServer.ClearModified( ); } /* From 02dcd0078875cdb9267c2d1e5ea879962eeeae3d Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 31 May 2021 13:57:45 +0200 Subject: [PATCH 18/42] - Hide game window when launching script debugger --- neo/tools/debugger/debugger.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/neo/tools/debugger/debugger.cpp b/neo/tools/debugger/debugger.cpp index 32614c8f..85c7d964 100644 --- a/neo/tools/debugger/debugger.cpp +++ b/neo/tools/debugger/debugger.cpp @@ -65,6 +65,9 @@ void DebuggerClientInit( const char *cmdline ) { goto DebuggerClientInitDone; } + + // hide the doom window by default + ::ShowWindow( win32.hWnd, SW_HIDE ); gDebuggerApp.Run ( ); From d7be3964d4d0b0ef859191b2c1e1dc0418a8703b Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sun, 13 Jun 2021 20:42:02 +0200 Subject: [PATCH 19/42] - always accept debugger messages from loopback --- neo/tools/debugger/DebuggerServer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 12fc9f6c..f95ee04b 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -171,11 +171,11 @@ bool rvDebuggerServer::ProcessMessages ( void ) msg.Init(buffer, sizeof(buffer)); msg.SetSize(msgSize); msg.BeginReading(); - - // Only accept packets from the debugger server for security reasons - if ( !Sys_CompareNetAdrBase ( adrFrom, mClientAdr ) ) - { - continue; + + if ( adrFrom.type != NA_LOOPBACK ) { + // Only accept packets from the debugger server for security reasons + if ( !Sys_CompareNetAdrBase( adrFrom, mClientAdr ) ) + continue; } command = msg.ReadShort( ); From 5260de58c4b8b9f66d928705cd1d79d4df89f329 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sun, 13 Jun 2021 20:50:13 +0200 Subject: [PATCH 20/42] - fixed command line arguments for game when debugger client launches it. --- neo/tools/debugger/DebuggerWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 83b8e895..4b6e215f 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -1126,7 +1126,7 @@ int rvDebuggerWindow::HandleCommand ( WPARAM wparam, LPARAM lparam ) GetCurrentDirectory ( MAX_PATH, curDir ); GetModuleFileName ( NULL, exeFile, MAX_PATH ); - const char* s = va("%s +set fs_game %s +set fs_cdpath %s", exeFile, cvarSystem->GetCVarString( "fs_game" ), cvarSystem->GetCVarString( "fs_cdpath" ) ); + const char* s = va("%s +set fs_game %s +set fs_cdpath %s +set com_enableDebuggerServer 1", exeFile, cvarSystem->GetCVarString( "fs_game" ), cvarSystem->GetCVarString( "fs_cdpath" ) ); CreateProcess ( NULL, (LPSTR)s, NULL, NULL, FALSE, 0, NULL, curDir, &startup, &process ); From d455ac5223b334c3df50c2737c6095b6d0d2a07d Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sun, 13 Jun 2021 21:39:19 +0200 Subject: [PATCH 21/42] - set com_editors appropiately when debugger forces connection. --- neo/tools/debugger/DebuggerServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index f95ee04b..bdf908c8 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -185,7 +185,7 @@ bool rvDebuggerServer::ProcessMessages ( void ) case DBMSG_CONNECT: mConnected = true; SendMessage ( DBMSG_CONNECTED ); - + com_editors |= EDITOR_DEBUGGER; break; case DBMSG_CONNECTED: From 07da116640c608b62cee89bd525dba8338b23f6a Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sun, 13 Jun 2021 22:44:39 +0200 Subject: [PATCH 22/42] Fix debugger resume --- neo/tools/debugger/DebuggerServer.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index bdf908c8..f3fe11fe 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -693,11 +693,9 @@ void rvDebuggerServer::Resume ( void ) return; } - mBreak = false; - // Start the game thread back up SDL_LockMutex( mGameThreadBreakLock ); - mBreak = true; + mBreak = false; SDL_CondSignal( mGameThreadBreakCond); SDL_UnlockMutex( mGameThreadBreakLock ); } From 40fa8a7dfa11c8f830ad1de7a9e4299a356b7776 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Mon, 14 Jun 2021 04:58:13 +0200 Subject: [PATCH 23/42] Fix script debugging when server is running on Linux the script paths were wrong, on Linux they were like "pak000.pk4/script/doom_util.script" while on Windows it's only "script/doom_util.script". Fixed idFileSystemLocal::OSPathToRelativePath() to skip ...pk4/ also fixed GCC compile error in Common.cpp --- neo/framework/Common.cpp | 8 ++++++-- neo/framework/FileSystem.cpp | 16 +++++++++++++--- neo/tools/debugger/DebuggerServer.cpp | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 5659f56f..b2e67327 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -2408,8 +2408,12 @@ void idCommonLocal::Frame( void ) { InitSIMD(); } - if ( com_enableDebuggerServer.IsModified( ) ) { - com_enableDebuggerServer.GetBool( ) ? DebuggerServerInit( ) : DebuggerServerShutdown( ); + if ( com_enableDebuggerServer.IsModified() ) { + if ( com_enableDebuggerServer.GetBool() ) { + DebuggerServerInit(); + } else { + DebuggerServerShutdown(); + } } eventLoop->RunEventLoop(); diff --git a/neo/framework/FileSystem.cpp b/neo/framework/FileSystem.cpp index bbe77f02..31b952a4 100644 --- a/neo/framework/FileSystem.cpp +++ b/neo/framework/FileSystem.cpp @@ -886,10 +886,20 @@ const char *idFileSystemLocal::OSPathToRelativePath( const char *OSPath ) { } if ( base ) { - s = strstr( base, "/" ); - if ( !s ) { - s = strstr( base, "\\" ); + // DG: on Windows base might look like "base\\pak008.pk4/script/doom_util.script" + // while on Linux it'll be more like "base/pak008.pk4/script/doom_util.script" + // I /think/ we want to get rid of the bla.pk4 part, at least that's what happens implicitly on Windows + // (I hope these problems don't exist if the file is not from a .pk4, so that case is handled like before) + s = strstr( base, ".pk4/" ); + if ( s != NULL ) { + s += 4; // skip ".pk4", but *not* the following '/', that'll be skipped below + } else { + s = strchr( base, '/' ); + if ( s == NULL ) { + s = strchr( base, '\\' ); + } } + if ( s ) { strcpy( relativePath, s + 1 ); if ( fs_debug.GetInteger() > 1 ) { diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index f3fe11fe..0b8e284e 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -110,7 +110,7 @@ bool rvDebuggerServer::Initialize ( void ) void rvDebuggerServer::OSPathToRelativePath( const char *osPath, idStr &qpath ) { - if ( strchr( osPath, ':' ) ) + if ( strchr( osPath, ':' ) ) // XXX: what about linux? { qpath = fileSystem->OSPathToRelativePath( osPath ); } From a0007f5f12c9db854d5fb1eb6e69b39d0448719a Mon Sep 17 00:00:00 2001 From: HarryVG Date: Sat, 19 Jun 2021 22:01:37 +0200 Subject: [PATCH 24/42] updated gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 48071768..f174fc58 100644 --- a/.gitignore +++ b/.gitignore @@ -11,5 +11,6 @@ /neo/.vs* /neo/out* /neo/build* +/.vs* /neo/CMakeSettings.json From 7e367a0e623ac4993314af637d4f4fd94c64b517 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 21 Jun 2021 14:59:28 +0200 Subject: [PATCH 25/42] - Added Console input / command exec to debugger --- neo/sys/win32/rc/Debugger.rc | 30 ++++++++--------- neo/sys/win32/rc/Debugger_resource.h | 1 + neo/tools/debugger/DebuggerClient.cpp | 22 ++++++++++++ neo/tools/debugger/DebuggerClient.h | 2 ++ neo/tools/debugger/DebuggerMessages.h | 3 +- neo/tools/debugger/DebuggerServer.cpp | 20 +++++++++++ neo/tools/debugger/DebuggerServer.h | 1 + neo/tools/debugger/DebuggerWindow.cpp | 48 ++++++++++++++++++++++++--- neo/tools/debugger/DebuggerWindow.h | 1 + 9 files changed, 108 insertions(+), 20 deletions(-) diff --git a/neo/sys/win32/rc/Debugger.rc b/neo/sys/win32/rc/Debugger.rc index 726848b4..d409f48f 100644 --- a/neo/sys/win32/rc/Debugger.rc +++ b/neo/sys/win32/rc/Debugger.rc @@ -126,21 +126,21 @@ IDI_DBG_EMPTY ICON "res\\dbg_empty.ico" IDR_DBG_ACCELERATORS ACCELERATORS BEGIN - VK_F9, ID_DBG_DEBUG_QUICKWATCH, VIRTKEY, SHIFT, NOINVERT - VK_F5, ID_DBG_DEBUG_RUN, VIRTKEY, NOINVERT - VK_F11, ID_DBG_DEBUG_STEPINTO, VIRTKEY, NOINVERT - VK_F10, ID_DBG_DEBUG_STEPOVER, VIRTKEY, NOINVERT - VK_F9, ID_DBG_DEBUG_TOGGLEBREAKPOINT, VIRTKEY, NOINVERT - VK_F3, ID_DBG_EDIT_FINDNEXT, VIRTKEY, NOINVERT - VK_F3, ID_DBG_EDIT_FINDPREV, VIRTKEY, SHIFT, NOINVERT - VK_F3, ID_DBG_EDIT_FINDSELECTED, VIRTKEY, CONTROL, NOINVERT - VK_F3, ID_DBG_EDIT_FINDSELECTED, VIRTKEY, CONTROL, NOINVERT - VK_F3, ID_DBG_EDIT_FINDSELECTEDPREV, VIRTKEY, SHIFT, CONTROL, - NOINVERT - VK_F4, ID_DBG_FILE_CLOSE, VIRTKEY, CONTROL, NOINVERT - VK_TAB, ID_DBG_FILE_NEXT, VIRTKEY, CONTROL, NOINVERT - "O", ID_DBG_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT - "F", ID_DBG_EDIT_FIND, VIRTKEY, CONTROL, NOINVERT + VK_F9, ID_DBG_DEBUG_QUICKWATCH, VIRTKEY, SHIFT, NOINVERT + VK_F5, ID_DBG_DEBUG_RUN, VIRTKEY, NOINVERT + VK_F11, ID_DBG_DEBUG_STEPINTO, VIRTKEY, NOINVERT + VK_F10, ID_DBG_DEBUG_STEPOVER, VIRTKEY, NOINVERT + VK_F9, ID_DBG_DEBUG_TOGGLEBREAKPOINT, VIRTKEY, NOINVERT + VK_F3, ID_DBG_EDIT_FINDNEXT, VIRTKEY, NOINVERT + VK_F3, ID_DBG_EDIT_FINDPREV, VIRTKEY, SHIFT, NOINVERT + VK_F3, ID_DBG_EDIT_FINDSELECTED, VIRTKEY, CONTROL, NOINVERT + VK_F3, ID_DBG_EDIT_FINDSELECTEDPREV, VIRTKEY, SHIFT, CONTROL,NOINVERT + VK_F4, ID_DBG_FILE_CLOSE, VIRTKEY, CONTROL, NOINVERT + VK_TAB, ID_DBG_FILE_NEXT, VIRTKEY, CONTROL, NOINVERT + VK_RETURN, ID_DBG_SEND_COMMAND, VIRTKEY, NOINVERT + "O", ID_DBG_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT + "F", ID_DBG_EDIT_FIND, VIRTKEY, CONTROL, NOINVERT + END diff --git a/neo/sys/win32/rc/Debugger_resource.h b/neo/sys/win32/rc/Debugger_resource.h index 55a6613e..2374c00e 100644 --- a/neo/sys/win32/rc/Debugger_resource.h +++ b/neo/sys/win32/rc/Debugger_resource.h @@ -76,6 +76,7 @@ If you have questions concerning this license or the applicable additional terms #define ID_DBG_EDIT_FINDPREV 22022 #define ID_DBG_EDIT_FINDSELECTEDPREV 22023 #define ID_DBG_HELP_ABOUT 22024 +#define ID_DBG_SEND_COMMAND 22025 // Next default values for new objects // diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index f9eb6cc7..fa68099e 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -661,3 +661,25 @@ void rvDebuggerClient::ClearThreads ( void ) mThreads.Clear ( ); } +/* +================ +rvDebuggerClient::SendCommand +================ +*/ +void rvDebuggerClient::SendCommand( const char *cmdStr ) +{ + idBitMsg msg; + byte buffer[MAX_MSGLEN]; + + if ( !mConnected ) { + return; + } + + msg.Init( buffer, sizeof( buffer ) ); + msg.BeginWriting( ); + msg.WriteShort( ( short ) DBMSG_EXECCOMMAND ); + msg.WriteString( cmdStr ); // FIXME: this implies make7bit ?! + + SendPacket( msg.GetData( ), msg.GetSize( ) ); +} + diff --git a/neo/tools/debugger/DebuggerClient.h b/neo/tools/debugger/DebuggerClient.h index 9a21b600..5889334e 100644 --- a/neo/tools/debugger/DebuggerClient.h +++ b/neo/tools/debugger/DebuggerClient.h @@ -88,6 +88,8 @@ public: void StepInto ( void ); void StepOver ( void ); + void SendCommand ( const char* cmdStr ); + // Breakpoints int AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly = false ); bool RemoveBreakpoint ( int bpID ); diff --git a/neo/tools/debugger/DebuggerMessages.h b/neo/tools/debugger/DebuggerMessages.h index f5eff0cd..91d8b43f 100644 --- a/neo/tools/debugger/DebuggerMessages.h +++ b/neo/tools/debugger/DebuggerMessages.h @@ -46,7 +46,8 @@ enum EDebuggerMessage DBMSG_INSPECTTHREADS, DBMSG_STEPOVER, DBMSG_STEPINTO, - DBMSG_INSPECTSCRIPTS + DBMSG_INSPECTSCRIPTS, + DBMSG_EXECCOMMAND }; #endif // DEBUGGER_MESSAGES_H_ \ No newline at end of file diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 0b8e284e..3eebfa8d 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -251,6 +251,10 @@ bool rvDebuggerServer::ProcessMessages ( void ) case DBMSG_INSPECTSCRIPTS: HandleInspectScripts( &msg ); break; + + case DBMSG_EXECCOMMAND: + HandleExecCommand( &msg ); + break; } } @@ -424,6 +428,22 @@ void rvDebuggerServer::HandleInspectThreads ( idBitMsg* msg ) SendPacket (msgOut.GetData(), msgOut.GetSize() ); } +/* +================ +rvDebuggerServer::HandleExecCommand + +Send the list of the current loaded scripts in the interpreter back to the debugger client +================ +*/ +void rvDebuggerServer::HandleExecCommand( idBitMsg *msg ) { + char cmdStr[2048]; // HvG: randomly chose this size + + msg->ReadString( cmdStr, sizeof( cmdStr ) ); + cmdSystem->BufferCommandText( CMD_EXEC_APPEND, cmdStr ); // valid command + cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "\n" ); +} + + /* ================ rvDebuggerServer::HandleInspectScripts diff --git a/neo/tools/debugger/DebuggerServer.h b/neo/tools/debugger/DebuggerServer.h index bcd44a99..efa100ad 100644 --- a/neo/tools/debugger/DebuggerServer.h +++ b/neo/tools/debugger/DebuggerServer.h @@ -78,6 +78,7 @@ private: void HandleInspectCallstack ( idBitMsg *msg ); void HandleInspectThreads ( idBitMsg *msg ); void HandleInspectScripts ( idBitMsg *msg ); + void HandleExecCommand ( idBitMsg *msg ); //// bool mConnected; diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 4b6e215f..8eb1c5f5 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -50,6 +50,7 @@ If you have questions concerning this license or the applicable additional terms #define IDC_DBG_THREADS 31008 #define IDC_DBG_TOOLBAR 31009 #define IDC_DBG_SCRIPTLIST 31010 +#define IDC_DBG_CONSOLEINPUT 31011 #define ID_DBG_FILE_MRU1 10000 @@ -765,7 +766,7 @@ int rvDebuggerWindow::HandleInitMenu ( WPARAM wParam, LPARAM lParam ) case ID_DBG_DEBUG_STEPOVER: case ID_DBG_DEBUG_STEPINTO: case ID_DBG_DEBUG_SHOWNEXTSTATEMENT: -// case ID_DBG_DEBUG_QUICKWATCH: + case ID_DBG_DEBUG_QUICKWATCH: if ( !mClient->IsConnected() || !mClient->IsStopped() ) { EnableMenuItem ( hmenu, nPos, MF_GRAYED|MF_BYPOSITION ); @@ -868,6 +869,12 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) SendMessage ( mWndConsole, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(18,10) ); SendMessage ( mWndConsole, EM_SETBKGNDCOLOR, 0, GetSysColor ( COLOR_3DFACE ) ); + mWndConsoleInput = CreateWindow( "RichEdit20A", "", WS_CHILD | ES_WANTRETURN | ES_AUTOVSCROLL | WS_VSCROLL | WS_BORDER, 0, 0, 100, 18, mWnd, ( HMENU ) IDC_DBG_CONSOLEINPUT, mInstance, 0 ); + lf.lfHeight = -MulDiv( 8, GetDeviceCaps( dc, LOGPIXELSY ), 72 ); + strcpy( lf.lfFaceName, "Arial" ); + SendMessage( mWndConsoleInput, WM_SETFONT, ( WPARAM ) CreateFontIndirect( &lf ), 0 ); + SendMessage( mWndConsoleInput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG( 18, 10 ) ); + mWndMargin = CreateWindow ( "STATIC", "", WS_VISIBLE|WS_CHILD, 0, 0, 0, 0, mWndScript, (HMENU)IDC_DBG_SPLITTER, mInstance, NULL ); SetWindowLongPtr ( mWndMargin, GWLP_USERDATA, (LONG_PTR)this ); SetWindowLongPtr ( mWndMargin, GWLP_WNDPROC, (LONG_PTR)MarginWndProc ); @@ -1058,6 +1065,36 @@ int rvDebuggerWindow::HandleCommand ( WPARAM wparam, LPARAM lparam ) switch ( id ) { + case ID_DBG_SEND_COMMAND: + { + if ( mClient->IsConnected( ) && GetFocus( ) == mWndConsoleInput ) { + GETTEXTLENGTHEX textLen; + int chars; + textLen.flags = GTL_DEFAULT | GTL_USECRLF; + textLen.codepage = CP_ACP; + chars = SendMessage( mWndConsoleInput, EM_GETTEXTLENGTHEX, ( WPARAM ) &textLen, 0 ); + + char *text = new char[chars + 1]; + + GETTEXTEX getText; + getText.cb = chars + 1; + getText.codepage = CP_ACP; + getText.flags = GT_DEFAULT | GT_USECRLF; + getText.lpDefaultChar = NULL; + getText.lpUsedDefChar = NULL; + SendMessage( mWndConsoleInput, EM_GETTEXTEX, ( WPARAM ) &getText, ( LPARAM ) text ); + idStr parse = text; + delete[] text; + + mClient->SendCommand( parse.c_str() ); + + SendMessage( mWndConsoleInput, EM_SETSEL, 0, -1 ); + SendMessage( mWndConsoleInput, EM_REPLACESEL, FALSE, ( LPARAM ) "" ); + UpdateWindow( mWndConsoleInput ); + } + break; + } + case ID_DBG_EDIT_FINDSELECTED: { idStr text; @@ -1325,7 +1362,8 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, MoveWindow ( window->mWndBorder, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); InflateRect ( &rect, -1, -1 ); MoveWindow ( window->mWndOutput, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); - MoveWindow ( window->mWndConsole, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); + MoveWindow ( window->mWndConsole, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top - s18, TRUE ); + MoveWindow ( window->mWndConsoleInput, rect.left, rect.bottom-s18, rect.right - rect.left, s18, TRUE ); MoveWindow ( window->mWndCallstack, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndWatch, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndThreads, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); @@ -1335,6 +1373,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, SendMessage(window->mWndCallstack, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); SendMessage(window->mWndOutput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); SendMessage(window->mWndConsole, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + SendMessage( window->mWndConsoleInput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG( s18, s10 ) ); break; } @@ -1562,7 +1601,6 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, } } break; - case IDC_DBG_CALLSTACK: if ( hdr->code == NM_DBLCLK ) { @@ -1607,6 +1645,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, { ShowWindow ( window->mWndOutput, SW_HIDE ); ShowWindow ( window->mWndConsole, SW_HIDE ); + ShowWindow ( window->mWndConsoleInput, SW_HIDE ); ShowWindow ( window->mWndCallstack, SW_HIDE ); ShowWindow ( window->mWndWatch, SW_HIDE ); ShowWindow ( window->mWndThreads, SW_HIDE ); @@ -1619,6 +1658,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, case 1: ShowWindow ( window->mWndConsole, SW_SHOW ); + ShowWindow( window->mWndConsoleInput, SW_SHOW ); break; case 2: @@ -1645,7 +1685,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, case WM_CLOSE: if ( window->mClient->IsConnected ( ) ) { - if ( IDNO == MessageBox ( wnd, "The debugger is currently connected to a running version of the game. Are you sure you want to close now?", "Quake 4 Script Debugger", MB_YESNO|MB_ICONQUESTION ) ) + if ( IDNO == MessageBox ( wnd, "The debugger is currently connected to a running version of the game. Are you sure you want to close now?", "Dhewm3 Script Debugger", MB_YESNO|MB_ICONQUESTION ) ) { return 0; } diff --git a/neo/tools/debugger/DebuggerWindow.h b/neo/tools/debugger/DebuggerWindow.h index cc86fe9d..1951d603 100644 --- a/neo/tools/debugger/DebuggerWindow.h +++ b/neo/tools/debugger/DebuggerWindow.h @@ -110,6 +110,7 @@ private: HWND mWndTabs; HWND mWndBorder; HWND mWndConsole; + HWND mWndConsoleInput; HWND mWndCallstack; HWND mWndScriptList; HWND mWndWatch; From d4db77b9ed24ffc0dd393d5faa828ed2b54f3861 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 28 Jun 2021 23:38:38 +0200 Subject: [PATCH 26/42] - Unbreaking Game and GameEdit API / ABI for game debugger use --- neo/d3xp/GameEdit.cpp | 12 ++++----- neo/d3xp/Game_local.cpp | 30 +++++++++++++++++------ neo/d3xp/Game_local.h | 7 +++--- neo/d3xp/script/Script_Interpreter.cpp | 26 +++++++++++--------- neo/d3xp/script/Script_Thread.cpp | 16 ++++++------ neo/framework/Common.cpp | 32 +++++++++++++++++------- neo/framework/Common.h | 9 +++++-- neo/framework/Game.h | 16 +++++++----- neo/framework/GameCallbacks_local.h | 7 ++++-- neo/framework/Session.cpp | 10 ++++---- neo/framework/async/AsyncServer.cpp | 2 +- neo/game/GameEdit.cpp | 14 +++++------ neo/game/Game_local.cpp | 31 +++++++++++++++-------- neo/game/Game_local.h | 6 ++--- neo/game/script/Script_Interpreter.cpp | 25 ++++++++++--------- neo/game/script/Script_Thread.cpp | 16 ++++++------ neo/tools/debugger/DebuggerServer.cpp | 34 ++++++++++++++------------ 17 files changed, 175 insertions(+), 118 deletions(-) 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 lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f int lastGUI; // last GUI on the lastGUIEnt - int editors; #ifdef _D3XP idEntityPtr 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(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(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(thread)->GetThreadNum(); } -const char* idGameEdit::ThreadGetName(const idThread* thread) const +const char* idGameEditExt::ThreadGetName(const idThread* thread) const { return const_cast(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(thread)->IsDoneProcessing(); } -bool idGameEdit::ThreadIsWaiting(const idThread* thread) const +bool idGameEditExt::ThreadIsWaiting(const idThread* thread) const { return const_cast(thread)->IsWaiting(); } -bool idGameEdit::ThreadIsDying(const idThread* thread) const +bool idGameEditExt::ThreadIsDying(const idThread* thread) const { return const_cast(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(thread)->GetThreadName()); msg->WriteInt(const_cast(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(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(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(thread)->GetThreadNum(); } -const char* idGameEdit::ThreadGetName(const idThread* thread) const +const char*idGameEditExt::ThreadGetName(const idThread* thread) const { return const_cast(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(thread)->IsDoneProcessing(); } -bool idGameEdit::ThreadIsWaiting(const idThread* thread) const +bool idGameEditExt::ThreadIsWaiting(const idThread* thread) const { return const_cast(thread)->IsWaiting(); } -bool idGameEdit::ThreadIsDying(const idThread* thread) const +bool idGameEditExt::ThreadIsDying(const idThread* thread) const { return const_cast(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(thread)->GetThreadName()); msg->WriteInt(const_cast(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(); From ebf53cdc21bcc8181b2a9fa4da2eae99ab7c8fab Mon Sep 17 00:00:00 2001 From: HarrievG Date: Thu, 1 Jul 2021 01:09:15 +0200 Subject: [PATCH 27/42] rev feedback v1. --- neo/d3xp/Game_local.cpp | 16 +-- neo/d3xp/script/Script_Interpreter.cpp | 178 +++++++++++++------------ neo/framework/Common.cpp | 14 +- neo/framework/Common.h | 14 +- neo/framework/GameCallbacks_local.h | 4 - neo/game/Game_local.cpp | 18 +-- neo/game/Game_local.h | 2 +- neo/game/script/Script_Interpreter.cpp | 4 +- neo/tools/debugger/debugger.cpp | 8 +- 9 files changed, 119 insertions(+), 139 deletions(-) diff --git a/neo/d3xp/Game_local.cpp b/neo/d3xp/Game_local.cpp index 38fa15bb..04a47017 100644 --- a/neo/d3xp/Game_local.cpp +++ b/neo/d3xp/Game_local.cpp @@ -302,16 +302,11 @@ void idGameLocal::Clear( void ) { #endif } -static DebuggerArgs_t * userDebuggerArgs; -static bool ( *checkDebuggerBreakpointFnPtr )( void ) = NULL; -bool IsGameDebuggerActive( idInterpreter *interpreter, idProgram *program, int instructionPointer ) { +static bool ( *updateDebuggerFnPtr )( idInterpreter *interpreter, idProgram *program, int instructionPointer ) = NULL; +bool updateGameDebugger( 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; + ret = updateDebuggerFnPtr ? updateDebuggerFnPtr( interpreter , program, instructionPointer ) : false; } return ret; } @@ -427,8 +422,7 @@ void idGameLocal::Init( void ) { Printf( "...%d aas types\n", aasList.Num() ); //debugger support - common->GetAdditionalFunction( idCommon::FT_CheckDebuggerBreakpoint, - ( idCommon::FunctionPointer * ) &checkDebuggerBreakpointFnPtr, ( void ** ) &userDebuggerArgs ); + common->GetAdditionalFunction( idCommon::FT_CheckDebuggerBreakpoint,( idCommon::FunctionPointer * ) &updateDebuggerFnPtr,NULL); } @@ -1370,7 +1364,7 @@ void idGameLocal::InitFromNewMap(const char* mapName, idRenderWorld* renderWorld 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; diff --git a/neo/d3xp/script/Script_Interpreter.cpp b/neo/d3xp/script/Script_Interpreter.cpp index 69828d08..8efd298d 100644 --- a/neo/d3xp/script/Script_Interpreter.cpp +++ b/neo/d3xp/script/Script_Interpreter.cpp @@ -36,7 +36,7 @@ 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 ); +extern bool updateGameDebugger( idInterpreter *interpreter, idProgram *program, int instructionPointer ); /* ================ @@ -181,102 +181,106 @@ void idInterpreter::Reset( void ) { doneProcessing = true; } -bool idInterpreter::GetRegisterValue(const char* name, idStr& out, int scopeDepth) { +/* +================ +idInterpreter::GetRegisterValue + +Returns a string representation of the value of the register. This is +used primarily for the debugger and debugging + +================ +*/ +bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDepth ) { varEval_t reg; - idVarDef* d; - char funcObject[1024]; - char* funcName; - const idVarDef* scope = NULL; - const idVarDef* scopeObj; - const idTypeDef* field; - const function_t* func; + idVarDef *d; + char funcObject[ 1024 ]; + char *funcName; + const idVarDef *scope = NULL; + const idVarDef *scopeObj; + const idTypeDef *field; + const function_t *func; out.Empty(); - - if (scopeDepth == -1) { + + if ( scopeDepth == -1 ) { scopeDepth = callStackDepth; - } - - if (scopeDepth == callStackDepth) { + } + + if ( scopeDepth == callStackDepth ) { func = currentFunction; + } else { + func = callStack[ scopeDepth ].f; } - else { - func = callStack[scopeDepth].f; - } - if (!func) { + if ( !func ) { return false; } - idStr::Copynz(funcObject, func->Name(), sizeof(funcObject)); - funcName = strstr(funcObject, "::"); - if (funcName) { + idStr::Copynz( funcObject, func->Name(), sizeof( funcObject ) ); + funcName = strstr( funcObject, "::" ); + if ( funcName ) { *funcName = '\0'; - scopeObj = gameLocal.program.GetDef(NULL, funcObject, &def_namespace); - funcName += 2; - if (scopeObj) + scopeObj = gameLocal.program.GetDef( NULL, funcObject, &def_namespace ); + funcName += 2; + if ( scopeObj ) { - scope = gameLocal.program.GetDef(NULL, funcName, scopeObj); + scope = gameLocal.program.GetDef( NULL, funcName, scopeObj ); } - } - else { + } else { funcName = funcObject; - scope = gameLocal.program.GetDef(NULL, func->Name(), &def_namespace); + scope = gameLocal.program.GetDef( NULL, func->Name(), &def_namespace ); scopeObj = NULL; } - if (!scope) + if ( !scope ) { return false; } - d = gameLocal.program.GetDef(NULL, name, scope); - + d = gameLocal.program.GetDef( NULL, name, scope ); + // Check the objects for it if it wasnt local to the function - if (!d) + if ( !d ) { - for (; scopeObj && scopeObj->TypeDef()->SuperClass(); scopeObj = scopeObj->TypeDef()->SuperClass()->def) + for ( ; scopeObj && scopeObj->TypeDef()->SuperClass(); scopeObj = scopeObj->TypeDef()->SuperClass()->def ) { - d = gameLocal.program.GetDef(NULL, name, scopeObj); - if (d) + d = gameLocal.program.GetDef( NULL, name, scopeObj ); + if ( d ) { break; } } - } + } - if (!d) + if ( !d ) { out = "???"; return false; } - - reg = GetVariable(d); - switch (d->Type()) { + + reg = GetVariable( d ); + switch( d->Type() ) { case ev_float: - if (reg.floatPtr) { - out = va("%g", *reg.floatPtr); - } - else { + if ( reg.floatPtr ) { + out = va("%g", *reg.floatPtr ); + } else { out = "0"; } return true; break; case ev_vector: - if (reg.vectorPtr) { - out = va("%g,%g,%g", reg.vectorPtr->x, reg.vectorPtr->y, reg.vectorPtr->z); - } - else { + if ( reg.vectorPtr ) { + out = va( "%g,%g,%g", reg.vectorPtr->x, reg.vectorPtr->y, reg.vectorPtr->z ); + } else { out = "0,0,0"; } return true; break; case ev_boolean: - if (reg.intPtr) { - out = va("%d", *reg.intPtr); - } - else { + if ( reg.intPtr ) { + out = va( "%d", *reg.intPtr ); + } else { out = "0"; } return true; @@ -284,63 +288,61 @@ bool idInterpreter::GetRegisterValue(const char* name, idStr& out, int scopeDept case ev_field: { - idEntity* entity; - idScriptObject* obj; - - if (scope == &def_namespace) { + idEntity* entity; + idScriptObject* obj; + + if ( scope == &def_namespace ) { // should never happen, but handle it safely anyway return false; } - field = d->TypeDef()->FieldType(); - entity = GetEntity(*((int*)&localstack[localstackBase])); - if (!entity || !field) + field = d->TypeDef()->FieldType(); + entity = GetEntity ( *((int*)&localstack[ localstackBase ]) ); + if ( !entity || !field ) { return false; } obj = &entity->scriptObject; - if (!obj) { + if ( !obj ) { return false; } + + switch ( field->Type() ) { + case ev_boolean: + out = va( "%d", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); + return true; - switch (field->Type()) { - case ev_boolean: - out = va("%d", *(reinterpret_cast(&obj->data[reg.ptrOffset]))); - return true; - - case ev_float: - out = va("%g", *(reinterpret_cast(&obj->data[reg.ptrOffset]))); - return true; - - case ev_string: { - const char* str; - str = reinterpret_cast(&obj->data[reg.ptrOffset]); - if (!str) { - out = "\"\""; + case ev_float: + out = va( "%g", *( reinterpret_cast( &obj->data[ reg.ptrOffset ] ) ) ); + return true; + + case ev_string: { + const char* str; + str = reinterpret_cast( &obj->data[ reg.ptrOffset ] ); + if ( !str ) { + out = "\"\""; + } else { + out = "\""; + out += str; + out += "\""; + } + return true; } - else { - out = "\""; - out += str; - out += "\""; - } - return true; - } - default: - return false; + default: + return false; } - + break; } case ev_string: - if (reg.stringPtr) { + if ( reg.stringPtr ) { out = "\""; out += reg.stringPtr; out += "\""; - } - else { + } else { out = "\"\""; } return true; @@ -1004,7 +1006,7 @@ bool idInterpreter::Execute( void ) { // next statement st = &gameLocal.program.GetStatement( instructionPointer ); - if ( !IsGameDebuggerActive( this, &gameLocal.program, instructionPointer ) + if ( !updateGameDebugger( this, &gameLocal.program, instructionPointer ) && g_debugScript.GetBool( ) ) { static int lastLineNumber = -1; diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 03f8bb1f..cfb7dbad 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -3290,13 +3290,11 @@ static bool isDemo( void ) return sessLocal.IsDemoVersion(); } -static DebuggerArgs_t userDebuggerArgs; - -static bool checkForDebuggerBreakPoint( void ) +static bool updateDebugger( idInterpreter *interpreter, idProgram *program, int instructionPointer ) { if (com_editors & EDITOR_DEBUGGER) { - DebuggerServerCheckBreakpoint( userDebuggerArgs.interpreter, userDebuggerArgs.program, userDebuggerArgs.instructionPointer ); + DebuggerServerCheckBreakpoint( interpreter, program, instructionPointer ); return true; } return false; @@ -3323,9 +3321,8 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F return true; case idCommon::FT_CheckDebuggerBreakpoint: - *out_fnptr = (idCommon::FunctionPointer)checkForDebuggerBreakPoint; - if (out_userArg != NULL ) - *out_userArg = &userDebuggerArgs; + *out_fnptr = (idCommon::FunctionPointer)updateDebugger; + return true; default: @@ -3339,13 +3336,10 @@ 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 8857a773..f6c1f691 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -117,12 +117,6 @@ class idLangDict; class idInterpreter; class idProgram; -struct DebuggerArgs_t { - idInterpreter *interpreter; - idProgram *program; - int instructionPointer; -}; - class idCommon { public: virtual ~idCommon( void ) {} @@ -277,6 +271,14 @@ 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, + // the function's signature is bool fn(void) - no arguments. + // it returns true if the game debugger is active + // relevant for mods. + FT_DebuggerActive, + // the function's signature is bool fn(idInterpreter,idProgram,int) with arguments: + // idInterpreter *interpreter, idProgram *program, int instructionPointer + // it returns true if the game debugger is active. + // relevant for mods. FT_CheckDebuggerBreakpoint, }; diff --git a/neo/framework/GameCallbacks_local.h b/neo/framework/GameCallbacks_local.h index 60f781a5..58bad7fc 100644 --- a/neo/framework/GameCallbacks_local.h +++ b/neo/framework/GameCallbacks_local.h @@ -43,10 +43,6 @@ struct idGameCallbacks { ReloadImagesCallback reloadImagesCB; void* reloadImagesUserArg; - typedef void ( *CheckBreakpointCallback )( void *userArg, idInterpreter *interpreter, idProgram *program, int instructionPointer ); - CheckBreakpointCallback checkBreakPointCB; - void* checkBreakPointUserArg; - idGameCallbacks(); // called when Game DLL is unloaded (=> the registered callbacks become invalid) diff --git a/neo/game/Game_local.cpp b/neo/game/Game_local.cpp index 110cda2e..8193cf72 100644 --- a/neo/game/Game_local.cpp +++ b/neo/game/Game_local.cpp @@ -270,18 +270,11 @@ bool IsDoom3DemoVersion() return ret; } -static DebuggerArgs_t * userDebuggerArgs; -static bool ( *checkDebuggerBreakpointFnPtr )( void ) = NULL; -bool IsGameDebuggerActive( idInterpreter *interpreter, idProgram *program, int instructionPointer ) -{ +static bool ( *updateDebuggerFnPtr )( idInterpreter *interpreter, idProgram *program, int instructionPointer ) = NULL; +bool updateGameDebugger( 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; + if ( interpreter != nullptr && program != nullptr ) { + ret = updateDebuggerFnPtr ? updateDebuggerFnPtr( interpreter, program, instructionPointer ) : false; } return ret; } @@ -368,8 +361,7 @@ 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 ); + common->GetAdditionalFunction(idCommon::FT_CheckDebuggerBreakpoint,(idCommon::FunctionPointer*) &updateDebuggerFnPtr,NULL); } /* diff --git a/neo/game/Game_local.h b/neo/game/Game_local.h index 6a346b43..df7456d1 100644 --- a/neo/game/Game_local.h +++ b/neo/game/Game_local.h @@ -293,7 +293,7 @@ public: idEntityPtr lastGUIEnt; // last entity with a GUI, used by Cmd_NextGUI_f int lastGUI; // last GUI on the lastGUIEnt - int editors; // Mirrored editors flags from common to determine which editors are running + // ---------------------- Public idGame Interface ------------------- idGameLocal(); diff --git a/neo/game/script/Script_Interpreter.cpp b/neo/game/script/Script_Interpreter.cpp index e6608d39..11fd06ab 100644 --- a/neo/game/script/Script_Interpreter.cpp +++ b/neo/game/script/Script_Interpreter.cpp @@ -36,7 +36,7 @@ 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 ); +extern bool updateGameDebugger( idInterpreter *interpreter, idProgram *program, int instructionPointer ); /* ================ @@ -1007,7 +1007,7 @@ bool idInterpreter::Execute( void ) { // next statement st = &gameLocal.program.GetStatement( instructionPointer ); - if ( !IsGameDebuggerActive( this, &gameLocal.program, instructionPointer ) + if ( !updateGameDebugger( this, &gameLocal.program, instructionPointer ) && g_debugScript.GetBool( ) ) { static int lastLineNumber = -1; diff --git a/neo/tools/debugger/debugger.cpp b/neo/tools/debugger/debugger.cpp index 85c7d964..d05a29f9 100644 --- a/neo/tools/debugger/debugger.cpp +++ b/neo/tools/debugger/debugger.cpp @@ -147,8 +147,11 @@ Starts up the debugger server */ bool DebuggerServerInit ( void ) { + com_enableDebuggerServer.ClearModified( ); + // Dont do this if we are in the debugger already - if ( com_editors & EDITOR_DEBUGGER ) + if ( gDebuggerServer != NULL + || ( com_editors & EDITOR_DEBUGGER ) ) { return false; } @@ -168,8 +171,6 @@ bool DebuggerServerInit ( void ) return false; } - com_enableDebuggerServer.ClearModified( ); - // Start the debugger server thread #if SDL_VERSION_ATLEAST(2, 0, 0) gDebuggerServerThread = SDL_CreateThread( DebuggerServerThread, "DebuggerServer", NULL ); @@ -177,7 +178,6 @@ bool DebuggerServerInit ( void ) gDebuggerServerThread = SDL_CreateThread( DebuggerServerThread, NULL ); #endif - return true; } From 61019b97ff26e6fa5863ea3d4a4d47e8262005d8 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Thu, 1 Jul 2021 09:07:35 +0200 Subject: [PATCH 28/42] rename functionType for debugger --- neo/d3xp/Game_local.cpp | 2 +- neo/framework/Common.cpp | 2 +- neo/framework/Common.h | 2 +- neo/game/Game_local.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/neo/d3xp/Game_local.cpp b/neo/d3xp/Game_local.cpp index 04a47017..f7a8ca8b 100644 --- a/neo/d3xp/Game_local.cpp +++ b/neo/d3xp/Game_local.cpp @@ -422,7 +422,7 @@ void idGameLocal::Init( void ) { Printf( "...%d aas types\n", aasList.Num() ); //debugger support - common->GetAdditionalFunction( idCommon::FT_CheckDebuggerBreakpoint,( idCommon::FunctionPointer * ) &updateDebuggerFnPtr,NULL); + common->GetAdditionalFunction( idCommon::FT_UpdateDebugger,( idCommon::FunctionPointer * ) &updateDebuggerFnPtr,NULL); } diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index cfb7dbad..19409e92 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -3320,7 +3320,7 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F // don't set *out_userArg, this function takes no arguments return true; - case idCommon::FT_CheckDebuggerBreakpoint: + case idCommon::FT_UpdateDebugger: *out_fnptr = (idCommon::FunctionPointer)updateDebugger; return true; diff --git a/neo/framework/Common.h b/neo/framework/Common.h index f6c1f691..7bf328f5 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -279,7 +279,7 @@ public: // idInterpreter *interpreter, idProgram *program, int instructionPointer // it returns true if the game debugger is active. // relevant for mods. - FT_CheckDebuggerBreakpoint, + FT_UpdateDebugger, }; // returns true if that function is available in this version of dhewm3 diff --git a/neo/game/Game_local.cpp b/neo/game/Game_local.cpp index 8193cf72..f7bc67e6 100644 --- a/neo/game/Game_local.cpp +++ b/neo/game/Game_local.cpp @@ -361,7 +361,7 @@ 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*) &updateDebuggerFnPtr,NULL); + common->GetAdditionalFunction(idCommon::FT_UpdateDebugger,(idCommon::FunctionPointer*) &updateDebuggerFnPtr,NULL); } /* From 784f1d567c3599b1d2a24bf1bc616e75d6f08785 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sat, 3 Jul 2021 01:14:49 +0200 Subject: [PATCH 29/42] - Moved debugger intialistion after GameDll load - DebuggerServer will not intialize when the additional function FT_UpdateDebugger is not set --- neo/framework/Common.cpp | 13 ++++++++----- neo/framework/Common.h | 6 ++---- neo/tools/debugger/debugger.cpp | 6 ++++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 19409e92..5f2354ae 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -116,6 +116,8 @@ volatile int com_ticNumber; // 60 hz tics int com_editors; // currently opened editor(s) bool com_editorActive; // true if an editor has focus +bool com_debuggerSupported = false; // only set to true when the updateDebugger function is set. see GetAdditionalFunction() + #ifdef _WIN32 HWND com_hwndMsg = NULL; bool com_outputMsg = false; @@ -3181,15 +3183,15 @@ void idCommonLocal::InitGame( void ) { // initialize the user interfaces uiManager->Init(); - // startup the script debugger - if ( com_enableDebuggerServer.GetBool( ) ) - DebuggerServerInit(); - PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04350" ) ); // load the game dll LoadGameDLL(); + // startup the script debugger + if ( com_enableDebuggerServer.GetBool( ) ) + DebuggerServerInit( ); + PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04351" ) ); // init the session @@ -3313,6 +3315,7 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F Warning("Called idCommon::GetAdditionalFunction() with out_fnptr == NULL!\n"); return false; } + switch(ft) { case idCommon::FT_IsDemo: @@ -3322,7 +3325,7 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F case idCommon::FT_UpdateDebugger: *out_fnptr = (idCommon::FunctionPointer)updateDebugger; - + com_debuggerSupported = true; return true; default: diff --git a/neo/framework/Common.h b/neo/framework/Common.h index 7bf328f5..3262e6cc 100644 --- a/neo/framework/Common.h +++ b/neo/framework/Common.h @@ -87,6 +87,8 @@ extern volatile int com_ticNumber; // 60 hz tics, incremented by async functio extern int com_editors; // current active editor(s) extern bool com_editorActive; // true if an editor has focus +extern bool com_debuggerSupported; // only set to true when the updateDebugger function is set. see GetAdditionalFunction() + #ifdef _WIN32 const char DMAP_MSGID[] = "DMAPOutput"; const char DMAP_DONE[] = "DMAPDone"; @@ -271,10 +273,6 @@ 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, - // the function's signature is bool fn(void) - no arguments. - // it returns true if the game debugger is active - // relevant for mods. - FT_DebuggerActive, // the function's signature is bool fn(idInterpreter,idProgram,int) with arguments: // idInterpreter *interpreter, idProgram *program, int instructionPointer // it returns true if the game debugger is active. diff --git a/neo/tools/debugger/debugger.cpp b/neo/tools/debugger/debugger.cpp index d05a29f9..3bb9043c 100644 --- a/neo/tools/debugger/debugger.cpp +++ b/neo/tools/debugger/debugger.cpp @@ -149,6 +149,12 @@ bool DebuggerServerInit ( void ) { com_enableDebuggerServer.ClearModified( ); + if ( !com_debuggerSupported ) + { + common->Warning( "Called DebuggerServerInit() without the gameDLL supporting it!\n" ); + return false; + } + // Dont do this if we are in the debugger already if ( gDebuggerServer != NULL || ( com_editors & EDITOR_DEBUGGER ) ) From b80de2b89b0dc0d5e3e034c4de4a888a0170e787 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sat, 3 Jul 2021 01:22:36 +0200 Subject: [PATCH 30/42] - correctly reset com_debuggerSupported --- neo/framework/Common.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 5f2354ae..79408923 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -2728,6 +2728,7 @@ void idCommonLocal::UnloadGameDLL( void ) { #endif + com_debuggerSupported = false; // HvG: Reset debugger availability. gameCallbacks.Reset(); // DG: these callbacks are invalid now because DLL has been unloaded } From e32b178fd143df3919d136270cfcfb877c9a3dee Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sat, 3 Jul 2021 01:33:46 +0200 Subject: [PATCH 31/42] - setting com_debuggerSupported=false in style. --- neo/framework/Common.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index 79408923..fbf2fbe2 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -116,7 +116,7 @@ volatile int com_ticNumber; // 60 hz tics int com_editors; // currently opened editor(s) bool com_editorActive; // true if an editor has focus -bool com_debuggerSupported = false; // only set to true when the updateDebugger function is set. see GetAdditionalFunction() +bool com_debuggerSupported; // only set to true when the updateDebugger function is set. see GetAdditionalFunction() #ifdef _WIN32 HWND com_hwndMsg = NULL; @@ -251,6 +251,7 @@ idCommonLocal::idCommonLocal( void ) { com_fullyInitialized = false; com_refreshOnPrint = false; com_errorEntered = 0; + com_debuggerSupported = false; strcpy( errorMessage, "" ); From fe162e626f14901819cc2784dd549d1769a1cca1 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Sat, 3 Jul 2021 21:46:16 +0200 Subject: [PATCH 32/42] - removed unused onceOnly flag for debugger breakpoints. --- neo/tools/debugger/DebuggerClient.cpp | 5 ++--- neo/tools/debugger/DebuggerClient.h | 4 ++-- neo/tools/debugger/DebuggerServer.cpp | 2 -- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index fa68099e..c1df08a4 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -495,7 +495,7 @@ rvDebuggerClient::AddBreakpoint Adds a breakpoint to the client and server with the give nfilename and linenumber ================ */ -int rvDebuggerClient::AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly ) +int rvDebuggerClient::AddBreakpoint ( const char* filename, int lineNumber ) { int index = mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber ) ); @@ -578,7 +578,7 @@ rvDebuggerClient::SendAddBreakpoint Send an individual breakpoint over to the debugger server ================ */ -void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly ) +void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp ) { idBitMsg msg; byte buffer[MAX_MSGLEN]; @@ -591,7 +591,6 @@ void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOn msg.Init( buffer, sizeof( buffer ) ); msg.BeginWriting(); msg.WriteShort ( (short)DBMSG_ADDBREAKPOINT ); - msg.WriteBits ( onceOnly?1:0, 1 ); msg.WriteInt ( (unsigned long) bp.GetLineNumber ( ) ); msg.WriteInt ( bp.GetID ( ) ); msg.WriteString ( bp.GetFilename() ); // FIXME: this implies make7bit ?! diff --git a/neo/tools/debugger/DebuggerClient.h b/neo/tools/debugger/DebuggerClient.h index 5889334e..10929ecf 100644 --- a/neo/tools/debugger/DebuggerClient.h +++ b/neo/tools/debugger/DebuggerClient.h @@ -91,7 +91,7 @@ public: void SendCommand ( const char* cmdStr ); // Breakpoints - int AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly = false ); + int AddBreakpoint ( const char* filename, int lineNumber ); bool RemoveBreakpoint ( int bpID ); void ClearBreakpoints ( void ); int GetBreakpointCount ( void ); @@ -102,7 +102,7 @@ protected: void SendMessage ( EDebuggerMessage dbmsg ); void SendBreakpoints ( void ); - void SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly = false ); + void SendAddBreakpoint ( rvDebuggerBreakpoint& bp ); void SendRemoveBreakpoint ( rvDebuggerBreakpoint& bp ); void SendPacket ( void* data, int datasize ); diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index d3f05d02..02b9176d 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -294,13 +294,11 @@ data supplied in the message. */ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg ) { - bool onceOnly = false; long lineNumber; long id; char filename[2048]; // DG: randomly chose this size // Read the breakpoint info - onceOnly = msg->ReadBits ( 1 ) ? true : false; lineNumber = msg->ReadInt ( ); id = msg->ReadInt ( ); From 6e8b6a6773f392a9ded0d4c3eb967b5122cd0be5 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 5 Jul 2021 10:09:28 +0200 Subject: [PATCH 33/42] - automatically enable com_enableDebuggerServer when launching the debugger from a game which does not have the debugger server running --- neo/framework/Common.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index fbf2fbe2..0319f764 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -1146,7 +1146,14 @@ Com_ScriptDebugger_f static void Com_ScriptDebugger_f( const idCmdArgs &args ) { // Make sure it wasnt on the command line if ( !( com_editors & EDITOR_DEBUGGER ) ) { - DebuggerClientLaunch(); + + //start debugger server if needed + if ( !com_enableDebuggerServer.GetBool() ) + com_enableDebuggerServer.SetBool( true ); + + //start debugger client. + DebuggerClientLaunch(); + } } From d7eff865af9f57e2b11f089f9be26e0213a0b4fd Mon Sep 17 00:00:00 2001 From: HarrievG Date: Mon, 5 Jul 2021 10:37:29 +0200 Subject: [PATCH 34/42] - automatically scroll the console output to last line on print --- neo/tools/debugger/DebuggerWindow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 8eb1c5f5..9bb24fa0 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -1821,10 +1821,17 @@ void rvDebuggerWindow::ProcessNetMessage ( idBitMsg* msg ) break; case DBMSG_PRINT: + { + HWND prevFocus = GetFocus(); + SetFocus ( mWndConsole ); SendMessage ( mWndConsole, EM_SETSEL, -1, -1 ); SendMessage ( mWndConsole, EM_REPLACESEL, 0, (LPARAM)(const char*)(msg->GetData()) + msg->GetReadCount() ); + SendMessage( mWndConsole, EM_SETSEL, -1, -1 ); SendMessage ( mWndConsole, EM_SCROLLCARET, 0, 0 ); + UpdateWindow( mWndConsole ); + SetFocus( prevFocus ); break; + } case DBMSG_BREAK: { From 4172b006cce9a633b3298a4516d5856403a40caa Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 13 Jul 2021 04:20:50 +0200 Subject: [PATCH 35/42] Debugger: Support OnceOnly-Breakpoints ("Run To Cursor") --- neo/tools/debugger/DebuggerBreakpoint.cpp | 3 ++- neo/tools/debugger/DebuggerBreakpoint.h | 9 ++++++++- neo/tools/debugger/DebuggerClient.cpp | 5 +++-- neo/tools/debugger/DebuggerServer.cpp | 21 ++++++++++++++++++++- neo/tools/debugger/DebuggerWindow.cpp | 20 ++++++++++++++++++++ 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/neo/tools/debugger/DebuggerBreakpoint.cpp b/neo/tools/debugger/DebuggerBreakpoint.cpp index 373140ea..89df7f57 100644 --- a/neo/tools/debugger/DebuggerBreakpoint.cpp +++ b/neo/tools/debugger/DebuggerBreakpoint.cpp @@ -36,11 +36,12 @@ If you have questions concerning this license or the applicable additional terms int rvDebuggerBreakpoint::mNextID = 1; -rvDebuggerBreakpoint::rvDebuggerBreakpoint ( const char* filename, int linenumber, int id ) +rvDebuggerBreakpoint::rvDebuggerBreakpoint ( const char* filename, int linenumber, int id, bool onceOnly ) { mFilename = filename; mLineNumber = linenumber; mEnabled = true; + mOnceOnly = onceOnly; if ( id == -1 ) { diff --git a/neo/tools/debugger/DebuggerBreakpoint.h b/neo/tools/debugger/DebuggerBreakpoint.h index da0ab5c4..84e85de1 100644 --- a/neo/tools/debugger/DebuggerBreakpoint.h +++ b/neo/tools/debugger/DebuggerBreakpoint.h @@ -34,17 +34,19 @@ class rvDebuggerBreakpoint { public: - rvDebuggerBreakpoint ( const char* filename, int linenumber, int id = -1 ); + rvDebuggerBreakpoint ( const char* filename, int linenumber, int id = -1, bool onceOnly = false ); rvDebuggerBreakpoint ( rvDebuggerBreakpoint& bp ); ~rvDebuggerBreakpoint ( void ); const char* GetFilename ( void ); int GetLineNumber ( void ); int GetID ( void ); + bool GetOnceOnly ( void ); protected: bool mEnabled; + bool mOnceOnly; int mID; int mLineNumber; idStr mFilename; @@ -68,4 +70,9 @@ ID_INLINE int rvDebuggerBreakpoint::GetID ( void ) return mID; } +ID_INLINE bool rvDebuggerBreakpoint::GetOnceOnly( void ) +{ + return mOnceOnly; +} + #endif // DEBUGGERBREAKPOINT_H_ diff --git a/neo/tools/debugger/DebuggerClient.cpp b/neo/tools/debugger/DebuggerClient.cpp index c1df08a4..3ffb3862 100644 --- a/neo/tools/debugger/DebuggerClient.cpp +++ b/neo/tools/debugger/DebuggerClient.cpp @@ -495,9 +495,9 @@ rvDebuggerClient::AddBreakpoint Adds a breakpoint to the client and server with the give nfilename and linenumber ================ */ -int rvDebuggerClient::AddBreakpoint ( const char* filename, int lineNumber ) +int rvDebuggerClient::AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly ) { - int index = mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber ) ); + int index = mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, -1, onceOnly ) ); SendAddBreakpoint ( *mBreakpoints[index] ); @@ -591,6 +591,7 @@ void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp ) msg.Init( buffer, sizeof( buffer ) ); msg.BeginWriting(); msg.WriteShort ( (short)DBMSG_ADDBREAKPOINT ); + msg.WriteBits ( bp.GetOnceOnly() ? 1 : 0, 1 ); msg.WriteInt ( (unsigned long) bp.GetLineNumber ( ) ); msg.WriteInt ( bp.GetID ( ) ); msg.WriteString ( bp.GetFilename() ); // FIXME: this implies make7bit ?! diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index 02b9176d..e8613a9f 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -321,7 +321,7 @@ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg ) SDL_LockMutex( mCriticalSection ); - mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id ) ); + mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id, onceOnly ) ); SDL_UnlockMutex( mCriticalSection ); } @@ -599,6 +599,25 @@ void rvDebuggerServer::CheckBreakpoints ( idInterpreter* interpreter, idProgram* continue; } + // DG: onceOnly support + if ( bp->GetOnceOnly() ) { + // we'll do the one Break() a few lines below; remove it here while mBreakpoints is unmodified + // (it can be modifed from the client while in Break() below) + mBreakpoints.RemoveIndex( i ); + delete bp; + + // also tell client to remove the breakpoint + idBitMsg msgOut; + byte buffer[MAX_MSGLEN]; + msgOut.Init( buffer, sizeof( buffer ) ); + msgOut.BeginWriting(); + msgOut.WriteShort( (short)DBMSG_REMOVEBREAKPOINT ); + msgOut.WriteInt( linenumber ); + msgOut.WriteString( qpath.c_str() ); + SendPacket( msgOut.GetData(), msgOut.GetSize() ); + } + // DG end + // Pop out of the critical section so we dont get stuck SDL_UnlockMutex( mCriticalSection ); diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 9bb24fa0..248cea18 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -1202,6 +1202,7 @@ int rvDebuggerWindow::HandleCommand ( WPARAM wparam, LPARAM lparam ) break; } + case 111: // DG: Debugger.rc has 'MENUITEM "Toggle &Breakpoint\tF9", 111' for the context menu no idea why 111 but this works case ID_DBG_DEBUG_TOGGLEBREAKPOINT: ToggleBreakpoint ( ); break; @@ -1277,6 +1278,23 @@ int rvDebuggerWindow::HandleCommand ( WPARAM wparam, LPARAM lparam ) UpdateScript ( ); break; } + + // DG: support "Run To Cursor" from context menu + case ID_DBG_DEBUG_RUNTOCURSOR: + { + // Find the currently selected line + DWORD sel; + SendMessage( mWndScript, EM_GETSEL, (WPARAM)&sel, 0 ); + int lineNumber = SendMessage( mWndScript, EM_LINEFROMCHAR, sel, 0 ) + 1; + + const char* filename = mScripts[mActiveScript]->GetFilename(); + mClient->AddBreakpoint( filename, lineNumber, true ); + mClient->Resume(); + break; + } + + // TODO: case ID_DBG_DEBUG_SHOWNEXTSTATEMENT: + // whatever this is supposed to do (also from context menu) } return 0; @@ -2102,6 +2120,8 @@ void rvDebuggerWindow::CreateToolbar ( void ) SendMessage( mWndToolbar, TB_ADDBITMAP, (WPARAM)4, (LPARAM) &tbab ); // Add the buttons to the toolbar + // FIXME: warning C4838: conversion from 'int' to 'BYTE' requires a narrowing conversion + // most probably because TBBUTTON has 4 more bytes in bReserved for alignment on _WIN64 TBBUTTON tbb[] = { { 0, 0, TBSTATE_ENABLED, BTNS_SEP, 0, 0, -1 }, { 8, ID_DBG_FILE_OPEN, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0, -1 }, { 0, 0, TBSTATE_ENABLED, BTNS_SEP, 0, 0, -1 }, From fbd188853c6cba7b353b8fe5003d43f0efca1107 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 13 Jul 2021 04:22:01 +0200 Subject: [PATCH 36/42] Debugger: Make "Filename" colums wider and "Line" column narrower. The "Filename" columns weren't wide enough for many script filenames --- neo/tools/debugger/DebuggerWindow.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 248cea18..5ca702e4 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -917,7 +917,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) col.cx = 20; col.pszText = ""; ListView_InsertColumn ( mWndScriptList, 0, &col); - col.cx = 150; + col.cx = 350; col.pszText = "Filename"; ListView_InsertColumn ( mWndScriptList, 1, &col ); @@ -927,10 +927,10 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) col.cx = 150; col.pszText = "Function"; ListView_InsertColumn ( mWndCallstack, 1, &col ); - col.cx = 150; + col.cx = 50; col.pszText = "Line"; ListView_InsertColumn ( mWndCallstack, 2, &col ); - col.cx = 150; + col.cx = 350; col.pszText = "Filename"; ListView_InsertColumn ( mWndCallstack, 3, &col ); From 6211d6e724f8934f4f36c0e824a96fbf69c189f5 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 13 Jul 2021 06:05:33 +0200 Subject: [PATCH 37/42] Debugger: Implement List of Breakpoints Double-clicking an entry opens the script at the correct line. Single-clicking the breakpoint symbol in the list removes the breakpoint, and so does selecting the breakpoint in the list and pressing the Del key. --- neo/tools/debugger/DebuggerWindow.cpp | 88 +++++++++++++++++++++++++++ neo/tools/debugger/DebuggerWindow.h | 2 + 2 files changed, 90 insertions(+) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 5ca702e4..d92f3801 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -51,6 +51,7 @@ If you have questions concerning this license or the applicable additional terms #define IDC_DBG_TOOLBAR 31009 #define IDC_DBG_SCRIPTLIST 31010 #define IDC_DBG_CONSOLEINPUT 31011 +#define IDC_DBG_BREAKLIST 31012 #define ID_DBG_FILE_MRU1 10000 @@ -644,6 +645,29 @@ void rvDebuggerWindow::UpdateScriptList(void) } } + +void rvDebuggerWindow::UpdateBreakpointList( void ) +{ + LVITEM item; + ListView_DeleteAllItems( mWndBreakList ); + ZeroMemory( &item, sizeof( item ) ); + item.mask = LVIF_TEXT | LVIF_IMAGE; + + int numBreakPoints = mClient->GetBreakpointCount(); + for ( int i = 0; i < numBreakPoints; i++ ) + { + rvDebuggerBreakpoint* bp = mClient->GetBreakpoint( i ); + item.iItem = ListView_GetItemCount( mWndBreakList ); + item.pszText = ""; + item.iImage = 2; // breakpoint + ListView_InsertItem( mWndBreakList, &item ); + // (Function |) Line | Filename + idStr lineStr( bp->GetLineNumber() ); + ListView_SetItemText( mWndBreakList, item.iItem, 1, (LPSTR)bp->GetFilename() ); + ListView_SetItemText( mWndBreakList, item.iItem, 2, (LPSTR)lineStr.c_str() ); + } +} + /* ================ rvDebuggerWindow::UpdateWatch @@ -905,15 +929,33 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) TabCtrl_InsertItem ( mWndTabs, 4, &item ); item.pszText = "Scripts"; TabCtrl_InsertItem ( mWndTabs, 5, &item ); + item.pszText = "Breakpoints"; + TabCtrl_InsertItem ( mWndTabs, 6, &item ); mWndCallstack = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_CALLSTACK, mInstance, NULL ); mWndWatch = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_EDITLABELS|LVS_OWNERDRAWFIXED, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_WATCH, mInstance, NULL ); mWndThreads = CreateWindow ( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_THREADS, mInstance, NULL ); mWndScriptList = CreateWindow( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_SCRIPTLIST, mInstance, NULL ); + mWndBreakList = CreateWindow( WC_LISTVIEW, "", LVS_REPORT|WS_CHILD|LVS_SHAREIMAGELISTS, 0, 0, 0, 0, mWnd, (HMENU)IDC_DBG_BREAKLIST, mInstance, NULL ); LVCOLUMN col; col.mask = LVCF_WIDTH|LVCF_TEXT; + col.cx = 20; + col.pszText = ""; + ListView_InsertColumn( mWndBreakList, 0, &col ); +#if 0 // TODO: figure out how to get the function name in UpdateBreakpointList() + col.cx = 150; + col.pszText = "Function"; + ListView_InsertColumn( mWndBreakList, 1, &col ); +#endif + col.cx = 350; + col.pszText = "Filename"; + ListView_InsertColumn( mWndBreakList, 1, &col ); + col.cx = 50; + col.pszText = "Line"; + ListView_InsertColumn( mWndBreakList, 2, &col ); + col.cx = 20; col.pszText = ""; ListView_InsertColumn ( mWndScriptList, 0, &col); @@ -967,6 +1009,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) ListView_SetImageList ( mWndScriptList, mTmpImageList, LVSIL_SMALL ); ListView_SetImageList ( mWndThreads, mImageList, LVSIL_SMALL ); ListView_SetImageList ( mWndCallstack, mImageList, LVSIL_SMALL ); + ListView_SetImageList ( mWndBreakList, mImageList, LVSIL_SMALL ); EnableWindows ( FALSE ); EnableWindow ( mWndScriptList, true ); @@ -974,6 +1017,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) ListView_SetExtendedListViewStyle ( mWndCallstack, LVS_EX_FULLROWSELECT ); ListView_SetExtendedListViewStyle ( mWndThreads, LVS_EX_FULLROWSELECT ); ListView_SetExtendedListViewStyle ( mWndScriptList, LVS_EX_FULLROWSELECT ); + ListView_SetExtendedListViewStyle ( mWndBreakList, LVS_EX_FULLROWSELECT ); gDebuggerApp.GetOptions().GetColumnWidths ( "cw_callstack", mWndCallstack ); gDebuggerApp.GetOptions().GetColumnWidths ( "cw_threads", mWndThreads ); @@ -1386,6 +1430,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, MoveWindow ( window->mWndWatch, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndThreads, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndScriptList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); + MoveWindow ( window->mWndBreakList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); SendMessage(window->mWndCallstack, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); @@ -1658,6 +1703,38 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, } } break; + + case IDC_DBG_BREAKLIST: + if ( hdr->code == NM_DBLCLK || hdr->code == NM_CLICK ) { + LPNMITEMACTIVATE ia = (LPNMITEMACTIVATE)lparam; + int sel = ia->iItem; + if ( sel != -1 ) { + rvDebuggerBreakpoint* bp = window->mClient->GetBreakpoint( sel ); + if ( bp != NULL ) { + if ( hdr->code == NM_DBLCLK ) { + // double clicked breakpoint => show it in its file + window->OpenScript( bp->GetFilename(), bp->GetLineNumber() - 1 ); + } else if( ia->iSubItem == 0 ) { + // clicked breakpoint symbol => delete breakpoint + window->mClient->RemoveBreakpoint( bp->GetID() ); + window->UpdateBreakpointList(); + } + } + } + } else if ( hdr->code == LVN_KEYDOWN ) { + // when user selects a breakpoints and presses the Del key, remove the breakpoint + int sel = ListView_GetNextItem( hdr->hwndFrom, -1, LVNI_SELECTED ); + if ( sel != -1 ) { + LPNMLVKEYDOWN kd = (LPNMLVKEYDOWN)lparam; + rvDebuggerBreakpoint* bp = window->mClient->GetBreakpoint( sel ); + if ( kd->wVKey == VK_DELETE && bp != NULL ) { + window->mClient->RemoveBreakpoint( bp->GetID() ); + window->UpdateBreakpointList(); + } + } + } + break; + case IDC_DBG_TABS: if ( hdr->code == TCN_SELCHANGE ) { @@ -1668,6 +1745,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, ShowWindow ( window->mWndWatch, SW_HIDE ); ShowWindow ( window->mWndThreads, SW_HIDE ); ShowWindow ( window->mWndScriptList, SW_HIDE ); + ShowWindow ( window->mWndBreakList, SW_HIDE ); switch ( TabCtrl_GetCurSel ( hdr->hwndFrom ) ) { case 0: @@ -1690,9 +1768,14 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, case 4: ShowWindow ( window->mWndThreads, SW_SHOW ); break; + case 5: ShowWindow(window->mWndScriptList, SW_SHOW); break; + + case 6: + ShowWindow( window->mWndBreakList, SW_SHOW ); + break; } } break; @@ -1756,6 +1839,7 @@ void rvDebuggerWindow::ProcessNetMessage ( idBitMsg* msg ) case DBMSG_REMOVEBREAKPOINT: MessageBeep(MB_ICONEXCLAMATION); InvalidateRect(mWndScript, NULL, FALSE); + UpdateBreakpointList(); break; case DBMSG_RESUMED: @@ -1858,6 +1942,7 @@ void rvDebuggerWindow::ProcessNetMessage ( idBitMsg* msg ) mCurrentStackDepth = 0; mClient->InspectVariable ( mTooltipVar, mCurrentStackDepth ); UpdateWatch ( ); + UpdateBreakpointList(); EnableWindows ( TRUE ); OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1 ); UpdateTitle ( ); @@ -2068,6 +2153,8 @@ void rvDebuggerWindow::ToggleBreakpoint ( void ) // Force a repaint of the script window InvalidateRect ( mWndScript, NULL, FALSE ); + + UpdateBreakpointList(); } /* @@ -2240,6 +2327,7 @@ int rvDebuggerWindow::HandleActivate ( WPARAM wparam, LPARAM lparam ) } } } + UpdateBreakpointList(); return 1; } diff --git a/neo/tools/debugger/DebuggerWindow.h b/neo/tools/debugger/DebuggerWindow.h index 1951d603..5b9cec0f 100644 --- a/neo/tools/debugger/DebuggerWindow.h +++ b/neo/tools/debugger/DebuggerWindow.h @@ -88,6 +88,7 @@ private: bool FindPrev ( const char* text = NULL ); bool FindNext ( const char* text = NULL ); + void UpdateBreakpointList( void ); void UpdateScriptList ( void ); void UpdateWatch ( void ); void UpdateWindowMenu ( void ); @@ -113,6 +114,7 @@ private: HWND mWndConsoleInput; HWND mWndCallstack; HWND mWndScriptList; + HWND mWndBreakList; // list of breakpoints HWND mWndWatch; HWND mWndThreads; HWND mWndToolTips; From b9833e7e6ee73401e444df3fdad66b6734300df5 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Tue, 13 Jul 2021 20:36:53 +0200 Subject: [PATCH 38/42] - Fixed Once Breakpoints - Send scriptlist on connect. - upped version info --- neo/sys/win32/rc/Debugger.rc | 8 ++++---- neo/tools/debugger/DebuggerClient.h | 2 +- neo/tools/debugger/DebuggerServer.cpp | 4 ++++ neo/tools/debugger/DebuggerWindow.cpp | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/neo/sys/win32/rc/Debugger.rc b/neo/sys/win32/rc/Debugger.rc index d409f48f..e9a1c032 100644 --- a/neo/sys/win32/rc/Debugger.rc +++ b/neo/sys/win32/rc/Debugger.rc @@ -149,17 +149,17 @@ END // Dialog // -IDD_DBG_ABOUT DIALOGEX 0, 0, 250, 80 +IDD_DBG_ABOUT DIALOGEX 0, 0, 250, 90 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About Script Debugger" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN LTEXT "Script Debugger",IDC_STATIC,35,7,81,8 - LTEXT "Version 1.0",IDC_STATIC,35,17,41,8 + LTEXT "Version 1.1",IDC_STATIC,35,17,41,8 LTEXT "Original version by Raven", IDC_STATIC, 35,28, 134, 8 - LTEXT "Dhewm3 version by Harrie van Ginneken", IDC_STATIC, 35, 38, 134, 8 - DEFPUSHBUTTON "OK",IDOK,165,60,50,14 + LTEXT "Dhewm3 version by Harrie van Ginneken \n\t\t\t\tand\n\t\t\t Daniel Gibson", IDC_STATIC, 35, 38, 134, 32 + DEFPUSHBUTTON "OK",IDOK,100,68,50,14 ICON 5098,IDC_STATIC,7,7,20,20 END diff --git a/neo/tools/debugger/DebuggerClient.h b/neo/tools/debugger/DebuggerClient.h index 10929ecf..0116bf9b 100644 --- a/neo/tools/debugger/DebuggerClient.h +++ b/neo/tools/debugger/DebuggerClient.h @@ -91,7 +91,7 @@ public: void SendCommand ( const char* cmdStr ); // Breakpoints - int AddBreakpoint ( const char* filename, int lineNumber ); + int AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly = false); bool RemoveBreakpoint ( int bpID ); void ClearBreakpoints ( void ); int GetBreakpointCount ( void ); diff --git a/neo/tools/debugger/DebuggerServer.cpp b/neo/tools/debugger/DebuggerServer.cpp index e8613a9f..612c22a4 100644 --- a/neo/tools/debugger/DebuggerServer.cpp +++ b/neo/tools/debugger/DebuggerServer.cpp @@ -187,11 +187,13 @@ bool rvDebuggerServer::ProcessMessages ( void ) case DBMSG_CONNECT: mConnected = true; SendMessage ( DBMSG_CONNECTED ); + HandleInspectScripts ( nullptr ); com_editors |= EDITOR_DEBUGGER; break; case DBMSG_CONNECTED: mConnected = true; + HandleInspectScripts( nullptr ); com_editors |= EDITOR_DEBUGGER; break; @@ -294,11 +296,13 @@ data supplied in the message. */ void rvDebuggerServer::HandleAddBreakpoint ( idBitMsg* msg ) { + bool onceOnly = false; long lineNumber; long id; char filename[2048]; // DG: randomly chose this size // Read the breakpoint info + onceOnly = msg->ReadBits( 1 ) ? true : false; lineNumber = msg->ReadInt ( ); id = msg->ReadInt ( ); diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index d92f3801..2b756f18 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -170,7 +170,7 @@ bool rvDebuggerWindow::Create ( HINSTANCE instance ) UpdateTitle ( ); - Printf ( "Dhewm3 Script Debugger v1.0\n\n" ); + Printf ( "Dhewm3 Script Debugger v1.1\n\n" ); ShowWindow ( mWnd, SW_SHOW ); UpdateWindow ( mWnd ); From 5c3d95efeec81b51a98e52be990fb6be52a9fc59 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Wed, 14 Jul 2021 23:32:28 +0200 Subject: [PATCH 39/42] - Added line nrs to script richedit --- neo/tools/debugger/DebuggerWindow.cpp | 40 +++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 2b756f18..c69636ec 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -361,7 +361,7 @@ LRESULT CALLBACK rvDebuggerWindow::ScriptWndProc ( HWND wnd, UINT msg, WPARAM wp GetWindowRect(window->mWndToolbar, &rect); MoveWindow(window->mWndMargin, 0, 0, window->mMarginSize, window->mSplitterRect.top - (rect.bottom - rect.top), TRUE); - SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18*2.25, s10)); } } @@ -412,10 +412,40 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp PAINTSTRUCT ps; RECT rect; GetClientRect ( wnd, &rect ); + dc = BeginPaint( wnd, &ps ); + FillRect( dc, &rect, GetSysColorBrush( COLOR_3DSHADOW ) ); - dc = BeginPaint ( wnd, &ps ); - FillRect ( dc, &rect, GetSysColorBrush ( COLOR_3DSHADOW ) ); + //draw line nrs + int iMaxNumberOfLines = ( (rect.bottom - rect.top ) ) + 1; + int iFirstVisibleLine = SendMessage( window->mWndScript, EM_GETFIRSTVISIBLELINE, 0, 0 ); + HFONT hf = CreateFont( height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New" ); + HFONT hfOld = ( HFONT ) SelectObject( dc, hf ); + SetBkMode( dc, OPAQUE ); + SetBkColor(dc, GetSysColor( COLOR_3DFACE )); + SetTextColor( dc, RGB( 0, 0, 255 ) ); + RECT lnrRect = rect; + lnrRect.left += rect.right - rect.left; + lnrRect.right += rect.right - rect.left; + FillRect( dc, &lnrRect, GetSysColorBrush( COLOR_3DFACE ) ); + for (int i = 0; i < iMaxNumberOfLines; ++i ) + { + int c; + POINTL pos; + c = SendMessage( window->mWndScript, EM_LINEINDEX, iFirstVisibleLine + i , 0 ); + SendMessage( window->mWndScript, EM_POSFROMCHAR, ( WPARAM ) &pos, c ); + RECT t = rect; + t.bottom += pos.y - t.top; + t.top = pos.y; + t.left += rect.right - rect.left; + t.right += rect.right - rect.left; + + idStr lntxt( iFirstVisibleLine + i + 1); + DrawText( dc, lntxt, lntxt.Length(), &t, DT_RIGHT ); + } + DeleteObject( hf ); + + //draw breakpoints if ( window->mScripts.Num ( ) ) { for ( int i = 0; i < window->mClient->GetBreakpointCount(); i ++ ) @@ -430,7 +460,7 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp c = SendMessage ( window->mWndScript, EM_LINEINDEX, bp->GetLineNumber ( ) - 1, 0 ); SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c ); - ImageList_DrawEx ( window->mTmpImageList, 2, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL ); + ImageList_DrawEx ( window->mTmpImageList, 2, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL ); } } @@ -1432,7 +1462,7 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, MoveWindow ( window->mWndScriptList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndBreakList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); - SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); + SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18*2.25, s10)); SendMessage(window->mWndCallstack, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); SendMessage(window->mWndOutput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); SendMessage(window->mWndConsole, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); From 764d23a394991afe87b320285a4bed63408eb340 Mon Sep 17 00:00:00 2001 From: HarrievG Date: Wed, 14 Jul 2021 23:37:28 +0200 Subject: [PATCH 40/42] - fixed lnr range after zoom/resize --- neo/tools/debugger/DebuggerWindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index c69636ec..8cae126d 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -416,17 +416,19 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp FillRect( dc, &rect, GetSysColorBrush( COLOR_3DSHADOW ) ); //draw line nrs - int iMaxNumberOfLines = ( (rect.bottom - rect.top ) ) + 1; + int iMaxNumberOfLines = ( (rect.bottom - rect.top ) / height ) + height; int iFirstVisibleLine = SendMessage( window->mWndScript, EM_GETFIRSTVISIBLELINE, 0, 0 ); HFONT hf = CreateFont( height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New" ); HFONT hfOld = ( HFONT ) SelectObject( dc, hf ); SetBkMode( dc, OPAQUE ); SetBkColor(dc, GetSysColor( COLOR_3DFACE )); SetTextColor( dc, RGB( 0, 0, 255 ) ); + RECT lnrRect = rect; lnrRect.left += rect.right - rect.left; lnrRect.right += rect.right - rect.left; FillRect( dc, &lnrRect, GetSysColorBrush( COLOR_3DFACE ) ); + for (int i = 0; i < iMaxNumberOfLines; ++i ) { int c; @@ -461,6 +463,7 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp c = SendMessage ( window->mWndScript, EM_LINEINDEX, bp->GetLineNumber ( ) - 1, 0 ); SendMessage ( window->mWndScript, EM_POSFROMCHAR, (WPARAM)&pos, c ); ImageList_DrawEx ( window->mTmpImageList, 2, dc, rect.left, pos.y, width, height, CLR_NONE, CLR_NONE, ILD_NORMAL ); + } } From c3d77abd2b8242be1a298b0035a11475524a3c11 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Thu, 15 Jul 2021 02:31:40 +0200 Subject: [PATCH 41/42] Script Debugger: Support line numbers up to 9999 but it's still a bit wonky with DPI-scaling I also made the rect calculations a bit more intuitive and removed a misleading comment in my breakpoint list code --- neo/tools/debugger/DebuggerWindow.cpp | 34 +++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 8cae126d..9d87f97b 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -361,7 +361,10 @@ LRESULT CALLBACK rvDebuggerWindow::ScriptWndProc ( HWND wnd, UINT msg, WPARAM wp GetWindowRect(window->mWndToolbar, &rect); MoveWindow(window->mWndMargin, 0, 0, window->mMarginSize, window->mSplitterRect.top - (rect.bottom - rect.top), TRUE); - SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18*2.25, s10)); + // FIXME: was *2.25, increased for line numbers up to 9999; but neither works particularly well + // if DPI scaling is involved, because script code text and linenumbers aren't DPI scaled + int lmargin = s18 * 3.5; + SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(lmargin, s10)); } } @@ -404,7 +407,6 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp float scaling_factor = Win_GetWindowScalingFactor(wnd); int s2 = int(2 * scaling_factor); int s4 = int(4 * scaling_factor); - int s22 = int(22 * scaling_factor); int width,height; window->ResizeImageList(width,height); @@ -421,13 +423,19 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp HFONT hf = CreateFont( height, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Courier New" ); HFONT hfOld = ( HFONT ) SelectObject( dc, hf ); SetBkMode( dc, OPAQUE ); - SetBkColor(dc, GetSysColor( COLOR_3DFACE )); + // I think it looks nicer when the line number background is white + SetBkColor( dc, RGB( 255, 255, 255 ) ); SetTextColor( dc, RGB( 0, 0, 255 ) ); + int lnrWidth = 8; + GetCharWidth32( dc, '9', '9', &lnrWidth ); + lnrWidth *= 4; // we want enough width for 4 chars ("9999"), not just one + lnrWidth += 2 * s4; // we want some space around the line number + RECT lnrRect = rect; - lnrRect.left += rect.right - rect.left; - lnrRect.right += rect.right - rect.left; - FillRect( dc, &lnrRect, GetSysColorBrush( COLOR_3DFACE ) ); + lnrRect.left = rect.right; + lnrRect.right = lnrRect.left + lnrWidth; + FillRect( dc, &lnrRect, WHITE_BRUSH ); for (int i = 0; i < iMaxNumberOfLines; ++i ) { @@ -436,11 +444,10 @@ LRESULT CALLBACK rvDebuggerWindow::MarginWndProc ( HWND wnd, UINT msg, WPARAM wp c = SendMessage( window->mWndScript, EM_LINEINDEX, iFirstVisibleLine + i , 0 ); SendMessage( window->mWndScript, EM_POSFROMCHAR, ( WPARAM ) &pos, c ); - RECT t = rect; - t.bottom += pos.y - t.top; + RECT t = lnrRect; t.top = pos.y; - t.left += rect.right - rect.left; - t.right += rect.right - rect.left; + t.bottom = t.top + height; + t.right -= s4; // a little space between text and "border" to code part of window idStr lntxt( iFirstVisibleLine + i + 1); DrawText( dc, lntxt, lntxt.Length(), &t, DT_RIGHT ); @@ -694,7 +701,7 @@ void rvDebuggerWindow::UpdateBreakpointList( void ) item.pszText = ""; item.iImage = 2; // breakpoint ListView_InsertItem( mWndBreakList, &item ); - // (Function |) Line | Filename + idStr lineStr( bp->GetLineNumber() ); ListView_SetItemText( mWndBreakList, item.iItem, 1, (LPSTR)bp->GetFilename() ); ListView_SetItemText( mWndBreakList, item.iItem, 2, (LPSTR)lineStr.c_str() ); @@ -1465,7 +1472,10 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam, MoveWindow ( window->mWndScriptList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); MoveWindow ( window->mWndBreakList, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE ); - SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18*2.25, s10)); + // FIXME: was *2.25, increased for line numbers up to 9999; but neither works particularly well + // if DPI scaling is involved, because script code text and linenumbers aren't DPI scaled + int lmargin = s18 * 3.5; + SendMessage(window->mWndScript, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(lmargin, s10)); SendMessage(window->mWndCallstack, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); SendMessage(window->mWndOutput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); SendMessage(window->mWndConsole, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(s18, s10)); From 21f1ba31619b020633876e73293e12e2fe739997 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Fri, 16 Jul 2021 02:19:27 +0200 Subject: [PATCH 42/42] Script Debugger: Scale script text according to DPI scaling and scale the breakpoint dots accordingly - now they don't looked all squashed anymore. I think ResizeImageList() is more correct now, at least this helped with the breakpoint dots. --- neo/tools/debugger/DebuggerWindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/neo/tools/debugger/DebuggerWindow.cpp b/neo/tools/debugger/DebuggerWindow.cpp index 9d87f97b..f13ea29d 100644 --- a/neo/tools/debugger/DebuggerWindow.cpp +++ b/neo/tools/debugger/DebuggerWindow.cpp @@ -868,7 +868,8 @@ void rvDebuggerWindow::ResizeImageList(int& widthOut, int& heightOut) GetTextMetrics(dc, &tm); int height = mZoomScaleDem ? (tm.tmHeight * (float)mZoomScaleNum / (float)mZoomScaleDem) : 16; - int width = mZoomScaleDem ? (s16 * (float)mZoomScaleNum / (float)mZoomScaleDem) : 16; + height *= scaling_factor; + int width = mZoomScaleDem ? (s16 * (float)mZoomScaleNum / (float)mZoomScaleDem) : s16; ImageList_Destroy(mTmpImageList); mTmpImageList = ImageList_Create(width, height, ILC_COLOR | ILC_MASK , 0, 2); @@ -915,7 +916,7 @@ int rvDebuggerWindow::HandleCreate ( WPARAM wparam, LPARAM lparam ) dc = GetDC ( mWndScript ); GetTextMetrics ( dc, &tm ); ZeroMemory ( &lf, sizeof(lf) ); - lf.lfHeight = tm.tmHeight; + lf.lfHeight = tm.tmHeight * Win_GetWindowScalingFactor( mWndScript ); strcpy ( lf.lfFaceName, "Courier New" ); SendMessage ( mWndScript, WM_SETFONT, (WPARAM)CreateFontIndirect ( &lf ), 0 );