diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/xbox/vxconsole/local_cmds.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'utils/xbox/vxconsole/local_cmds.cpp')
| -rw-r--r-- | utils/xbox/vxconsole/local_cmds.cpp | 1307 |
1 files changed, 1307 insertions, 0 deletions
diff --git a/utils/xbox/vxconsole/local_cmds.cpp b/utils/xbox/vxconsole/local_cmds.cpp new file mode 100644 index 0000000..05e5cdb --- /dev/null +++ b/utils/xbox/vxconsole/local_cmds.cpp @@ -0,0 +1,1307 @@ +//========= 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; +} |