|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// LOCAL_CMDS.CPP
//
// Local commands ( *xxxx ) executed by this application.
//=====================================================================================//
#include "vxconsole.h"
localCommand_t g_localCommands[] = { // Command name, Flags Handler Help string
// console commands
{ "*cls", FN_CONSOLE, lc_cls, ": Clear the screen" }, { "*connect", FN_CONSOLE, lc_autoConnect, ": Connect and listen until successful" }, { "*disconnect", FN_CONSOLE, lc_disconnect, ": Terminate Debug Console session" }, { "*help", FN_CONSOLE, lc_help, "[command] : List commands/usage" }, { "*quit", FN_CONSOLE, lc_quit, ": Terminate console" }, { "*run", FN_XBOX, lc_run, "[app.xex] : Run application or Reboot" }, { "*reset", FN_XBOX, lc_reset, "Reboot" }, { "*screenshot", FN_XBOX, lc_screenshot, "<file.bmp> : Copy the screen to file.bmp" }, { "*memory", FN_APP, lc_memory, ": Dump Memory Stats" }, { "*dir", FN_XBOX, lc_dir, "<filepath> [/s]: Directory listing" }, { "*del", FN_XBOX, lc_del, "<filepath> [/s] [/q]: Delete file" }, { "*modules", FN_XBOX, lc_modules, ": Lists currently loaded modules" }, { "*sections", FN_XBOX, lc_sections, "<module> : Lists the sections in the module" }, { "*bug", FN_CONSOLE, lc_bug, ": Open bug submission form" }, { "*clearconfigs", FN_XBOX, lc_ClearConfigs, ": Erase all game configs" },
// xcommands
{ "*break", FN_XBOX, NULL, " addr=<address> | 'Write'/'Read'/'Execute'=<address> size=<DataSize> ['clear']: Sets/Clears a breakpoint" }, // { "*bye", FN_XBOX, NULL, ": Closes connection" },
{ "*continue", FN_XBOX, NULL, " thread=<threadid>: Resumes execution of a thread which has been stopped" }, // { "*delete", FN_XBOX, NULL, " name=<remotefile>: Deletes a file on the Xbox" },
// { "*dirlist", FN_XBOX, NULL, " name=<remotedir>: Lists the items in the directory" },
{ "*getcontext", FN_XBOX, NULL, " thread=<threadid> 'Control' | 'Int' | 'FP' | 'Full': Gets the context of the thread" }, { "*getfileattributes", FN_XBOX, NULL, " name=<remotefile>: Gets attributes of a file" }, { "*getmem", FN_XBOX, NULL, " addr=<address> length=<len>: Reads memory from the Xbox" }, { "*go", FN_XBOX, NULL, ": Resumes suspended title threads" }, { "*halt", FN_XBOX, NULL, " thread=<threadid> Breaks a thread" }, { "*isstopped", FN_XBOX, NULL, " thread=<threadid>: Determines if a thread is stopped and why" }, { "*mkdir", FN_XBOX, NULL, " name=<remotedir>: Creates a new directory on the Xbox" }, { "*modlong", FN_XBOX, NULL, " name=<module>: Lists the long name of the module" }, // { "*reboot", FN_XBOX, NULL, " [warm] [wait]: Reboots the xbox" },
{ "*rename", FN_XBOX, NULL, " name=<remotefile> newname=<newname>: Renames a file on the Xbox" }, { "*resume", FN_XBOX, NULL, " thread=<threadid>: Resumes thread execution" }, { "*setcontext", FN_XBOX, NULL, " thread=<threadid>: Sets the context of the thread." }, { "*setfileattributes", FN_XBOX, NULL, " <remotefile> <attrs>: Sets attributes of a file" }, { "*setmem", FN_XBOX, NULL, " addr=<address> data=<rawdata>: Sets memory on the Xbox" }, { "*stop", FN_XBOX, NULL, ": Stops the process" }, { "*suspend", FN_XBOX, NULL, " thread=<threadid>: Suspends the thread" }, { "*systime", FN_XBOX, NULL, ": Gets the system time of the xbox" }, { "*threadinfo", FN_XBOX, NULL, " thread=<threadid>: Gets thread info" }, { "*threads", FN_XBOX, lc_threads, ": Gets the thread list" }, // { "*title", FN_XBOX, NULL, " dir=<remotedir> name=<remotexex> [cmdline=<cmdline>]: Sets title to run" },
{ "*xexinfo", FN_XBOX, NULL, " name=<remotexex | 'running'>: Gets info on an xex" }, { "*crash", FN_XBOX, lc_crashdump, " crash the console, emitting a dump" }, }; const int g_numLocalCommands = sizeof( g_localCommands )/sizeof( g_localCommands[0] );
static BOOL g_bAutoConnectQuiet; static int g_bAutoConnectWait;
//-----------------------------------------------------------------------------
// MatchCommands
//
//-----------------------------------------------------------------------------
int MatchLocalCommands( char* cmdStr, const char* cmdList[], int maxCmds ) { int numCommands = 0;
// look in local
int matchLen = strlen( cmdStr ); for ( int i=0; i<g_numLocalCommands; i++ ) { if ( !strnicmp( cmdStr, g_localCommands[i].strCommand, matchLen ) ) { cmdList[numCommands++] = g_localCommands[i].strCommand; if ( numCommands >= maxCmds ) break; } }
return ( numCommands ); }
//-----------------------------------------------------------------------------
// DecodeRebootArgs
//
//-----------------------------------------------------------------------------
void DecodeRebootArgs( int argc, char** argv, char* xexPath, char* xexName, char* xexArgs ) { char drive[MAX_PATH]; char dir[MAX_PATH]; char filename[MAX_PATH]; char extension[MAX_PATH];
xexPath[0] = '\0'; xexName[0] = '\0'; xexArgs[0] = '\0';
if ( !argc ) return;
_splitpath( argv[0], drive, dir, filename, extension );
sprintf( xexPath, "%s%s", drive, dir ); sprintf( xexName, "%s%s", filename, extension );
for ( int i=1; i<argc; i++ ) { strcat( xexArgs, argv[i] ); if ( i < argc-1 ) strcat( xexArgs, " " ); } }
//-----------------------------------------------------------------------------
// Helper function. Causes a disconnect, has optional re-connect time.
// A non-zero wait will delay before attempting re-connect.
//-----------------------------------------------------------------------------
void DoDisconnect( BOOL bKeepConnection, int waitTime ) { // save state, user gates auto-connect ability
int autoConnect = g_autoConnect;
// full disconnect, disables autoconnect
lc_disconnect( 0, NULL );
if ( autoConnect && bKeepConnection && waitTime > 0 ) { // restore autoconnect status
lc_autoConnect( 0, NULL );
// lets the system settle a little between contexts
g_bAutoConnectWait = waitTime; g_bAutoConnectQuiet = FALSE; } }
//-----------------------------------------------------------------------------
// lc_bug
//
//-----------------------------------------------------------------------------
BOOL lc_bug( int argc, char* argv[] ) { if ( argc != 1 ) { char* args[2] = {"*help", argv[0]}; lc_help( 1, args ); goto cleanUp; }
BugDlg_Open();
return TRUE;
cleanUp: return FALSE; }
//-----------------------------------------------------------------------------
// lc_dir
//
//-----------------------------------------------------------------------------
BOOL lc_dir( int argc, char* argv[] ) { fileNode_t *nodePtr; fileNode_t *pFileList; int numFiles; int numDirs; __int64 totalBytes; bool recurse; char dateTimeString[256]; char sizeString[64]; char filePath[MAX_PATH]; char fileName[MAX_PATH]; char targetName[MAX_PATH]; char newPath[MAX_PATH]; SYSTEMTIME systemTime; SYSTEMTIME localTime; const char *dirString; BOOL errCode; int nPass; TIME_ZONE_INFORMATION tzInfo;
pFileList = NULL; errCode = FALSE;
if ( argc < 2 ) { char* args[2] = {"*dir", argv[0]}; lc_help( 2, args ); goto cleanUp; }
strcpy( newPath, argv[1] );
// seperate components
Sys_StripFilename( newPath, filePath, sizeof( filePath ) ); Sys_StripPath( newPath, fileName, sizeof( fileName ) );
if ( fileName[0] ) { if ( !strstr( fileName,"*" ) && !strstr( fileName,"?" ) ) { // assume filename was a directory name
strcat( newPath, "\\" ); Sys_StripFilename( newPath, filePath, sizeof( filePath ) ); Sys_StripPath( newPath, fileName, sizeof( fileName ) ); } }
recurse = false; if ( argc >= 3 ) { if ( !stricmp( argv[2], "/s" ) ) recurse = true; }
if ( !GetTargetFileList_r( filePath, recurse, FA_NORMAL|FA_DIRECTORY|FA_READONLY, 0, &pFileList ) ) { ConsoleWindowPrintf( RGB( 255,0,0 ), "Bad Target Path '%s'\n", filePath ); goto cleanUp; }
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\nDirectory of %s\n\n", argv[1] );
GetTimeZoneInformation( &tzInfo );
numFiles = 0; numDirs = 0; totalBytes = 0; for ( nPass=0; nPass<2; nPass++ ) { for ( nodePtr=pFileList; nodePtr; nodePtr=nodePtr->nextPtr ) { if ( !nPass && !( nodePtr->attributes & FA_DIRECTORY ) ) { // first pass, dirs only
continue; } else if ( nPass && ( nodePtr->attributes & FA_DIRECTORY ) ) { // second pass, files only
continue; }
Sys_StripPath( nodePtr->filename, targetName, sizeof( targetName ) );
if ( fileName[0] && !Sys_IsWildcardMatch( fileName, targetName, false ) ) continue;
FileTimeToSystemTime( &nodePtr->changeTime, &systemTime ); SystemTimeToTzSpecificLocalTime( &tzInfo, &systemTime, &localTime ); SystemTimeToString( &localTime, dateTimeString, sizeof( dateTimeString ) );
__int64 fullSize = MAKEINT64( nodePtr->sizeHigh, nodePtr->sizeLow );
if ( nodePtr->attributes & FA_DIRECTORY ) { numDirs++; dirString = "<DIR>"; sprintf( sizeString, "%s", " " ); } else { numFiles++; dirString = " "; Sys_NumberToCommaString( fullSize, sizeString, sizeof( sizeString ) ); totalBytes += fullSize; }
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s %s %12s %s\n", dateTimeString, dirString, sizeString, targetName ); } }
Sys_NumberToCommaString( totalBytes, sizeString, sizeof( sizeString ) ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%9s %d File(s) %s bytes\n", " ", numFiles, sizeString ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%9s %d Dir(s)\n", " ", numDirs );
// success
errCode = TRUE;
cleanUp: if ( pFileList ) FreeTargetFileList( pFileList );
return errCode; }
//-----------------------------------------------------------------------------
// lc_del
//
//-----------------------------------------------------------------------------
BOOL lc_del( int argc, char* argv[] ) { HRESULT hr; fileNode_t *nodePtr; fileNode_t *pFileList; int numDeleted; int numErrors; bool recurse; char filePath[MAX_PATH]; char fileName[MAX_PATH]; char targetName[MAX_PATH]; BOOL errCode;
pFileList = NULL; errCode = FALSE;
if ( argc < 2 ) { char* args[2] = {"*del", argv[0]}; lc_help( 2, args ); goto cleanUp; }
// seperate components
Sys_StripFilename( argv[1], filePath, sizeof( filePath ) ); Sys_StripPath( argv[1], fileName, sizeof( fileName ) );
bool bQuiet = false; recurse = false; if ( argc >= 3 ) { for ( int i = 2; i < argc; i++ ) { if ( !V_stricmp( argv[i], "/s" ) ) { recurse = true; } else if ( !V_stricmp( argv[i], "/q" ) ) { // silence errors
bQuiet = true; } } }
if ( !GetTargetFileList_r( filePath, recurse, FA_NORMAL|FA_READONLY|FA_DIRECTORY, 0, &pFileList ) ) { ConsoleWindowPrintf( XBX_CLR_RED, "Bad Target Path '%s'\n", filePath ); goto cleanUp; }
numErrors = 0; numDeleted = 0; for ( nodePtr=pFileList; nodePtr; nodePtr=nodePtr->nextPtr ) { Sys_StripPath( nodePtr->filename, targetName, sizeof( targetName ) );
if ( fileName[0] && !Sys_IsWildcardMatch( fileName, targetName, false ) ) continue;
hr = DmDeleteFile( nodePtr->filename, ( nodePtr->attributes & FA_DIRECTORY ) != 0 ); if ( hr != XBDM_NOERR ) { if ( !bQuiet ) { ConsoleWindowPrintf( XBX_CLR_RED, "Error Deleting '%s'\n", nodePtr->filename ); } numErrors++; } else { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Deleted '%s'\n", nodePtr->filename ); numDeleted++; } }
if ( !numDeleted && !numErrors ) { ConsoleWindowPrintf( XBX_CLR_RED, "No Files found for '%s'\n", argv[1] ); } else { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%d files deleted.\n", numDeleted ); }
// success
errCode = TRUE;
cleanUp: if ( pFileList ) FreeTargetFileList( pFileList );
return errCode; }
//-----------------------------------------------------------------------------
// lc_memory
//
//-----------------------------------------------------------------------------
BOOL lc_memory( int argc, char* argv[] ) { HRESULT hr;
hr = DmAPI_SendCommand( VXCONSOLE_COMMAND_PREFIX "!" "__memory__", true ); if ( FAILED( hr ) ) return FALSE;
// success
return TRUE; }
//-----------------------------------------------------------------------------
// lc_screenshot
//
//-----------------------------------------------------------------------------
BOOL lc_screenshot( int argc, char* argv[] ) { char filename[MAX_PATH]; char filepath[MAX_PATH]; static int shot = 0; struct _stat dummyStat;
if ( argc <= 1 ) { strcpy( filepath, g_localPath ); Sys_AddFileSeperator( filepath, sizeof( filepath ) );
// spin up to available file
while ( 1 ) { sprintf( filename, "%sscreenshot_%4.4d.bmp", filepath, shot ); if ( _stat( filename, &dummyStat ) == -1 ) { // filename not in use
break; } shot++; } } else if ( argc == 2 ) { strcpy( filename, argv[1] ); Sys_AddExtension( ".bmp", filename, sizeof( filename ) ); } else if ( argc > 2 ) { char* args[2] = {"*help", argv[0]}; lc_help( 2, args ); goto cleanUp; }
HRESULT hr = DmScreenShot( filename ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_screenshot(): DmScreenShot() failure", hr ); goto cleanUp; }
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Screenshot saved to %s\n", filename );
// advance the shot
shot++;
// success
return TRUE;
cleanUp: return FALSE; }
//-----------------------------------------------------------------------------
// lc_modules
//
//-----------------------------------------------------------------------------
BOOL lc_modules( int argc, char* argv[] ) { HRESULT hr; PDM_WALK_MODULES pWalkMod = NULL; CUtlVector< DMN_MODLOAD > list;
// add a fake module at 0xFFFFFFFF to make sorting simple
DMN_MODLOAD modLoad = { 0 }; modLoad.BaseAddress = (VOID*)0xFFFFFFFF; list.AddToTail( modLoad );
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Modules:\n" ); while ( 1 ) { hr = DmWalkLoadedModules( &pWalkMod, &modLoad ); if ( hr == XBDM_ENDOFLIST ) { hr = XBDM_NOERR; break; } else if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_modules(): DmWalkLoadedModules() failure", hr ); break; }
// add in ascending address order
for ( int i = 0; i < list.Count(); i++ ) { if ( modLoad.BaseAddress <= list[i].BaseAddress ) { list.InsertBefore( i, modLoad ); break; } } }
unsigned int total = 0; for ( int i = 0; i < list.Count()-1; i++ ) { DMN_MODLOAD *pModule = &list[i]; ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Base: 0x%8.8x, Size: %5.2f MB, [%s]\n", pModule->BaseAddress, pModule->Size/( 1024.0f*1024.0f ), pModule->Name );
total += pModule->Size; }
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Total: %.2f MB\n\n", total/( 1024.0f*1024.0f ) );
if ( pWalkMod ) { DmCloseLoadedModules( pWalkMod ); }
if ( !FAILED( hr ) ) { // success
return TRUE; }
return FALSE; }
//-----------------------------------------------------------------------------
// lc_sections
//
//-----------------------------------------------------------------------------
BOOL lc_sections( int argc, char* argv[] ) { char moduleName[MAX_PATH]; HRESULT hr; PDM_WALK_MODSECT pWalkModSect = NULL; DMN_SECTIONLOAD sectLoad;
if ( argc != 2 ) { char* args[2] = {"*help", argv[0]}; lc_help( 2, args ); goto cleanUp; }
strcpy( moduleName, argv[1] );
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Sections:\n" ); while ( 1 ) { hr = DmWalkModuleSections( &pWalkModSect, moduleName, §Load ); if ( hr == XBDM_ENDOFLIST ) { hr = XBDM_NOERR; break; } else if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_sections(): DmWalkModuleSections() failure", hr ); break; }
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "[%s]:\n", sectLoad.Name ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Base: 0x%8.8x\n", sectLoad.BaseAddress ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Size: %.2f MB ( %d bytes )\n", sectLoad.Size/( 1024.0f*1024.0f ), sectLoad.Size ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Index: %d\n", sectLoad.Index ); }
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "End.\n\n" );
if ( pWalkModSect ) DmCloseModuleSections( pWalkModSect );
if ( !FAILED( hr ) ) { // success
return TRUE; }
cleanUp: return FALSE; }
//-----------------------------------------------------------------------------
// lc_threads
//
//-----------------------------------------------------------------------------
BOOL lc_threads( int argc, char* argv[] ) { char nameBuff[256]; char suspendBuff[32];
DWORD threadList[256]; DWORD numThreads = 256; memset( &threadList, 0, sizeof( threadList ) ); HRESULT hr = DmGetThreadList( threadList, &numThreads ); if ( FAILED( hr ) ) return FALSE;
// enumerate threads and display sorted by processor
DM_THREADINFOEX threadInfoEx; for ( int core = 0; core < 3; core++ ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n--- CORE %d ---\n", core );
for ( int unit = 0; unit < 2; unit++ ) { for ( int i = 0; i < (int)numThreads; i++ ) { threadInfoEx.Size = sizeof( DM_THREADINFOEX ); hr = DmGetThreadInfoEx( threadList[i], &threadInfoEx ); if ( FAILED( hr ) ) return FALSE;
if ( threadInfoEx.CurrentProcessor != core*2 + unit ) { continue; } nameBuff[0] = '\0'; DmGetMemory( threadInfoEx.ThreadNameAddress, threadInfoEx.ThreadNameLength, nameBuff, NULL ); if ( !nameBuff[0] ) { strcpy( nameBuff, "???" ); }
suspendBuff[0] = '\0'; if ( threadInfoEx.SuspendCount ) { sprintf( suspendBuff, "(Suspend: %d)", threadInfoEx.SuspendCount ); }
ConsoleWindowPrintf( XBX_CLR_DEFAULT, " Id: 0x%8.8x Pri: %2d Proc: %1d Stack: %7.2f KB [%s] %s\n", threadList[i], threadInfoEx.Priority, threadInfoEx.CurrentProcessor, (float)( (unsigned int)threadInfoEx.StackBase - (unsigned int)threadInfoEx.StackLimit )/1024.0f, nameBuff, suspendBuff ); } } }
return TRUE; }
//-----------------------------------------------------------------------------
// lc_run
//
//-----------------------------------------------------------------------------
BOOL lc_run( int argc, char* argv[] ) { HRESULT hr; char xexDrive[MAX_PATH]; char xexPath[MAX_PATH]; char xexName[MAX_PATH]; char xexArgs[MAX_PATH];
if ( !argc ) { char* args[2] = {"*help", argv[0]}; lc_help( 2, args ); goto cleanUp; } // copy args
g_rebootArgc = argc-1; for ( int i=1; i<argc; i++ ) { if ( i==1 ) { strcpy( xexPath, argv[i] ); Sys_AddExtension( ".xex", xexPath, sizeof( xexPath ) ); _splitpath( xexPath, xexDrive, NULL, NULL, NULL ); if ( !xexDrive[0] ) { char szTempPath[MAX_PATH]; V_strncpy( szTempPath, "e:\\", sizeof( szTempPath ) ); V_strncat( szTempPath, xexPath, sizeof( szTempPath ) ); V_strncpy( xexPath, szTempPath, sizeof( xexPath ) ); }
g_rebootArgv[i-1] = Sys_CopyString( xexPath ); } else { g_rebootArgv[i-1] = Sys_CopyString( argv[i] ); } }
if ( !g_rebootArgc ) { // reboot
hr = DmReboot( DMBOOT_COLD ); } else { DecodeRebootArgs( g_rebootArgc, g_rebootArgv, xexPath, xexName, xexArgs );
// trial set title - ensure title is present
hr = DmSetTitle( xexPath, xexName, xexArgs ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_Run(): DmSetTitle() failure", hr ); goto cleanUp; } // reboot - wait for 15s to connect and run title
hr = DmReboot( DMBOOT_WAIT ); } if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_Run(): DmReboot() failure", hr ); goto cleanUp; }
// set reboot state
g_reboot = true;
return TRUE;
cleanUp: // free args
for ( int i=0; i<g_rebootArgc; i++ ) Sys_Free( g_rebootArgv[i] ); g_rebootArgc = 0;
return FALSE; }
//-----------------------------------------------------------------------------
// lc_reset
//
//-----------------------------------------------------------------------------
BOOL lc_reset( int argc, char* argv[] ) { if ( !argc ) { char* args[2] = {"*help", argv[0]}; lc_help( 2, args ); return FALSE; }
HRESULT hr = DmReboot( DMBOOT_COLD );
if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_Run(): DmReboot() failure", hr ); return FALSE; }
// set reboot state
g_reboot = true;
return TRUE; }
//-----------------------------------------------------------------------------
// lc_help
//
// Handles the "help" command. If no args, prints a list of built-in
// and remote commands ( remote only if connected ). If a command
// is specified, prints detailed help for that command
//-----------------------------------------------------------------------------
BOOL lc_help( int argc, char* argv[] ) { if ( argc <= 1 ) { // no arguments - print out our list of commands
ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n" ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Console Commands:\n" ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, "---------------\n" ); for ( int i = 0; i < g_numLocalCommands; i++ ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s\n", g_localCommands[i].strCommand ); }
if ( g_connectedToApp ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Remote Commands: ( %d )\n", g_numRemoteCommands ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, "----------------\n" ); if ( !g_numRemoteCommands ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "( None )\n" ); } else { for ( int i=0; i<g_numRemoteCommands; i++ ) ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s\n", g_remoteCommands[i]->strCommand ); } ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n" ); } } else { // match as many as possible
int cch = lstrlenA( argv[1] );
// print help description for all local matches
for ( int i=0; i<g_numLocalCommands; i++ ) { if ( !_strnicmp( g_localCommands[i].strCommand, argv[1], cch ) && g_localCommands[i].strHelp ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s %s\n", g_localCommands[i].strCommand, g_localCommands[i].strHelp ); } }
// print help description for all remote matches
if ( g_connectedToApp ) { for ( int i=0; i<g_numRemoteCommands; i++ ) { if ( !_strnicmp( g_remoteCommands[i]->strCommand, argv[1], cch ) && g_remoteCommands[i]->strHelp ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s %s\n", g_remoteCommands[i]->strCommand, g_remoteCommands[i]->strHelp ); } } } ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\n" ); }
return TRUE; }
//-----------------------------------------------------------------------------
// lc_cls
//-----------------------------------------------------------------------------
BOOL lc_cls( int argc, char* argv[] ) { SetWindowText( g_hwndOutputWindow, "" );
// non't let the compiler complain about unused parameters
( VOID )argc; ( VOID )argv;
return TRUE; }
//-----------------------------------------------------------------------------
// lc_connect
//
// Connect to XBox
//-----------------------------------------------------------------------------
BOOL lc_connect( int argc, char* argv[] ) { HRESULT hr; BOOL connected = FALSE;
if ( g_connectedToXBox ) { if ( !lc_disconnect( 0, NULL ) ) return FALSE; }
if ( argc >= 1 && argv[0][0] ) { hr = DmSetXboxName( argv[0] ); if ( FAILED( hr ) ) { char message[255]; sprintf( message, "ConnectToXBox(): DmSetXboxName( %s ) failure", argv[0] ); DmAPI_DisplayError( message, hr ); goto cleanUp; } }
// open connection
hr = DmOpenConnection( &g_pdmConnection ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "ConnectToXBox(): DmOpenConnection() failure", hr ); goto cleanUp; } connected = TRUE;
DWORD namelen = MAX_XBOXNAMELEN; hr = DmGetXboxName( g_xboxName, &namelen ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "ConnectToXBox(): DmGetXboxName() failure", hr ); goto cleanUp; } hr = DmResolveXboxName( &g_xboxAddress ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "ConnectToXBox(): DmResolveXboxName() failure", hr ); goto cleanUp; }
// success
g_connectedToXBox = TRUE; g_connectFailure = 0;
if ( !g_connectCount ) ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Connected To: '%s'(%d.%d.%d.%d)\n", g_xboxName, ( ( byte* )&g_xboxAddress )[3], ( ( byte* )&g_xboxAddress )[2], ( ( byte* )&g_xboxAddress )[1], ( ( byte* )&g_xboxAddress )[0] ); g_connectCount++;
SetConnectionIcon( ICON_CONNECTED_XBOX );
if ( g_connectCount == 1 ) { // inital connect
}
return TRUE;
cleanUp: if ( connected ) DmCloseConnection( g_pdmConnection );
return FALSE; }
//-----------------------------------------------------------------------------
// lc_listen
//
// Open listen session with App
//-----------------------------------------------------------------------------
BOOL lc_listen( int argc, char* argv[] ) { HRESULT hr; BOOL success; BOOL sessionStarted; BOOL sessionValid; char *args[1]; char cmdStr[256];
if ( g_connectedToXBox || g_connectedToApp ) { if ( !lc_disconnect( 0, NULL ) ) return ( FALSE ); }
if ( !g_connectedToXBox ) { // connect to xbox
args[0] = g_xboxTargetName; if ( !lc_connect( 1, args ) ) return FALSE; }
// until otherwise
success = FALSE; sessionStarted = FALSE; sessionValid = FALSE;
// init session
hr = DmOpenNotificationSession( 0, &g_pdmnSession ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_session(): DmOpenNotificationSession() failure", hr ); goto cleanUp; } sessionStarted = TRUE;
// get notifications of app debugging output
hr = DmNotify( g_pdmnSession, DM_DEBUGSTR, Remote_NotifyDebugString ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_session(): DmNotify() failure", hr ); goto cleanUp; }
// get command notifications
hr = DmRegisterNotificationProcessor( g_pdmnSession, VXCONSOLE_COMMAND_PREFIX, Remote_NotifyCommandFunc ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_session(): DmRegisterNotificationProcessor() failure", hr ); goto cleanUp; }
// get print notifications
hr = DmRegisterNotificationProcessor( g_pdmnSession, VXCONSOLE_PRINT_PREFIX, Remote_NotifyPrintFunc ); if ( FAILED( hr ) ) { DmAPI_DisplayError( "lc_session(): DmRegisterNotificationProcessor() failure", hr ); goto cleanUp; } sessionValid = TRUE;
// Send initial connect command to the External Command Processor so it knows we're here
sprintf( cmdStr, "%s %d", VXCONSOLE_COMMAND_PREFIX "!" "__connect__", VXCONSOLE_PROTOCOL_VERSION ); hr = DmAPI_SendCommand( cmdStr, true ); if ( FAILED( hr ) ) { if ( !g_autoConnect ) ConsoleWindowPrintf( RGB( 255,0,0 ), "Couldn't Find Application\n" ); goto cleanUp; } else { // connected
success = TRUE; g_connectedToApp = TRUE; g_connectedTime = Sys_GetSystemTime(); SetConnectionIcon( ICON_CONNECTED_APP1 );
if ( g_clsOnConnect ) { if ( g_bPlayTestMode ) { // demarcate the log
ConsoleWindowPrintf( CLR_DEFAULT, "\n******** CONNECTION ********\n" ); }
lc_cls( 0, NULL ); CpuProfile_Clear(); TimeStampLog_Clear(); }
goto cleanUp; }
cleanUp: if ( !success ) { if ( sessionValid ) DmNotify( g_pdmnSession, DM_NONE, NULL );
if ( sessionStarted ) DmCloseNotificationSession( g_pdmnSession ); }
return ( success ); }
//-----------------------------------------------------------------------------
// AutoConnectTimerProc
//
//-----------------------------------------------------------------------------
void AutoConnectTimerProc( HWND hwnd, UINT_PTR idEvent ) { static BOOL busy; int icon; char* cmdStr; BOOL bKeepConnection = TRUE;
// blink the connection icon
if ( g_connectedToApp && (! g_bSuppressBlink ) ) { if ( g_currentIcon == ICON_CONNECTED_APP0 ) icon = ICON_CONNECTED_APP1; else icon = ICON_CONNECTED_APP0; SetConnectionIcon( icon ); }
if ( busy ) { // not ready for new tick
return; }
if ( g_bAutoConnectWait > 0 ) { if ( g_bAutoConnectWait && !g_bAutoConnectQuiet ) ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Waiting... %d seconds remaining\n", g_bAutoConnectWait ); g_bAutoConnectWait--; return; }
// no more ticks until ready
busy = TRUE;
if ( !g_connectedToApp ) { // looking for application - must force re-connect every time
if ( g_connectedToXBox ) { // temporary "partial" disconnect
DmCloseConnection( g_pdmConnection ); g_connectedToXBox = FALSE; }
// attempt to start or re-establish connection and session
lc_listen( 0, NULL );
if ( !g_connectedToXBox ) { SetConnectionIcon( ICON_DISCONNECTED ); g_connectFailure++; }
if ( g_reboot && g_connectedToXBox ) { char xexPath[MAX_PATH]; char xexName[MAX_PATH]; char xexArgs[MAX_PATH];
DecodeRebootArgs( g_rebootArgc, g_rebootArgv, xexPath, xexName, xexArgs );
if ( g_rebootArgc ) { // free args
for ( int i=0; i<g_rebootArgc; i++ ) Sys_Free( g_rebootArgv[i] ); g_rebootArgc = 0;
HRESULT hr = DmSetTitle( xexPath, xexName, xexArgs ); if ( FAILED( hr ) ) DmAPI_DisplayError( "Reboot: DmSetTitle() failure", hr ); else { hr = DmGo(); if ( FAILED( hr ) ) DmAPI_DisplayError( "Reboot: DmGo() failure", hr ); } }
g_reboot = false; }
if ( !g_connectFailure ) { // quietly attempt re-connection or ping every 3 seconds
g_bAutoConnectWait = 3; g_bAutoConnectQuiet = TRUE; busy = FALSE; } else { if ( g_connectFailure == 1 ) { // console may be rebooting, allow sufficient dvd boot up delay, then attempt re-connection
// 5 seconds barely covers the xbox splash
g_bAutoConnectWait = 15; g_bAutoConnectQuiet = FALSE; busy = FALSE; } else { // a sustained connection failure means the xbox is just not there
// re-trying is too cpu intensive and causes pc to appear locked
// warn and stop auto connecting, user must fix
bKeepConnection = FALSE; goto disconnect; } } return; } else { // try to send ping across open connection at an idle interval
cmdStr = VXCONSOLE_COMMAND_PREFIX "!"; HRESULT hr = DmAPI_SendCommand( cmdStr, false ); if ( FAILED( hr ) && hr != XBDM_UNDEFINED ) goto disconnect;
// quietly ping
g_bAutoConnectWait = 3; g_bAutoConnectQuiet = TRUE; busy = FALSE; return; }
disconnect: ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Connection To Xbox Lost.\n" );
DoDisconnect( bKeepConnection, 3 );
busy = FALSE; }
//-----------------------------------------------------------------------------
// lc_autoConnect
//-----------------------------------------------------------------------------
BOOL lc_autoConnect( int argc, char* argv[] ) { if ( !g_autoConnect ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Enabling Auto Connect.\n" ); ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Looking for Connection...\n" ); g_autoConnect = TRUE; } else { // already enabled
return ( TRUE ); }
if ( !g_autoConnectTimer ) { UINT_PTR timer = TIMERID_AUTOCONNECT; g_autoConnectTimer = SetTimer( g_hDlgMain, timer, 1000, NULL ); }
return ( TRUE ); }
//-----------------------------------------------------------------------------
// lc_disconnect
//-----------------------------------------------------------------------------
BOOL lc_disconnect( int argc, char* argv[] ) { if ( g_autoConnect ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Disabling Auto Connect.\n" ); if ( g_autoConnectTimer ) { UINT_PTR timer = TIMERID_AUTOCONNECT; KillTimer( g_hDlgMain, timer ); } g_autoConnectTimer = 0; g_autoConnect = FALSE; }
if ( g_connectedToApp ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Closing Session.\n" );
DmAPI_SendCommand( VXCONSOLE_COMMAND_PREFIX "!" "__disconnect__", false ); // close session
DmNotify( g_pdmnSession, DM_NONE, NULL ); DmCloseNotificationSession( g_pdmnSession );
g_connectedToApp = FALSE; }
if ( g_connectedToXBox ) { ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Closing Connection.\n" );
// close connection
DmCloseConnection( g_pdmConnection );
// set the command ready mutex
SetEvent( g_hCommandReadyEvent );
g_connectedToXBox = FALSE; g_xboxName[0] = '\0'; g_xboxAddress = 0; }
SetConnectionIcon( ICON_DISCONNECTED );
g_connectCount = 0;
// free remote commands
Remote_DeleteCommands();
// Don't let the compiler complain about unused parameters
( VOID )argc; ( VOID )argv;
return TRUE; }
//-----------------------------------------------------------------------------
// lc_crashdump
//-----------------------------------------------------------------------------
BOOL lc_crashdump( int argc, char* argv[] ) { DmCrashDump();
// Don't let the compiler complain about unused parameters
( VOID )argc; ( VOID )argv;
return TRUE; }
//-----------------------------------------------------------------------------
// lc_quit
//-----------------------------------------------------------------------------
BOOL lc_quit( int argc, char* argv[] ) { PostMessage( g_hDlgMain, WM_CLOSE, 0, 0 );
// don't let the compiler complain about unused parameters
( VOID )argc; ( VOID )argv;
return TRUE; }
//-----------------------------------------------------------------------------
// lc_ClearConfigs
//
//-----------------------------------------------------------------------------
BOOL lc_ClearConfigs( int argc, char* argv[] ) { if ( argc != 1 ) { char* args[2] = {"*help", argv[0]}; lc_help( 1, args ); goto cleanUp; }
// delete any configurations (ignore errors)
char szTempFilename[MAX_PATH]; V_ComposeFileName( "HDD:\\Content", "*.*", szTempFilename, sizeof( szTempFilename ) ); char *pArgs[4]; pArgs[0] = "*del"; pArgs[1] = szTempFilename; pArgs[2] = "/s"; pArgs[3] = "/q"; lc_del( 4, pArgs );
return TRUE;
cleanUp: return FALSE; }
|