summaryrefslogtreecommitdiff
path: root/utils/xbox/vxconsole/remote_cmds.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/xbox/vxconsole/remote_cmds.cpp')
-rw-r--r--utils/xbox/vxconsole/remote_cmds.cpp484
1 files changed, 484 insertions, 0 deletions
diff --git a/utils/xbox/vxconsole/remote_cmds.cpp b/utils/xbox/vxconsole/remote_cmds.cpp
new file mode 100644
index 0000000..f74bda0
--- /dev/null
+++ b/utils/xbox/vxconsole/remote_cmds.cpp
@@ -0,0 +1,484 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// REMOTE_CMDS.CPP
+//
+// Remote commands received by an external application and dispatched.
+//=====================================================================================//
+#include "vxconsole.h"
+
+remoteCommand_t *g_remoteCommands[MAX_RCMDS];
+int g_numRemoteCommands;
+
+//-----------------------------------------------------------------------------
+// MatchRemoteCommands
+//
+//-----------------------------------------------------------------------------
+int MatchRemoteCommands( char *pCmdStr, const char *cmdList[], int maxCmds )
+{
+ int numCommands = 0;
+
+ // look in local
+ int matchLen = strlen( pCmdStr );
+ for ( int i=0; i<g_numRemoteCommands; i++ )
+ {
+ if ( !strnicmp( pCmdStr, g_remoteCommands[i]->strCommand, matchLen ) )
+ {
+ cmdList[numCommands++] = g_remoteCommands[i]->strCommand;
+ if ( numCommands >= maxCmds )
+ break;
+ }
+ }
+
+ return ( numCommands );
+}
+
+//-----------------------------------------------------------------------------
+// GetToken
+//
+//-----------------------------------------------------------------------------
+char *GetToken( char **ppTokenStream )
+{
+ static char token[MAX_TOKENCHARS];
+ int len;
+ char c;
+ char *pData;
+
+ len = 0;
+ token[0] = 0;
+
+ if ( !ppTokenStream )
+ return NULL;
+
+ pData = *ppTokenStream;
+
+ // skip whitespace
+skipwhite:
+ while ( ( c = *pData ) <= ' ' )
+ {
+ if ( !c )
+ goto cleanup;
+ pData++;
+ }
+
+ // skip // comments
+ if ( c=='/' && pData[1] == '/' )
+ {
+ while ( *pData && *pData != '\n' )
+ pData++;
+ goto skipwhite;
+ }
+
+ // handle quoted strings specially
+ if ( c == '\"' )
+ {
+ pData++;
+ while ( 1 )
+ {
+ c = *pData++;
+ if ( c=='\"' || !c )
+ goto cleanup;
+
+ token[len] = c;
+ len++;
+ if ( len > MAX_TOKENCHARS-1 )
+ goto cleanup;
+ }
+ }
+
+ // parse a regular word
+ do
+ {
+ token[len] = c;
+ pData++;
+ len++;
+ if ( len > MAX_TOKENCHARS-1 )
+ break;
+ c = *pData;
+ }
+ while ( c > ' ' && c <= '~' );
+
+cleanup:
+ token[len] = 0;
+ *ppTokenStream = pData;
+ return ( token );
+}
+
+//-----------------------------------------------------------------------------
+// CommandCompleted
+//
+//-----------------------------------------------------------------------------
+void CommandCompleted( int errCode )
+{
+ char cmdString[MAX_PATH];
+
+ // send command complete
+ sprintf( cmdString, "%s!__complete__%d", VXCONSOLE_COMMAND_PREFIX, errCode );
+ DmAPI_SendCommand( cmdString, true );
+}
+
+//-----------------------------------------------------------------------------
+// DebugCommand
+//-----------------------------------------------------------------------------
+void DebugCommand( const char *pStrFormat, ... )
+{
+ char buffer[MAX_QUEUEDSTRINGLEN];
+ va_list arglist;
+
+ if ( !g_debugCommands )
+ return;
+
+ va_start( arglist, pStrFormat );
+ _vsnprintf( buffer, MAX_QUEUEDSTRINGLEN, pStrFormat, arglist );
+ va_end( arglist );
+
+ PrintToQueue( RGB( 0,128,0 ), "[CMD]: %s", buffer );
+}
+
+//-----------------------------------------------------------------------------
+// Remote_NotifyPrintFunc
+//
+//-----------------------------------------------------------------------------
+DWORD __stdcall Remote_NotifyPrintFunc( const CHAR *pStrNotification )
+{
+ int color;
+
+ if ( !strnicmp( pStrNotification, VXCONSOLE_PRINT_PREFIX, strlen( VXCONSOLE_PRINT_PREFIX ) ) )
+ {
+ // skip past prefix!
+ pStrNotification += strlen( VXCONSOLE_PRINT_PREFIX )+1;
+ }
+
+ color = XBX_CLR_DEFAULT;
+
+ if ( !strnicmp( pStrNotification, VXCONSOLE_COLOR_PREFIX, strlen( VXCONSOLE_COLOR_PREFIX ) ) )
+ {
+ // skip past prefix[12345678]
+ char buff[16];
+ pStrNotification += strlen( VXCONSOLE_COLOR_PREFIX );
+ memcpy( buff, pStrNotification, 10 );
+ if ( buff[0] == '[' && buff[9] == ']' )
+ {
+ buff[0] = ' ';
+ buff[9] = ' ';
+ buff[10] = '\0';
+
+ sscanf( buff, "%x", &color );
+ pStrNotification += 10;
+ }
+ }
+
+ PrintToQueue( color, "%s\n", pStrNotification );
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------
+// Remote_NotifyDebugString
+//
+// Print as [DBG]:xxxx
+//-----------------------------------------------------------------------------
+DWORD __stdcall Remote_NotifyDebugString( ULONG dwNotification, DWORD dwParam )
+{
+ if ( g_captureDebugSpew )
+ {
+ PDMN_DEBUGSTR p = ( PDMN_DEBUGSTR )dwParam;
+ int len;
+
+ // strip all terminating cr
+ len = p->Length-1;
+ while ( len > 0 )
+ {
+ if ( p->String[len] != '\n' )
+ {
+ len++;
+ break;
+ }
+ len--;
+ }
+
+ // for safety, terminate
+ CHAR* strTemp = new CHAR[len+1];
+ memcpy( strTemp, p->String, len*sizeof( CHAR ) );
+ strTemp[len] = '\0';
+
+ PrintToQueue( RGB( 0,0,255 ), "[DBG]: %s\n", strTemp );
+
+ delete[] strTemp;
+ }
+
+ // Don't let the compiler complain about unused parameters
+ ( VOID )dwNotification;
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Remote_CompareCommands
+//
+//-----------------------------------------------------------------------------
+int Remote_CompareCommands( const void *pElem1, const void *pElem2 )
+{
+ remoteCommand_t *pCmd1;
+ remoteCommand_t *pCmd2;
+
+ pCmd1 = *( remoteCommand_t** )( pElem1 );
+ pCmd2 = *( remoteCommand_t** )( pElem2 );
+
+ return ( strcmp( pCmd1->strCommand, pCmd2->strCommand ) );
+}
+
+//-----------------------------------------------------------------------------
+// Remote_DeleteCommands
+//
+//-----------------------------------------------------------------------------
+void Remote_DeleteCommands()
+{
+ if ( !g_numRemoteCommands )
+ return;
+
+ for ( int i=0; i<g_numRemoteCommands; i++ )
+ {
+ delete [] g_remoteCommands[i]->strCommand;
+ delete [] g_remoteCommands[i]->strHelp;
+ delete g_remoteCommands[i];
+
+ g_remoteCommands[i] = NULL;
+ }
+
+ g_numRemoteCommands = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Remote_AddCommand
+//
+//-----------------------------------------------------------------------------
+bool Remote_AddCommand( char *command, char *helptext )
+{
+ if ( g_numRemoteCommands == MAX_RCMDS )
+ {
+ // full
+ return false;
+ }
+
+ // look for duplicate
+ int i;
+ for ( i = 0; i < g_numRemoteCommands; i++ )
+ {
+ if ( !stricmp( command, g_remoteCommands[i]->strCommand ) )
+ break;
+ }
+ if ( i < g_numRemoteCommands )
+ {
+ // already in list, skip - not an error
+ return true;
+ }
+
+ // add new command to list
+ g_remoteCommands[g_numRemoteCommands] = new remoteCommand_t;
+ g_remoteCommands[g_numRemoteCommands]->strCommand = new char[strlen( command )+1];
+ strcpy( g_remoteCommands[g_numRemoteCommands]->strCommand, command );
+
+ g_remoteCommands[g_numRemoteCommands]->strHelp = new char[strlen( helptext )+1];
+ strcpy( g_remoteCommands[g_numRemoteCommands]->strHelp, helptext );
+
+ g_numRemoteCommands++;
+
+ // success
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// rc_AddCommands
+//
+// Exposes an app's list of remote commands
+//-----------------------------------------------------------------------------
+int rc_AddCommands( char *commandPtr )
+{
+ char* cmdToken;
+ int numCommands;
+ int cmdList;
+ int retAddr;
+ int retVal;
+ int errCode;
+ xrCommand_t* locallist;
+
+ errCode = -1;
+
+ // pacifier for lengthy operation
+ ConsoleWindowPrintf( RGB( 0, 0, 0 ), "Receiving Console Commands From Game..." );
+
+ // get number of commands
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &numCommands );
+
+ // get command list
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &cmdList );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &retAddr );
+
+ locallist = new xrCommand_t[numCommands];
+ memset( locallist, 0, numCommands*sizeof( xrCommand_t ) );
+
+ // get the caller's command list
+ DmGetMemory( ( void* )cmdList, numCommands*sizeof( xrCommand_t ), locallist, NULL );
+
+ int numAdded = 0;
+ for ( int i=0; i<numCommands; i++ )
+ {
+ if ( Remote_AddCommand( locallist[i].nameString, locallist[i].helpString ) )
+ numAdded++;
+ }
+
+ // sort the list
+ qsort( g_remoteCommands, g_numRemoteCommands, sizeof( remoteCommand_t* ), Remote_CompareCommands );
+
+ ConsoleWindowPrintf( RGB( 0, 0, 0 ), "Completed.\n" );
+
+ // return the result
+ retVal = numAdded;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = AddCommands( 0x%8.8x, 0x%8.8x )\n", retVal, numCommands, cmdList );
+
+ delete [] locallist;
+
+ // success
+ errCode = 0;
+
+ if ( g_bPlayTestMode )
+ {
+ if ( g_connectedToApp )
+ {
+ // send the developer command
+ ProcessCommand( "developer 1" );
+ }
+ }
+
+cleanUp:
+ return ( errCode );
+}
+
+//-----------------------------------------------------------------------------
+// Remote_NotifyCommandFunc
+//
+//-----------------------------------------------------------------------------
+DWORD __stdcall Remote_NotifyCommandFunc( const CHAR *strNotification )
+{
+ CHAR* commandPtr;
+ CHAR* cmdToken;
+ int errCode;
+ bool async;
+
+ // skip over the command prefix and the exclamation mark
+ strNotification += strlen( VXCONSOLE_COMMAND_PREFIX ) + 1;
+ commandPtr = ( CHAR* )strNotification;
+
+ // failure until otherwise
+ errCode = -1;
+
+ // default synchronous
+ async = false;
+
+ cmdToken = GetToken( &commandPtr );
+
+ if ( cmdToken && !stricmp( cmdToken, "AddCommands()" ) )
+ {
+ errCode = rc_AddCommands( commandPtr );
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "SetProfile()" ) )
+ {
+ // first arg dictates routing
+ cmdToken = GetToken( &commandPtr );
+ if ( cmdToken && !stricmp( cmdToken, "cpu" ) )
+ errCode = rc_SetCpuProfile( commandPtr );
+ else if ( cmdToken && !stricmp( cmdToken, "texture" ) )
+ errCode = rc_SetTexProfile( commandPtr );
+
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "SetProfileData()" ) )
+ {
+ // first arg dictates routing
+ cmdToken = GetToken( &commandPtr );
+ if ( cmdToken && !stricmp( cmdToken, "cpu" ) )
+ errCode = rc_SetCpuProfileData( commandPtr );
+ else if ( cmdToken && !stricmp( cmdToken, "texture" ) )
+ errCode = rc_SetTexProfileData( commandPtr );
+
+ async = true;
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "TextureList()" ) )
+ {
+ errCode = rc_TextureList( commandPtr );
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "MaterialList()" ) )
+ {
+ errCode = rc_MaterialList( commandPtr );
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "SoundList()" ) )
+ {
+ errCode = rc_SoundList( commandPtr );
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "TimeStampLog()" ) )
+ {
+ errCode = rc_TimeStampLog( commandPtr );
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "MemDump()" ) )
+ {
+ errCode = rc_MemDump( commandPtr );
+ async = true;
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "MapInfo()" ) )
+ {
+ errCode = rc_MapInfo( commandPtr );
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "Assert()" ) )
+ {
+ errCode = rc_Assert( commandPtr );
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "FreeMemory()" ) )
+ {
+ errCode = rc_FreeMemory( commandPtr );
+ async = true;
+ goto cleanUp;
+ }
+ else if ( cmdToken && !stricmp( cmdToken, "Disconnect()" ) )
+ {
+ // disconnect requires specialized processing
+ // send command status first while connection valid, then do actual disconnect
+ // disconnect is always assumed to be valid, can't be denied
+ CommandCompleted( 0 );
+ DoDisconnect( TRUE );
+ return S_OK;
+ }
+ else
+ {
+ // unknown command
+ PrintToQueue( RGB( 255,0,0 ), "Unknown Command: %s\n", strNotification );
+ goto cleanUp;
+ }
+
+cleanUp:
+ if ( !async )
+ CommandCompleted( errCode );
+
+ return ( S_OK );
+}