mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-02-20 11:03:09 +00:00
Merge branch 'debugger'
This commit is contained in:
commit
5e4e1d61be
42 changed files with 2048 additions and 658 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -11,4 +11,6 @@
|
|||
/neo/.vs*
|
||||
/neo/out*
|
||||
/neo/build*
|
||||
/.vs*
|
||||
|
||||
/neo/CMakeSettings.json
|
||||
|
|
|
@ -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}
|
||||
|
@ -862,6 +873,23 @@ 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
|
||||
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")
|
||||
|
@ -881,13 +909,17 @@ 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"
|
||||
)
|
||||
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()
|
||||
|
||||
|
||||
|
@ -1052,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}")
|
||||
|
|
|
@ -670,7 +670,7 @@ void idEditEntities::DisplayEntities( void ) {
|
|||
===============================================================================
|
||||
*/
|
||||
|
||||
idGameEdit gameEditLocal;
|
||||
idGameEditExt gameEditLocal;
|
||||
idGameEdit * gameEdit = &gameEditLocal;
|
||||
|
||||
|
||||
|
@ -1146,3 +1146,62 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
Debugger
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
bool idGameEditExt::IsLineCode( const char *filename, int linenumber ) const {
|
||||
idStr fileStr;
|
||||
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 idGameEditExt::GetLoadedScripts(idStrList** result)
|
||||
{
|
||||
(*result)->Clear();
|
||||
idProgram* program = &gameLocal.program;
|
||||
|
||||
for (int i = 0; i < program->NumFilenames(); i++)
|
||||
{
|
||||
(*result)->AddUnique(idStr(program->GetFilename(i)));
|
||||
}
|
||||
}
|
||||
|
||||
void idGameEditExt::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* idGameEditExt::GetFilenameForStatement(idProgram* program, int index) const
|
||||
{
|
||||
return program->GetFilenameForStatement(index);
|
||||
}
|
||||
|
||||
int idGameEditExt::GetLineNumberForStatement(idProgram* program, int index) const
|
||||
{
|
||||
return program->GetLineNumberForStatement(index);
|
||||
}
|
||||
|
|
|
@ -302,6 +302,16 @@ void idGameLocal::Clear( void ) {
|
|||
#endif
|
||||
}
|
||||
|
||||
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 ) {
|
||||
ret = updateDebuggerFnPtr ? updateDebuggerFnPtr( interpreter , program, instructionPointer ) : false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===========
|
||||
idGameLocal::Init
|
||||
|
@ -410,6 +420,10 @@ void idGameLocal::Init( void ) {
|
|||
gamestate = GAMESTATE_NOMAP;
|
||||
|
||||
Printf( "...%d aas types\n", aasList.Num() );
|
||||
|
||||
//debugger support
|
||||
common->GetAdditionalFunction( idCommon::FT_UpdateDebugger,( idCommon::FunctionPointer * ) &updateDebuggerFnPtr,NULL);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1312,7 +1326,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) {
|
||||
|
||||
this->isServer = isServer;
|
||||
this->isClient = isClient;
|
||||
|
@ -2436,14 +2450,14 @@ 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) {
|
||||
idEntity* ent;
|
||||
int num;
|
||||
float ms;
|
||||
idTimer timer_think, timer_events, timer_singlethink;
|
||||
gameReturn_t ret;
|
||||
idPlayer* player;
|
||||
const renderView_t* view;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ( isMultiplayer ) {
|
||||
|
|
|
@ -365,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 );
|
||||
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 );
|
||||
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 );
|
||||
virtual gameReturn_t RunFrame(const usercmd_t* clientCmds );
|
||||
virtual bool Draw( int clientNum );
|
||||
virtual escReply_t HandleESC( idUserInterface **gui );
|
||||
virtual idUserInterface *StartMenu( void );
|
||||
|
|
|
@ -33,6 +33,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "script/Script_Interpreter.h"
|
||||
|
||||
#include "framework/FileSystem.h"
|
||||
|
||||
// HvG: Debugger support
|
||||
extern bool updateGameDebugger( idInterpreter *interpreter, idProgram *program, int instructionPointer );
|
||||
|
||||
/*
|
||||
================
|
||||
idInterpreter::idInterpreter()
|
||||
|
@ -183,7 +188,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 +195,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 +219,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 +269,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 +287,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<const idScriptObject **>( &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<int *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
case ev_boolean:
|
||||
out = va( "%d", *( reinterpret_cast<int *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
|
||||
case ev_float:
|
||||
out = va( "%g", *( reinterpret_cast<float *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
case ev_float:
|
||||
out = va( "%g", *( reinterpret_cast<float *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
|
||||
case ev_string: {
|
||||
const char* str;
|
||||
str = reinterpret_cast<const char*>( &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 ) {
|
||||
|
@ -313,7 +351,6 @@ bool idInterpreter::GetRegisterValue( const char *name, idStr &out, int scopeDep
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idInterpreter::GetCallstackDepth
|
||||
|
@ -969,6 +1006,19 @@ bool idInterpreter::Execute( void ) {
|
|||
// next statement
|
||||
st = &gameLocal.program.GetStatement( instructionPointer );
|
||||
|
||||
if ( !updateGameDebugger( this, &gameLocal.program, instructionPointer )
|
||||
&& 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 +1883,99 @@ bool idInterpreter::Execute( void ) {
|
|||
|
||||
return threadDying;
|
||||
}
|
||||
|
||||
|
||||
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 idGameEditExt::ReturnedFromFunction(const idProgram* program, const idInterpreter* interpreter, int index) const
|
||||
{
|
||||
|
||||
return (const_cast<idProgram*>(program)->GetStatement(index).op == OP_RETURN && interpreter->GetCallstackDepth() <= 1);
|
||||
}
|
||||
|
||||
bool idGameEditExt::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const
|
||||
{
|
||||
return const_cast<idInterpreter*>(interpreter)->GetRegisterValue(name, out, scopeDepth);
|
||||
}
|
||||
|
||||
const idThread* idGameEditExt::GetThread(const idInterpreter* interpreter) const
|
||||
{
|
||||
return interpreter->GetThread();
|
||||
}
|
||||
|
||||
void idGameEditExt::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("<UNKNOWN>");
|
||||
msg->WriteString("<UNKNOWN>");
|
||||
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<idProgram*>(program)->GetStatement(instructionPtr);
|
||||
else // Use the calling statement as the filename and linenumber where the call was made from
|
||||
st = &const_cast<idProgram*>(program)->GetStatement(stack->s);
|
||||
|
||||
if (st)
|
||||
{
|
||||
idStr qpath = const_cast<idProgram*>(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("<UNKNOWN>");
|
||||
msg->WriteInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
void idGameEditExt::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 idGameEditExt::GetInterpreterCallStackDepth(const idInterpreter* interpreter)
|
||||
{
|
||||
return interpreter->GetCallstackDepth();
|
||||
}
|
||||
|
||||
const function_t* idGameEditExt::GetInterpreterCallStackFunction(const idInterpreter* interpreter, int stackDepth/* = -1*/)
|
||||
{
|
||||
return interpreter->GetCallstack()[stackDepth > -1 ? stackDepth : interpreter->GetCallstackDepth()].f;
|
||||
}
|
|
@ -1921,3 +1921,49 @@ void idThread::Event_InfluenceActive( void ) {
|
|||
idThread::ReturnInt( false );
|
||||
}
|
||||
}
|
||||
|
||||
int idGameEditExt::ThreadGetNum(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->GetThreadNum();
|
||||
}
|
||||
|
||||
const char* idGameEditExt::ThreadGetName(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->GetThreadName();
|
||||
}
|
||||
|
||||
int idGameEditExt::GetTotalScriptThreads() const
|
||||
{
|
||||
return idThread::GetThreads().Num();
|
||||
}
|
||||
|
||||
const idThread* idGameEditExt::GetThreadByIndex(int index) const
|
||||
{
|
||||
return idThread::GetThreads()[index];
|
||||
}
|
||||
|
||||
bool idGameEditExt::ThreadIsDoneProcessing(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsDoneProcessing();
|
||||
}
|
||||
|
||||
bool idGameEditExt::ThreadIsWaiting(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsWaiting();
|
||||
}
|
||||
|
||||
bool idGameEditExt::ThreadIsDying(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsDying();
|
||||
}
|
||||
|
||||
void idGameEditExt::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter)
|
||||
{
|
||||
msg->WriteString(const_cast<idThread*>(thread)->GetThreadName());
|
||||
msg->WriteInt(const_cast<idThread*>(thread)->GetThreadNum());
|
||||
|
||||
msg->WriteBits((int)(thread == interpreter->GetThread()), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsDoneProcessing(), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsWaiting(), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsDying(), 1);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -98,6 +98,10 @@ 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, "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." );
|
||||
|
||||
// com_speeds times
|
||||
|
@ -112,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; // only set to true when the updateDebugger function is set. see GetAdditionalFunction()
|
||||
|
||||
#ifdef _WIN32
|
||||
HWND com_hwndMsg = NULL;
|
||||
bool com_outputMsg = false;
|
||||
|
@ -245,6 +251,7 @@ idCommonLocal::idCommonLocal( void ) {
|
|||
com_fullyInitialized = false;
|
||||
com_refreshOnPrint = false;
|
||||
com_errorEntered = 0;
|
||||
com_debuggerSupported = false;
|
||||
|
||||
strcpy( errorMessage, "" );
|
||||
|
||||
|
@ -382,12 +389,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 );
|
||||
|
||||
// print to script debugger server
|
||||
// DebuggerServerPrint( msg );
|
||||
|
||||
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 );
|
||||
} else {
|
||||
Sys_Printf( "%s", msg );
|
||||
}
|
||||
#if 0 // !@#
|
||||
#if defined(_DEBUG) && defined(WIN32)
|
||||
if ( strlen( msg ) < 512 ) {
|
||||
|
@ -1134,8 +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 ) ) {
|
||||
common->Printf( "Script debugger is currently disabled\n" );
|
||||
// DebuggerClientLaunch();
|
||||
|
||||
//start debugger server if needed
|
||||
if ( !com_enableDebuggerServer.GetBool() )
|
||||
com_enableDebuggerServer.SetBool( true );
|
||||
|
||||
//start debugger client.
|
||||
DebuggerClientLaunch();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2020,6 +2038,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]);
|
||||
|
@ -2398,6 +2417,14 @@ void idCommonLocal::Frame( void ) {
|
|||
InitSIMD();
|
||||
}
|
||||
|
||||
if ( com_enableDebuggerServer.IsModified() ) {
|
||||
if ( com_enableDebuggerServer.GetBool() ) {
|
||||
DebuggerServerInit();
|
||||
} else {
|
||||
DebuggerServerShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
eventLoop->RunEventLoop();
|
||||
|
||||
com_frameTime = com_ticNumber * USERCMD_MSEC;
|
||||
|
@ -2666,7 +2693,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 );
|
||||
|
@ -2709,6 +2736,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
|
||||
}
|
||||
|
||||
|
@ -3175,14 +3203,15 @@ void idCommonLocal::InitGame( void ) {
|
|||
// initialize the user interfaces
|
||||
uiManager->Init();
|
||||
|
||||
// startup the script debugger
|
||||
// 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
|
||||
|
@ -3214,7 +3243,8 @@ void idCommonLocal::ShutdownGame( bool reloading ) {
|
|||
}
|
||||
|
||||
// shutdown the script debugger
|
||||
// DebuggerServerShutdown();
|
||||
if ( com_enableDebuggerServer.GetBool() )
|
||||
DebuggerServerShutdown();
|
||||
|
||||
idAsyncNetwork::client.Shutdown();
|
||||
|
||||
|
@ -3277,11 +3307,21 @@ bool idCommonLocal::SetCallback(idCommon::CallbackType cbt, idCommon::FunctionPo
|
|||
}
|
||||
}
|
||||
|
||||
static bool isDemo(void)
|
||||
static bool isDemo( void )
|
||||
{
|
||||
return sessLocal.IsDemoVersion();
|
||||
}
|
||||
|
||||
static bool updateDebugger( idInterpreter *interpreter, idProgram *program, int instructionPointer )
|
||||
{
|
||||
if (com_editors & EDITOR_DEBUGGER)
|
||||
{
|
||||
DebuggerServerCheckBreakpoint( interpreter, program, 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)
|
||||
|
@ -3295,6 +3335,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:
|
||||
|
@ -3302,6 +3343,11 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F
|
|||
// don't set *out_userArg, this function takes no arguments
|
||||
return true;
|
||||
|
||||
case idCommon::FT_UpdateDebugger:
|
||||
*out_fnptr = (idCommon::FunctionPointer)updateDebugger;
|
||||
com_debuggerSupported = true;
|
||||
return true;
|
||||
|
||||
default:
|
||||
*out_fnptr = NULL;
|
||||
Warning("Called idCommon::SetCallback() with unknown FunctionType %d!\n", ft);
|
||||
|
@ -3309,7 +3355,6 @@ bool idCommonLocal::GetAdditionalFunction(idCommon::FunctionType ft, idCommon::F
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
idGameCallbacks gameCallbacks;
|
||||
|
||||
idGameCallbacks::idGameCallbacks()
|
||||
|
|
|
@ -73,6 +73,9 @@ extern idCVar com_showAsyncStats;
|
|||
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
|
||||
|
@ -84,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";
|
||||
|
@ -111,6 +116,8 @@ struct MemInfo_t {
|
|||
};
|
||||
|
||||
class idLangDict;
|
||||
class idInterpreter;
|
||||
class idProgram;
|
||||
|
||||
class idCommon {
|
||||
public:
|
||||
|
@ -158,6 +165,7 @@ public:
|
|||
// Writes cvars with the given flags to a file.
|
||||
virtual void WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd ) = 0;
|
||||
|
||||
|
||||
// Begins redirection of console output to the given buffer.
|
||||
virtual void BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) ) = 0;
|
||||
|
||||
|
@ -265,6 +273,11 @@ 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(idInterpreter,idProgram,int) with arguments:
|
||||
// idInterpreter *interpreter, idProgram *program, int instructionPointer
|
||||
// it returns true if the game debugger is active.
|
||||
// relevant for mods.
|
||||
FT_UpdateDebugger,
|
||||
};
|
||||
|
||||
// returns true if that function is available in this version of dhewm3
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -310,11 +316,44 @@ 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;
|
||||
|
||||
};
|
||||
|
||||
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;
|
||||
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 );
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
|
|
@ -40,9 +40,8 @@ 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;
|
||||
|
||||
idGameCallbacks();
|
||||
|
||||
|
|
|
@ -670,7 +670,7 @@ void idEditEntities::DisplayEntities( void ) {
|
|||
===============================================================================
|
||||
*/
|
||||
|
||||
idGameEdit gameEditLocal;
|
||||
idGameEditExt gameEditLocal;
|
||||
idGameEdit * gameEdit = &gameEditLocal;
|
||||
|
||||
|
||||
|
@ -1146,3 +1146,64 @@ void idGameEdit::MapEntityTranslate( const char *name, const idVec3 &v ) const {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
Debugger
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
bool idGameEditExt::IsLineCode(const char* filename, int linenumber) const
|
||||
{
|
||||
idStr fileStr;
|
||||
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 idGameEditExt::GetLoadedScripts( idStrList** result )
|
||||
{
|
||||
(*result)->Clear();
|
||||
idProgram* program = &gameLocal.program;
|
||||
|
||||
for (int i = 0; i < program->NumFilenames(); i++)
|
||||
{
|
||||
(*result)->AddUnique( idStr(program->GetFilename( i )) );
|
||||
}
|
||||
}
|
||||
|
||||
void idGameEditExt::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*idGameEditExt::GetFilenameForStatement(idProgram* program, int index) const
|
||||
{
|
||||
return program->GetFilenameForStatement(index);
|
||||
}
|
||||
|
||||
int idGameEditExt::GetLineNumberForStatement(idProgram* program, int index) const
|
||||
{
|
||||
return program->GetLineNumberForStatement(index);
|
||||
}
|
|
@ -270,6 +270,14 @@ bool IsDoom3DemoVersion()
|
|||
return ret;
|
||||
}
|
||||
|
||||
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 ) {
|
||||
ret = updateDebuggerFnPtr ? updateDebuggerFnPtr( interpreter, program, instructionPointer ) : false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -352,6 +360,8 @@ 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_UpdateDebugger,(idCommon::FunctionPointer*) &updateDebuggerFnPtr,NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1192,7 +1202,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) {
|
||||
|
||||
this->isServer = isServer;
|
||||
this->isClient = isClient;
|
||||
|
@ -2216,13 +2226,13 @@ 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;
|
||||
idEntity * ent;
|
||||
int num;
|
||||
float ms;
|
||||
idTimer timer_think, timer_events, timer_singlethink;
|
||||
gameReturn_t ret;
|
||||
idPlayer *player;
|
||||
const renderView_t *view;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if ( isMultiplayer ) {
|
||||
|
|
|
@ -33,6 +33,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "script/Script_Interpreter.h"
|
||||
|
||||
#include "framework/FileSystem.h"
|
||||
|
||||
// HvG: Debugger support
|
||||
extern bool updateGameDebugger( idInterpreter *interpreter, idProgram *program, int instructionPointer );
|
||||
|
||||
/*
|
||||
================
|
||||
idInterpreter::idInterpreter()
|
||||
|
@ -183,7 +188,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 +195,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 +219,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 +269,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 +287,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<const idScriptObject **>( &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<int *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
case ev_boolean:
|
||||
out = va( "%d", *( reinterpret_cast<int *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
|
||||
case ev_float:
|
||||
out = va( "%g", *( reinterpret_cast<float *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
case ev_float:
|
||||
out = va( "%g", *( reinterpret_cast<float *>( &obj->data[ reg.ptrOffset ] ) ) );
|
||||
return true;
|
||||
|
||||
case ev_string: {
|
||||
const char* str;
|
||||
str = reinterpret_cast<const char*>( &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 +1007,19 @@ bool idInterpreter::Execute( void ) {
|
|||
// next statement
|
||||
st = &gameLocal.program.GetStatement( instructionPointer );
|
||||
|
||||
if ( !updateGameDebugger( this, &gameLocal.program, instructionPointer )
|
||||
&& 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 +1884,98 @@ bool idInterpreter::Execute( void ) {
|
|||
|
||||
return threadDying;
|
||||
}
|
||||
|
||||
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 idGameEditExt::ReturnedFromFunction(const idProgram* program, const idInterpreter* interpreter, int index) const
|
||||
{
|
||||
|
||||
return ( const_cast<idProgram*>(program)->GetStatement(index).op == OP_RETURN && interpreter->GetCallstackDepth ( ) <= 1 );
|
||||
}
|
||||
|
||||
bool idGameEditExt::GetRegisterValue(const idInterpreter* interpreter, const char* name, idStr& out, int scopeDepth) const
|
||||
{
|
||||
return const_cast<idInterpreter*>(interpreter)->GetRegisterValue(name, out, scopeDepth);
|
||||
}
|
||||
|
||||
const idThread*idGameEditExt::GetThread(const idInterpreter* interpreter) const
|
||||
{
|
||||
return interpreter->GetThread();
|
||||
}
|
||||
|
||||
void idGameEditExt::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 ( "<UNKNOWN>" );
|
||||
msg->WriteString ( "<UNKNOWN>" );
|
||||
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<idProgram*>( program )->GetStatement( instructionPtr );
|
||||
else // Use the calling statement as the filename and linenumber where the call was made from
|
||||
st = &const_cast<idProgram*>( program )->GetStatement ( stack->s );
|
||||
|
||||
if ( st )
|
||||
{
|
||||
idStr qpath = const_cast<idProgram*>( 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 ( "<UNKNOWN>" );
|
||||
msg->WriteInt ( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void idGameEditExt::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 idGameEditExt::GetInterpreterCallStackDepth(const idInterpreter* interpreter)
|
||||
{
|
||||
return interpreter->GetCallstackDepth();
|
||||
}
|
||||
|
||||
const function_t*idGameEditExt::GetInterpreterCallStackFunction( const idInterpreter* interpreter, int stackDepth/* = -1*/)
|
||||
{
|
||||
return interpreter->GetCallstack( )[ stackDepth > -1 ? stackDepth :interpreter->GetCallstackDepth( ) ].f;
|
||||
}
|
|
@ -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( "<execute>", NULL );
|
||||
const idEventDef EV_Thread_SetCallback( "<script_setcallback>", NULL );
|
||||
|
@ -1841,3 +1841,49 @@ void idThread::Event_InfluenceActive( void ) {
|
|||
idThread::ReturnInt( false );
|
||||
}
|
||||
}
|
||||
|
||||
int idGameEditExt::ThreadGetNum(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->GetThreadNum();
|
||||
}
|
||||
|
||||
const char*idGameEditExt::ThreadGetName(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->GetThreadName();
|
||||
}
|
||||
|
||||
int idGameEditExt::GetTotalScriptThreads() const
|
||||
{
|
||||
return idThread::GetThreads().Num();
|
||||
}
|
||||
|
||||
const idThread*idGameEditExt::GetThreadByIndex(int index) const
|
||||
{
|
||||
return idThread::GetThreads()[index];
|
||||
}
|
||||
|
||||
bool idGameEditExt::ThreadIsDoneProcessing(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsDoneProcessing();
|
||||
}
|
||||
|
||||
bool idGameEditExt::ThreadIsWaiting(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsWaiting();
|
||||
}
|
||||
|
||||
bool idGameEditExt::ThreadIsDying(const idThread* thread) const
|
||||
{
|
||||
return const_cast<idThread*>(thread)->IsDying();
|
||||
}
|
||||
|
||||
void idGameEditExt::MSG_WriteThreadInfo(idBitMsg* msg, const idThread* thread, const idInterpreter* interpreter)
|
||||
{
|
||||
msg->WriteString(const_cast<idThread*>(thread)->GetThreadName());
|
||||
msg->WriteInt(const_cast<idThread*>(thread)->GetThreadNum());
|
||||
|
||||
msg->WriteBits((int)(thread == interpreter->GetThread()), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsDoneProcessing(), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsWaiting(), 1);
|
||||
msg->WriteBits((int)const_cast<idThread*>(thread)->IsDying(), 1);
|
||||
}
|
|
@ -85,7 +85,7 @@ public:
|
|||
void WriteShort( int c );
|
||||
void WriteUShort( int c );
|
||||
void WriteInt( int c );
|
||||
void WriteFloat( float f );
|
||||
void WriteFloat( float f );
|
||||
void WriteFloat( float f, int exponentBits, int mantissaBits );
|
||||
void WriteAngle8( float f );
|
||||
void WriteAngle16( float f );
|
||||
|
|
|
@ -2169,6 +2169,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 ) {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
@ -149,17 +149,17 @@ END
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_DBG_ABOUT DIALOGEX 0, 0, 222, 71
|
||||
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 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.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 \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
|
||||
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -269,8 +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
|
||||
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
|
||||
|
|
|
@ -673,7 +673,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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1031,7 +1054,10 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
// Launch the script debugger
|
||||
if ( strstr( GetCommandLine(), "+debugger" ) ) {
|
||||
// DebuggerClientInit( lpCmdLine );
|
||||
|
||||
#ifdef ID_ALLOW_TOOLS
|
||||
DebuggerClientInit(GetCommandLine());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -25,20 +25,23 @@ 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;
|
||||
|
||||
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 )
|
||||
{
|
||||
|
|
|
@ -28,25 +28,28 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#ifndef DEBUGGERBREAKPOINT_H_
|
||||
#define DEBUGGERBREAKPOINT_H_
|
||||
|
||||
class idProgram;
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
static int mNextID;
|
||||
|
@ -67,4 +70,9 @@ ID_INLINE int rvDebuggerBreakpoint::GetID ( void )
|
|||
return mID;
|
||||
}
|
||||
|
||||
ID_INLINE bool rvDebuggerBreakpoint::GetOnceOnly( void )
|
||||
{
|
||||
return mOnceOnly;
|
||||
}
|
||||
|
||||
#endif // DEBUGGERBREAKPOINT_H_
|
||||
|
|
|
@ -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 ( 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
|
||||
|
@ -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;
|
||||
|
||||
//int64_t ptr64b = msg->ReadInt64();
|
||||
//mBreakProgram = (idProgram*)ptr64b;
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
@ -422,7 +497,7 @@ Adds a breakpoint to the client and server with the give nfilename and linenumbe
|
|||
*/
|
||||
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] );
|
||||
|
||||
|
@ -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() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -502,9 +578,9 @@ rvDebuggerClient::SendAddBreakpoint
|
|||
Send an individual breakpoint over to the debugger server
|
||||
================
|
||||
*/
|
||||
void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp, bool onceOnly )
|
||||
void rvDebuggerClient::SendAddBreakpoint ( rvDebuggerBreakpoint& bp )
|
||||
{
|
||||
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 ( bp.GetOnceOnly() ? 1 : 0, 1 );
|
||||
msg.WriteInt ( (unsigned long) bp.GetLineNumber ( ) );
|
||||
msg.WriteInt ( bp.GetID ( ) );
|
||||
msg.WriteString ( bp.GetFilename() ); // FIXME: this implies make7bit ?!
|
||||
|
||||
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() );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -583,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( ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -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<rvDebuggerCallstack*> rvDebuggerCallstackList;
|
||||
typedef idList<rvDebuggerThread*> rvDebuggerThreadList;
|
||||
|
@ -75,19 +75,23 @@ 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 );
|
||||
void StepOver ( void );
|
||||
|
||||
void SendCommand ( const char* cmdStr );
|
||||
|
||||
// Breakpoints
|
||||
int AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly = false );
|
||||
int AddBreakpoint ( const char* filename, int lineNumber, bool onceOnly = false);
|
||||
bool RemoveBreakpoint ( int bpID );
|
||||
void ClearBreakpoints ( void );
|
||||
int GetBreakpointCount ( void );
|
||||
|
@ -98,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 );
|
||||
|
||||
|
@ -119,6 +123,8 @@ protected:
|
|||
|
||||
EDebuggerMessage mWaitFor;
|
||||
|
||||
idStrList mServerScripts;
|
||||
|
||||
private:
|
||||
|
||||
void ClearCallstack ( void );
|
||||
|
@ -127,10 +133,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 );
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -286,4 +295,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_
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -46,6 +46,8 @@ enum EDebuggerMessage
|
|||
DBMSG_INSPECTTHREADS,
|
||||
DBMSG_STEPOVER,
|
||||
DBMSG_STEPINTO,
|
||||
DBMSG_INSPECTSCRIPTS,
|
||||
DBMSG_EXECCOMMAND
|
||||
};
|
||||
|
||||
#endif // DEBUGGER_MESSAGES_H_
|
|
@ -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 );
|
||||
|
|
|
@ -26,12 +26,14 @@ 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 "../../game/script/Script_Program.h"
|
||||
#include "../../ui/Window.h"
|
||||
#include "../../ui/UserInterfaceLocal.h"
|
||||
|
||||
|
@ -57,6 +59,7 @@ rvDebuggerScript::~rvDebuggerScript ( void )
|
|||
Unload ( );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerScript::Unload
|
||||
|
@ -72,10 +75,6 @@ void rvDebuggerScript::Unload ( void )
|
|||
{
|
||||
delete mInterface;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete mProgram;
|
||||
}
|
||||
|
||||
mContents = NULL;
|
||||
mProgram = NULL;
|
||||
|
@ -116,60 +115,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 +140,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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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_
|
|
@ -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").
|
||||
|
||||
|
@ -26,17 +28,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 "../../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"
|
||||
#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"
|
||||
|
||||
/*
|
||||
|
@ -51,10 +52,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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -82,15 +90,17 @@ 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 );
|
||||
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
|
||||
|
@ -102,7 +112,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 );
|
||||
}
|
||||
|
@ -130,8 +140,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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -144,39 +162,46 @@ 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;
|
||||
|
||||
// Only accept packets from the debugger server for security reasons
|
||||
if ( !Sys_CompareNetAdrBase ( adrFrom, mClientAdr ) )
|
||||
{
|
||||
continue;
|
||||
short command;
|
||||
msg.Init(buffer, sizeof(buffer));
|
||||
msg.SetSize(msgSize);
|
||||
msg.BeginReading();
|
||||
|
||||
if ( adrFrom.type != NA_LOOPBACK ) {
|
||||
// Only accept packets from the debugger server for security reasons
|
||||
if ( !Sys_CompareNetAdrBase( adrFrom, mClientAdr ) )
|
||||
continue;
|
||||
}
|
||||
|
||||
command = (unsigned short) MSG_ReadShort ( &msg );
|
||||
command = msg.ReadShort( );
|
||||
|
||||
switch ( command )
|
||||
{
|
||||
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;
|
||||
|
||||
case DBMSG_DISCONNECT:
|
||||
ClearBreakpoints ( );
|
||||
Resume ( );
|
||||
mConnected = false;
|
||||
com_editors &= ~EDITOR_DEBUGGER;
|
||||
break;
|
||||
|
||||
case DBMSG_ADDBREAKPOINT:
|
||||
|
@ -188,7 +213,7 @@ bool rvDebuggerServer::ProcessMessages ( void )
|
|||
break;
|
||||
|
||||
case DBMSG_RESUME:
|
||||
Resume ( );
|
||||
HandleResume ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_BREAK:
|
||||
|
@ -197,11 +222,11 @@ bool rvDebuggerServer::ProcessMessages ( void )
|
|||
|
||||
case DBMSG_STEPOVER:
|
||||
mBreakStepOver = true;
|
||||
mBreakStepOverDepth = mBreakInterpreter->GetCallstackDepth ( );
|
||||
mBreakStepOverFunc1 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()].f;
|
||||
if ( mBreakInterpreter->GetCallstackDepth() > 0 )
|
||||
mBreakStepOverDepth = ((idGameEditExt*) gameEdit)->GetInterpreterCallStackDepth(mBreakInterpreter);
|
||||
mBreakStepOverFunc1 = ((idGameEditExt*) gameEdit)->GetInterpreterCallStackFunction(mBreakInterpreter);
|
||||
if (mBreakStepOverDepth)
|
||||
{
|
||||
mBreakStepOverFunc2 = mBreakInterpreter->GetCallstack()[mBreakInterpreter->GetCallstackDepth()-1].f;
|
||||
mBreakStepOverFunc2 = ((idGameEditExt*) gameEdit)->GetInterpreterCallStackFunction(mBreakInterpreter,mBreakStepOverDepth - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -226,6 +251,14 @@ bool rvDebuggerServer::ProcessMessages ( void )
|
|||
case DBMSG_INSPECTTHREADS:
|
||||
HandleInspectThreads ( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_INSPECTSCRIPTS:
|
||||
HandleInspectScripts( &msg );
|
||||
break;
|
||||
|
||||
case DBMSG_EXECCOMMAND:
|
||||
HandleExecCommand( &msg );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -241,13 +274,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,29 +289,44 @@ 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;
|
||||
long id;
|
||||
char filename[MAX_PATH];
|
||||
char filename[2048]; // DG: randomly chose this size
|
||||
|
||||
// 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 ( msg, filename, MAX_PATH );
|
||||
msg->ReadString ( filename, sizeof(filename) );
|
||||
|
||||
// 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 );
|
||||
//check for statement on requested breakpoint location
|
||||
if (!((idGameEditExt*) 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;
|
||||
}
|
||||
|
||||
|
||||
SDL_LockMutex( mCriticalSection );
|
||||
mBreakpoints.Append ( new rvDebuggerBreakpoint ( filename, lineNumber, id, onceOnly ) );
|
||||
SDL_UnlockMutex( mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -289,17 +338,17 @@ 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
|
||||
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 ++ )
|
||||
|
@ -312,52 +361,21 @@ void rvDebuggerServer::HandleRemoveBreakpoint ( msg_t* msg )
|
|||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
SDL_UnlockMutex( mCriticalSection );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
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, "<UNKNOWN>" );
|
||||
MSG_WriteString ( msg, "<UNKNOWN>" );
|
||||
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, "<UNKNOWN>" );
|
||||
MSG_WriteInt ( msg, 0 );
|
||||
}
|
||||
//Empty msg
|
||||
Resume();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -368,31 +386,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 ( ) );
|
||||
((idGameEditExt*) 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 +407,67 @@ 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)((idGameEditExt*) 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 < ((idGameEditExt*) 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 );
|
||||
((idGameEditExt*) gameEdit)->MSG_WriteThreadInfo(&msgOut,((idGameEditExt*) 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::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
|
||||
|
||||
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);
|
||||
|
||||
((idGameEditExt*) gameEdit)->MSG_WriteScriptList( &msgOut );
|
||||
|
||||
SendPacket(msgOut.GetData(), msgOut.GetSize());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -440,7 +477,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 +487,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 (!((idGameEditExt*) 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 +522,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 +529,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 = ((idGameEditExt*) gameEdit)->GetFilenameForStatement(program, instructionPointer);
|
||||
int linenumber = ((idGameEditExt*) 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 ( ((idGameEditExt*) gameEdit)->ReturnedFromFunction(program, interpreter,instructionPointer))
|
||||
{
|
||||
mBreakStepOver = false;
|
||||
mBreakStepInto = false;
|
||||
|
@ -517,6 +555,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 +563,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 (((idGameEditExt*) gameEdit)->CheckForBreakPointHit(interpreter, mBreakStepOverFunc1, mBreakStepOverFunc2, mBreakStepOverDepth))
|
||||
{
|
||||
Break ( interpreter, program, instructionPointer );
|
||||
return;
|
||||
|
@ -536,6 +574,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;
|
||||
|
@ -545,7 +584,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 ++ )
|
||||
|
@ -553,30 +592,50 @@ 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;
|
||||
}
|
||||
|
||||
// Pop out of the critical section so we dont get stuck
|
||||
LeaveCriticalSection ( &mCriticalSection );
|
||||
// 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 );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -589,9 +648,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 +658,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 = ((idGameEditExt*) gameEdit)->GetFilenameForStatement(program,instructionPointer);
|
||||
int linenumber = ((idGameEditExt*) gameEdit)->GetLineNumberForStatement(program, instructionPointer);
|
||||
idStr fileStr = filename;
|
||||
fileStr.BackSlashesToSlashes();
|
||||
|
||||
// Give the mouse cursor back to the world
|
||||
Sys_GrabMouseCursor( false );
|
||||
|
@ -617,19 +673,33 @@ 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.WriteInt64( (int64_t)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
|
||||
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
|
||||
|
@ -640,8 +710,10 @@ void rvDebuggerServer::Break ( idInterpreter* interpreter, idProgram* program, i
|
|||
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.
|
||||
Sys_GrabMouseCursor( true );
|
||||
|
||||
// Clear all commands that were generated before we went into suspended mode. This is
|
||||
|
@ -664,10 +736,11 @@ void rvDebuggerServer::Resume ( void )
|
|||
return;
|
||||
}
|
||||
|
||||
mBreak = false;
|
||||
|
||||
// Start the game thread back up
|
||||
ResumeThread ( mGameThread );
|
||||
SDL_LockMutex( mGameThreadBreakLock );
|
||||
mBreak = false;
|
||||
SDL_CondSignal( mGameThreadBreakCond);
|
||||
SDL_UnlockMutex( mGameThreadBreakLock );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -703,12 +776,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() );
|
||||
}
|
||||
|
|
|
@ -28,20 +28,16 @@ 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"
|
||||
#include <SDL.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,31 +46,52 @@ 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 );
|
||||
void HandleExecCommand ( idBitMsg *msg );
|
||||
////
|
||||
|
||||
// protected member variables
|
||||
bool mConnected;
|
||||
netadr_t mClientAdr;
|
||||
idPort mPort;
|
||||
idList<rvDebuggerBreakpoint*> mBreakpoints;
|
||||
CRITICAL_SECTION mCriticalSection;
|
||||
SDL_mutex* mCriticalSection;
|
||||
|
||||
HANDLE mGameThread;
|
||||
|
||||
SDL_cond* mGameThreadBreakCond;
|
||||
SDL_mutex* mGameThreadBreakLock;
|
||||
bool mBreak;
|
||||
|
||||
bool mBreakNext;
|
||||
bool mBreakStepOver;
|
||||
bool mBreakStepInto;
|
||||
|
@ -87,27 +104,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 );
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -125,9 +124,19 @@ 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 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
rvDebuggerServer::GameSuspended
|
||||
================
|
||||
*/
|
||||
ID_INLINE bool rvDebuggerServer::GameSuspended( void )
|
||||
{
|
||||
return mBreak;
|
||||
}
|
||||
|
||||
#endif // DEBUGGERSERVER_H_
|
||||
|
|
|
@ -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,9 @@ 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 IDC_DBG_CONSOLEINPUT 31011
|
||||
#define IDC_DBG_BREAKLIST 31012
|
||||
|
||||
#define ID_DBG_FILE_MRU1 10000
|
||||
|
||||
|
@ -167,7 +170,7 @@ bool rvDebuggerWindow::Create ( HINSTANCE instance )
|
|||
|
||||
UpdateTitle ( );
|
||||
|
||||
Printf ( "Quake 4 Script Debugger v0.1\n\n" );
|
||||
Printf ( "Dhewm3 Script Debugger v1.1\n\n" );
|
||||
|
||||
ShowWindow ( mWnd, SW_SHOW );
|
||||
UpdateWindow ( mWnd );
|
||||
|
@ -248,7 +251,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 )
|
||||
|
@ -347,6 +350,23 @@ 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);
|
||||
// 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));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return CallWindowProc ( wndproc, wnd, msg, wparam, lparam );
|
||||
|
@ -354,7 +374,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 )
|
||||
{
|
||||
|
@ -384,15 +404,57 @@ 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 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 ) );
|
||||
dc = BeginPaint( wnd, &ps );
|
||||
FillRect( dc, &rect, GetSysColorBrush( COLOR_3DSHADOW ) );
|
||||
|
||||
//draw line nrs
|
||||
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 );
|
||||
// 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;
|
||||
lnrRect.right = lnrRect.left + lnrWidth;
|
||||
FillRect( dc, &lnrRect, WHITE_BRUSH );
|
||||
|
||||
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 = lnrRect;
|
||||
t.top = pos.y;
|
||||
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 );
|
||||
}
|
||||
DeleteObject( hf );
|
||||
|
||||
//draw breakpoints
|
||||
if ( window->mScripts.Num ( ) )
|
||||
{
|
||||
for ( int i = 0; i < window->mClient->GetBreakpointCount(); i ++ )
|
||||
|
@ -407,7 +469,8 @@ 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 +484,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 +497,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 +531,7 @@ void rvDebuggerWindow::UpdateTitle ( void )
|
|||
{
|
||||
idStr title;
|
||||
|
||||
title = "Quake 4 Script Debugger - ";
|
||||
title = "Dhewm3 Script Debugger - ";
|
||||
|
||||
if ( mClient->IsConnected ( ) )
|
||||
{
|
||||
|
@ -487,7 +552,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 +658,56 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
|
||||
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
|
||||
|
@ -712,7 +830,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 );
|
||||
|
@ -737,6 +855,33 @@ 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;
|
||||
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);
|
||||
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,18 +905,18 @@ 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 );
|
||||
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 );
|
||||
|
||||
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 );
|
||||
|
@ -782,15 +927,22 @@ 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 );
|
||||
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 );
|
||||
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 );
|
||||
|
||||
|
@ -816,23 +968,52 @@ 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 );
|
||||
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);
|
||||
col.cx = 350;
|
||||
col.pszText = "Filename";
|
||||
ListView_InsertColumn ( mWndScriptList, 1, &col );
|
||||
|
||||
col.cx = 20;
|
||||
col.pszText = "";
|
||||
ListView_InsertColumn ( mWndCallstack, 0, &col );
|
||||
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 );
|
||||
|
||||
|
@ -863,13 +1044,21 @@ 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 );
|
||||
ListView_SetImageList ( mWndBreakList, 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 );
|
||||
ListView_SetExtendedListViewStyle ( mWndBreakList, LVS_EX_FULLROWSELECT );
|
||||
|
||||
gDebuggerApp.GetOptions().GetColumnWidths ( "cw_callstack", mWndCallstack );
|
||||
gDebuggerApp.GetOptions().GetColumnWidths ( "cw_threads", mWndThreads );
|
||||
|
@ -920,6 +1109,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;
|
||||
}
|
||||
|
||||
|
@ -957,6 +1150,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;
|
||||
|
@ -1025,7 +1248,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 );
|
||||
|
||||
|
@ -1049,13 +1272,13 @@ 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;
|
||||
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
|
||||
{
|
||||
|
@ -1064,6 +1287,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;
|
||||
|
@ -1139,6 +1363,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;
|
||||
|
@ -1153,7 +1394,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 )
|
||||
{
|
||||
|
@ -1176,7 +1417,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;
|
||||
}
|
||||
|
||||
|
@ -1202,8 +1443,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,14 +1461,27 @@ 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 );
|
||||
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 );
|
||||
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 );
|
||||
|
||||
// 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));
|
||||
SendMessage( window->mWndConsoleInput, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG( s18, s10 ) );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1258,7 +1517,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 )
|
||||
{
|
||||
|
@ -1320,7 +1589,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 );
|
||||
|
@ -1439,7 +1708,6 @@ LRESULT CALLBACK rvDebuggerWindow::WndProc ( HWND wnd, UINT msg, WPARAM wparam,
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_DBG_CALLSTACK:
|
||||
if ( hdr->code == NM_DBLCLK )
|
||||
{
|
||||
|
@ -1454,14 +1722,74 @@ 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_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 )
|
||||
{
|
||||
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 );
|
||||
ShowWindow ( window->mWndScriptList, SW_HIDE );
|
||||
ShowWindow ( window->mWndBreakList, SW_HIDE );
|
||||
switch ( TabCtrl_GetCurSel ( hdr->hwndFrom ) )
|
||||
{
|
||||
case 0:
|
||||
|
@ -1470,6 +1798,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:
|
||||
|
@ -1483,6 +1812,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;
|
||||
|
@ -1493,7 +1830,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;
|
||||
}
|
||||
|
@ -1535,14 +1872,20 @@ 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);
|
||||
UpdateBreakpointList();
|
||||
break;
|
||||
|
||||
case DBMSG_RESUMED:
|
||||
UpdateTitle ( );
|
||||
UpdateToolbar ( );
|
||||
|
@ -1554,9 +1897,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;
|
||||
|
@ -1624,10 +1967,17 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* 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->data) + msg->readcount );
|
||||
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:
|
||||
{
|
||||
|
@ -1636,6 +1986,7 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg )
|
|||
mCurrentStackDepth = 0;
|
||||
mClient->InspectVariable ( mTooltipVar, mCurrentStackDepth );
|
||||
UpdateWatch ( );
|
||||
UpdateBreakpointList();
|
||||
EnableWindows ( TRUE );
|
||||
OpenScript ( mClient->GetBreakFilename(), mClient->GetBreakLineNumber() - 1 );
|
||||
UpdateTitle ( );
|
||||
|
@ -1643,7 +1994,11 @@ void rvDebuggerWindow::ProcessNetMessage ( msg_t* msg )
|
|||
SetForegroundWindow ( mWnd );
|
||||
break;
|
||||
}
|
||||
|
||||
case DBMSG_INSPECTSCRIPTS:
|
||||
{
|
||||
UpdateScriptList ( );
|
||||
break;
|
||||
}
|
||||
case DBMSG_INSPECTCALLSTACK:
|
||||
{
|
||||
UpdateCallstack ( );
|
||||
|
@ -1719,7 +2074,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 +2103,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 +2131,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 +2139,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
|
||||
|
@ -1843,6 +2197,8 @@ void rvDebuggerWindow::ToggleBreakpoint ( void )
|
|||
|
||||
// Force a repaint of the script window
|
||||
InvalidateRect ( mWndScript, NULL, FALSE );
|
||||
|
||||
UpdateBreakpointList();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1895,6 +2251,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 },
|
||||
|
@ -2013,6 +2371,7 @@ int rvDebuggerWindow::HandleActivate ( WPARAM wparam, LPARAM lparam )
|
|||
}
|
||||
}
|
||||
}
|
||||
UpdateBreakpointList();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -2193,7 +2552,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 +2589,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 +2606,7 @@ then the last text used will be searched for.
|
|||
*/
|
||||
bool rvDebuggerWindow::FindPrev ( const char* text )
|
||||
{
|
||||
int start;
|
||||
long start;
|
||||
FINDTEXT ft;
|
||||
|
||||
if ( text )
|
||||
|
|
|
@ -52,38 +52,57 @@ 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 UpdateBreakpointList( 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;
|
||||
|
@ -92,7 +111,10 @@ protected:
|
|||
HWND mWndTabs;
|
||||
HWND mWndBorder;
|
||||
HWND mWndConsole;
|
||||
HWND mWndConsoleInput;
|
||||
HWND mWndCallstack;
|
||||
HWND mWndScriptList;
|
||||
HWND mWndBreakList; // list of breakpoints
|
||||
HWND mWndWatch;
|
||||
HWND mWndThreads;
|
||||
HWND mWndToolTips;
|
||||
|
@ -108,6 +130,7 @@ protected:
|
|||
|
||||
HINSTANCE mInstance;
|
||||
HIMAGELIST mImageList;
|
||||
HIMAGELIST mTmpImageList;
|
||||
|
||||
RECT mSplitterRect;
|
||||
bool mSplitterDrag;
|
||||
|
@ -129,25 +152,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 );
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -26,26 +26,26 @@ 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; // this is also used in other source files
|
||||
static HWND gDebuggerWindow = NULL;
|
||||
#endif
|
||||
|
||||
rvDebuggerApp gDebuggerApp;
|
||||
HWND gDebuggerWindow = NULL;
|
||||
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 )
|
||||
/*
|
||||
================
|
||||
DebuggerMain
|
||||
|
@ -65,6 +65,9 @@ void DebuggerClientInit( const char *cmdline )
|
|||
{
|
||||
goto DebuggerClientInitDone;
|
||||
}
|
||||
|
||||
// hide the doom window by default
|
||||
::ShowWindow( win32.hWnd, SW_HIDE );
|
||||
|
||||
gDebuggerApp.Run ( );
|
||||
|
||||
|
@ -113,6 +116,7 @@ void DebuggerClientLaunch ( void )
|
|||
CloseHandle ( process.hThread );
|
||||
CloseHandle ( process.hProcess );
|
||||
}
|
||||
#endif // #if defined( ID_ALLOW_TOOLS )
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -121,14 +125,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;
|
||||
|
@ -143,8 +147,17 @@ Starts up the debugger server
|
|||
*/
|
||||
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 ( com_editors & EDITOR_DEBUGGER )
|
||||
if ( gDebuggerServer != NULL
|
||||
|| ( com_editors & EDITOR_DEBUGGER ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -163,9 +176,13 @@ bool DebuggerServerInit ( void )
|
|||
gDebuggerServer = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Start the debugger server thread
|
||||
gDebuggerServerThread = CreateThread ( NULL, 0, DebuggerServerThread, 0, 0, &gDebuggerServerThreadID );
|
||||
#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;
|
||||
}
|
||||
|
@ -179,13 +196,14 @@ 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();
|
||||
|
@ -193,10 +211,10 @@ void DebuggerServerShutdown ( void )
|
|||
delete gDebuggerServer;
|
||||
gDebuggerServer = NULL;
|
||||
|
||||
// Cleanup the thread handle
|
||||
CloseHandle ( gDebuggerServerThread );
|
||||
gDebuggerServerThread = NULL;
|
||||
com_editors &= ~EDITOR_DEBUGGER;
|
||||
}
|
||||
|
||||
com_enableDebuggerServer.ClearModified( );
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
162
neo/tools/debugger/debugger_common.h
Normal file
162
neo/tools/debugger/debugger_common.h
Normal file
|
@ -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
|
|
@ -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" ); }
|
||||
|
||||
|
|
Loading…
Reference in a new issue