Skip to content

Commit

Permalink
Add Squirrel debugger
Browse files Browse the repository at this point in the history
  • Loading branch information
samisalreadytaken committed Jun 22, 2024
1 parent 82bc30c commit 76ef30b
Show file tree
Hide file tree
Showing 14 changed files with 11,435 additions and 10 deletions.
22 changes: 21 additions & 1 deletion sp/src/game/client/vscript_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
extern IScriptManager *scriptmanager;
extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );

#ifdef MAPBASE_VSCRIPT
extern int vscript_debugger_port;
#endif

// #define VMPROFILE 1

#ifdef VMPROFILE
Expand Down Expand Up @@ -682,6 +686,14 @@ bool VScriptClientInit()
//g_pScriptVM->RegisterInstance( &g_ScriptEntityIterator, "Entities" );
#endif

#ifdef MAPBASE_VSCRIPT
if ( vscript_debugger_port )
{
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
vscript_debugger_port = 0;
}
#endif

if (scriptLanguage == SL_SQUIRREL)
{
g_pScriptVM->Run( g_Script_vscript_client );
Expand Down Expand Up @@ -768,11 +780,19 @@ class CVScriptGameSystem : public CAutoGameSystemPerFrame
VScriptClientTerm();
}

virtual void FrameUpdatePostEntityThink()
#ifdef MAPBASE_VSCRIPT
virtual void Update( float frametime )
{
if ( g_pScriptVM )
g_pScriptVM->Frame( frametime );
}
#else
virtual void FrameUpdatePostEntityThink()
{
if ( g_pScriptVM )
g_pScriptVM->Frame( gpGlobals->frametime );
}
#endif

bool m_bAllowEntityCreationInScripts;
};
Expand Down
12 changes: 12 additions & 0 deletions sp/src/game/server/vscript_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );

#ifdef MAPBASE_VSCRIPT
extern int vscript_debugger_port;
#endif

// #define VMPROFILE 1

#ifdef VMPROFILE
Expand Down Expand Up @@ -663,6 +667,14 @@ bool VScriptServerInit()
RegisterSharedScriptFunctions();
#endif

#ifdef MAPBASE_VSCRIPT
if ( vscript_debugger_port )
{
g_pScriptVM->ConnectDebugger( vscript_debugger_port );
vscript_debugger_port = 0;
}
#endif

if (scriptLanguage == SL_SQUIRREL)
{
g_pScriptVM->Run( g_Script_vscript_server );
Expand Down
19 changes: 19 additions & 0 deletions sp/src/game/shared/vscript_shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ extern ScriptClassDesc_t * GetScriptDesc( CBaseEntity * );
#ifdef MAPBASE_VSCRIPT
// This is to ensure a dependency exists between the vscript library and the game DLLs
extern int vscript_token;
extern int vscript_debugger_port;
int vscript_token_hack = vscript_token;
#endif

Expand Down Expand Up @@ -390,12 +391,30 @@ CON_COMMAND_F( script_debug, "Connect the vscript VM to the script debugger", FC
if ( !IsCommandIssuedByServerAdmin() )
return;

#ifdef MAPBASE_VSCRIPT
#ifdef GAME_DLL
int port = 1212;
#else
int port = 1213;
#endif
#endif

if ( !g_pScriptVM )
{
#ifdef MAPBASE_VSCRIPT
vscript_debugger_port = port;
CGMsg( 0, CON_GROUP_VSCRIPT, "VScript VM is not running, waiting for it to attach the debugger to port %d...\n", port );
#else
CGWarning( 0, CON_GROUP_VSCRIPT, "Scripting disabled or no server running\n" );
#endif
return;
}

#ifdef MAPBASE_VSCRIPT
g_pScriptVM->ConnectDebugger( port );
#else
g_pScriptVM->ConnectDebugger();
#endif
}

#ifdef CLIENT_DLL
Expand Down
4 changes: 4 additions & 0 deletions sp/src/public/vscript/ivscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,11 @@ class IScriptVM
virtual bool Init() = 0;
virtual void Shutdown() = 0;

#ifdef MAPBASE_VSCRIPT
virtual bool ConnectDebugger( int port = 0 ) = 0;
#else
virtual bool ConnectDebugger() = 0;
#endif
virtual void DisconnectDebugger() = 0;

virtual ScriptLanguage_t GetLanguage() = 0;
Expand Down
47 changes: 47 additions & 0 deletions sp/src/vscript/sqdbg/include/sqdbg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//-----------------------------------------------------------------------
// github.com/samisalreadytaken/sqdbg
//-----------------------------------------------------------------------
//
// Squirrel Debugger
//

#ifndef SQDBG_SERVER_H
#define SQDBG_SERVER_H

#include <squirrel.h>

#define SQDBG_SV_API_VER 1

struct SQDebugServer;
typedef SQDebugServer* HSQDEBUGSERVER;

#ifdef __cplusplus
extern "C" {
#endif

// Create and attach a new debugger
// Memory is owned by the VM, it is freed when the VM dies or
// the debugger is disconnected via sqdbg_destroy_debugger()
extern HSQDEBUGSERVER sqdbg_attach_debugger( HSQUIRRELVM vm );

// Detach and destroy the debugger attached to this VM
// Invalidates the handle returned from sqdbg_attach_debugger()
extern void sqdbg_destroy_debugger( HSQUIRRELVM vm );

// Open specified port and allow client connections
// Returns 0 on success
extern int sqdbg_listen_socket( HSQDEBUGSERVER dbg, unsigned short port );

// Process client connections and incoming messages
extern void sqdbg_frame( HSQDEBUGSERVER dbg );

// Redirects to sq_compilebuffer
// If the VM has a debugger attached, copies every script to be able to source them to debugger clients
extern SQRESULT sqdbg_compilebuffer( HSQUIRRELVM vm, const SQChar *script, SQInteger size,
const SQChar *sourcename, SQBool raiseerror );

#ifdef __cplusplus
}
#endif

#endif // SQDBG_SERVER_H
137 changes: 137 additions & 0 deletions sp/src/vscript/sqdbg/sqdbg/debug.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//-----------------------------------------------------------------------
// github.com/samisalreadytaken/sqdbg
//-----------------------------------------------------------------------
//

#ifndef SQDBG_DEBUG_H
#define SQDBG_DEBUG_H

#ifdef _DEBUG
#ifdef _WIN32
#include <crtdbg.h>

bool __IsDebuggerPresent();

static inline const char *GetModuleBaseName()
{
static char module[MAX_PATH];
DWORD len = GetModuleFileNameA( NULL, module, sizeof(module) );

if ( len != 0 )
{
for ( char *pBase = module + len; pBase-- > module; )
{
if ( *pBase == '\\' )
return pBase + 1;
}

return module;
}

return "";
}

#define DebuggerBreak() do { if ( __IsDebuggerPresent() ) __debugbreak(); } while(0);

#define Assert(x) \
do { \
__CAT( L, __LINE__ ): \
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), #x)) ) { \
if ( !__IsDebuggerPresent() ) \
goto __CAT( L, __LINE__ ); \
__debugbreak(); \
} \
} while(0)

#define AssertMsg(x,msg) \
do { \
__CAT( L, __LINE__ ): \
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg)) ) { \
if ( !__IsDebuggerPresent() ) \
goto __CAT( L, __LINE__ ); \
__debugbreak(); \
} \
} while(0)

#define AssertMsgF(x,msg,...) \
do { \
__CAT( L, __LINE__ ): \
if ( !(x) && (1 == _CrtDbgReport(_CRT_ASSERT, __FILE__, __LINE__, GetModuleBaseName(), msg, __VA_ARGS__)) ) { \
if ( !__IsDebuggerPresent() ) \
goto __CAT( L, __LINE__ ); \
__debugbreak(); \
} \
} while(0)
#else
extern "C" int printf(const char *, ...);

#define DebuggerBreak() asm("int3")

#define Assert(x) \
do { \
if ( !(x) ) \
{ \
::printf("Assertion failed %s:%d: %s\n", __FILE__, __LINE__, #x); \
DebuggerBreak(); \
} \
} while(0)

#define AssertMsg(x,msg) \
do { \
if ( !(x) ) \
{ \
::printf("Assertion failed %s:%d: %s\n", __FILE__, __LINE__, msg); \
DebuggerBreak(); \
} \
} while(0)

#define AssertMsgF(x,msg,...) \
do { \
if ( !(x) ) \
{ \
::printf("Assertion failed %s:%d: ", __FILE__, __LINE__); \
::printf(msg, __VA_ARGS__); \
::printf("\n"); \
DebuggerBreak(); \
} \
} while(0)
#endif
#define Verify(x) Assert(x)
#else
#define DebuggerBreak()
#define Assert(x)
#define AssertMsg(x,msg)
#define AssertMsgF(x,msg,...)
#define Verify(x) x
#endif // _DEBUG

#ifdef _WIN32
#define UNREACHABLE() do { Assert(!"UNREACHABLE"); __assume(0); } while(0);
#else
#define UNREACHABLE() do { Assert(!"UNREACHABLE"); __builtin_unreachable(); } while(0);
#endif

#define ___CAT(a, b) a##b
#define __CAT(a, b) ___CAT(a,b)

#ifndef assert
#define assert(x) Assert(x)
#endif

#ifdef _DEBUG
class CEntryCounter
{
int *count;
public:
CEntryCounter( int *p ) : count(p) { (*count)++; }
~CEntryCounter() { (*count)--; }
};

#define TRACK_ENTRIES() \
static int s_EntryCount = 0; \
CEntryCounter entrycounter( &s_EntryCount );
#else
#define TRACK_ENTRIES()
#endif

#endif // SQDBG_DEBUG_H
Loading

0 comments on commit 76ef30b

Please sign in to comment.