summaryrefslogtreecommitdiff
path: root/utils/xbox/vxconsole
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/xbox/vxconsole
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/xbox/vxconsole')
-rw-r--r--utils/xbox/vxconsole/assert_dialog.cpp155
-rw-r--r--utils/xbox/vxconsole/assert_dialog.rc107
-rw-r--r--utils/xbox/vxconsole/assert_resource.h29
-rw-r--r--utils/xbox/vxconsole/bindings.cpp591
-rw-r--r--utils/xbox/vxconsole/bug.cpp1576
-rw-r--r--utils/xbox/vxconsole/common.cpp73
-rw-r--r--utils/xbox/vxconsole/config.cpp217
-rw-r--r--utils/xbox/vxconsole/cpu_profile.cpp983
-rw-r--r--utils/xbox/vxconsole/exclude_paths.cpp1134
-rw-r--r--utils/xbox/vxconsole/fileio.cpp416
-rw-r--r--utils/xbox/vxconsole/icon_connect1.icobin0 -> 318 bytes
-rw-r--r--utils/xbox/vxconsole/icon_connect2.icobin0 -> 318 bytes
-rw-r--r--utils/xbox/vxconsole/icon_connect2a.icobin0 -> 318 bytes
-rw-r--r--utils/xbox/vxconsole/icon_disconnect.icobin0 -> 318 bytes
-rw-r--r--utils/xbox/vxconsole/local_cmds.cpp1307
-rw-r--r--utils/xbox/vxconsole/mem_profile.cpp561
-rw-r--r--utils/xbox/vxconsole/progress.cpp359
-rw-r--r--utils/xbox/vxconsole/remote_cmds.cpp484
-rw-r--r--utils/xbox/vxconsole/resource.h241
-rw-r--r--utils/xbox/vxconsole/show_materials.cpp575
-rw-r--r--utils/xbox/vxconsole/show_memdump.cpp1440
-rw-r--r--utils/xbox/vxconsole/show_sounds.cpp778
-rw-r--r--utils/xbox/vxconsole/show_textures.cpp971
-rw-r--r--utils/xbox/vxconsole/sync_files.cpp942
-rw-r--r--utils/xbox/vxconsole/sys_scriptlib.cpp292
-rw-r--r--utils/xbox/vxconsole/sys_scriptlib.h34
-rw-r--r--utils/xbox/vxconsole/sys_utils.cpp1090
-rw-r--r--utils/xbox/vxconsole/sys_utils.h65
-rw-r--r--utils/xbox/vxconsole/tex_profile.cpp993
-rw-r--r--utils/xbox/vxconsole/timestamp_log.cpp623
-rw-r--r--utils/xbox/vxconsole/vxconsole.cpp1528
-rw-r--r--utils/xbox/vxconsole/vxconsole.h479
-rw-r--r--utils/xbox/vxconsole/vxconsole.icobin0 -> 2238 bytes
-rw-r--r--utils/xbox/vxconsole/vxconsole.rc557
-rw-r--r--utils/xbox/vxconsole/vxconsole.vpc85
35 files changed, 18685 insertions, 0 deletions
diff --git a/utils/xbox/vxconsole/assert_dialog.cpp b/utils/xbox/vxconsole/assert_dialog.cpp
new file mode 100644
index 0000000..9abcd35
--- /dev/null
+++ b/utils/xbox/vxconsole/assert_dialog.cpp
@@ -0,0 +1,155 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// ASSERT_DIALOG.CPP
+//
+// Handle Remote Assert().
+//=====================================================================================//
+#include "vxconsole.h"
+
+AssertAction_t g_AssertAction = ASSERT_ACTION_BREAK;
+static const char * g_AssertInfo = "Assert Info Not Available.";
+bool g_AssertDialogActive = false;
+
+//-----------------------------------------------------------------------------
+// AssertDialogProc
+//
+//-----------------------------------------------------------------------------
+int CALLBACK AssertDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ switch( uMsg )
+ {
+ case WM_INITDIALOG:
+ {
+ SetWindowText( hDlg, "Xbox 360 Assert!" );
+ SetDlgItemText( hDlg, IDC_FILENAME_CONTROL, g_AssertInfo );
+
+ // Center the dialog.
+ RECT rcDlg, rcDesktop;
+ GetWindowRect( hDlg, &rcDlg );
+ GetWindowRect( GetDesktopWindow(), &rcDesktop );
+ SetWindowPos(
+ hDlg,
+ HWND_TOP,
+ ((rcDesktop.right-rcDesktop.left) - (rcDlg.right-rcDlg.left)) / 2,
+ ((rcDesktop.bottom-rcDesktop.top) - (rcDlg.bottom-rcDlg.top)) / 2,
+ 0,
+ 0,
+ SWP_NOSIZE );
+ }
+ return true;
+
+ case WM_COMMAND:
+ {
+ switch( LOWORD( wParam ) )
+ {
+ // Ignore Asserts in this file from now on.
+ case IDC_IGNORE_FILE:
+ {
+ g_AssertAction = ASSERT_ACTION_IGNORE_FILE;
+ EndDialog( hDlg, 0 );
+ return true;
+ }
+
+ // Ignore this Assert once.
+ case IDC_IGNORE_THIS:
+ {
+ g_AssertAction = ASSERT_ACTION_IGNORE_THIS;
+ EndDialog( hDlg, 0 );
+ return true;
+ }
+
+ // Always ignore this Assert.
+ case IDC_IGNORE_ALWAYS:
+ {
+ g_AssertAction = ASSERT_ACTION_IGNORE_ALWAYS;
+ EndDialog( hDlg, 0 );
+ return true;
+ }
+
+ // Ignore all Asserts from now on.
+ case IDC_IGNORE_ALL:
+ {
+ g_AssertAction = ASSERT_ACTION_IGNORE_ALL;
+ EndDialog( hDlg, 0 );
+ return true;
+ }
+
+ case IDC_BREAK:
+ {
+ g_AssertAction = ASSERT_ACTION_BREAK;
+ EndDialog( hDlg, 0 );
+ return true;
+ }
+ }
+
+ case WM_KEYDOWN:
+ {
+ // Escape?
+ if ( wParam == 2 )
+ {
+ // Ignore this Assert.
+ g_AssertAction = ASSERT_ACTION_IGNORE_THIS;
+ EndDialog( hDlg, 0 );
+ return true;
+ }
+ }
+ }
+ return true;
+ }
+
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// rc_Assert
+//
+// Sent from application on hitting an Assert
+//-----------------------------------------------------------------------------
+int rc_Assert( char* commandPtr )
+{
+ char* cmdToken;
+ int retAddr;
+ int errCode = -1;
+
+ // Flash the taskbar icon (otherwise users may not realise the app has stalled on an Assert, esp. during loading)
+ FLASHWINFO flashWInfo = { sizeof(FLASHWINFO), g_hDlgMain, FLASHW_ALL|FLASHW_TIMERNOFG, 0, 1000 };
+ FlashWindowEx( &flashWInfo );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ if (1 != sscanf( cmdToken, "%x", &retAddr ))
+ goto cleanUp;
+
+ // skip whitespace
+ while ( commandPtr[0] == ' ' )
+ {
+ commandPtr++;
+ }
+
+ // Display file/line/expression info from the message in the Assert dialog
+ // (convert '\t' to '\n'; way simpler than tokenizing a general assert expression)
+ g_AssertInfo = commandPtr;
+ char *tab = commandPtr;
+ while( ( tab = strchr( tab, '\t' ) ) != NULL )
+ {
+ tab[0] = '\n';
+ }
+
+ // Open the Assert dialog, to determine the desired action
+ g_AssertAction = ASSERT_ACTION_BREAK;
+ g_AssertDialogActive = true;
+ DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_ASSERT_DIALOG ), g_hDlgMain, ( DLGPROC )AssertDialogProc );
+ g_AssertDialogActive = false;
+
+ // Write the (endian-converted) result directly back into the application's memory:
+ int xboxRetVal = BigDWord( g_AssertAction );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return errCode;
+}
diff --git a/utils/xbox/vxconsole/assert_dialog.rc b/utils/xbox/vxconsole/assert_dialog.rc
new file mode 100644
index 0000000..0d19bd2
--- /dev/null
+++ b/utils/xbox/vxconsole/assert_dialog.rc
@@ -0,0 +1,107 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "assert_resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "assert_resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ASSERT_DIALOG DIALOGEX 0, 0, 268, 158
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Assert"
+FONT 8, "MS Sans Serif", 0, 0, 0x0
+BEGIN
+ LTEXT "c:/hl2/src/blah.cpp",IDC_FILENAME_CONTROL,7,7,246,34
+ DEFPUSHBUTTON "&Break in Debugger",IDC_BREAK,7,49,98,14
+ PUSHBUTTON "&Ignore This Assert",IDC_IGNORE_THIS,7,66,98,14
+ EDITTEXT IDC_IGNORE_NUMTIMES,110,66,24,14,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ LTEXT "time(s).",IDC_NOID,138,69,23,8
+ PUSHBUTTON "Always Ignore &This Assert",IDC_IGNORE_ALWAYS,7,83,98,14
+ PUSHBUTTON "Ignore &Nearby Asserts",IDC_IGNORE_NEARBY,7,100,98,14,WS_DISABLED
+ LTEXT "within",IDC_NOID,109,103,19,8
+ EDITTEXT IDC_IGNORE_NUMLINES,131,100,40,14,ES_AUTOHSCROLL | ES_NUMBER | WS_DISABLED
+ LTEXT "lines.",IDC_NOID,175,103,17,8
+ PUSHBUTTON "Ignore Asserts in This &File",IDC_IGNORE_FILE,7,117,98,14
+ PUSHBUTTON "Ignore &All Asserts",IDC_IGNORE_ALL,7,134,98,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_ASSERT_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 261
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 151
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/utils/xbox/vxconsole/assert_resource.h b/utils/xbox/vxconsole/assert_resource.h
new file mode 100644
index 0000000..b23c645
--- /dev/null
+++ b/utils/xbox/vxconsole/assert_resource.h
@@ -0,0 +1,29 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by assert_dialog.rc
+//
+#define IDD_ASSERT_DIALOG 101
+#define IDC_FILENAME_CONTROL 1000
+#define IDC_LINE_CONTROL 1001
+#define IDC_IGNORE_FILE 1002
+#define IDC_IGNORE_NEARBY 1003
+#define IDC_IGNORE_NUMLINES 1004
+#define IDC_IGNORE_THIS 1005
+#define IDC_BREAK 1006
+#define IDC_IGNORE_ALL 1008
+#define IDC_IGNORE_ALWAYS 1009
+#define IDC_IGNORE_NUMTIMES 1010
+#define IDC_ASSERT_MSG_CTRL 1011
+#define IDC_NOID -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1005
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/utils/xbox/vxconsole/bindings.cpp b/utils/xbox/vxconsole/bindings.cpp
new file mode 100644
index 0000000..67bce48
--- /dev/null
+++ b/utils/xbox/vxconsole/bindings.cpp
@@ -0,0 +1,591 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// BINDINGS.CPP
+//
+// Keyboard Shortcuts
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define ID_BINDINGS_LISTVIEW 100
+
+// column id
+#define ID_BIND_KEYCODE 0
+#define ID_BIND_MENUNAME 1
+#define ID_BIND_COMMAND 2
+
+typedef struct
+{ const CHAR* name;
+ int width;
+ int subItemIndex;
+} label_t;
+
+typedef struct
+{
+ int keyCode;
+ const char *pKeyString;
+ char *pMenuName;
+ char *pCommandString;
+} bind_t;
+
+// {VK_F1, "F1", "WireFrame", "incrementvar mat_wireframe 0 2 1"},
+// {VK_F2, "F2", "FullBright", "incrementvar mat_fullbright 0 2 1"},
+// {VK_F3, "F3", "Impulse 101", "impulse 101"},
+// {VK_F4, "F4", "Screenshot", "*screenshot"},
+
+
+bind_t g_bindings[MAX_BINDINGS] =
+{
+ {VK_F1, "F1", NULL, NULL},
+ {VK_F2, "F2", NULL, NULL},
+ {VK_F3, "F3", NULL, NULL},
+ {VK_F4, "F4", NULL, NULL},
+ {VK_F5, "F5", NULL, NULL},
+ {VK_F6, "F6", NULL, NULL},
+ {VK_F7, "F7", NULL, NULL},
+ {VK_F8, "F8", NULL, NULL},
+ {VK_F9, "F9", NULL, NULL},
+ {VK_F10, "F10", NULL, NULL},
+ {VK_F11, "F11", NULL, NULL},
+ {VK_F12, "F12", NULL, NULL},
+};
+
+label_t g_bindings_labels[] =
+{
+ {"Key", 80, ID_BIND_KEYCODE},
+ {"Menu Name", 150, ID_BIND_MENUNAME},
+ {"Command", 400, ID_BIND_COMMAND},
+};
+
+HWND g_bindings_hWnd;
+HWND g_bindings_hWndListView;
+RECT g_bindings_windowRect;
+char g_bindingsModify_menuName[256];
+char g_bindingsModify_command[256];
+char g_bindingsModify_keyCode[256];
+
+//-----------------------------------------------------------------------------
+// Bindings_ModifyEntry
+//
+//-----------------------------------------------------------------------------
+void Bindings_ModifyEntry( int i, const char *pMenuName, const char *pCommandString )
+{
+ if ( g_bindings[i].pMenuName && g_bindings[i].pMenuName[0] )
+ Sys_Free( g_bindings[i].pMenuName );
+ g_bindings[i].pMenuName = Sys_CopyString( pMenuName );
+
+ if ( g_bindings[i].pCommandString && g_bindings[i].pCommandString[0] )
+ Sys_Free( g_bindings[i].pCommandString );
+ g_bindings[i].pCommandString = Sys_CopyString( pCommandString );
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_GetSelectedItem
+//
+//-----------------------------------------------------------------------------
+int Bindings_GetSelectedItem()
+{
+ int i;
+ int selection = -1;
+ int state;
+
+ for ( i=0; i<MAX_BINDINGS; i++ )
+ {
+ state = ListView_GetItemState( g_bindings_hWndListView, i, LVIS_SELECTED );
+ if ( state == LVIS_SELECTED )
+ {
+ selection = i;
+ break;
+ }
+ }
+
+ return selection;
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_TranslateKey
+//
+//-----------------------------------------------------------------------------
+bool Bindings_TranslateKey( int vkKeyCode )
+{
+ int i;
+
+ for ( i=0; i<MAX_BINDINGS; i++ )
+ {
+ if ( !g_bindings[i].pCommandString || !g_bindings[i].pCommandString[0] )
+ continue;
+
+ if ( vkKeyCode == g_bindings[i].keyCode )
+ {
+ ProcessCommand( g_bindings[i].pCommandString );
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_MenuSelection
+//
+//-----------------------------------------------------------------------------
+bool Bindings_MenuSelection( int wID )
+{
+ int index;
+
+ index = wID - IDM_BINDINGS_BIND1;
+ if ( index < 0 || index > MAX_BINDINGS-1 )
+ return false;
+
+ // as if the key were pressed...
+ return ( Bindings_TranslateKey( g_bindings[index].keyCode ) );
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_UpdateMenu
+//
+// Builds the dynamic menu
+//-----------------------------------------------------------------------------
+void Bindings_UpdateMenu()
+{
+ HMENU hMenu;
+ HMENU hNewMenu;
+ MENUITEMINFO menuItemInfo;
+ int i;
+ int numAdded;
+ char menuBuff[64];
+
+ hMenu = GetMenu( g_hDlgMain );
+ if ( !hMenu )
+ return;
+
+ memset( &menuItemInfo, 0, sizeof( menuItemInfo ) );
+ menuItemInfo.cbSize = sizeof( MENUITEMINFO );
+
+ numAdded = 0;
+ hNewMenu = CreatePopupMenu();
+ menuItemInfo.fMask = MIIM_ID|MIIM_FTYPE|MIIM_STRING;
+ menuItemInfo.fType = MFT_STRING;
+ for ( i=MAX_BINDINGS-1; i>=0; i-- )
+ {
+ if ( !g_bindings[i].pCommandString || !g_bindings[i].pCommandString[0] )
+ continue;
+
+ menuItemInfo.wID = IDM_BINDINGS_BIND1+i;
+ sprintf( menuBuff, "%s\tF%d", g_bindings[i].pMenuName, g_bindings[i].keyCode-VK_F1+1 );
+ menuItemInfo.dwTypeData = ( LPSTR )menuBuff;
+ InsertMenuItem( hNewMenu, 0, true, &menuItemInfo );
+
+ numAdded++;
+ }
+
+ if ( numAdded )
+ {
+ // add seperator
+ menuItemInfo.fMask = MIIM_FTYPE;
+ menuItemInfo.fType = MFT_SEPARATOR;
+ InsertMenuItem( hNewMenu, 0, true, &menuItemInfo );
+ }
+
+ menuItemInfo.fMask = MIIM_ID|MIIM_FTYPE|MIIM_STRING;
+ menuItemInfo.fType = MFT_STRING;
+ menuItemInfo.wID = IDM_BINDINGS_EDIT;
+ menuItemInfo.dwTypeData = "Edit...";
+ InsertMenuItem( hNewMenu, 0, true, &menuItemInfo );
+
+ // delete the previous menu
+ menuItemInfo.fMask = MIIM_SUBMENU;
+ GetMenuItemInfo( hMenu, IDM_BINDINGS, false, &menuItemInfo );
+ if ( menuItemInfo.hSubMenu )
+ DestroyMenu( menuItemInfo.hSubMenu );
+ else
+ {
+ // add a new menu at the tail of the app menu
+ AppendMenu( hMenu, MF_STRING, ( UINT_PTR )IDM_BINDINGS, "Bindings" );
+ }
+
+ // add the new menu to bar
+ menuItemInfo.fMask = MIIM_SUBMENU;
+ menuItemInfo.hSubMenu = hNewMenu;
+ SetMenuItemInfo( hMenu, IDM_BINDINGS, false, &menuItemInfo );
+
+ DrawMenuBar( g_hDlgMain );
+}
+
+//-----------------------------------------------------------------------------
+// BindingsModifyDlg_Proc
+//
+//-----------------------------------------------------------------------------
+BOOL CALLBACK BindingsModifyDlg_Proc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ SetDlgItemText( hWnd, IDC_MODIFYBIND_KEYCODE, g_bindingsModify_keyCode );
+ SetDlgItemText( hWnd, IDC_MODIFYBIND_MENUNAME, g_bindingsModify_menuName );
+ SetDlgItemText( hWnd, IDC_MODIFYBIND_COMMAND, g_bindingsModify_command );
+ return ( TRUE );
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_OK:
+ GetDlgItemText( hWnd, IDC_MODIFYBIND_MENUNAME, g_bindingsModify_menuName, sizeof( g_bindingsModify_menuName ) );
+ GetDlgItemText( hWnd, IDC_MODIFYBIND_COMMAND, g_bindingsModify_command, sizeof( g_bindingsModify_command ) );
+ case IDCANCEL:
+ case IDC_CANCEL:
+ EndDialog( hWnd, wParam );
+ return ( TRUE );
+ }
+ break;
+ }
+ return ( FALSE );
+}
+
+//-----------------------------------------------------------------------------
+// BindingsModifyDlg_Open
+//
+//-----------------------------------------------------------------------------
+void BindingsModifyDlg_Open( int selection )
+{
+ int result;
+
+ sprintf( g_bindingsModify_keyCode, "F%d", selection+1 );
+ strcpy( g_bindingsModify_menuName, g_bindings[selection].pMenuName );
+ strcpy( g_bindingsModify_command, g_bindings[selection].pCommandString );
+
+ result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_MODIFYBIND ), g_hDlgMain, ( DLGPROC )BindingsModifyDlg_Proc );
+ if ( LOWORD( result ) != IDC_OK )
+ return;
+
+ // accept changes and update
+ Bindings_ModifyEntry( selection, g_bindingsModify_menuName, g_bindingsModify_command );
+ ListView_RedrawItems( g_bindings_hWndListView, 0, MAX_BINDINGS-1 );
+ UpdateWindow( g_bindings_hWndListView );
+ Bindings_UpdateMenu();
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void Bindings_LoadConfig()
+{
+ char valueBuff[256];
+ char keyBuff[32];
+ char menuName[256];
+ char commandString[256];
+ char *ptr;
+ char *token;
+ int keyCode;
+ int i;
+ int numArgs;
+ char buff[256];
+
+ for ( i=0; i<MAX_BINDINGS; i++ )
+ {
+ menuName[0] = '\0';
+ commandString[0] = '\0';
+
+ sprintf( keyBuff, "bind%d", i );
+ Sys_GetRegistryString( keyBuff, valueBuff, "", sizeof( valueBuff ) );
+
+ // parse and populate valid values
+ ptr = valueBuff;
+ token = Sys_GetToken( &ptr, false, NULL );
+ if ( token[0] )
+ keyCode = atoi( token );
+
+ token = Sys_GetToken( &ptr, false, NULL );
+ if ( token[0] )
+ strcpy( menuName, token );
+
+ token = Sys_GetToken( &ptr, false, NULL );
+ if ( token[0] )
+ strcpy( commandString, token );
+
+ Bindings_ModifyEntry( i, menuName, commandString );
+ }
+
+ Sys_GetRegistryString( "bindingsWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_bindings_windowRect.left, &g_bindings_windowRect.top, &g_bindings_windowRect.right, &g_bindings_windowRect.bottom );
+ if ( numArgs != 4 )
+ memset( &g_bindings_windowRect, 0, sizeof( g_bindings_windowRect ) );
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void Bindings_SaveConfig()
+{
+ char valueBuff[256];
+ char buff[256];
+ char keyBuff[32];
+ char *pMenuName;
+ char *pCommandString;
+ int len;
+ int i;
+ WINDOWPLACEMENT wp;
+
+ if ( g_bindings_hWnd )
+ {
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_bindings_hWnd, &wp );
+ g_bindings_windowRect = wp.rcNormalPosition;
+ sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom );
+ Sys_SetRegistryString( "bindingsWindowRect", buff );
+ }
+
+ for ( i=0; i<MAX_BINDINGS; i++ )
+ {
+ sprintf( keyBuff, "bind%d", i );
+
+ pMenuName = g_bindings[i].pMenuName;
+ if ( !pMenuName )
+ pMenuName = "";
+
+ pCommandString = g_bindings[i].pCommandString;
+ if ( !pCommandString )
+ pCommandString = "";
+
+ len = _snprintf( valueBuff, sizeof( valueBuff ), "%d \"%s\" \"%s\"", g_bindings[i].keyCode, pMenuName, pCommandString );
+ if ( len == -1 )
+ {
+ // kill it
+ valueBuff[0] = '\0';
+ }
+
+ Sys_SetRegistryString( keyBuff, valueBuff );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_SizeWindow
+//
+//-----------------------------------------------------------------------------
+void Bindings_SizeWindow( HWND hwnd, int cx, int cy )
+{
+ if ( cx==0 || cy==0 )
+ {
+ RECT rcClient;
+ GetClientRect( hwnd, &rcClient );
+ cx = rcClient.right;
+ cy = rcClient.bottom;
+ }
+
+ // position the ListView
+ SetWindowPos( g_bindings_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER );
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK Bindings_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ bind_t* pBind;
+ int selection;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ return 0L;
+
+ case WM_DESTROY:
+ Bindings_SaveConfig();
+ Bindings_UpdateMenu();
+
+ g_bindings_hWnd = NULL;
+ return 0L;
+
+ case WM_SIZE:
+ Bindings_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) );
+ return 0L;
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lParam )->code )
+ {
+ case LVN_GETDISPINFO:
+ NMLVDISPINFO* plvdi;
+ plvdi = ( NMLVDISPINFO* )lParam;
+ pBind = ( bind_t* )plvdi->item.lParam;
+ switch ( plvdi->item.iSubItem )
+ {
+ case ID_BIND_KEYCODE:
+ plvdi->item.pszText = ( LPSTR )pBind->pKeyString;
+ return 0L;
+
+ case ID_BIND_MENUNAME:
+ plvdi->item.pszText = pBind->pMenuName;
+ return 0L;
+
+ case ID_BIND_COMMAND:
+ plvdi->item.pszText = pBind->pCommandString;
+ return 0L;
+
+ default:
+ break;
+ }
+ break;
+
+ case NM_DBLCLK:
+ NMITEMACTIVATE *pnmitem;
+ pnmitem = ( LPNMITEMACTIVATE )lParam;
+ BindingsModifyDlg_Open( pnmitem->iItem );
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_BINDOPTIONS_MODIFY:
+ selection = Bindings_GetSelectedItem();
+ if ( selection >= 0 )
+ BindingsModifyDlg_Open( selection );
+ return 0L;
+
+ case IDM_BINDOPTIONS_DELETE:
+ selection = Bindings_GetSelectedItem();
+ if ( selection >= 0 )
+ {
+ Bindings_ModifyEntry( selection, "", "" );
+ ListView_RedrawItems( g_bindings_hWndListView, 0, MAX_BINDINGS-1 );
+ UpdateWindow( g_bindings_hWndListView );
+ Bindings_UpdateMenu();
+ }
+ return 0L;
+ }
+ break;
+ }
+
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_Open
+//
+//-----------------------------------------------------------------------------
+void Bindings_Open()
+{
+ RECT clientRect;
+ HWND hWnd;
+ int i;
+ LVITEM lvi;
+
+ if ( g_bindings_hWnd )
+ {
+ // only one instance
+ if ( IsIconic( g_bindings_hWnd ) )
+ ShowWindow( g_bindings_hWnd, SW_RESTORE );
+ SetForegroundWindow( g_bindings_hWnd );
+ return;
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "BINDINGSCLASS",
+ "Edit Bindings",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 600,
+ 300,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ NULL );
+ g_bindings_hWnd = hWnd;
+
+ GetClientRect( g_bindings_hWnd, &clientRect );
+ hWnd = CreateWindow(
+ WC_LISTVIEW,
+ "",
+ WS_VISIBLE|WS_CHILD|LVS_REPORT|LVS_SHOWSELALWAYS|LVS_SINGLESEL|LVS_NOSORTHEADER,
+ 0,
+ 0,
+ clientRect.right-clientRect.left,
+ clientRect.bottom-clientRect.top,
+ g_bindings_hWnd,
+ ( HMENU )ID_BINDINGS_LISTVIEW,
+ g_hInstance,
+ NULL );
+ g_bindings_hWndListView = hWnd;
+
+ // init list view columns
+ for ( i=0; i<sizeof( g_bindings_labels )/sizeof( g_bindings_labels[0] ); i++ )
+ {
+ LVCOLUMN lvc;
+ memset( &lvc, 0, sizeof( lvc ) );
+
+ lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
+ lvc.iSubItem = 0;
+ lvc.cx = g_bindings_labels[i].width;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.pszText = ( LPSTR )g_bindings_labels[i].name;
+
+ ListView_InsertColumn( g_bindings_hWndListView, i, &lvc );
+ }
+
+ ListView_SetBkColor( g_bindings_hWndListView, g_backgroundColor );
+ ListView_SetTextBkColor( g_bindings_hWndListView, g_backgroundColor );
+
+ DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP;
+ ListView_SetExtendedListViewStyleEx( g_bindings_hWndListView, style, style );
+
+ // populate list view
+ for ( i=0; i<MAX_BINDINGS; i++ )
+ {
+ int itemCount = ListView_GetItemCount( g_bindings_hWndListView );
+
+ // setup and insert at end of list
+ memset( &lvi, 0, sizeof( lvi ) );
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = itemCount;
+ lvi.iSubItem = 0;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = ( LPARAM )&g_bindings[i];
+
+ ListView_InsertItem( g_bindings_hWndListView, &lvi );
+ }
+
+ // set the first item selected
+ ListView_SetItemState( g_bindings_hWndListView, 0, LVIS_SELECTED, LVIS_SELECTED );
+ SetFocus( g_bindings_hWndListView );
+
+ if ( g_bindings_windowRect.right && g_bindings_windowRect.bottom )
+ MoveWindow( g_bindings_hWnd, g_bindings_windowRect.left, g_bindings_windowRect.top, g_bindings_windowRect.right-g_bindings_windowRect.left, g_bindings_windowRect.bottom-g_bindings_windowRect.top, FALSE );
+ ShowWindow( g_bindings_hWnd, SHOW_OPENWINDOW );
+}
+
+//-----------------------------------------------------------------------------
+// Bindings_Init
+//
+//-----------------------------------------------------------------------------
+bool Bindings_Init()
+{
+ // set up our window class
+ WNDCLASS wndclass;
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = Bindings_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_BINDOPTIONS );
+ wndclass.lpszClassName = "BINDINGSCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ Bindings_LoadConfig();
+ Bindings_UpdateMenu();
+
+ return true;
+} \ No newline at end of file
diff --git a/utils/xbox/vxconsole/bug.cpp b/utils/xbox/vxconsole/bug.cpp
new file mode 100644
index 0000000..1d288eb
--- /dev/null
+++ b/utils/xbox/vxconsole/bug.cpp
@@ -0,0 +1,1576 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// BUG.CPP
+//
+// Tracker bridge
+//=====================================================================================//
+#include "vxconsole.h"
+
+// two bug systems, certain games are tied to a specific system
+#define BUG_REPORTER_DLLNAME_1 "bugreporter.dll"
+#define BUG_REPORTER_DLLNAME_2 "bugreporter_filequeue.dll"
+
+#define BUG_REPOSITORY_URL "\\\\fileserver\\bugs"
+#define REPOSITORY_VALIDATION_FILE "info.txt"
+#define BUG_ERRORTITLE "Bug Error"
+#define BUG_COLOR ( RGB( 0,255,255 ) )
+
+HWND g_bug_hWnd;
+HMODULE g_bug_hBugReporter1;
+HMODULE g_bug_hBugReporter2;
+IBugReporter *g_bug_pReporter1;
+IBugReporter *g_bug_pReporter2;
+IBugReporter *g_bug_pReporter;
+char g_bug_szTitle[512];
+char g_bug_szDescription[1024];
+char g_bug_szOwner[128];
+char g_bug_szSeverity[128];
+char g_bug_szReportType[128];
+char g_bug_szPriority[128];
+char g_bug_szArea[128];
+char g_bug_szMapNumber[128];
+int g_bug_GameType;
+bool g_bug_bActive;
+char g_bug_szScreenshot[MAX_PATH];
+char g_bug_szSavegame[MAX_PATH];
+char g_bug_szBSPName[MAX_PATH];
+xrMapInfo_t g_bug_mapInfo;
+bool g_bug_bCompressScreenshot;
+bool g_bug_bFirstCommand;
+
+struct GameSystem_t
+{
+ const char *pFriendlyName;
+ const char *pGameName;
+ bool bUsesSystem1;
+};
+
+GameSystem_t g_Games[] =
+{
+ { "Half Life 2", "hl2", true },
+ { "Episode 1", "episodic", true },
+ { "Episode 2", "ep2", true },
+ { "Portal", "portal", false },
+ { "Team Fortress 2", "tf", false },
+};
+
+static const char *GetRepositoryURL( void )
+{
+ const char *pURL = g_bug_pReporter->GetRepositoryURL();
+ if ( pURL )
+ {
+ return pURL;
+ }
+
+ return BUG_REPOSITORY_URL;
+}
+
+const char *GetSubmissionURL( int bugid )
+{
+ const char *pURL = g_bug_pReporter->GetSubmissionURL();
+ if ( pURL )
+ {
+ return pURL;
+ }
+
+ static char url[MAX_PATH];
+ Q_snprintf( url, sizeof(url), "%s/%i", GetRepositoryURL(), bugid );
+
+ return url;
+}
+
+//-----------------------------------------------------------------------------
+// BugReporter_SelectReporter
+//
+//-----------------------------------------------------------------------------
+bool BugReporter_SelectReporter( const char *pGameName )
+{
+ int system = -1;
+ for ( int i = 0; i < ARRAYSIZE( g_Games ); i++ )
+ {
+ if ( pGameName && !V_stricmp( g_Games[i].pGameName, pGameName ) )
+ {
+ system = i;
+ break;
+ }
+ }
+
+ if ( system == -1 )
+ {
+ // not found, slam to first
+ system = 0;
+ }
+
+ // games uses different systems
+ int oldGameType = g_bug_GameType;
+ g_bug_GameType = system;
+ if ( g_Games[system].bUsesSystem1 )
+ {
+ g_bug_pReporter = g_bug_pReporter1;
+ }
+ else
+ {
+ g_bug_pReporter = g_bug_pReporter2;
+ }
+
+ // force the game area
+ if ( g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ strcpy( g_bug_szArea, "XBOX 360" );
+ }
+ else
+ {
+ strcpy( g_bug_szArea, g_Games[g_bug_GameType].pFriendlyName );
+ }
+
+ bool bChanged = ( oldGameType != g_bug_GameType );
+ return bChanged;
+}
+
+//-----------------------------------------------------------------------------
+// BugReporter_LoadDLL
+//
+//-----------------------------------------------------------------------------
+IBugReporter *BugReporter_LoadDLL( const char *pDLLName, HMODULE *phModule )
+{
+ HMODULE hModule;
+ IBugReporter *pBugReporter;
+
+ *phModule = NULL;
+
+ hModule = LoadLibrary( pDLLName );
+ if ( !hModule )
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "Could not open '%s'\n", pDLLName );
+ return NULL;
+ }
+
+ FARPROC pCreateInterface = GetProcAddress( hModule, CREATEINTERFACE_PROCNAME );
+ if ( !pCreateInterface )
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "Missing '%s' interface for '%s'\n", CREATEINTERFACE_PROCNAME, pDLLName );
+ return NULL;
+ }
+
+ pBugReporter = (IBugReporter *)((CreateInterfaceFn)pCreateInterface)( INTERFACEVERSION_BUGREPORTER, NULL );
+ if ( !pBugReporter )
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "Missing interface '%s' for '%s'\n", INTERFACEVERSION_BUGREPORTER, pDLLName );
+ return NULL;
+ }
+
+ bool bSuccess = pBugReporter->Init( NULL );
+ if ( !bSuccess )
+ {
+ return NULL;
+ }
+
+ *phModule = hModule;
+ return pBugReporter;
+}
+
+//-----------------------------------------------------------------------------
+// BugReporter_GetInterfaces
+//
+//-----------------------------------------------------------------------------
+bool BugReporter_GetInterfaces()
+{
+ if ( !g_bug_pReporter1 )
+ {
+ g_bug_pReporter1 = BugReporter_LoadDLL( BUG_REPORTER_DLLNAME_1, &g_bug_hBugReporter1 );
+ if ( !g_bug_pReporter1 )
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "PVCS intialization failed!\n" );
+ }
+ }
+
+ if ( !g_bug_pReporter2 )
+ {
+ g_bug_pReporter2 = BugReporter_LoadDLL( BUG_REPORTER_DLLNAME_2, &g_bug_hBugReporter2 );
+ if ( !g_bug_pReporter2 )
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "BugBait intialization failed!\n" );
+ }
+ }
+
+ if ( g_bug_pReporter1 )
+ {
+ // determine submitter name
+ ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: PVCS Username: '%s' Display As: '%s'\n", g_bug_pReporter1->GetUserName(), g_bug_pReporter1->GetUserName_Display() );
+ }
+ if ( g_bug_pReporter2 )
+ {
+ // determine submitter name
+ ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: BugBait Username: '%s' Display As: '%s'\n", g_bug_pReporter2->GetUserName(), g_bug_pReporter2->GetUserName_Display() );
+ }
+
+ BugReporter_SelectReporter( NULL );
+
+ // See if we can see the bug repository right now
+ char fn[MAX_PATH];
+ V_snprintf( fn, sizeof( fn ), "%s/%s", GetRepositoryURL(), REPOSITORY_VALIDATION_FILE );
+ Sys_NormalizePath( fn, false );
+
+ FILE *fp = fopen( fn, "rb" );
+ if ( fp )
+ {
+ ConsoleWindowPrintf( BUG_COLOR, "PVCS Repository '%s'\n", GetRepositoryURL() );
+ fclose( fp );
+ }
+ else
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "Unable to see '%s', check permissions and network connectivity.\n", fn );
+ return false;
+ }
+
+ // success
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// BugReporter_FreeInterfaces
+//
+//-----------------------------------------------------------------------------
+void BugReporter_FreeInterfaces()
+{
+ if ( g_bug_pReporter1 )
+ {
+ g_bug_pReporter1->Shutdown();
+ g_bug_pReporter1 = NULL;
+ FreeLibrary( g_bug_hBugReporter1 );
+ g_bug_hBugReporter1 = NULL;
+ }
+
+ if ( g_bug_pReporter2 )
+ {
+ g_bug_pReporter2->Shutdown();
+ g_bug_pReporter2 = NULL;
+ FreeLibrary( g_bug_hBugReporter2 );
+ g_bug_hBugReporter2 = NULL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Expanded data destination object for CUtlBuffer output
+//-----------------------------------------------------------------------------
+struct JPEGDestinationManager_t
+{
+ struct jpeg_destination_mgr pub; // public fields
+
+ CUtlBuffer *pBuffer; // target/final buffer
+ byte *buffer; // start of temp buffer
+};
+
+// choose an efficiently bufferaable size
+#define OUTPUT_BUF_SIZE 4096
+
+//-----------------------------------------------------------------------------
+// Purpose: Initialize destination --- called by jpeg_start_compress
+// before any data is actually written.
+//-----------------------------------------------------------------------------
+void init_destination( j_compress_ptr cinfo )
+{
+ JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t *) cinfo->dest;
+
+ // Allocate the output buffer --- it will be released when done with image
+ dest->buffer = (byte *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * sizeof(byte));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Empty the output buffer --- called whenever buffer fills up.
+// Input : boolean -
+//-----------------------------------------------------------------------------
+boolean empty_output_buffer( j_compress_ptr cinfo )
+{
+ JPEGDestinationManager_t *dest = ( JPEGDestinationManager_t * ) cinfo->dest;
+
+ CUtlBuffer *buf = dest->pBuffer;
+
+ // Add some data
+ buf->Put( dest->buffer, OUTPUT_BUF_SIZE );
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Terminate destination --- called by jpeg_finish_compress
+// after all data has been written. Usually needs to flush buffer.
+//
+// NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+// application must deal with any cleanup that should happen even
+// for error exit.
+//-----------------------------------------------------------------------------
+void term_destination( j_compress_ptr cinfo )
+{
+ JPEGDestinationManager_t *dest = (JPEGDestinationManager_t *) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ CUtlBuffer *buf = dest->pBuffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0)
+ {
+ buf->Put( dest->buffer, datacount );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Set up functions for writing data to a CUtlBuffer instead of FILE *
+//-----------------------------------------------------------------------------
+void jpeg_UtlBuffer_dest( j_compress_ptr cinfo, CUtlBuffer *pBuffer )
+{
+ JPEGDestinationManager_t *dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_stdio_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(JPEGDestinationManager_t));
+ }
+
+ dest = ( JPEGDestinationManager_t * ) cinfo->dest;
+
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->pBuffer = pBuffer;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_CompressScreenshot
+//
+// Compress .BMP to .JPG, Delete .BMP
+//-----------------------------------------------------------------------------
+bool BugDlg_CompressScreenshot()
+{
+ if ( !g_bug_szScreenshot[0] )
+ {
+ return false;
+ }
+
+ bool bSuccess = false;
+ HBITMAP hBitmap = NULL;
+ HDC hDC = NULL;
+ char *pBMPBits = NULL;
+
+ CUtlBuffer buf( 0, 0 );
+
+ hBitmap = (HBITMAP)LoadImage( NULL, g_bug_szScreenshot, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE );
+ if ( !hBitmap )
+ goto cleanUp;
+
+ hDC = CreateCompatibleDC( NULL );
+ if ( !hDC )
+ goto cleanUp;
+
+ BITMAPINFO bitmapInfo;
+ ZeroMemory( &bitmapInfo, sizeof( BITMAPINFO ) );
+ bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
+
+ // populate the bmp info
+ if ( !GetDIBits( hDC, hBitmap, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS ) )
+ goto cleanUp;
+
+ pBMPBits = (char *)Sys_Alloc( bitmapInfo.bmiHeader.biSizeImage );
+ if ( !pBMPBits )
+ goto cleanUp;
+
+ // could be bottom-up or top-down
+ int nHeight = abs( bitmapInfo.bmiHeader.biHeight );
+
+ if ( bitmapInfo.bmiHeader.biBitCount != 32 )
+ {
+ // unexpected format
+ goto cleanUp;
+ }
+
+ if ( bitmapInfo.bmiHeader.biCompression != BI_RGB && bitmapInfo.bmiHeader.biCompression != BI_BITFIELDS )
+ {
+ // unexpected format
+ goto cleanUp;
+ }
+
+ // don't want color masks
+ bitmapInfo.bmiHeader.biCompression = BI_RGB;
+
+ // get the raw bits
+ if ( !GetDIBits( hDC, hBitmap, 0, nHeight, pBMPBits, &bitmapInfo, DIB_RGB_COLORS ) )
+ goto cleanUp;
+
+ JSAMPROW row_pointer[1];
+
+ // compression data structure
+ struct jpeg_compress_struct cinfo;
+ ZeroMemory( &cinfo, sizeof( jpeg_compress_struct ) );
+
+ // point at stderr
+ struct jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error( &jerr );
+
+ // create compressor
+ jpeg_create_compress( &cinfo );
+
+ // Hook CUtlBuffer to compression
+ jpeg_UtlBuffer_dest( &cinfo, &buf );
+
+ // image width and height, in pixels
+ cinfo.image_width = bitmapInfo.bmiHeader.biWidth;
+ cinfo.image_height = nHeight;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ // Apply settings
+ jpeg_set_defaults( &cinfo );
+ jpeg_set_quality( &cinfo, 50, TRUE );
+
+ // Start compressor
+ jpeg_start_compress( &cinfo, TRUE);
+
+ char *pRowBuffer = (char*)_alloca( bitmapInfo.bmiHeader.biWidth * 3 );
+ row_pointer[0] = (JSAMPROW)pRowBuffer;
+
+ // Write scanlines
+ while ( cinfo.next_scanline < cinfo.image_height )
+ {
+ char *pSrc;
+ if ( bitmapInfo.bmiHeader.biHeight < 0 )
+ {
+ // top down
+ pSrc = &pBMPBits[cinfo.next_scanline * bitmapInfo.bmiHeader.biWidth * 4];
+ }
+ else
+ {
+ // bottom up
+ pSrc = &pBMPBits[(nHeight-1 - cinfo.next_scanline) * bitmapInfo.bmiHeader.biWidth * 4];
+ }
+
+ // convert to BGR to RGB
+ char *pDst = pRowBuffer;
+ for ( int i=0; i<bitmapInfo.bmiHeader.biWidth; i++ )
+ {
+ pDst[0] = pSrc[2];
+ pDst[1] = pSrc[1];
+ pDst[2] = pSrc[0];
+ pSrc += 4;
+ pDst += 3;
+ }
+ jpeg_write_scanlines( &cinfo, row_pointer, 1 );
+ }
+
+ // Finalize image
+ jpeg_finish_compress( &cinfo );
+
+ char jpgFilename[MAX_PATH];
+ Sys_StripExtension( g_bug_szScreenshot, jpgFilename, sizeof( jpgFilename ) );
+ Sys_AddExtension( ".jpg", jpgFilename, sizeof( jpgFilename ) );
+ if ( !Sys_SaveFile( jpgFilename, buf.Base(), buf.TellMaxPut() ) )
+ goto cleanUp;
+
+ // remove the uncompressed version
+ unlink( g_bug_szScreenshot );
+ strcpy( g_bug_szScreenshot, jpgFilename );
+
+ bSuccess = true;
+
+cleanUp:
+ if ( hBitmap )
+ DeleteObject( hBitmap );
+ if ( hDC )
+ DeleteDC( hDC );
+ if ( pBMPBits )
+ Sys_Free( pBMPBits );
+
+ return bSuccess;
+}
+
+
+//-----------------------------------------------------------------------------
+// BugDlg_GetAppData
+//
+//-----------------------------------------------------------------------------
+void BugDlg_GetAppData( HWND hWnd )
+{
+ // clear stale data from previous query
+ memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
+
+ SetDlgItemText( hWnd, IDC_BUG_POSITION_LABEL, "" );
+ SetDlgItemText( hWnd, IDC_BUG_ORIENTATION_LABEL, "" );
+ SetDlgItemText( hWnd, IDC_BUG_MAP_LABEL, "" );
+ SetDlgItemText( hWnd, IDC_BUG_BUILD_LABEL, "" );
+
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_SAVEGAME ), false );
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_INCLUDEBSP ), false );
+
+ if ( g_connectedToApp )
+ {
+ // send to app, responds with position info
+ if ( !g_bug_bFirstCommand )
+ {
+ // first command must send pause and status to be processed correctly
+ g_bug_bFirstCommand = true;
+ ProcessCommand( "pause ; status" );
+ }
+ else
+ {
+ ProcessCommand( "status" );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_GetDataFileBase
+//
+//-----------------------------------------------------------------------------
+void BugDlg_GetDataFileBase( char const *suffix, bool bLocalPath, char *buf, int bufsize )
+{
+ char filepath[MAX_PATH];
+ char filename[MAX_PATH];
+
+ struct tm t;
+
+ time_t ltime;
+ time( &ltime );
+ tm *pTime = localtime( &ltime );
+ memcpy( &t, pTime, sizeof( t ) );
+
+ char who[128];
+ strncpy( who, suffix, sizeof( who ) );
+ _strlwr( who );
+
+ if ( bLocalPath )
+ {
+ // add a qualified local path
+ // used as a gathering store before uploading to server
+ strcpy( filepath, g_localPath );
+ Sys_AddFileSeperator( filepath, sizeof( filepath ) );
+ strcat( filepath, "bug/" );
+ Sys_NormalizePath( filepath, false );
+ Sys_CreatePath( filepath );
+ }
+ else
+ {
+ filepath[0] = '\0';
+ }
+
+ sprintf( filename, "%i_%02i_%02i_%s", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, who );
+ V_snprintf( buf, bufsize, "%s%s", filepath, filename );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_CheckSubmit
+//
+//-----------------------------------------------------------------------------
+bool BugDlg_CheckSubmit( HWND hWnd )
+{
+ bool bEnableSubmit = false;
+
+ if ( g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ if ( g_bug_szTitle[0] &&
+ g_bug_szDescription[0] &&
+ g_bug_szSeverity[0] &&
+ g_bug_szOwner[0] &&
+ g_bug_szReportType[0] &&
+ g_bug_szPriority[0] &&
+ g_bug_szArea[0] )
+ {
+ bEnableSubmit = true;
+ }
+ }
+ else
+ {
+ if ( g_bug_szTitle[0] &&
+ g_bug_szDescription[0] &&
+ g_bug_szSeverity[0] &&
+ g_bug_szOwner[0] &&
+ g_bug_szArea[0] &&
+ g_bug_szMapNumber[0] )
+ {
+ bEnableSubmit = true;
+ }
+ }
+
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_SUBMIT ), bEnableSubmit );
+
+ return bEnableSubmit;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_GetChanges
+//
+//-----------------------------------------------------------------------------
+bool BugDlg_GetChanges( HWND hWnd )
+{
+ int curSel;
+
+ // title
+ GetDlgItemText( hWnd, IDC_BUG_TITLE, g_bug_szTitle, sizeof( g_bug_szTitle ) );
+
+ // description
+ GetDlgItemText( hWnd, IDC_BUG_DESCRIPTION, g_bug_szDescription, sizeof( g_bug_szDescription ) );
+
+ // owner
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_GETCURSEL, 0, 0 );
+ if ( curSel == CB_ERR )
+ {
+ g_bug_szOwner[0] = '\0';
+ }
+ else
+ {
+ strncpy( g_bug_szOwner, g_bug_pReporter->GetDisplayName( curSel ), sizeof( g_bug_szOwner ) );
+ g_bug_szOwner[sizeof( g_bug_szOwner )-1] = '\0';
+
+ if ( V_stristr( g_bug_szOwner, "unassigned" ) )
+ {
+ g_bug_szOwner[0] = '\0';
+ }
+ }
+
+ // severity
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_GETCURSEL, 0, 0 );
+ if ( curSel == CB_ERR )
+ {
+ g_bug_szSeverity[0] = '\0';
+ }
+ else
+ {
+ V_strncpy( g_bug_szSeverity, g_bug_pReporter->GetSeverity( curSel ), sizeof( g_bug_szSeverity ) );
+ }
+
+ // report type
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_GETCURSEL, 0, 0 );
+ if ( curSel == CB_ERR )
+ {
+ g_bug_szReportType[0] = '\0';
+ }
+ else
+ {
+ V_strncpy( g_bug_szReportType, g_bug_pReporter->GetReportType( curSel ), sizeof( g_bug_szReportType ) );
+ }
+
+ // priority
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_GETCURSEL, 0, 0 );
+ if ( curSel == CB_ERR )
+ {
+ g_bug_szPriority[0] = '\0';
+ }
+ else
+ {
+ V_strncpy( g_bug_szPriority, g_bug_pReporter->GetPriority( curSel ), sizeof( g_bug_szPriority ) );
+ }
+
+ // area
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_GETCURSEL, 0, 0 );
+ int areaIndex = 0;
+ if ( curSel == CB_ERR )
+ {
+ g_bug_szArea[0] = '\0';
+ }
+ else
+ {
+ V_strncpy( g_bug_szArea, g_bug_pReporter->GetArea( curSel ), sizeof( g_bug_szArea ) );
+ areaIndex = curSel;
+ }
+
+ if ( !g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ // map number
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_GETCURSEL, 0, 0 );
+ if ( curSel == CB_ERR )
+ {
+ g_bug_szMapNumber[0] = '\0';
+ }
+ else
+ {
+ V_strncpy( g_bug_szMapNumber, g_bug_pReporter->GetLevel( areaIndex, curSel ), sizeof( g_bug_szMapNumber ) );
+ }
+ }
+
+ g_bug_bCompressScreenshot = ( IsDlgButtonChecked( hWnd, IDC_BUG_COMPRESS_SCREENSHOT ) != 0 );
+
+ BugDlg_CheckSubmit( hWnd );
+
+ // success
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_UpdateReporter
+//
+//-----------------------------------------------------------------------------
+bool BugDlg_UpdateReporter( HWND hWnd )
+{
+ // game
+ int newGameType;
+ int curSel = SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_GETCURSEL, 0, 0 );
+ if ( curSel == CB_ERR )
+ {
+ newGameType = 0;
+ }
+ else
+ {
+ newGameType = curSel;
+ }
+
+ return BugReporter_SelectReporter( g_Games[newGameType].pGameName );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_Populate
+//
+//-----------------------------------------------------------------------------
+void BugDlg_Populate( HWND hWnd )
+{
+ int i;
+ int count;
+ int curSel;
+
+ g_bug_bActive = false;
+
+ // title
+ SendDlgItemMessage( hWnd, IDC_BUG_TITLE, EM_LIMITTEXT, sizeof( g_bug_szTitle )-1, 0 );
+ SetDlgItemText( hWnd, IDC_BUG_TITLE, g_bug_szTitle );
+
+ // description
+ SendDlgItemMessage( hWnd, IDC_BUG_DESCRIPTION, EM_LIMITTEXT, sizeof( g_bug_szDescription )-1, 0 );
+ SetDlgItemText( hWnd, IDC_BUG_DESCRIPTION, g_bug_szDescription );
+
+ // submitter
+ SetDlgItemText( hWnd, IDC_BUG_SUBMITTER_LABEL, g_bug_pReporter->GetUserName_Display() );
+
+ // owner
+ SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_RESETCONTENT, 0, 0 );
+ count = g_bug_pReporter->GetDisplayNameCount();
+ for ( i = 0; i < count; i++ )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetDisplayName( i ) );
+ }
+ if ( count )
+ {
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szOwner );
+ if ( curSel != CB_ERR )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_OWNER, CB_SETCURSEL, curSel, 0 );
+ }
+ }
+
+ // severity
+ SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_RESETCONTENT, 0, 0 );
+ count = g_bug_pReporter->GetSeverityCount();
+ for ( i = 0; i < count; i++ )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetSeverity( i ) );
+ }
+ if ( count )
+ {
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szSeverity );
+ if ( curSel != CB_ERR )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_SEVERITY, CB_SETCURSEL, curSel, 0 );
+ }
+ }
+
+ // report type
+ SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_RESETCONTENT, 0, 0 );
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_REPORTTYPE ), g_Games[g_bug_GameType].bUsesSystem1 );
+ if ( g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ count = g_bug_pReporter->GetReportTypeCount();
+ for ( i = 0; i < count; i++ )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetReportType( i ) );
+ }
+ if ( count )
+ {
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szReportType );
+ if ( curSel != CB_ERR )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_REPORTTYPE, CB_SETCURSEL, curSel, 0 );
+ }
+ }
+ }
+
+ // priority
+ SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_RESETCONTENT, 0, 0 );
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_PRIORITY ), g_Games[g_bug_GameType].bUsesSystem1 );
+ if ( g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ count = g_bug_pReporter->GetPriorityCount();
+ for ( i = 0; i < count; i++ )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetPriority( i ) );
+ }
+ if ( count )
+ {
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szPriority );
+ if ( curSel != CB_ERR )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_PRIORITY, CB_SETCURSEL, curSel, 0 );
+ }
+ }
+ }
+
+ // area
+ SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_RESETCONTENT, 0, 0 );
+ count = g_bug_pReporter->GetAreaCount();
+ int areaIndex = 0;
+ for ( i = 0; i < count; i++ )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetArea( i ) );
+ }
+ if ( count )
+ {
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szArea );
+ if ( curSel != CB_ERR )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_AREA, CB_SETCURSEL, curSel, 0 );
+ areaIndex = curSel;
+ }
+ }
+
+ // map name or number
+ SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_RESETCONTENT, 0, 0 );
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_MAPNUMBER ), g_Games[g_bug_GameType].bUsesSystem1 == false );
+ if ( !g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ // new system has map names
+ count = g_bug_pReporter->GetLevelCount( areaIndex );
+ for ( i = 0; i < count; i++ )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_bug_pReporter->GetLevel( areaIndex, i ) );
+ }
+ }
+ if ( count )
+ {
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szMapNumber );
+ if ( curSel != CB_ERR )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_MAPNUMBER, CB_SETCURSEL, curSel, 0 );
+ }
+ }
+
+ // game
+ SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_RESETCONTENT, 0, 0 );
+ count = ARRAYSIZE( g_Games );
+ for ( i = 0; i < count; i++ )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)g_Games[i].pFriendlyName );
+ }
+ if ( count )
+ {
+ curSel = SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_Games[g_bug_GameType].pFriendlyName );
+ if ( curSel != CB_ERR )
+ {
+ SendDlgItemMessage( hWnd, IDC_BUG_GAME, CB_SETCURSEL, curSel, 0 );
+ }
+ }
+
+ CheckDlgButton( hWnd, IDC_BUG_COMPRESS_SCREENSHOT, g_bug_bCompressScreenshot ? BST_CHECKED : BST_UNCHECKED );
+
+ SetDlgItemText( hWnd, IDC_BUG_TAKESHOT_LABEL, g_bug_szScreenshot );
+ SetDlgItemText( hWnd, IDC_BUG_SAVEGAME_LABEL, g_bug_szSavegame );
+ SetDlgItemText( hWnd, IDC_BUG_INCLUDEBSP_LABEL, g_bug_szBSPName );
+ SetDlgItemText( hWnd, IDC_BUG_INCLUDEVMF_LABEL, "" );
+
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_TAKESHOT ), g_connectedToApp );
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_INCLUDEVMF ), false );
+ EnableWindow( GetDlgItem( hWnd, IDC_BUG_UPDATE ), g_connectedToApp );
+
+ BugDlg_GetAppData( hWnd );
+
+ BugDlg_CheckSubmit( hWnd );
+
+ g_bug_bActive = true;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_TakeScreenshot
+//
+//-----------------------------------------------------------------------------
+void BugDlg_TakeScreenshot( HWND hWnd )
+{
+ char buff[1024];
+
+ SetDlgItemText( hWnd, IDC_BUG_TAKESHOT_LABEL, "Working..." );
+
+ BugDlg_GetDataFileBase( g_bug_pReporter->GetUserName(), true, g_bug_szScreenshot, sizeof( g_bug_szScreenshot ) );
+ strcat( g_bug_szScreenshot, ".bmp" );
+
+ // remove local version
+ unlink( g_bug_szScreenshot );
+
+ sprintf( buff, "*screenshot \"%s\"", g_bug_szScreenshot );
+ if ( !ProcessCommand( buff ) )
+ {
+ g_bug_szScreenshot[0] = '\0';
+ }
+
+ SetDlgItemText( hWnd, IDC_BUG_TAKESHOT_LABEL, g_bug_szScreenshot );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_SaveGame
+//
+//-----------------------------------------------------------------------------
+void BugDlg_SaveGame( HWND hWnd )
+{
+ char buff[1024];
+ char savename[MAX_PATH];
+ char remoteFile[MAX_PATH];
+
+ if ( !g_bug_mapInfo.savePath[0] )
+ {
+ return;
+ }
+
+ SetDlgItemText( hWnd, IDC_BUG_SAVEGAME_LABEL, "Working..." );
+
+ BugDlg_GetDataFileBase( g_bug_pReporter->GetUserName(), true, g_bug_szSavegame, sizeof( g_bug_szSavegame ) );
+ Sys_StripPath( g_bug_szSavegame, savename, sizeof( savename ) );
+ strcat( g_bug_szSavegame, ".360.sav" );
+
+ sprintf( remoteFile, "%s\\%s.360.sav", g_bug_mapInfo.savePath, savename );
+
+ // delete file locally
+ unlink( g_bug_szSavegame );
+
+ // delete file remotely
+ DmDeleteFile( remoteFile, false );
+
+ // save, and wait to ensure async completes
+ sprintf( buff, "save \"%s\" notmostrecent wait", savename );
+ if ( !ProcessCommand( buff ) )
+ {
+ // failed
+ g_bug_szSavegame[0] = '\0';
+ }
+ else
+ {
+ DM_FILE_ATTRIBUTES fileAttributes;
+ for (int i=0; i<5; i++)
+ {
+ // wait for the save file to appear
+ HRESULT hr = DmGetFileAttributes( remoteFile, &fileAttributes );
+ if ( hr == XBDM_NOERR )
+ break;
+
+ // wait for it
+ Sleep( 1000 );
+ }
+
+ HRESULT hr = DmReceiveFile( g_bug_szSavegame, remoteFile );
+ if ( hr != XBDM_NOERR )
+ {
+ // failed
+ g_bug_szSavegame[0] = '\0';
+ }
+ }
+
+ SetDlgItemText( hWnd, IDC_BUG_SAVEGAME_LABEL, g_bug_szSavegame );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_IncludeBSP
+//
+//-----------------------------------------------------------------------------
+void BugDlg_IncludeBSP( HWND hWnd )
+{
+ if ( !g_bug_mapInfo.mapPath[0] )
+ {
+ return;
+ }
+
+ SetDlgItemText( hWnd, IDC_BUG_INCLUDEBSP_LABEL, "Working..." );
+
+ BugDlg_GetDataFileBase( g_bug_pReporter->GetUserName(), true, g_bug_szBSPName, sizeof( g_bug_szBSPName ) );
+ strcat( g_bug_szBSPName, ".360.bsp" );
+
+ // remove local version
+ unlink( g_bug_szBSPName );
+
+ // get the file locally
+ HRESULT hr = DmReceiveFile( g_bug_szBSPName, g_bug_mapInfo.mapPath );
+ if ( hr != XBDM_NOERR )
+ {
+ // failed
+ g_bug_szBSPName[0] = '\0';
+ }
+
+ SetDlgItemText( hWnd, IDC_BUG_INCLUDEBSP_LABEL, g_bug_szBSPName );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_ResetAndPopulate
+//
+//-----------------------------------------------------------------------------
+void BugDlg_ResetAndPopulate( HWND hWnd, bool bFullReset = true )
+{
+ // reset all fields
+ if ( bFullReset )
+ {
+ g_bug_szTitle[0] = '\0';
+ g_bug_szDescription[0] = '\0';
+ }
+ g_bug_szOwner[0] = '\0';
+ g_bug_szSeverity[0] = '\0';
+ g_bug_szReportType[0] = '\0';
+ g_bug_szPriority[0] = '\0';
+ g_bug_szMapNumber[0] = '\0';
+
+ if ( bFullReset )
+ {
+ g_bug_szScreenshot[0] = '\0';
+ g_bug_szSavegame[0] = '\0';
+ g_bug_szBSPName[0] = '\0';
+ }
+
+ g_bug_bCompressScreenshot = true;
+
+ memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
+
+ // populate with reset fields
+ BugDlg_Populate( hWnd );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_Setup
+//
+//-----------------------------------------------------------------------------
+void BugDlg_Setup( HWND hWnd )
+{
+ g_bug_hWnd = hWnd;
+
+ // clear stale data from app
+ g_bug_bFirstCommand = false;
+ memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
+
+ // always reset these fields
+ g_bug_szTitle[0] = '\0';
+ g_bug_szDescription[0] = '\0';
+ g_bug_szScreenshot[0] = '\0';
+ g_bug_szSavegame[0] = '\0';
+ g_bug_szBSPName[0] = '\0';
+
+ g_bug_bCompressScreenshot = true;
+
+ memset( &g_bug_mapInfo, 0, sizeof( g_bug_mapInfo ) );
+
+ BugDlg_Populate( hWnd );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_UploadFile
+//
+//-----------------------------------------------------------------------------
+bool BugDlg_UploadFile( char const *pLocalName, char const *pRemoteName, bool bDeleteLocal )
+{
+ FILE *fp;
+ int len;
+ void *pLocalData;
+
+ ConsoleWindowPrintf( BUG_COLOR, "Uploading %s to %s\n", pLocalName, pRemoteName );
+
+ len = Sys_LoadFile( pLocalName, &pLocalData );
+ if ( !pLocalData || !len )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "UploadFile: Unable to open local path '%s'\n", pLocalName );
+ return false;
+ }
+
+ Sys_CreatePath( pRemoteName );
+
+ fp = fopen( pRemoteName, "wb" );
+ if ( !fp )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "UploadFile: Unable to open remote path '%s'\n", pRemoteName );
+ Sys_Free( pLocalData );
+ return false;
+ }
+
+ fwrite( pLocalData, len, 1, fp );
+
+ fclose( fp );
+ Sys_Free( pLocalData );
+
+ if ( bDeleteLocal )
+ {
+ unlink( pLocalName );
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_UploadBugSubmission
+//
+// Expects fully qualified source paths
+//-----------------------------------------------------------------------------
+bool BugDlg_UploadBugSubmission( int bugID, char const *pSavefile, char const *pScreenshot, char const *pBspFile, char const *pVmfFile )
+{
+ char szFilename[MAX_PATH];
+ char szLocalfile[MAX_PATH];
+ char szRemotefile[MAX_PATH];
+ bool bSuccess = true;
+
+ if ( pSavefile && pSavefile[0] )
+ {
+ V_snprintf( szLocalfile, sizeof( szLocalfile ), "%s", pSavefile );
+ Sys_StripPath( pSavefile, szFilename, sizeof( szFilename ) );
+ V_snprintf( szRemotefile, sizeof( szRemotefile ), "%s/%s", GetSubmissionURL( bugID ), szFilename );
+ Sys_NormalizePath( szLocalfile, false );
+ Sys_NormalizePath( szRemotefile, false );
+
+ if ( !BugDlg_UploadFile( szLocalfile, szRemotefile, false ) )
+ {
+ bSuccess = false;
+ }
+ }
+
+ if ( pScreenshot && pScreenshot[0] )
+ {
+ V_snprintf( szLocalfile, sizeof( szLocalfile ), "%s", pScreenshot );
+ Sys_StripPath( pScreenshot, szFilename, sizeof( szFilename ) );
+ V_snprintf( szRemotefile, sizeof( szRemotefile ), "%s/%s", GetSubmissionURL( bugID ), szFilename );
+ Sys_NormalizePath( szLocalfile, false );
+ Sys_NormalizePath( szRemotefile, false );
+
+ if ( !BugDlg_UploadFile( szLocalfile, szRemotefile, true ) )
+ {
+ bSuccess = false;
+ }
+ }
+
+ if ( pBspFile && pBspFile[0] )
+ {
+ V_snprintf( szLocalfile, sizeof( szLocalfile ), "%s", pBspFile );
+ Sys_StripPath( pBspFile, szFilename, sizeof( szFilename ) );
+ V_snprintf( szRemotefile, sizeof( szRemotefile ), "%s/%s", GetSubmissionURL( bugID ), szFilename );
+ Sys_NormalizePath( szLocalfile, false );
+ Sys_NormalizePath( szRemotefile, false );
+
+ if ( !BugDlg_UploadFile( szLocalfile, szRemotefile, true ) )
+ {
+ bSuccess = false;
+ }
+ }
+
+ return bSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_Submit
+//
+//-----------------------------------------------------------------------------
+bool BugDlg_Submit( HWND hWnd )
+{
+ char title[1024];
+ char miscInfo[1024];
+ char basename[MAX_PATH];
+ char filename[MAX_PATH];
+ char positionName[MAX_PATH];
+ char orientationName[MAX_PATH];
+ char buildName[MAX_PATH];
+ char mapName[MAX_PATH];
+ bool bSuccess = false;
+
+ sprintf( positionName, "%f %f %f", g_bug_mapInfo.position[0], g_bug_mapInfo.position[1], g_bug_mapInfo.position[2] );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_POSITION_LABEL, positionName );
+
+ sprintf( orientationName, "%f %f %f", g_bug_mapInfo.angle[0], g_bug_mapInfo.angle[1], g_bug_mapInfo.angle[2] );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_ORIENTATION_LABEL, orientationName );
+
+ sprintf( buildName, "%d", g_bug_mapInfo.build );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_BUILD_LABEL, buildName );
+
+ V_FileBase( g_bug_mapInfo.mapPath, mapName, sizeof( mapName ) );
+ char *pExtension = V_stristr( mapName, ".bsp" );
+ if ( pExtension )
+ {
+ *pExtension = '\0';
+ }
+ pExtension = V_stristr( mapName, ".360" );
+ if ( pExtension )
+ {
+ *pExtension = '\0';
+ }
+
+ V_snprintf( miscInfo, sizeof( miscInfo ), "skill %d", g_bug_mapInfo.skill );
+
+ // Stuff bug data files up to server
+ g_bug_pReporter->StartNewBugReport();
+
+ g_bug_pReporter->SetOwner( g_bug_pReporter->GetUserNameForDisplayName( g_bug_szOwner ) );
+ g_bug_pReporter->SetSubmitter( NULL );
+
+ if ( mapName[0] )
+ V_snprintf( title, sizeof( title ), "%s: %s", mapName, g_bug_szTitle );
+ else
+ V_snprintf( title, sizeof( title ), "%s", g_bug_szTitle );
+ g_bug_pReporter->SetTitle( title );
+
+ g_bug_pReporter->SetDescription( g_bug_szDescription );
+ g_bug_pReporter->SetLevel( mapName );
+ g_bug_pReporter->SetPosition( positionName );
+ g_bug_pReporter->SetOrientation( orientationName );
+ g_bug_pReporter->SetBuildNumber( buildName );
+
+ g_bug_pReporter->SetSeverity( g_bug_szSeverity );
+ g_bug_pReporter->SetPriority( g_bug_szPriority );
+ g_bug_pReporter->SetArea( g_bug_szArea );
+ g_bug_pReporter->SetMapNumber( g_bug_szMapNumber );
+ g_bug_pReporter->SetReportType( g_bug_szReportType );
+ g_bug_pReporter->SetMiscInfo( miscInfo );
+
+ g_bug_pReporter->SetDriverInfo( "" );
+ g_bug_pReporter->SetExeName( "" );
+ g_bug_pReporter->SetGameDirectory( "" );
+ g_bug_pReporter->SetRAM( 0 );
+ g_bug_pReporter->SetCPU( 0 );
+ g_bug_pReporter->SetProcessor( "" );
+ g_bug_pReporter->SetDXVersion( 0, 0, 0, 0 );
+ g_bug_pReporter->SetOSVersion( "" );
+ g_bug_pReporter->ResetIncludedFiles();
+ g_bug_pReporter->SetZipAttachmentName( "" );
+
+ if ( g_bug_szScreenshot[0] )
+ {
+ if ( g_bug_bCompressScreenshot )
+ {
+ BugDlg_CompressScreenshot();
+ }
+
+ // strip the fully qualified path into filename only
+ Sys_StripPath( g_bug_szScreenshot, basename, sizeof( basename ) );
+ V_snprintf( filename, sizeof( filename ), "%s/BugId/%s", GetRepositoryURL(), basename );
+ Sys_NormalizePath( filename, false );
+ g_bug_pReporter->SetScreenShot( filename );
+ }
+
+ if ( g_bug_szSavegame[0] )
+ {
+ // strip the fully qualified path into filename only
+ Sys_StripPath( g_bug_szSavegame, basename, sizeof( basename ) );
+ V_snprintf( filename, sizeof( filename ), "%s/BugId/%s", GetRepositoryURL(), basename );
+ Sys_NormalizePath( filename, false );
+ g_bug_pReporter->SetSaveGame( filename );
+ }
+
+ if ( g_bug_szBSPName[0] )
+ {
+ // strip the fully qualified path into filename only
+ Sys_StripPath( g_bug_szBSPName, basename, sizeof( basename ) );
+ V_snprintf( filename, sizeof( filename ), "%s/BugId/%s", GetRepositoryURL(), basename );
+ Sys_NormalizePath( filename, false );
+ g_bug_pReporter->SetBSPName( filename );
+ }
+
+ int bugID = -1;
+
+ bSuccess = g_bug_pReporter->CommitBugReport( bugID );
+ if ( bSuccess )
+ {
+ if ( !BugDlg_UploadBugSubmission( bugID, g_bug_szSavegame, g_bug_szScreenshot, g_bug_szBSPName, NULL ) )
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "Unable to upload files to bug repository!\n" );
+ bSuccess = false;
+ }
+ }
+ else
+ {
+ Sys_MessageBox( BUG_ERRORTITLE, "Unable to post bug report to database!\n" );
+ }
+
+ if ( bSuccess )
+ {
+ if ( g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: PVCS submission succeeded for bug! (%d)\n", bugID );
+ }
+ else
+ {
+ ConsoleWindowPrintf( BUG_COLOR, "Bug Reporter: BugBait submission succeeded for bug!\n" );
+ }
+ }
+ else
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Bug Reporter: Submission failed\n" );
+ }
+
+ return bSuccess;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_Proc
+//
+//-----------------------------------------------------------------------------
+BOOL CALLBACK BugDlg_Proc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ BugDlg_Setup( hwnd );
+ return ( TRUE );
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_BUG_TAKESHOT:
+ BugDlg_TakeScreenshot( hwnd );
+ break;
+
+ case IDC_BUG_SAVEGAME:
+ BugDlg_SaveGame( hwnd );
+ break;
+
+ case IDC_BUG_INCLUDEBSP:
+ BugDlg_IncludeBSP( hwnd );
+ break;
+
+ case IDC_BUG_INCLUDEVMF:
+ // not implemented, no reason to
+ break;
+
+ case IDC_BUG_CLEARFORM:
+ BugDlg_ResetAndPopulate( hwnd );
+ return TRUE;
+
+ case IDC_BUG_UPDATE:
+ BugDlg_GetAppData( hwnd );
+ return TRUE;
+
+ case IDC_BUG_OWNER:
+ case IDC_BUG_SEVERITY:
+ case IDC_BUG_REPORTTYPE:
+ case IDC_BUG_PRIORITY:
+ case IDC_BUG_AREA:
+ case IDC_BUG_MAPNUMBER:
+ if ( g_bug_bActive && HIWORD( wParam ) == CBN_CLOSEUP )
+ {
+ BugDlg_GetChanges( hwnd );
+ return TRUE;
+ }
+ break;
+
+ case IDC_BUG_GAME:
+ if ( HIWORD( wParam ) == CBN_CLOSEUP )
+ {
+ if ( BugDlg_UpdateReporter( hwnd ) )
+ {
+ // reporter changed, clear critical parts of form
+ BugDlg_ResetAndPopulate( hwnd, false );
+ }
+ return TRUE;
+ }
+ break;
+
+ case IDC_BUG_TITLE:
+ case IDC_BUG_DESCRIPTION:
+ if ( g_bug_bActive && HIWORD( wParam ) == EN_CHANGE )
+ {
+ BugDlg_GetChanges( hwnd );
+ return TRUE;
+ }
+ break;
+
+ case IDC_BUG_COMPRESS_SCREENSHOT:
+ BugDlg_GetChanges( hwnd );
+ return TRUE;
+
+ case IDC_BUG_SUBMIT:
+ if ( !BugDlg_Submit( hwnd ) )
+ break;
+ // fall through
+ case IDCANCEL:
+ case IDC_CANCEL:
+ if ( g_connectedToApp && g_bug_bFirstCommand )
+ {
+ ProcessCommand( "unpause" );
+ }
+ EndDialog( hwnd, wParam );
+ return ( TRUE );
+ }
+ break;
+ }
+ return ( FALSE );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void BugDlg_SaveConfig()
+{
+ Sys_SetRegistryString( "bug_owner", g_bug_szOwner );
+ Sys_SetRegistryString( "bug_severity", g_bug_szSeverity );
+ Sys_SetRegistryString( "bug_reporttype", g_bug_szReportType );
+ Sys_SetRegistryString( "bug_priority", g_bug_szPriority );
+ Sys_SetRegistryInteger( "bug_gametype", g_bug_GameType );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void BugDlg_LoadConfig()
+{
+ // get our config
+ Sys_GetRegistryString( "bug_owner", g_bug_szOwner, "", sizeof( g_bug_szOwner ) );
+ Sys_GetRegistryString( "bug_severity", g_bug_szSeverity, "", sizeof( g_bug_szSeverity ) );
+ Sys_GetRegistryString( "bug_reporttype", g_bug_szReportType, "", sizeof( g_bug_szReportType ) );
+ Sys_GetRegistryString( "bug_priority", g_bug_szPriority, "", sizeof( g_bug_szPriority ) );
+ Sys_GetRegistryInteger( "bug_gametype", 0, g_bug_GameType );
+
+ // start with expected reporter
+ BugReporter_SelectReporter( g_Games[g_bug_GameType].pGameName );
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_Open
+//
+//-----------------------------------------------------------------------------
+void BugDlg_Open( void )
+{
+ int result;
+
+ // need access to bug databases via DLLs
+ if ( !BugReporter_GetInterfaces() )
+ {
+ return;
+ }
+
+ BugDlg_LoadConfig();
+
+ result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_BUG ), g_hDlgMain, ( DLGPROC )BugDlg_Proc );
+ if ( LOWORD( result ) == IDC_BUG_SUBMIT )
+ {
+ BugDlg_SaveConfig();
+ }
+
+ g_bug_hWnd = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// BugDlg_Init
+//
+//-----------------------------------------------------------------------------
+bool BugDlg_Init()
+{
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// rc_MapInfo
+//
+// Sent from application with bug dialog info
+//-----------------------------------------------------------------------------
+int rc_MapInfo( char* commandPtr )
+{
+ char* cmdToken;
+ int errCode;
+ int infoAddr;
+ int retVal;
+ int retAddr;
+ char buff[128];
+
+ // success
+ errCode = 0;
+
+ // get address of data
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &infoAddr );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &retAddr );
+
+ // get the caller's info data
+ DmGetMemory( ( void* )infoAddr, sizeof( xrMapInfo_t ), &g_bug_mapInfo, NULL );
+
+ // swap the structure
+ BigFloat( &g_bug_mapInfo.position[0], &g_bug_mapInfo.position[0] );
+ BigFloat( &g_bug_mapInfo.position[1], &g_bug_mapInfo.position[1] );
+ BigFloat( &g_bug_mapInfo.position[2], &g_bug_mapInfo.position[2] );
+ BigFloat( &g_bug_mapInfo.angle[0], &g_bug_mapInfo.angle[0] );
+ BigFloat( &g_bug_mapInfo.angle[1], &g_bug_mapInfo.angle[1] );
+ BigFloat( &g_bug_mapInfo.angle[2], &g_bug_mapInfo.angle[2] );
+ g_bug_mapInfo.build = BigDWord( g_bug_mapInfo.build );
+ g_bug_mapInfo.skill = BigDWord( g_bug_mapInfo.skill );
+
+ Sys_NormalizePath( g_bug_mapInfo.savePath, false );
+ Sys_NormalizePath( g_bug_mapInfo.mapPath, false );
+
+ if ( g_bug_hWnd )
+ {
+ if ( g_bug_mapInfo.mapPath[0] )
+ {
+ Sys_StripPath( g_bug_mapInfo.mapPath, buff, sizeof( buff ) );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_MAP_LABEL, buff );
+
+ if ( !g_Games[g_bug_GameType].bUsesSystem1 )
+ {
+ char *pExtension = V_stristr( buff, ".bsp" );
+ if ( pExtension )
+ {
+ *pExtension = '\0';
+ }
+ pExtension = V_stristr( buff, ".360" );
+ if ( pExtension )
+ {
+ *pExtension = '\0';
+ }
+ V_strncpy( g_bug_szMapNumber, buff, sizeof( g_bug_szMapNumber ) );
+
+ int curSel = SendDlgItemMessage( g_bug_hWnd, IDC_BUG_MAPNUMBER, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)(LPCSTR)g_bug_szMapNumber );
+ if ( curSel == CB_ERR )
+ curSel = 0;
+ SendDlgItemMessage( g_bug_hWnd, IDC_BUG_MAPNUMBER, CB_SETCURSEL, curSel, 0 );
+ }
+
+ sprintf( buff, "%.2f %.2f %.2f", g_bug_mapInfo.position[0], g_bug_mapInfo.position[1], g_bug_mapInfo.position[2] );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_POSITION_LABEL, buff );
+
+ sprintf( buff, "%.2f %.2f %.2f", g_bug_mapInfo.angle[0], g_bug_mapInfo.angle[1], g_bug_mapInfo.angle[2] );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_ORIENTATION_LABEL, buff );
+ }
+ else
+ {
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_MAP_LABEL, "" );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_POSITION_LABEL, "" );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_ORIENTATION_LABEL, "" );
+ }
+
+ sprintf( buff, "%d", g_bug_mapInfo.build );
+ SetDlgItemText( g_bug_hWnd, IDC_BUG_BUILD_LABEL, buff );
+
+ EnableWindow( GetDlgItem( g_bug_hWnd, IDC_BUG_SAVEGAME ), g_bug_mapInfo.savePath[0] != '\0' && g_bug_mapInfo.mapPath[0] != '\0' );
+ EnableWindow( GetDlgItem( g_bug_hWnd, IDC_BUG_INCLUDEBSP ), g_bug_mapInfo.mapPath[0] != '\0' );
+ }
+
+ // return the result
+ retVal = 0;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = MapInfo( 0x%8.8x )\n", retVal, infoAddr );
+
+cleanUp:
+ return errCode;
+}
+
diff --git a/utils/xbox/vxconsole/common.cpp b/utils/xbox/vxconsole/common.cpp
new file mode 100644
index 0000000..1b8418c
--- /dev/null
+++ b/utils/xbox/vxconsole/common.cpp
@@ -0,0 +1,73 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// COMMON.CPP
+//
+// Common/Misc specialized support routines not uniquely owned.
+//=====================================================================================//
+#include "vxconsole.h"
+
+vprofState_e g_vprof_state = VPROF_OFF;
+
+//-----------------------------------------------------------------------------
+// NotImplementedYet
+//
+//-----------------------------------------------------------------------------
+void NotImplementedYet()
+{
+ Sys_MessageBox( "Attention!", "Sorry, Not Implemented Yet." );
+}
+
+//-----------------------------------------------------------------------------
+// VProf_GetState
+//
+//-----------------------------------------------------------------------------
+vprofState_e VProf_GetState()
+{
+ return g_vprof_state;
+}
+
+//-----------------------------------------------------------------------------
+// VProf_Enable
+//
+// Coordinates multiple vprof commands for proper exclusion
+//-----------------------------------------------------------------------------
+void VProf_Enable( vprofState_e state )
+{
+ char commandString[256];
+
+ switch ( state )
+ {
+ case VPROF_CPU:
+ strcpy( commandString, "vprof_off ; vprof_on ; vprof_update cpu" );
+ break;
+
+ case VPROF_TEXTURE:
+ strcpy( commandString, "vprof_off ; vprof_on ; vprof_update texture" );
+ break;
+
+ case VPROF_TEXTUREFRAME:
+ strcpy( commandString, "vprof_off ; vprof_on ; vprof_update texture_frame" );
+ break;
+
+ default:
+ state = VPROF_OFF;
+ strcpy( commandString, "vprof_off" );
+ break;
+
+ }
+
+ // track state
+ if ( g_vprof_state != state )
+ {
+ g_vprof_state = state;
+
+ // do command
+ ProcessCommand( commandString );
+
+ // update all the dependant titles
+ CpuProfile_SetTitle();
+ TexProfile_SetTitle();
+ }
+}
+
+
diff --git a/utils/xbox/vxconsole/config.cpp b/utils/xbox/vxconsole/config.cpp
new file mode 100644
index 0000000..85558d7
--- /dev/null
+++ b/utils/xbox/vxconsole/config.cpp
@@ -0,0 +1,217 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// CONFIG.CPP
+//
+// Configuration Dialog
+//=====================================================================================//
+#include "vxconsole.h"
+
+CHAR g_xboxTargetName[MAX_XBOXNAMELEN];
+char g_localPath[MAX_PATH];
+char g_targetPath[MAX_PATH];
+BOOL g_clsOnConnect;
+BOOL g_loadSymbolsOnConnect;
+char g_xexTargetPath[MAX_PATH];
+BOOL g_alwaysAutoConnect;
+BOOL g_startMinimized;
+char g_installPath[MAX_PATH];
+BOOL g_captureDebugSpew_StartupState;
+
+//-----------------------------------------------------------------------------
+// ConfigDlg_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void ConfigDlg_LoadConfig()
+{
+ // get our config
+ Sys_GetRegistryString( "xboxName", g_xboxTargetName, "", sizeof( g_xboxTargetName ) );
+ Sys_GetRegistryString( "localPath", g_localPath, "u:\\dev\\game", sizeof( g_localPath ) );
+ Sys_GetRegistryString( "targetPath", g_targetPath, "e:\\valve", sizeof( g_targetPath ) );
+ Sys_GetRegistryString( "installPath", g_installPath, "\\\\fileserver\\user\\xbox\\xbox_orange", sizeof( g_installPath ) );
+ Sys_GetRegistryInteger( "clearOnConnect", true, g_clsOnConnect );
+ Sys_GetRegistryInteger( "loadSymbolsOnConnect", false, g_loadSymbolsOnConnect );
+ Sys_GetRegistryInteger( "alwaysAutoConnect", false, g_alwaysAutoConnect );
+ Sys_GetRegistryInteger( "startMinimized", false, g_startMinimized );
+ Sys_GetRegistryInteger( "captureDebugSpew", true, g_captureDebugSpew_StartupState );
+}
+
+//-----------------------------------------------------------------------------
+// ConfigDlg_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void ConfigDlg_SaveConfig()
+{
+ // save config
+ Sys_SetRegistryString( "xboxName", g_xboxTargetName );
+ Sys_SetRegistryString( "localPath", g_localPath );
+ Sys_SetRegistryString( "targetPath", g_targetPath );
+ Sys_SetRegistryString( "installPath", g_installPath );
+ Sys_SetRegistryInteger( "clearOnConnect", g_clsOnConnect );
+ Sys_SetRegistryInteger( "loadSymbolsOnConnect", g_loadSymbolsOnConnect );
+ Sys_SetRegistryInteger( "alwaysAutoConnect", g_alwaysAutoConnect );
+ Sys_SetRegistryInteger( "startMinimized", g_startMinimized );
+ Sys_SetRegistryInteger( "captureDebugSpew", g_captureDebugSpew_StartupState );
+
+ // update
+ SetMainWindowTitle();
+}
+
+//-----------------------------------------------------------------------------
+// ConfigDlg_Setup
+//
+//-----------------------------------------------------------------------------
+void ConfigDlg_Setup( HWND hWnd )
+{
+ SetDlgItemText( hWnd,IDC_CONFIG_XBOXNAME, g_xboxTargetName );
+ SetDlgItemText( hWnd,IDC_CONFIG_LOCALPATH, g_localPath );
+ SetDlgItemText( hWnd,IDC_CONFIG_TARGETPATH, g_targetPath );
+ SetDlgItemText( hWnd,IDC_CONFIG_INSTALLPATH, g_installPath );
+
+ EnableWindow( GetDlgItem( hWnd, IDC_CONFIG_PING ), strlen( g_xboxTargetName ) > 0 );
+
+ CheckDlgButton( hWnd, IDC_CONFIG_CLEARONCONNECT, g_clsOnConnect ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hWnd, IDC_CONFIG_ALWAYSAUTOCONNECT, g_alwaysAutoConnect ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hWnd, IDC_CONFIG_STARTMINIMIZED, g_startMinimized ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hWnd, IDC_CONFIG_CAPTUREDEBUGSPEW, g_captureDebugSpew_StartupState ? BST_CHECKED : BST_UNCHECKED );
+}
+
+//-----------------------------------------------------------------------------
+// ConfigDlg_Ping
+//
+//-----------------------------------------------------------------------------
+BOOL ConfigDlg_Ping( HWND hwnd )
+{
+ char xboxName[MAX_XBOXNAMELEN];
+ BOOL canConnect;
+ char* args[1];
+
+ xboxName[0] = '\0';
+ GetDlgItemText( hwnd, IDC_CONFIG_XBOXNAME, xboxName, MAX_XBOXNAMELEN );
+
+ // ignore ping to current connection
+ if ( !stricmp( g_xboxName, xboxName ) )
+ {
+ if ( g_connectedToXBox )
+ {
+ Sys_MessageBox( "Ping", "Already Connected To: '%s'", xboxName );
+ return true;
+ }
+ }
+
+ // terminate any current connection
+ lc_disconnect( 0, NULL );
+
+ // trial connect
+ args[0] = xboxName;
+ canConnect = lc_connect( 1, args );
+
+ if ( !canConnect )
+ Sys_MessageBox( "Ping FAILURE", "Could Not Connect To: %s", xboxName );
+ else
+ Sys_MessageBox( "Ping SUCCESS", "Connection Valid To: %s", g_xboxName );
+
+ if ( canConnect )
+ lc_disconnect( 0, NULL );
+
+ return canConnect;
+}
+
+//-----------------------------------------------------------------------------
+// ConfigDlg_GetChanges
+//
+//-----------------------------------------------------------------------------
+bool ConfigDlg_GetChanges( HWND hwnd )
+{
+ char remotePath[MAX_PATH];
+ char localPath[MAX_PATH];
+ char targetPath[MAX_PATH];
+ char installPath[MAX_PATH];
+ char xboxName[MAX_XBOXNAMELEN];
+ char xexLocalPath[MAX_PATH];
+ char xexTargetPath[MAX_PATH];
+
+ xboxName[0] = '\0';
+ remotePath[0] = '\0';
+ localPath[0] = '\0';
+ targetPath[0] = '\0';
+ xexLocalPath[0] = '\0';
+ xexTargetPath[0] = '\0';
+
+ GetDlgItemText( hwnd, IDC_CONFIG_XBOXNAME, xboxName, MAX_XBOXNAMELEN );
+ GetDlgItemText( hwnd, IDC_CONFIG_LOCALPATH, localPath, MAX_PATH );
+ GetDlgItemText( hwnd, IDC_CONFIG_TARGETPATH, targetPath, MAX_PATH );
+ GetDlgItemText( hwnd, IDC_CONFIG_INSTALLPATH, installPath, MAX_PATH );
+
+ strcpy( g_localPath, localPath );
+ Sys_NormalizePath( g_localPath, true );
+
+ strcpy( g_targetPath, targetPath );
+ Sys_NormalizePath( g_targetPath, true );
+
+ strcpy( g_installPath, installPath );
+ Sys_NormalizePath( g_installPath, true );
+
+ strcpy( g_xboxTargetName, xboxName );
+
+ g_clsOnConnect = IsDlgButtonChecked( hwnd, IDC_CONFIG_CLEARONCONNECT );
+ g_loadSymbolsOnConnect = IsDlgButtonChecked( hwnd, IDC_CONFIG_LOADSYMBOLS );
+ g_alwaysAutoConnect = IsDlgButtonChecked( hwnd, IDC_CONFIG_ALWAYSAUTOCONNECT );
+ g_startMinimized = IsDlgButtonChecked( hwnd, IDC_CONFIG_STARTMINIMIZED );
+ g_captureDebugSpew_StartupState = IsDlgButtonChecked( hwnd, IDC_CONFIG_CAPTUREDEBUGSPEW );
+
+ // success
+ return ( true );
+}
+
+//-----------------------------------------------------------------------------
+// ConfigDlg_Proc
+//
+//-----------------------------------------------------------------------------
+BOOL CALLBACK ConfigDlg_Proc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ ConfigDlg_Setup( hwnd );
+ return ( TRUE );
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_CONFIG_PING:
+ ConfigDlg_Ping( hwnd );
+ break;
+
+ case IDC_CONFIG_XBOXNAME:
+ CHAR buff[MAX_XBOXNAMELEN];
+ GetDlgItemText( hwnd, IDC_CONFIG_XBOXNAME, buff, sizeof( buff ) );
+ EnableWindow( GetDlgItem( hwnd, IDC_CONFIG_PING ), strlen( buff ) > 0 );
+ break;
+
+ case IDC_OK:
+ if ( !ConfigDlg_GetChanges( hwnd ) )
+ break;
+ case IDCANCEL:
+ case IDC_CANCEL:
+ EndDialog( hwnd, wParam );
+ return ( TRUE );
+ }
+ break;
+ }
+ return ( FALSE );
+}
+
+//-----------------------------------------------------------------------------
+// ConfigDlg_Open
+//
+//-----------------------------------------------------------------------------
+void ConfigDlg_Open( void )
+{
+ int result;
+
+ result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_CONFIG ), g_hDlgMain, ( DLGPROC )ConfigDlg_Proc );
+ if ( LOWORD( result ) != IDC_OK )
+ return;
+
+ ConfigDlg_SaveConfig();
+}
diff --git a/utils/xbox/vxconsole/cpu_profile.cpp b/utils/xbox/vxconsole/cpu_profile.cpp
new file mode 100644
index 0000000..57571e4
--- /dev/null
+++ b/utils/xbox/vxconsole/cpu_profile.cpp
@@ -0,0 +1,983 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// CPU_PROFILE.CPP
+//
+// Cpu Profiling Display
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define PROFILE_MAXCOUNTERS 64
+#define PROFILE_MAXSAMPLES 512
+
+#define PROFILE_HISTORY_TIMINGHEIGHT 100
+#define PROFILE_HISTORY_NUMMINORTICKS 3
+#define PROFILE_HISTORY_LABELWIDTH 50
+#define PROFILE_HISTORY_SCALESTEPS 5
+#define PROFILE_HISTORY_MINSCALE 0.3f
+#define PROFILE_HISTORY_MAXSCALE 3.0f
+
+#define PROFILE_SAMPLES_ITEMHEIGHT 15
+#define PROFILE_SAMPLES_BARHEIGHT 10
+#define PROFILE_SAMPLES_TIMINGWIDTH 200
+#define PROFILE_SAMPLES_LABELWIDTH 150
+#define PROFILE_SAMPLES_LABELGAP 5
+#define PROFILE_SAMPLES_NUMMINORTICKS 3
+#define PROFILE_SAMPLES_PEAKHOLDTIME 3000
+#define PROFILE_SAMPLES_SCALESTEPS 10
+#define PROFILE_SAMPLES_MINSCALE 0.3f
+#define PROFILE_SAMPLES_MAXSCALE 3.0f
+
+#define ID_CPUPROFILE_SAMPLES 1
+#define ID_CPUPROFILE_HISTORY 2
+
+typedef struct
+{
+ unsigned int samples[PROFILE_MAXSAMPLES];
+ unsigned int peakSample;
+ char label[64];
+ COLORREF color;
+} profileCounter_t;
+
+HWND g_cpuProfile_hWndSamples;
+HWND g_cpuProfile_hWndHistory;
+int g_cpuProfile_numCounters;
+profileCounter_t g_cpuProfile_counters[PROFILE_MAXCOUNTERS];
+RECT g_cpuProfile_samplesWindowRect;
+RECT g_cpuProfile_historyWindowRect;
+DWORD g_cpuProfile_lastPeakTime;
+bool g_cpuProfile_history_tickMarks = true;
+bool g_cpuProfile_history_colors = true;
+int g_cpuProfile_history_scale;
+bool g_cpuProfile_samples_tickMarks = true;
+bool g_cpuProfile_samples_colors = true;
+int g_cpuProfile_samples_scale;
+int g_cpuProfile_numSamples;
+int g_cpuProfile_fpsLabels;
+
+//-----------------------------------------------------------------------------
+// CpuProfile_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void CpuProfile_SaveConfig()
+{
+ char buff[256];
+ WINDOWPLACEMENT wp;
+
+ // profile samples
+ if ( g_cpuProfile_hWndSamples )
+ {
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_cpuProfile_hWndSamples, &wp );
+ g_cpuProfile_samplesWindowRect = wp.rcNormalPosition;
+ sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom );
+ Sys_SetRegistryString( "profileSamplesWindowRect", buff );
+ }
+ Sys_SetRegistryInteger( "profileSamplesScale", g_cpuProfile_samples_scale );
+
+ // profile history
+ if ( g_cpuProfile_hWndHistory )
+ {
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_cpuProfile_hWndHistory, &wp );
+ g_cpuProfile_historyWindowRect = wp.rcNormalPosition;
+ sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom );
+ Sys_SetRegistryString( "profileHistoryWindowRect", buff );
+ }
+ Sys_SetRegistryInteger( "profileHistoryScale", g_cpuProfile_history_scale );
+
+ Sys_SetRegistryInteger( "cpuProfileFpsLabels", g_cpuProfile_fpsLabels );
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void CpuProfile_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ // profile samples
+ Sys_GetRegistryString( "profileSamplesWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_cpuProfile_samplesWindowRect.left, &g_cpuProfile_samplesWindowRect.top, &g_cpuProfile_samplesWindowRect.right, &g_cpuProfile_samplesWindowRect.bottom );
+ if ( numArgs != 4 )
+ memset( &g_cpuProfile_samplesWindowRect, 0, sizeof( g_cpuProfile_samplesWindowRect ) );
+ Sys_GetRegistryInteger( "profileSamplesScale", 0, g_cpuProfile_samples_scale );
+ if ( g_cpuProfile_samples_scale < -PROFILE_SAMPLES_SCALESTEPS || g_cpuProfile_samples_scale > PROFILE_SAMPLES_SCALESTEPS )
+ g_cpuProfile_samples_scale = 0;
+
+ // profile history
+ Sys_GetRegistryString( "profileHistoryWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_cpuProfile_historyWindowRect.left, &g_cpuProfile_historyWindowRect.top, &g_cpuProfile_historyWindowRect.right, &g_cpuProfile_historyWindowRect.bottom );
+ if ( numArgs != 4 )
+ memset( &g_cpuProfile_historyWindowRect, 0, sizeof( g_cpuProfile_historyWindowRect ) );
+ Sys_GetRegistryInteger( "profileHistoryScale", 0, g_cpuProfile_history_scale );
+ if ( g_cpuProfile_history_scale < -PROFILE_HISTORY_SCALESTEPS || g_cpuProfile_history_scale > PROFILE_HISTORY_SCALESTEPS )
+ g_cpuProfile_history_scale = 0;
+
+ Sys_GetRegistryInteger( "cpuProfileFpsLabels", 0, g_cpuProfile_fpsLabels );
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_SetTitle
+//
+//-----------------------------------------------------------------------------
+void CpuProfile_SetTitle()
+{
+ char titleBuff[128];
+
+ if ( g_cpuProfile_hWndSamples )
+ {
+ strcpy( titleBuff, "CPU Usage Snapshot" );
+ if ( VProf_GetState() == VPROF_CPU )
+ strcat( titleBuff, " [ON]" );
+
+ SetWindowText( g_cpuProfile_hWndSamples, titleBuff );
+ }
+
+ if ( g_cpuProfile_hWndHistory )
+ {
+ strcpy( titleBuff, "CPU Usage History" );
+ if ( VProf_GetState() == VPROF_CPU )
+ strcat( titleBuff, " [ON]" );
+
+ SetWindowText( g_cpuProfile_hWndHistory, titleBuff );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_UpdateWindow
+//
+//-----------------------------------------------------------------------------
+void CpuProfile_UpdateWindow()
+{
+ if ( g_cpuProfile_hWndSamples && !IsIconic( g_cpuProfile_hWndSamples ) )
+ {
+ // visible - force a client repaint
+ InvalidateRect( g_cpuProfile_hWndSamples, NULL, true );
+ }
+
+ if ( g_cpuProfile_hWndHistory && !IsIconic( g_cpuProfile_hWndHistory ) )
+ {
+ // visible - force a client repaint
+ InvalidateRect( g_cpuProfile_hWndHistory, NULL, true );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// rc_SetCpuProfile
+//
+//-----------------------------------------------------------------------------
+int rc_SetCpuProfile( char* commandPtr )
+{
+ int i;
+ char* cmdToken;
+ int retAddr;
+ int errCode = -1;
+ xrProfile_t* localList;
+ int profileList;
+ int numProfiles;
+ int retVal;
+
+ // get numProfiles
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken,"%x",&numProfiles );
+
+ // get profile attributes
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &profileList );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken,"%x",&retAddr );
+
+ localList = new xrProfile_t[numProfiles];
+ memset( localList, 0, numProfiles*sizeof( xrProfile_t ) );
+
+ // get the caller's profile list
+ DmGetMemory( ( void* )profileList, numProfiles*sizeof( xrProfile_t ), localList, NULL );
+
+ g_cpuProfile_numCounters = numProfiles;
+ if ( g_cpuProfile_numCounters > PROFILE_MAXCOUNTERS-1 )
+ g_cpuProfile_numCounters = PROFILE_MAXCOUNTERS-1;
+
+ for ( i=0; i<g_cpuProfile_numCounters; i++ )
+ {
+ // swap the structure
+ localList[i].color = BigDWord( localList[i].color );
+
+ // clear the old counter
+ memset( &g_cpuProfile_counters[i], 0, sizeof( profileCounter_t ) );
+
+ V_strncpy( g_cpuProfile_counters[i].label, localList[i].labelString, sizeof( g_cpuProfile_counters[i].label ) );
+ g_cpuProfile_counters[i].color = localList[i].color;
+ }
+
+ // build out the reserved last counter as total count
+ memset( &g_cpuProfile_counters[g_cpuProfile_numCounters], 0, sizeof( profileCounter_t ) );
+ strcpy( g_cpuProfile_counters[g_cpuProfile_numCounters].label, "Total" );
+ g_cpuProfile_counters[i].color = RGB( 255,255,255 );
+ g_cpuProfile_numCounters++;
+
+ // set the return code
+ retVal = g_cpuProfile_numCounters-1;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = SetCpuProfile( 0x%8.8x, 0x%8.8x )\n", retVal, numProfiles, profileList );
+
+ delete [] localList;
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
+
+//-----------------------------------------------------------------------------
+// rc_SetCpuProfileData
+//
+//-----------------------------------------------------------------------------
+int rc_SetCpuProfileData( char* commandPtr )
+{
+ int i;
+ int total;
+ char* cmdToken;
+ int errCode = -1;
+ int counters;
+ int currentSample;
+ bool newPeaks;
+ unsigned int localCounters[PROFILE_MAXCOUNTERS];
+ DWORD newTime;
+
+ // get profiles
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ {
+ goto cleanUp;
+ }
+ sscanf( cmdToken, "%x", &counters );
+
+ // get the caller's profile list
+ if ( g_cpuProfile_numCounters )
+ {
+ DmGetMemory( ( void* )counters, ( g_cpuProfile_numCounters-1 )*sizeof( int ), localCounters, NULL );
+ }
+
+ // timeout peaks
+ newTime = Sys_GetSystemTime();
+ if ( newTime - g_cpuProfile_lastPeakTime > PROFILE_SAMPLES_PEAKHOLDTIME )
+ {
+ g_cpuProfile_lastPeakTime = newTime;
+ newPeaks = true;
+ }
+ else
+ {
+ newPeaks = false;
+ }
+
+ // next sample
+ currentSample = g_cpuProfile_numSamples % PROFILE_MAXSAMPLES;
+ g_cpuProfile_numSamples++;
+
+ total = 0;
+ for ( i=0; i<g_cpuProfile_numCounters; i++ )
+ {
+ // swap
+ localCounters[i] = BigDWord( localCounters[i] );
+
+ if ( i != g_cpuProfile_numCounters-1 )
+ {
+ g_cpuProfile_counters[i].samples[currentSample] = localCounters[i];
+ total += localCounters[i];
+ }
+ else
+ {
+ // reserved total counter
+ g_cpuProfile_counters[i].samples[currentSample] = total;
+ }
+
+ if ( newPeaks || g_cpuProfile_counters[i].peakSample < g_cpuProfile_counters[i].samples[currentSample] )
+ {
+ g_cpuProfile_counters[i].peakSample = g_cpuProfile_counters[i].samples[currentSample];
+ }
+ }
+
+ DebugCommand( "SetCpuProfileData( 0x%8.8x )\n", counters );
+
+ CpuProfile_UpdateWindow();
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_ZoomIn
+//
+//-----------------------------------------------------------------------------
+void CpuProfile_ZoomIn( int& scale, int numSteps )
+{
+ scale++;
+ if ( scale > numSteps )
+ {
+ scale = numSteps;
+ return;
+ }
+ CpuProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_ZoomOut
+//
+//-----------------------------------------------------------------------------
+void CpuProfile_ZoomOut( int& scale, int numSteps )
+{
+ scale--;
+ if ( scale < -numSteps )
+ {
+ scale = -numSteps;
+ return;
+ }
+ CpuProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_CalcScale
+//
+//-----------------------------------------------------------------------------
+float CpuProfile_CalcScale( int scale, int numSteps, float min, float max )
+{
+ float t;
+
+ // from integral scale [-numSteps..numSteps] to float scale [min..max]
+ t = ( float )( scale + numSteps )/( float )( 2*numSteps );
+ t = min + t*( max-min );
+
+ return t;
+}
+
+//-----------------------------------------------------------------------------
+// ProfileSamples_Draw
+//
+//-----------------------------------------------------------------------------
+void ProfileSamples_Draw( HDC hdc, RECT* clientRect )
+{
+ int i;
+ int j;
+ int x;
+ int y;
+ int x0;
+ int y0;
+ int w;
+ float t;
+ float scale;
+ float sampleTime;
+ char labelBuff[128];
+ HPEN hBlackPen;
+ HPEN hPenOld;
+ HPEN hGreyPen;
+ HBRUSH hColoredBrush;
+ HBRUSH hbrushOld;
+ HFONT hFontOld;
+ RECT rect;
+ int currentSample;
+ int numTicks;
+ int timingWidth;
+ int windowWidth;
+ int windowHeight;
+
+ hBlackPen = CreatePen( PS_SOLID, 1, RGB( 0,0,0 ) );
+ hGreyPen = CreatePen( PS_SOLID, 1, Sys_ColorScale( g_backgroundColor, 0.85f ) );
+ hPenOld = ( HPEN )SelectObject( hdc, hBlackPen );
+ hFontOld = SelectFont( hdc, g_hProportionalFont );
+
+ SetBkColor( hdc, g_backgroundColor );
+
+ // zoom
+ scale = CpuProfile_CalcScale( g_cpuProfile_samples_scale, PROFILE_SAMPLES_SCALESTEPS, PROFILE_SAMPLES_MINSCALE, PROFILE_SAMPLES_MAXSCALE );
+ timingWidth = ( int )( PROFILE_SAMPLES_TIMINGWIDTH*scale );
+ windowWidth = clientRect->right-clientRect->left;
+ windowHeight = clientRect->bottom-clientRect->top;
+
+ numTicks = ( windowWidth-PROFILE_SAMPLES_LABELWIDTH )/timingWidth + 1;
+ if ( numTicks < 0 )
+ numTicks = 1;
+
+ rect.left = 0;
+ rect.right = PROFILE_SAMPLES_LABELWIDTH;
+ rect.top = 0;
+ rect.bottom = PROFILE_SAMPLES_ITEMHEIGHT;
+ DrawText( hdc, "Name", -1, &rect, DT_LEFT );
+
+ // draw timing ticks
+ x = PROFILE_SAMPLES_LABELWIDTH;
+ y = 0;
+ for ( i=0; i<numTicks; i++ )
+ {
+ // tick labels
+ rect.left = x-40;
+ rect.right = x+40;
+ rect.top = y;
+ rect.bottom = y+PROFILE_SAMPLES_ITEMHEIGHT;
+ if ( !g_cpuProfile_fpsLabels )
+ sprintf( labelBuff, "%.2fms", i*( 1000.0f/60.0f ) );
+ else
+ sprintf( labelBuff, "%.2ffps", i == 0 ? 0 : 60.0f/i );
+ DrawText( hdc, labelBuff, -1, &rect, DT_CENTER );
+
+ // major ticks
+ x0 = x;
+ y0 = y + PROFILE_SAMPLES_ITEMHEIGHT;
+ SelectObject( hdc, hBlackPen );
+ MoveToEx( hdc, x0, y0, NULL );
+ LineTo( hdc, x0, y0+windowHeight );
+
+ if ( g_cpuProfile_samples_tickMarks && g_cpuProfile_samples_scale > -PROFILE_SAMPLES_SCALESTEPS )
+ {
+ // minor ticks
+ x0 = x;
+ y0 = y + PROFILE_SAMPLES_ITEMHEIGHT;
+ SelectObject( hdc, hGreyPen );
+ for ( j=0; j<PROFILE_SAMPLES_NUMMINORTICKS; j++ )
+ {
+ x0 += timingWidth/( PROFILE_SAMPLES_NUMMINORTICKS+1 );
+
+ MoveToEx( hdc, x0, y0, NULL );
+ LineTo( hdc, x0, y0+windowHeight );
+ }
+ }
+ x += timingWidth;
+ }
+
+ // seperator
+ SelectObject( hdc, hBlackPen );
+ MoveToEx( hdc, 0, PROFILE_SAMPLES_ITEMHEIGHT, NULL );
+ LineTo( hdc, windowWidth, PROFILE_SAMPLES_ITEMHEIGHT );
+
+ // draw labels
+ x = 0;
+ y = PROFILE_SAMPLES_ITEMHEIGHT;
+ for ( i=0; i<g_cpuProfile_numCounters; i++ )
+ {
+ if ( !g_cpuProfile_counters[i].label )
+ continue;
+
+ rect.left = x;
+ rect.right = x+PROFILE_SAMPLES_LABELWIDTH-PROFILE_SAMPLES_LABELGAP;
+ rect.top = y;
+ rect.bottom = y+PROFILE_SAMPLES_ITEMHEIGHT;
+ DrawText( hdc, g_cpuProfile_counters[i].label, -1, &rect, DT_VCENTER|DT_RIGHT|DT_SINGLELINE|DT_END_ELLIPSIS|DT_MODIFYSTRING );
+
+ // draw the under line
+ MoveToEx( hdc, x, y+PROFILE_SAMPLES_ITEMHEIGHT, NULL );
+ LineTo( hdc, x+PROFILE_SAMPLES_LABELWIDTH, y+PROFILE_SAMPLES_ITEMHEIGHT );
+
+ y += PROFILE_SAMPLES_ITEMHEIGHT;
+ }
+
+ // draw bars
+ SelectObject( hdc, hBlackPen );
+ x = PROFILE_SAMPLES_LABELWIDTH;
+ y = PROFILE_SAMPLES_ITEMHEIGHT;
+ currentSample = g_cpuProfile_numSamples-1;
+ if ( currentSample < 0 )
+ currentSample = 0;
+ else
+ currentSample %= PROFILE_MAXSAMPLES;
+ for ( i=0; i<g_cpuProfile_numCounters; i++ )
+ {
+ if ( !g_cpuProfile_counters[i].label )
+ continue;
+
+ hColoredBrush = CreateSolidBrush( g_cpuProfile_samples_colors ? g_cpuProfile_counters[i].color : g_backgroundColor );
+ hbrushOld = ( HBRUSH )SelectObject( hdc, hColoredBrush );
+
+ // bar - count is in us i.e. 1 major tick = 16667us
+ t = ( float )g_cpuProfile_counters[i].samples[currentSample]/( 1000000.0f/60.0f );
+ w = ( int )( t * ( float )timingWidth );
+ if ( w > windowWidth )
+ w = windowWidth;
+ x0 = x;
+ y0 = y + ( PROFILE_SAMPLES_ITEMHEIGHT-PROFILE_SAMPLES_BARHEIGHT )/2 + 1;
+ Rectangle( hdc, x0, y0, x0 + w, y0 + PROFILE_SAMPLES_BARHEIGHT );
+
+ // peak
+ t = ( float )g_cpuProfile_counters[i].peakSample/( 1000000.0f/60.0f );
+ w = ( int )( t * ( float )timingWidth );
+ if ( w > windowWidth )
+ w = windowWidth;
+ x0 = x + w;
+ y0 = y + PROFILE_SAMPLES_ITEMHEIGHT/2 + 1;
+
+ POINT points[4];
+ points[0].x = x0;
+ points[0].y = y0-4;
+ points[1].x = x0+4;
+ points[1].y = y0;
+ points[2].x = x0;
+ points[2].y = y0+4;
+ points[3].x = x0-4;
+ points[3].y = y0;
+ Polygon( hdc, points, 4 );
+
+ SelectObject( hdc, hbrushOld );
+ DeleteObject( hColoredBrush );
+
+ // draw peak times
+ sampleTime = ( float )g_cpuProfile_counters[i].peakSample/1000.0f;
+ if ( sampleTime >= 0.01F )
+ {
+ sprintf( labelBuff, "%.2f", sampleTime );
+ rect.left = x0 + 8;
+ rect.right = x0 + 8 + 100;
+ rect.top = y;
+ rect.bottom = y + PROFILE_SAMPLES_ITEMHEIGHT;
+ DrawText( hdc, labelBuff, -1, &rect, DT_VCENTER|DT_LEFT|DT_SINGLELINE );
+ }
+
+ y += PROFILE_SAMPLES_ITEMHEIGHT;
+ }
+
+ SelectObject( hdc, hFontOld );
+ SelectObject( hdc, hPenOld );
+ DeleteObject( hBlackPen );
+ DeleteObject( hGreyPen );
+}
+
+//-----------------------------------------------------------------------------
+// ProfileHistory_Draw
+//
+//-----------------------------------------------------------------------------
+void ProfileHistory_Draw( HDC hdc, RECT* clientRect )
+{
+ char labelBuff[128];
+ HPEN hBlackPen;
+ HPEN hPenOld;
+ HPEN hNullPen;
+ HPEN hGreyPen;
+ HBRUSH hColoredBrush;
+ HBRUSH hBrushOld;
+ HFONT hFontOld;
+ int currentSample;
+ int numTicks;
+ int timingHeight;
+ int windowWidth;
+ int windowHeight;
+ int x;
+ int y;
+ int y0;
+ int i;
+ int j;
+ int h;
+ int numbars;
+ RECT rect;
+ float t;
+ float scale;
+
+ hBlackPen = CreatePen( PS_SOLID, 1, RGB( 0,0,0 ) );
+ hGreyPen = CreatePen( PS_SOLID, 1, Sys_ColorScale( g_backgroundColor, 0.85f ) );
+ hNullPen = CreatePen( PS_NULL, 0, RGB( 0,0,0 ) );
+ hPenOld = ( HPEN )SelectObject( hdc, hBlackPen );
+ hFontOld = SelectFont( hdc, g_hProportionalFont );
+
+ // zoom
+ scale = CpuProfile_CalcScale( g_cpuProfile_history_scale, PROFILE_HISTORY_SCALESTEPS, PROFILE_HISTORY_MINSCALE, PROFILE_HISTORY_MAXSCALE );
+ timingHeight = ( int )( PROFILE_HISTORY_TIMINGHEIGHT*scale );
+ windowWidth = clientRect->right-clientRect->left;
+ windowHeight = clientRect->bottom-clientRect->top;
+
+ numTicks = windowHeight/timingHeight + 2;
+ if ( numTicks < 0 )
+ numTicks = 1;
+
+ SetBkColor( hdc, g_backgroundColor );
+
+ x = 0;
+ y = windowHeight;
+ for ( i=0; i<numTicks; i++ )
+ {
+ // major ticks
+ SelectObject( hdc, hBlackPen );
+ MoveToEx( hdc, 0, y, NULL );
+ LineTo( hdc, windowWidth, y );
+
+ if ( g_cpuProfile_history_tickMarks && g_cpuProfile_history_scale > -PROFILE_HISTORY_SCALESTEPS )
+ {
+ // minor ticks
+ y0 = y;
+ SelectObject( hdc, hGreyPen );
+ for ( j=0; j<PROFILE_HISTORY_NUMMINORTICKS; j++ )
+ {
+ y0 += timingHeight/( PROFILE_SAMPLES_NUMMINORTICKS+1 );
+ MoveToEx( hdc, 0, y0, NULL );
+ LineTo( hdc, windowWidth, y0 );
+ }
+ }
+
+ // tick labels
+ if ( i )
+ {
+ rect.left = windowWidth-50;
+ rect.right = windowWidth;
+ rect.top = y-20;
+ rect.bottom = y;
+ if ( !g_cpuProfile_fpsLabels )
+ sprintf( labelBuff, "%.2fms", i*( 1000.0f/60.0f ) );
+ else
+ sprintf( labelBuff, "%.2ffps", 60.0f/i );
+ DrawText( hdc, labelBuff, -1, &rect, DT_RIGHT|DT_SINGLELINE|DT_BOTTOM );
+ }
+
+ y -= timingHeight;
+ }
+
+ // vertical bars
+ if ( g_cpuProfile_numSamples )
+ {
+ SelectObject( hdc, hNullPen );
+
+ numbars = windowWidth-PROFILE_HISTORY_LABELWIDTH;
+ currentSample = g_cpuProfile_numSamples-1;
+ for ( x=numbars-1; x>=0; x-=4 )
+ {
+ // all the counters at this sample
+ y = windowHeight;
+ for ( j=0; j<g_cpuProfile_numCounters-1; j++ )
+ {
+ if ( !g_cpuProfile_counters[j].label )
+ continue;
+
+ t = ( float )g_cpuProfile_counters[j].samples[currentSample % PROFILE_MAXSAMPLES]/( 1000000.0f/60.0f );
+ h = ( int )( t * ( float )timingHeight );
+ if ( h )
+ {
+ if ( h > windowHeight )
+ h = windowHeight;
+
+ hColoredBrush = CreateSolidBrush( g_cpuProfile_history_colors ? g_cpuProfile_counters[j].color : RGB( 80,80,80 ) );
+ hBrushOld = ( HBRUSH )SelectObject( hdc, hColoredBrush );
+
+ Rectangle( hdc, x-4, y-h, x, y+1 );
+ y -= h;
+
+ SelectObject( hdc, hBrushOld );
+ DeleteObject( hColoredBrush );
+ }
+ }
+ currentSample--;
+ if ( currentSample < 0 )
+ {
+ // no data
+ break;
+ }
+ }
+ }
+
+ SelectObject( hdc, hFontOld );
+ SelectObject( hdc, hPenOld );
+ DeleteObject( hBlackPen );
+ DeleteObject( hGreyPen );
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK CpuProfile_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rect;
+ int id;
+ bool bIsSamples;
+ bool bIsHistory;
+ CREATESTRUCT *createStructPtr;
+
+ // identify window
+ id = ( int )GetWindowLong( hwnd, GWL_USERDATA+0 );
+ bIsSamples = ( id == ID_CPUPROFILE_SAMPLES );
+ bIsHistory = ( id == ID_CPUPROFILE_HISTORY );
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ // set the window identifier
+ createStructPtr = ( CREATESTRUCT* )lParam;
+ SetWindowLong( hwnd, GWL_USERDATA+0, ( LONG )createStructPtr->lpCreateParams );
+
+ // reset peaks
+ g_cpuProfile_lastPeakTime = 0;
+ return 0L;
+
+ case WM_DESTROY:
+ CpuProfile_SaveConfig();
+
+ if ( bIsSamples )
+ g_cpuProfile_hWndSamples = NULL;
+ else if ( bIsHistory )
+ g_cpuProfile_hWndHistory = NULL;
+
+ if ( VProf_GetState() == VPROF_CPU )
+ {
+ VProf_Enable( VPROF_OFF );
+ }
+ return 0L;
+
+ case WM_INITMENU:
+ if ( bIsSamples )
+ {
+ CheckMenuItem( ( HMENU )wParam, IDM_CPUPROFILE_TICKMARKS, MF_BYCOMMAND | ( g_cpuProfile_samples_tickMarks ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_CPUPROFILE_COLORS, MF_BYCOMMAND | ( g_cpuProfile_samples_colors ? MF_CHECKED : MF_UNCHECKED ) );
+ }
+ else if ( bIsHistory )
+ {
+ CheckMenuItem( ( HMENU )wParam, IDM_CPUPROFILE_TICKMARKS, MF_BYCOMMAND | ( g_cpuProfile_history_tickMarks ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_CPUPROFILE_COLORS, MF_BYCOMMAND | ( g_cpuProfile_history_colors ? MF_CHECKED : MF_UNCHECKED ) );
+ }
+ CheckMenuItem( ( HMENU )wParam, IDM_CPUPROFILE_FPSLABELS, MF_BYCOMMAND | ( g_cpuProfile_fpsLabels ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_CPUPROFILE_ENABLE, MF_BYCOMMAND | ( VProf_GetState() == VPROF_CPU ? MF_CHECKED : MF_UNCHECKED ) );
+ return 0L;
+
+ case WM_PAINT:
+ GetClientRect( hwnd, &rect );
+ hdc = BeginPaint( hwnd, &ps );
+ if ( bIsSamples )
+ ProfileSamples_Draw( hdc, &rect );
+ else if ( bIsHistory )
+ ProfileHistory_Draw( hdc, &rect );
+ EndPaint( hwnd, &ps );
+ return 0L;
+
+ case WM_SIZE:
+ // force a redraw
+ CpuProfile_UpdateWindow();
+ return 0L;
+
+ case WM_KEYDOWN:
+ switch ( wParam )
+ {
+ case VK_INSERT:
+ if ( bIsSamples )
+ CpuProfile_ZoomIn( g_cpuProfile_samples_scale, PROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ CpuProfile_ZoomIn( g_cpuProfile_history_scale, PROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+
+ case VK_DELETE:
+ if ( bIsSamples )
+ CpuProfile_ZoomOut( g_cpuProfile_samples_scale, PROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ CpuProfile_ZoomOut( g_cpuProfile_history_scale, PROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_CPUPROFILE_TICKMARKS:
+ if ( bIsSamples )
+ g_cpuProfile_samples_tickMarks ^= 1;
+ else if ( bIsHistory )
+ g_cpuProfile_history_tickMarks ^= 1;
+ CpuProfile_UpdateWindow();
+ return 0L;
+
+ case IDM_CPUPROFILE_COLORS:
+ if ( bIsSamples )
+ g_cpuProfile_samples_colors ^= 1;
+ else if ( bIsHistory )
+ g_cpuProfile_history_colors ^= 1;
+ CpuProfile_UpdateWindow();
+ return 0L;
+
+ case IDM_CPUPROFILE_FPSLABELS:
+ g_cpuProfile_fpsLabels ^= 1;
+ CpuProfile_UpdateWindow();
+ return 0L;
+
+ case IDM_CPUPROFILE_ZOOMIN:
+ if ( bIsSamples )
+ CpuProfile_ZoomIn( g_cpuProfile_samples_scale, PROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ CpuProfile_ZoomIn( g_cpuProfile_history_scale, PROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+
+ case IDM_CPUPROFILE_ZOOMOUT:
+ if ( bIsSamples )
+ CpuProfile_ZoomOut( g_cpuProfile_samples_scale, PROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ CpuProfile_ZoomOut( g_cpuProfile_history_scale, PROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+
+ case IDM_CPUPROFILE_ENABLE:
+ bool bEnable = ( VProf_GetState() == VPROF_CPU );
+ bEnable ^= 1;
+ if ( !bEnable )
+ VProf_Enable( VPROF_OFF );
+ else
+ VProf_Enable( VPROF_CPU );
+ CpuProfile_SetTitle();
+ return 0L;
+ }
+ break;
+ }
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfileHistory_Open
+//
+//-----------------------------------------------------------------------------
+void CpuProfileHistory_Open()
+{
+ HWND hWnd;
+
+ if ( g_cpuProfile_hWndHistory )
+ {
+ // only one profile instance
+ if ( IsIconic( g_cpuProfile_hWndHistory ) )
+ ShowWindow( g_cpuProfile_hWndHistory, SW_RESTORE );
+ SetForegroundWindow( g_cpuProfile_hWndHistory );
+ return;
+ }
+
+ if ( VProf_GetState() == VPROF_OFF )
+ {
+ VProf_Enable( VPROF_CPU );
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "CPUPROFILEHISTORYCLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 600,
+ 500,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ ( void* )ID_CPUPROFILE_HISTORY );
+ g_cpuProfile_hWndHistory = hWnd;
+
+ CpuProfile_SetTitle();
+
+ if ( g_cpuProfile_historyWindowRect.right && g_cpuProfile_historyWindowRect.bottom )
+ MoveWindow( g_cpuProfile_hWndHistory, g_cpuProfile_historyWindowRect.left, g_cpuProfile_historyWindowRect.top, g_cpuProfile_historyWindowRect.right-g_cpuProfile_historyWindowRect.left, g_cpuProfile_historyWindowRect.bottom-g_cpuProfile_historyWindowRect.top, FALSE );
+ ShowWindow( g_cpuProfile_hWndHistory, SHOW_OPENWINDOW );
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfileSamples_Open
+//
+//-----------------------------------------------------------------------------
+void CpuProfileSamples_Open()
+{
+ HWND hWnd;
+
+ if ( g_cpuProfile_hWndSamples )
+ {
+ // only one profile instance
+ if ( IsIconic( g_cpuProfile_hWndSamples ) )
+ ShowWindow( g_cpuProfile_hWndSamples, SW_RESTORE );
+ SetForegroundWindow( g_cpuProfile_hWndSamples );
+ return;
+ }
+
+ if ( VProf_GetState() == VPROF_OFF )
+ {
+ VProf_Enable( VPROF_CPU );
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "CPUPROFILESAMPLESCLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 600,
+ 500,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ ( void* )ID_CPUPROFILE_SAMPLES );
+ g_cpuProfile_hWndSamples = hWnd;
+
+ CpuProfile_SetTitle();
+
+ if ( g_cpuProfile_samplesWindowRect.right && g_cpuProfile_samplesWindowRect.bottom )
+ MoveWindow( g_cpuProfile_hWndSamples, g_cpuProfile_samplesWindowRect.left, g_cpuProfile_samplesWindowRect.top, g_cpuProfile_samplesWindowRect.right-g_cpuProfile_samplesWindowRect.left, g_cpuProfile_samplesWindowRect.bottom-g_cpuProfile_samplesWindowRect.top, FALSE );
+ ShowWindow( g_cpuProfile_hWndSamples, SHOW_OPENWINDOW );
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_Clear
+//
+//-----------------------------------------------------------------------------
+void CpuProfile_Clear()
+{
+ // clear counters and history
+ g_cpuProfile_numCounters = 0;
+ g_cpuProfile_numSamples = 0;
+
+ CpuProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// CpuProfile_Init
+//
+//-----------------------------------------------------------------------------
+bool CpuProfile_Init()
+{
+ WNDCLASS wndclass;
+
+ // set up our window class
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = CpuProfile_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_CPUPROFILE );
+ wndclass.lpszClassName = "CPUPROFILESAMPLESCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ // set up our window class
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = CpuProfile_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_CPUPROFILE );
+ wndclass.lpszClassName = "CPUPROFILEHISTORYCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ CpuProfile_LoadConfig();
+
+ return true;
+}
diff --git a/utils/xbox/vxconsole/exclude_paths.cpp b/utils/xbox/vxconsole/exclude_paths.cpp
new file mode 100644
index 0000000..668a835
--- /dev/null
+++ b/utils/xbox/vxconsole/exclude_paths.cpp
@@ -0,0 +1,1134 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// EXCLUDE_PATHS.CPP
+//
+// DVD Exclude paths.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define UM_CHECKSTATECHANGE (WM_USER + 100)
+#define UM_FIRSTTIMEPOPULATE (WM_USER + 101)
+
+#define MAX_TREE_DEPTH 32
+#define ROOT_NAME "Xbox:\\"
+#define EXCLUDEPATHS_FILE "xbox_exclude_paths.txt"
+
+// known shipping 360 gamedirs
+struct GameName_t
+{
+ const char *pName;
+ bool bIsModPath;
+};
+
+struct GamePath_t
+{
+ CUtlString pathName;
+ bool bIsModPath;
+};
+
+GameName_t g_GameNames[] =
+{
+ { "bin", false },
+ { "platform", false },
+ { "tf", true },
+ { "portal", true },
+ { "hl2", true },
+ { "episodic", true },
+ { "ep2", true }
+};
+
+CUtlVector< CUtlString > g_ExcludePaths;
+BOOL g_bLinkGameDirs;
+
+inline bool PathLessThan( GamePath_t const &lhs, GamePath_t const &rhs )
+{
+ if ( lhs.bIsModPath != rhs.bIsModPath )
+ {
+ // sort mod paths to the bottom
+ return ( lhs.bIsModPath == false );
+ }
+
+ return ( stricmp( lhs.pathName.String(), rhs.pathName.String() ) < 0 );
+}
+CUtlRBTree< GamePath_t > g_PathTable( 0, 0, PathLessThan );
+
+//-----------------------------------------------------------------------------
+// Add string to TreeView at specified level. Assumes an inorder insert.
+// A node (at specified depth) must be inserted before it's children.
+//-----------------------------------------------------------------------------
+static HTREEITEM AddItemToTree( HWND hWndTree, LPSTR lpszItem, int nLevel, bool bIsModPath )
+{
+ TVITEM tvi = { 0 };
+ TVINSERTSTRUCT tvins = { 0 };
+ static HTREEITEM s_hPrevItems[MAX_TREE_DEPTH];
+
+ if ( nLevel < 0 || nLevel >= MAX_TREE_DEPTH )
+ {
+ Assert( 0 );
+ return NULL;
+ }
+
+ HTREEITEM hParent;
+ HTREEITEM hPrev;
+ if ( !nLevel )
+ {
+ // one root item only, reset
+ for ( int i = 0; i < ARRAYSIZE( s_hPrevItems ); i++ )
+ {
+ s_hPrevItems[i] = NULL;
+ }
+ hParent = TVI_ROOT;
+ hPrev = (HTREEITEM)TVI_FIRST;
+ }
+ else
+ {
+ hParent = s_hPrevItems[nLevel-1];
+ hPrev = s_hPrevItems[nLevel];
+ if ( !hParent )
+ {
+ // parent should have been setup
+ Assert( 0 );
+ return NULL;
+ }
+ if ( !hPrev )
+ {
+ hPrev = TVI_FIRST;
+ }
+ }
+
+ tvi.mask = TVIF_TEXT | TVIF_PARAM;
+ tvi.pszText = lpszItem;
+ tvi.cchTextMax = sizeof(tvi.pszText)/sizeof(tvi.pszText[0]);
+ tvi.lParam = (LPARAM)MAKELONG( nLevel, bIsModPath );
+
+ tvins.item = tvi;
+ tvins.hParent = hParent;
+ tvins.hInsertAfter = hPrev;
+
+ // Add the item to the tree-view control.
+ hPrev = TreeView_InsertItem( hWndTree, &tvins );
+ s_hPrevItems[nLevel] = hPrev;
+
+ if ( nLevel > 0 )
+ {
+ // set a back link to its parent
+ tvi.mask = TVIF_HANDLE;
+ tvi.hItem = TreeView_GetParent( hWndTree, hPrev );
+ TreeView_SetItem( hWndTree, &tvi );
+ }
+
+ return hPrev;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Get list of files from current path that match pattern
+//-----------------------------------------------------------------------------
+static int GetFileList( const char* pDirPath, const char* pPattern, CUtlVector< CUtlString > &fileList )
+{
+ char sourcePath[MAX_PATH];
+ char fullPath[MAX_PATH];
+ bool bFindDirs;
+
+ fileList.Purge();
+
+ strcpy( sourcePath, pDirPath );
+ int len = (int)strlen( sourcePath );
+ if ( !len )
+ {
+ strcpy( sourcePath, ".\\" );
+ }
+ else if ( sourcePath[len-1] != '\\' )
+ {
+ sourcePath[len] = '\\';
+ sourcePath[len+1] = '\0';
+ }
+
+ strcpy( fullPath, sourcePath );
+ if ( pPattern[0] == '\\' && pPattern[1] == '\0' )
+ {
+ // find directories only
+ bFindDirs = true;
+ strcat( fullPath, "*" );
+ }
+ else
+ {
+ // find files, use provided pattern
+ bFindDirs = false;
+ strcat( fullPath, pPattern );
+ }
+
+ struct _finddata_t findData;
+ intptr_t h = _findfirst( fullPath, &findData );
+ if ( h == -1 )
+ {
+ return 0;
+ }
+
+ do
+ {
+ // dos attribute complexities i.e. _A_NORMAL is 0
+ if ( bFindDirs )
+ {
+ // skip non dirs
+ if ( !( findData.attrib & _A_SUBDIR ) )
+ continue;
+ }
+ else
+ {
+ // skip dirs
+ if ( findData.attrib & _A_SUBDIR )
+ continue;
+ }
+
+ if ( !stricmp( findData.name, "." ) )
+ continue;
+
+ if ( !stricmp( findData.name, ".." ) )
+ continue;
+
+ char fileName[MAX_PATH];
+ strcpy( fileName, sourcePath );
+ strcat( fileName, findData.name );
+
+ int j = fileList.AddToTail();
+ fileList[j].Set( fileName );
+ }
+ while ( !_findnext( h, &findData ) );
+
+ _findclose( h );
+
+ return fileList.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Recursively determine directory tree
+//-----------------------------------------------------------------------------
+static void RecurseFileTree_r( const char *pBasePath, const char *pDirPath, int depth, CUtlVector< CUtlString > &dirList, bool bIsModPath )
+{
+ if ( depth >= 2 )
+ {
+ // too much unecessary detail
+ return;
+ }
+
+ // ignore path roots, only interested in subdirs
+ const char *pSubName = pDirPath + strlen( pBasePath );
+ if ( pSubName[0] )
+ {
+ GamePath_t gamePath;
+ gamePath.pathName = pSubName;
+ gamePath.bIsModPath = bIsModPath;
+
+ int iIndex = g_PathTable.Find( gamePath );
+ if ( iIndex == g_PathTable.InvalidIndex() )
+ {
+ g_PathTable.Insert( gamePath );
+ }
+ }
+
+ // recurse from source directory, get directories only
+ CUtlVector< CUtlString > fileList;
+ int dirCount = GetFileList( pDirPath, "\\", fileList );
+ if ( !dirCount )
+ {
+ // add directory name to search tree
+ int j = dirList.AddToTail();
+ dirList[j].Set( pDirPath );
+ return;
+ }
+
+ for ( int i=0; i<dirCount; i++ )
+ {
+ // form new path name, recurse into
+ RecurseFileTree_r( pBasePath, fileList[i].String(), depth+1, dirList, bIsModPath );
+ }
+
+ int j = dirList.AddToTail();
+ dirList[j].Set( pDirPath );
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_SetCheckState_r
+//
+// Propogate the check state to all children
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_SetCheckState_r( HWND hWndTree, HTREEITEM hTree, int depth, int checkState )
+{
+ if ( !hTree )
+ {
+ return;
+ }
+
+ TreeView_SetCheckState( hWndTree, hTree, ( checkState == 1 ) );
+
+ TVITEM tvi = { 0 };
+ tvi.mask = TVIF_HANDLE | TVIF_CHILDREN;
+ tvi.hItem = hTree;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hTree );
+ if ( hChild )
+ {
+ ExcludePathsDlg_SetCheckState_r( hWndTree, hChild, depth+1, checkState );
+ }
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ if ( !depth )
+ {
+ // only iterate siblings of the parent's child
+ return;
+ }
+
+ HTREEITEM hSibling = hTree;
+ while ( 1 )
+ {
+ hSibling = TreeView_GetNextSibling( hWndTree, hSibling );
+ if ( !hSibling )
+ {
+ return;
+ }
+
+ TreeView_SetCheckState( hWndTree, hSibling, ( checkState == 1 ) );
+
+ tvi.hItem = hSibling;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hSibling );
+ if ( hChild )
+ {
+ ExcludePathsDlg_SetCheckState_r( hWndTree, hChild, depth+1, checkState );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_SetCheckStateLinked_r
+//
+// Propogate the check state to all "mod path" children that match the specified name.
+// A NULL name matches all.
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_SetCheckStateLinked_r( HWND hWndTree, HTREEITEM hTree, int depth, int checkState, const char *pName )
+{
+ if ( !hTree )
+ {
+ return;
+ }
+
+ char szNodeName[MAX_PATH];
+ TVITEM tvi = { 0 };
+ tvi.mask = TVIF_HANDLE | TVIF_CHILDREN | TVIF_TEXT | TVIF_PARAM;
+ tvi.hItem = hTree;
+ tvi.pszText = szNodeName;
+ tvi.cchTextMax = sizeof( szNodeName );
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ bool bIsModPath = HIWORD( tvi.lParam ) != 0;
+ if ( bIsModPath && ( !pName || !V_stricmp( szNodeName, pName ) ) )
+ {
+ TreeView_SetCheckState( hWndTree, hTree, ( checkState == 1 ) );
+ }
+
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hTree );
+ if ( hChild )
+ {
+ ExcludePathsDlg_SetCheckStateLinked_r( hWndTree, hChild, depth+1, checkState, pName );
+ }
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ if ( !depth )
+ {
+ // only iterate siblings of the parent's child
+ return;
+ }
+
+ HTREEITEM hSibling = hTree;
+ while ( 1 )
+ {
+ hSibling = TreeView_GetNextSibling( hWndTree, hSibling );
+ if ( !hSibling )
+ {
+ return;
+ }
+
+ tvi.hItem = hSibling;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ bool bIsModPath = HIWORD( tvi.lParam ) != 0;
+ if ( bIsModPath && ( !pName || !V_stricmp( szNodeName, pName ) ) )
+ {
+ TreeView_SetCheckState( hWndTree, hSibling, ( checkState == 1 ) );
+ }
+
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hSibling );
+ if ( hChild )
+ {
+ ExcludePathsDlg_SetCheckStateLinked_r( hWndTree, hChild, depth+1, checkState, pName );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_GetCheckState_r
+//
+// Caller invokes at node. Returns with state set.
+// State 0: unchecked, 1: checked, -1:unknown.
+// Returns true if All children match, false otherwise.
+//-----------------------------------------------------------------------------
+bool ExcludePathsDlg_GetCheckState_r( HWND hWndTree, HTREEITEM hTree, int depth, int *pCheckState )
+{
+ int checkState;
+
+ checkState = TreeView_GetCheckState( hWndTree, hTree );
+ if ( *pCheckState == -1 )
+ {
+ *pCheckState = checkState;
+ }
+ else if ( *pCheckState != checkState )
+ {
+ // disparate state, no need to recurse
+ return false;
+ }
+
+ TVITEM tvi = { 0 };
+ tvi.mask = TVIF_HANDLE | TVIF_CHILDREN;
+ tvi.hItem = hTree;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hTree );
+ if ( hChild )
+ {
+ if ( !ExcludePathsDlg_GetCheckState_r( hWndTree, hChild, depth+1, pCheckState ) )
+ {
+ return false;
+ }
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ if ( !depth )
+ {
+ // only iterate siblings of the parent's child
+ return true;
+ }
+
+ HTREEITEM hSibling = hTree;
+ while ( 1 )
+ {
+ hSibling = TreeView_GetNextSibling( hWndTree, hSibling );
+ if ( !hSibling )
+ {
+ break;
+ }
+
+ checkState = TreeView_GetCheckState( hWndTree, hSibling );
+ if ( *pCheckState != checkState )
+ {
+ // disparate state, no need to recurse
+ return false;
+ }
+
+ tvi.hItem = hSibling;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hSibling );
+ if ( hChild )
+ {
+ if ( !ExcludePathsDlg_GetCheckState_r( hWndTree, hChild, depth+1, pCheckState ) )
+ {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_Expand_r
+//
+// MaxDepth >= 0, Expand/Collapse up to specified depth.
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_Expand_r( HWND hWndTree, HTREEITEM hTree, int depth, int maxDepth, bool bExpand )
+{
+ if ( !hTree )
+ {
+ return;
+ }
+
+ if ( maxDepth >= 0 && depth >= maxDepth )
+ {
+ return;
+ }
+
+ int flags;
+ if ( bExpand )
+ flags = TVE_EXPAND;
+ else
+ flags = TVE_COLLAPSE;
+
+ TVITEM tvi = { 0 };
+ tvi.mask = TVIF_HANDLE | TVIF_CHILDREN;
+ tvi.hItem = hTree;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ if ( tvi.cChildren )
+ {
+ TreeView_Expand( hWndTree, hTree, flags );
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hTree );
+ if ( hChild )
+ {
+ ExcludePathsDlg_Expand_r( hWndTree, hChild, depth+1, maxDepth, bExpand );
+ }
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ if ( !depth )
+ {
+ // only iterate siblings of the parent's child
+ return;
+ }
+
+ HTREEITEM hSibling = hTree;
+ while ( 1 )
+ {
+ hSibling = TreeView_GetNextSibling( hWndTree, hSibling );
+ if ( !hSibling )
+ {
+ return;
+ }
+
+ tvi.hItem = hSibling;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ if ( tvi.cChildren )
+ {
+ TreeView_Expand( hWndTree, hSibling, flags );
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hSibling );
+ if ( hChild )
+ {
+ ExcludePathsDlg_Expand_r( hWndTree, hChild, depth+1, maxDepth, bExpand );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_ExpandToShowState_r
+//
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_ExpandToShowState_r( HWND hWndTree, HTREEITEM hTree, int depth )
+{
+ if ( !hTree )
+ {
+ return;
+ }
+
+ TVITEM tvi = { 0 };
+ tvi.mask = TVIF_HANDLE | TVIF_CHILDREN;
+ tvi.hItem = hTree;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ int checkState = -1;
+ bool bStateIsSame = ExcludePathsDlg_GetCheckState_r( hWndTree, hTree, 0, &checkState );
+
+ if ( tvi.cChildren && !bStateIsSame )
+ {
+ TreeView_Expand( hWndTree, hTree, TVE_EXPAND );
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hTree );
+ if ( hChild )
+ {
+ ExcludePathsDlg_ExpandToShowState_r( hWndTree, hChild, depth+1 );
+ }
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ if ( !depth )
+ {
+ // only iterate siblings of the parent's child
+ return;
+ }
+
+ HTREEITEM hSibling = hTree;
+ while ( 1 )
+ {
+ hSibling = TreeView_GetNextSibling( hWndTree, hSibling );
+ if ( !hSibling )
+ {
+ return;
+ }
+
+ tvi.hItem = hSibling;
+ if ( TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ int checkState = -1;
+ bool bStateIsSame = ExcludePathsDlg_GetCheckState_r( hWndTree, hSibling, 0, &checkState );
+
+ if ( tvi.cChildren && !bStateIsSame )
+ {
+ TreeView_Expand( hWndTree, hSibling, TVE_EXPAND );
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hSibling );
+ if ( hChild )
+ {
+ ExcludePathsDlg_ExpandToShowState_r( hWndTree, hChild, depth+1 );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_Find_r
+//
+//-----------------------------------------------------------------------------
+HTREEITEM ExcludePathsDlg_Find_r( HWND hWndTree, HTREEITEM hTree, int depth, const char *pBasePath, const char *pFindPath )
+{
+ TVITEM tvi = { 0 };
+ char szName[MAX_PATH];
+ tvi.mask = TVIF_HANDLE | TVIF_CHILDREN | TVIF_TEXT;
+ tvi.hItem = hTree;
+ tvi.pszText = szName;
+ tvi.cchTextMax = sizeof( szName );
+ if ( !TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ return NULL;
+ }
+
+ char szPath[MAX_PATH];
+ V_ComposeFileName( pBasePath, szName, szPath, sizeof( szPath ) );
+ if ( !stricmp( szPath, pFindPath ) )
+ {
+ return hTree;
+ }
+
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hTree );
+ if ( hChild )
+ {
+ HTREEITEM hFindTree = ExcludePathsDlg_Find_r( hWndTree, hChild, depth+1, szPath, pFindPath );
+ if ( hFindTree )
+ {
+ return hFindTree;
+ }
+ }
+ }
+
+ if ( !depth )
+ {
+ // only iterate siblings of the parent's child
+ return NULL;
+ }
+
+ // iterate siblings
+ HTREEITEM hSibling = hTree;
+ while ( 1 )
+ {
+ hSibling = TreeView_GetNextSibling( hWndTree, hSibling );
+ if ( !hSibling )
+ {
+ break;
+ }
+
+ tvi.hItem = hSibling;
+ if ( !TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ break;
+ }
+
+ V_ComposeFileName( pBasePath, szName, szPath, sizeof( szPath ) );
+ if ( !stricmp( szPath, pFindPath ) )
+ {
+ return hSibling;
+ }
+
+ if ( tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hSibling );
+ if ( hChild )
+ {
+ HTREEITEM hFindTree = ExcludePathsDlg_Find_r( hWndTree, hChild, depth+1, szPath, pFindPath );
+ if ( hFindTree )
+ {
+ return hFindTree;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_BuildExcludeList_r
+//
+// An exclude path represents the path head, and thus does not need to iterate its children
+// if they are deemed to the same exclusion state.
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_BuildExcludeList_r( HWND hWndTree, HTREEITEM hTree, int depth, const char *pPath )
+{
+ int checkState = -1;
+ bool bStateIsSame = ExcludePathsDlg_GetCheckState_r( hWndTree, hTree, 0, &checkState );
+ if ( checkState == -1 )
+ {
+ return;
+ }
+
+ TVITEM tvi = { 0 };
+ char szName[MAX_PATH];
+ tvi.mask = TVIF_HANDLE | TVIF_CHILDREN | TVIF_TEXT;
+ tvi.hItem = hTree;
+ tvi.pszText = szName;
+ tvi.cchTextMax = sizeof( szName );
+ if ( !TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ return;
+ }
+
+ char szPath[MAX_PATH];
+ V_ComposeFileName( pPath, szName, szPath, sizeof( szPath ) );
+
+ if ( checkState == 1 && ( bStateIsSame || !tvi.cChildren ) )
+ {
+ // add to exclude list
+ g_ExcludePaths.AddToTail( szPath );
+ }
+
+ if ( !bStateIsSame && tvi.cChildren )
+ {
+ // mixed states, must recurse to resolve
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hTree );
+ if ( hChild )
+ {
+ ExcludePathsDlg_BuildExcludeList_r( hWndTree, hChild, depth+1, szPath );
+ }
+ }
+
+ if ( !depth )
+ {
+ // only iterate siblings of the parent's child
+ return;
+ }
+
+ // iterate siblings
+ HTREEITEM hSibling = hTree;
+ while ( 1 )
+ {
+ hSibling = TreeView_GetNextSibling( hWndTree, hSibling );
+ if ( !hSibling )
+ {
+ break;
+ }
+
+ checkState = -1;
+ bStateIsSame = ExcludePathsDlg_GetCheckState_r( hWndTree, hSibling, 0, &checkState );
+ if ( checkState == -1 )
+ {
+ break;
+ }
+
+ tvi.hItem = hSibling;
+ if ( !TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ break;
+ }
+
+ V_ComposeFileName( pPath, szName, szPath, sizeof( szPath ) );
+
+ if ( checkState == 1 && ( bStateIsSame || !tvi.cChildren ) )
+ {
+ // add to exclude list
+ g_ExcludePaths.AddToTail( szPath );
+ }
+
+ if ( !bStateIsSame && tvi.cChildren )
+ {
+ HTREEITEM hChild = TreeView_GetChild( hWndTree, hSibling );
+ if ( hChild )
+ {
+ ExcludePathsDlg_BuildExcludeList_r( hWndTree, hChild, depth+1, szPath );
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_SaveChanges
+//
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_SaveChanges( HWND hWnd )
+{
+ g_ExcludePaths.Purge();
+ HWND hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE );
+ ExcludePathsDlg_BuildExcludeList_r( hWndTree, TreeView_GetRoot( hWndTree ), 0, "" );
+
+ char szPath[MAX_PATH];
+ V_ComposeFileName( g_localPath, EXCLUDEPATHS_FILE, szPath, sizeof( szPath ) );
+
+ if ( !g_ExcludePaths.Count() )
+ {
+ // no exclude paths
+ unlink( szPath );
+ }
+ else
+ {
+ FILE *fp = fopen( szPath, "wt" );
+ if ( !fp )
+ {
+ Sys_MessageBox( "Error", "Could not open '%s' for writing\n", szPath );
+ return;
+ }
+
+ fprintf( fp, "// Auto-Generated by VXConsole - DO NOT MODIFY!\n" );
+ for ( int i = 0; i < g_ExcludePaths.Count(); i++ )
+ {
+ // strip expected root path
+ const char *pPath = g_ExcludePaths[i].String();
+ pPath += strlen( ROOT_NAME );
+ if ( !pPath[0] )
+ {
+ // special code for root
+ fprintf( fp, "*\n" );
+ break;
+ }
+ fprintf( fp, "\"\\%s\"\n", pPath );
+ }
+ fclose( fp );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_Populate
+//
+// Generate a path table.
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_Populate( HWND hWnd, bool bRefresh )
+{
+ struct GamePath_t
+ {
+ CUtlString pathName;
+ bool bIsModPath;
+ };
+
+ CUtlVector< GamePath_t > gamePaths;
+
+ // can skip the time consuming directory scan, unless forced
+ if ( bRefresh || !g_PathTable.Count() )
+ {
+ g_PathTable.Purge();
+
+ for ( int i = 0; i < ARRAYSIZE( g_GameNames ); i++ )
+ {
+ char szTargetPath[MAX_PATH];
+ V_strncpy( szTargetPath, g_localPath, sizeof( szTargetPath ) );
+ V_AppendSlash( szTargetPath, sizeof( szTargetPath ) );
+ V_strncat( szTargetPath, g_GameNames[i].pName, sizeof( szTargetPath ) );
+
+ GamePath_t gamePath;
+ gamePath.pathName = szTargetPath;
+ gamePath.bIsModPath = g_GameNames[i].bIsModPath;
+ gamePaths.AddToTail( gamePath );
+ }
+
+ // iterate all game paths
+ for ( int i = 0; i < gamePaths.Count(); i++ )
+ {
+ CUtlVector< CUtlString > dirList;
+ RecurseFileTree_r( g_localPath, gamePaths[i].pathName.String(), 0, dirList, gamePaths[i].bIsModPath );
+ }
+ }
+
+ // reset the tree
+ HWND hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE );
+ TreeView_DeleteAllItems( hWndTree );
+
+ // reset and add root
+ // only the root is at depth 0
+ AddItemToTree( hWndTree, ROOT_NAME, 0, false );
+
+ // build the tree view
+ for ( int iIndex = g_PathTable.FirstInorder(); iIndex != g_PathTable.InvalidIndex(); iIndex = g_PathTable.NextInorder( iIndex ) )
+ {
+ // due to sorting, number of slashes is depth
+ const char *pString = g_PathTable[iIndex].pathName.String();
+ int depth = 0;
+ for ( int j = 0; j < (int)strlen( pString ); j++ )
+ {
+ if ( pString[j] == '\\' )
+ {
+ depth++;
+ }
+ }
+ if ( !depth )
+ {
+ depth = 1;
+ }
+
+ char szPath[MAX_PATH];
+ V_FileBase( pString, szPath, sizeof( szPath ) );
+ AddItemToTree( hWndTree, szPath, depth, g_PathTable[iIndex].bIsModPath );
+ }
+
+ HTREEITEM hTreeRoot = TreeView_GetRoot( hWndTree );
+ for ( int i = 0; i < g_ExcludePaths.Count(); i++ )
+ {
+ HTREEITEM hTree = ExcludePathsDlg_Find_r( hWndTree, hTreeRoot, 0, "", g_ExcludePaths[i].String() );
+ if ( hTree )
+ {
+ ExcludePathsDlg_SetCheckState_r( hWndTree, hTree, 0, true );
+ }
+ }
+
+ // expand the root node to show state
+ ExcludePathsDlg_ExpandToShowState_r( hWndTree, hTreeRoot, 0 );
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_Setup
+//
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_Setup( HWND hWnd )
+{
+ TreeView_SetBkColor( GetDlgItem( hWnd, IDC_PATHS_TREE ), g_backgroundColor );
+
+ CheckDlgButton( hWnd, IDC_PATHS_LINKGAMEDIRS, g_bLinkGameDirs ? BST_CHECKED : BST_UNCHECKED );
+
+ // read the exisiting exclude paths
+ g_ExcludePaths.Purge();
+ char szFilename[MAX_PATH];
+ V_ComposeFileName( g_localPath, EXCLUDEPATHS_FILE, szFilename, sizeof( szFilename ) );
+ if ( Sys_Exists( szFilename ) )
+ {
+ Sys_LoadScriptFile( szFilename );
+ while ( 1 )
+ {
+ char *pToken = Sys_GetToken( true );
+ if ( !pToken || !pToken[0] )
+ {
+ break;
+ }
+ Sys_StripQuotesFromToken( pToken );
+ if ( !stricmp( pToken, "*" ) )
+ {
+ pToken = "";
+ }
+ else if ( pToken[0] == '\\' )
+ {
+ pToken++;
+ }
+
+ char szPath[MAX_PATH];
+ V_ComposeFileName( ROOT_NAME, pToken, szPath, sizeof( szPath ) );
+ V_FixSlashes( szPath );
+
+ g_ExcludePaths.AddToTail( szPath );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_Proc
+//
+//-----------------------------------------------------------------------------
+BOOL CALLBACK ExcludePathsDlg_Proc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ HWND hWndTree;
+ LPNMHDR lpnmh;
+ HTREEITEM hTree;
+ HTREEITEM hTreeRoot;
+ int checkState;
+ static bool s_bAllowPopulate = 0;
+
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ ExcludePathsDlg_Setup( hWnd );
+ s_bAllowPopulate = true;
+ return TRUE;
+
+ case WM_NOTIFY:
+ lpnmh = (LPNMHDR)lParam;
+ if ( ( lpnmh->code == NM_CLICK ) && ( lpnmh->idFrom == IDC_PATHS_TREE ) )
+ {
+ TVHITTESTINFO ht = {0};
+ DWORD dwpos = GetMessagePos();
+ ht.pt.x = GET_X_LPARAM( dwpos );
+ ht.pt.y = GET_Y_LPARAM( dwpos );
+ MapWindowPoints( HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1 );
+ TreeView_HitTest( lpnmh->hwndFrom, &ht );
+ if ( ht.flags & TVHT_ONITEMSTATEICON )
+ {
+ PostMessage( hWnd, UM_CHECKSTATECHANGE, 0, (LPARAM)ht.hItem );
+ }
+ }
+ break;
+
+ case UM_CHECKSTATECHANGE:
+ hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE );
+ hTreeRoot = TreeView_GetRoot( hWndTree );
+ hTree = (HTREEITEM)lParam;
+ checkState = TreeView_GetCheckState( hWndTree, hTree );
+ if ( checkState != -1 )
+ {
+ TVITEM tvi = { 0 };
+ char szName[MAX_PATH];
+ tvi.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
+ tvi.hItem = hTree;
+ tvi.pszText = szName;
+ tvi.cchTextMax = sizeof( szName );
+ if ( !TreeView_GetItem( hWndTree, &tvi ) )
+ {
+ break;
+ }
+ int nDepth = LOWORD( tvi.lParam );
+ bool bIsModPath = HIWORD( tvi.lParam ) != 0;
+
+ if ( g_bLinkGameDirs && bIsModPath )
+ {
+ // a mod path root is at depth 1
+ // a child of a mod path (depth > 1), will match all other children in mod paths
+ // a mod path (depth = 1) will match all other modpaths
+ ExcludePathsDlg_SetCheckStateLinked_r( hWndTree, hTreeRoot, 0, checkState, nDepth == 1 ? NULL : szName );
+ }
+ else
+ {
+ ExcludePathsDlg_SetCheckState_r( hWndTree, hTree, 0, checkState );
+ }
+ }
+ break;
+
+ case WM_PAINT:
+ if ( s_bAllowPopulate )
+ {
+ // unfortunate, but tree view needs to paint first before its state can be set
+ // related to checkbox style which doesn't manifest until after WM_INITDIALOG
+ // stall the initial population until after the first paint
+ s_bAllowPopulate = false;
+ PostMessage( hWnd, UM_FIRSTTIMEPOPULATE, 0, 0 );
+ }
+ break;
+
+ case UM_FIRSTTIMEPOPULATE:
+ ExcludePathsDlg_Populate( hWnd, false );
+ break;
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_OK:
+ ExcludePathsDlg_SaveChanges( hWnd );
+ EndDialog( hWnd, wParam );
+ return TRUE;
+
+ case IDC_PATHS_RESCAN:
+ ExcludePathsDlg_Populate( hWnd, true );
+ return TRUE;
+
+ case IDC_PATHS_EXPAND:
+ // expand from root
+ hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE );
+ ExcludePathsDlg_Expand_r( hWndTree, TreeView_GetRoot( hWndTree ), 0, -1, true );
+ return TRUE;
+
+ case IDC_PATHS_COLLAPSE:
+ // collapse from root
+ hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE );
+ ExcludePathsDlg_Expand_r( hWndTree, TreeView_GetRoot( hWndTree ), 0, -1, false );
+ return TRUE;
+
+ case IDC_PATHS_LINKGAMEDIRS:
+ g_bLinkGameDirs = IsDlgButtonChecked( hWnd, IDC_PATHS_LINKGAMEDIRS );
+ return TRUE;
+
+ case IDCANCEL:
+ case IDC_CANCEL:
+ EndDialog( hWnd, wParam );
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_LoadConfig()
+{
+ // get our config
+ Sys_GetRegistryInteger( "ExcludePaths_LinkGameDirs", true, g_bLinkGameDirs );
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_SaveConfig()
+{
+ Sys_SetRegistryInteger( "ExcludePaths_LinkGameDirs", g_bLinkGameDirs );
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_Init
+//
+//-----------------------------------------------------------------------------
+bool ExcludePathsDlg_Init()
+{
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// ExcludePathsDlg_Open
+//
+//-----------------------------------------------------------------------------
+void ExcludePathsDlg_Open()
+{
+ ExcludePathsDlg_LoadConfig();
+
+ int result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_EXCLUDEPATHS ), g_hDlgMain, ( DLGPROC )ExcludePathsDlg_Proc );
+ if ( LOWORD( result ) != IDC_OK )
+ return;
+
+ ExcludePathsDlg_SaveConfig();
+}
diff --git a/utils/xbox/vxconsole/fileio.cpp b/utils/xbox/vxconsole/fileio.cpp
new file mode 100644
index 0000000..9b9ca25
--- /dev/null
+++ b/utils/xbox/vxconsole/fileio.cpp
@@ -0,0 +1,416 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// FILEIO.CPP
+//
+// File I/O Service Routines
+//=====================================================================================//
+#include "vxconsole.h"
+
+//-----------------------------------------------------------------------------
+// SystemTimeToString
+//
+// mm/dd/yyyy hh:mm:ss am
+//-----------------------------------------------------------------------------
+char *SystemTimeToString( SYSTEMTIME *systemTime, char *buffer, int bufferSize )
+{
+ char timeString[256];
+ char dateString[256];
+ int length;
+
+ GetDateFormat( LOCALE_SYSTEM_DEFAULT, 0, systemTime, "MM'/'dd'/'yyyy", dateString, sizeof( dateString ) );
+ GetTimeFormat( LOCALE_SYSTEM_DEFAULT, 0, systemTime, "hh':'mm':'ss tt", timeString, sizeof( timeString ) );
+ length = _snprintf( buffer, bufferSize, "%s %s", dateString, timeString );
+ if ( length == -1 )
+ buffer[bufferSize-1] = '\0';
+
+ return buffer;
+}
+
+//-----------------------------------------------------------------------------
+// CompareFileTimes_NTFStoFATX
+//
+//-----------------------------------------------------------------------------
+int CompareFileTimes_NTFStoFATX( FILETIME* ntfsFileTime, char *ntfsTimeString, int ntfsStringSize, FILETIME* fatxFileTime, char *fatxTimeString, int fatxStringSize )
+{
+ SYSTEMTIME ntfsSystemTime;
+ SYSTEMTIME fatxSystemTime;
+ int diff;
+ int ntfsSeconds;
+ int fatxSeconds;
+
+ TIME_ZONE_INFORMATION tzInfo;
+ GetTimeZoneInformation( &tzInfo );
+
+ // cannot compare UTC file times directly
+ // disjoint filesystems - xbox has a +/- 2s error
+ // daylight savings time handling on each file system may cause problems
+ FileTimeToSystemTime( ntfsFileTime, &ntfsSystemTime );
+ FileTimeToSystemTime( fatxFileTime, &fatxSystemTime );
+
+ // operate on local times, assumes xbox and pc are both set for same time zone and daylight saving
+ SYSTEMTIME ntfsLocalTime;
+ SYSTEMTIME fatxLocalTime;
+ SystemTimeToTzSpecificLocalTime( &tzInfo, &ntfsSystemTime, &ntfsLocalTime );
+ SystemTimeToTzSpecificLocalTime( &tzInfo, &fatxSystemTime, &fatxLocalTime );
+
+ if ( ntfsTimeString )
+ {
+ SystemTimeToString( &ntfsLocalTime, ntfsTimeString, ntfsStringSize );
+ }
+
+ if ( fatxTimeString )
+ {
+ SystemTimeToString( &fatxLocalTime, fatxTimeString, fatxStringSize );
+ }
+
+ diff = ntfsLocalTime.wYear-fatxLocalTime.wYear;
+ if ( diff )
+ return diff;
+
+ diff = ntfsLocalTime.wMonth-fatxLocalTime.wMonth;
+ if ( diff )
+ return diff;
+
+ diff = ntfsLocalTime.wDay-fatxLocalTime.wDay;
+ if ( diff )
+ return diff;
+
+ diff = ntfsLocalTime.wHour-fatxLocalTime.wHour;
+ if ( diff )
+ return diff;
+
+ // allow for +/- 3s error
+ ntfsSeconds = ntfsLocalTime.wHour*60*60 + ntfsLocalTime.wMinute*60 + ntfsLocalTime.wSecond;
+ fatxSeconds = fatxLocalTime.wHour*60*60 + fatxLocalTime.wMinute*60 + fatxLocalTime.wSecond;
+
+ diff = ntfsSeconds-fatxSeconds;
+ if ( diff > 3 || diff < -3 )
+ return diff;
+
+ // times are considered equal
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// FreeTargetFileList
+//
+//-----------------------------------------------------------------------------
+void FreeTargetFileList( fileNode_t* pFileList )
+{
+ fileNode_t *nodePtr;
+ fileNode_t *nextPtr;
+
+ if ( !pFileList )
+ return;
+
+ nodePtr = pFileList;
+ while ( nodePtr )
+ {
+ nextPtr = nodePtr->nextPtr;
+
+ Sys_Free( nodePtr->filename );
+ Sys_Free( nodePtr );
+
+ nodePtr = nextPtr;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// GetTargetFileList_r
+//
+//-----------------------------------------------------------------------------
+bool GetTargetFileList_r( char* targetPath, bool recurse, int attributes, int level, fileNode_t** pFileList )
+{
+ HRESULT hr;
+ PDM_WALK_DIR pWalkDir = NULL;
+ DM_FILE_ATTRIBUTES fileAttr;
+ bool valid;
+ char filename[MAX_PATH];
+ fileNode_t* nodePtr;
+ bool bGetNormal;
+ int fixedAttributes;
+
+ if ( !level )
+ *pFileList = NULL;
+
+ fixedAttributes = attributes;
+ if ( fixedAttributes & FILE_ATTRIBUTE_NORMAL )
+ {
+ fixedAttributes &= ~FILE_ATTRIBUTE_NORMAL;
+ bGetNormal = true;
+ }
+ else
+ bGetNormal = false;
+
+ while ( 1 )
+ {
+ hr = DmWalkDir( &pWalkDir, targetPath, &fileAttr );
+ if ( hr != XBDM_NOERR )
+ break;
+
+ strcpy( filename, targetPath );
+ Sys_AddFileSeperator( filename, sizeof( filename ) );
+ strcat( filename, fileAttr.Name );
+
+ // restrict to desired attributes
+ if ( ( bGetNormal && !fileAttr.Attributes ) || ( fileAttr.Attributes & fixedAttributes ) )
+ {
+ Sys_NormalizePath( filename, false );
+
+ // create a new file node
+ nodePtr = ( fileNode_t* )Sys_Alloc( sizeof( fileNode_t ) );
+
+ // link it in
+ nodePtr->filename = Sys_CopyString( filename );
+ nodePtr->changeTime = fileAttr.ChangeTime;
+ nodePtr->creationTime = fileAttr.CreationTime;
+ nodePtr->sizeHigh = fileAttr.SizeHigh;
+ nodePtr->sizeLow = fileAttr.SizeLow;
+ nodePtr->attributes = fileAttr.Attributes;
+ nodePtr->level = level;
+ nodePtr->nextPtr = *pFileList;
+ *pFileList = nodePtr;
+ }
+
+ if ( fileAttr.Attributes & FILE_ATTRIBUTE_DIRECTORY )
+ {
+ if ( recurse )
+ {
+ // descend into directory
+ valid = GetTargetFileList_r( filename, recurse, attributes, level+1, pFileList );
+ if ( !valid )
+ return false;
+ }
+ }
+ }
+ DmCloseDir( pWalkDir );
+
+ if ( hr != XBDM_ENDOFLIST )
+ {
+ // failure
+ return false;
+ }
+
+ // ok
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// FileSyncEx
+//
+// -1: failure, 0: nothing, 1: synced
+//-----------------------------------------------------------------------------
+int FileSyncEx( const char* localFilename, const char* targetFilename, int fileSyncMode, bool bVerbose, bool bNoWrite )
+{
+ bool copy;
+ bool pathExist;
+ WIN32_FILE_ATTRIBUTE_DATA localAttributes;
+ DM_FILE_ATTRIBUTES targetAttributes;
+ HRESULT hr;
+ int errCode;
+ int deltaTime;
+ char localTimeString[256];
+ char targetTimeString[256];
+
+ if ( ( fileSyncMode & FSYNC_TYPEMASK ) == FSYNC_OFF )
+ {
+ return 0;
+ }
+
+ if ( !GetFileAttributesEx( localFilename, GetFileExInfoStandard, &localAttributes ) )
+ {
+ // failed to get the local file's attributes
+ if ( bVerbose )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Sync Failure: Local file %s not available\n", localFilename );
+ }
+ return -1;
+ }
+
+ if ( localAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ {
+ // ignore directory
+ return 0;
+ }
+
+ if ( fileSyncMode & FSYNC_ANDEXISTSONTARGET )
+ {
+ hr = DmGetFileAttributes( targetFilename, &targetAttributes );
+ if ( hr != XBDM_NOERR )
+ {
+ // target doesn't exist, no sync operation should commence
+ if ( bVerbose )
+ {
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "No Update, Target file %s not available\n", targetFilename );
+ }
+ return 0;
+ }
+ }
+
+ // default success, no operation
+ errCode = 0;
+
+ // default, create path and copy
+ copy = true;
+ pathExist = false;
+
+ if ( ( fileSyncMode & FSYNC_TYPEMASK ) == FSYNC_IFNEWER )
+ {
+ hr = DmGetFileAttributes( targetFilename, &targetAttributes );
+ if ( hr == XBDM_NOERR )
+ {
+ // target path to file exists
+ pathExist = true;
+
+ // compare times
+ deltaTime = CompareFileTimes_NTFStoFATX( &localAttributes.ftLastWriteTime, localTimeString, sizeof( localTimeString), &targetAttributes.ChangeTime, targetTimeString, sizeof( targetTimeString ) );
+ if ( deltaTime < 0 )
+ {
+ // ntfs is older, fatx is newer, no update
+ if ( bVerbose )
+ {
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "No Update, %s [%s] is newer than %s [%s]\n", targetFilename, targetTimeString, localFilename, localTimeString );
+ }
+ copy = false;
+ }
+ else if ( !deltaTime )
+ {
+ // equal times, compare sizes
+ if ( localAttributes.nFileSizeLow == targetAttributes.SizeLow &&
+ localAttributes.nFileSizeHigh == targetAttributes.SizeHigh )
+ {
+ // file appears synced
+ copy = false;
+ }
+ if ( bVerbose )
+ {
+ if ( copy )
+ {
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Update, %s [%s] [%d] has different size than %s [%s] [%d]\n", targetFilename, targetTimeString, targetAttributes.SizeLow, localFilename, localTimeString, localAttributes.nFileSizeLow );
+ }
+ else
+ {
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "No Update, %s [%s] [%d] has same time and file size as %s [%s] [%d]\n", targetFilename, targetTimeString, targetAttributes.SizeLow, localFilename, localTimeString, localAttributes.nFileSizeLow );
+ }
+ }
+ }
+ else
+ {
+ // ntfs is newer, fatx is older, update
+ if ( bVerbose )
+ {
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Update, %s [%s] is older than %s [%s]\n", targetFilename, targetTimeString, localFilename, localTimeString );
+ }
+ }
+ }
+ }
+ else if ( ( fileSyncMode & FSYNC_TYPEMASK ) == FSYNC_ALWAYS )
+ {
+ if ( bVerbose )
+ {
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Force Update, %s\n", targetFilename );
+ }
+ }
+
+ if ( copy && !bNoWrite )
+ {
+ if ( !pathExist )
+ {
+ CreateTargetPath( targetFilename );
+ }
+
+ hr = DmSendFile( localFilename, targetFilename );
+ if ( hr == XBDM_NOERR )
+ {
+ // force the target to match the local attributes
+ // to ensure sync
+ memset( &targetAttributes, 0, sizeof( targetAttributes ) );
+ targetAttributes.SizeHigh = localAttributes.nFileSizeHigh;
+ targetAttributes.SizeLow = localAttributes.nFileSizeLow;
+ targetAttributes.CreationTime = localAttributes.ftCreationTime;
+ targetAttributes.ChangeTime = localAttributes.ftLastWriteTime;
+ DmSetFileAttributes( targetFilename, &targetAttributes );
+
+ // success, file copied
+ errCode = 1;
+ }
+ else
+ {
+ // failure
+ if ( bVerbose )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Sync Failed!\n" );
+ }
+ errCode = -1;
+ }
+
+ DebugCommand( "0x%8.8x = FileSyncEx( %s, %s )\n", hr, localFilename, targetFilename );
+ }
+
+ return errCode;
+}
+
+//-----------------------------------------------------------------------------
+// LoadTargetFile
+//
+//-----------------------------------------------------------------------------
+bool LoadTargetFile( const char *pTargetPath, int *pFileSize, void **pData )
+{
+ DM_FILE_ATTRIBUTES fileAttributes;
+ HRESULT hr;
+ DWORD bytesRead;
+ char *pBuffer;
+
+ *pFileSize = 0;
+ *pData = (void *)NULL;
+
+ hr = DmGetFileAttributes( pTargetPath, &fileAttributes );
+ if ( hr != XBDM_NOERR || !fileAttributes.SizeLow )
+ return false;
+
+ // allocate for size and terminating null
+ pBuffer = (char *)Sys_Alloc( fileAttributes.SizeLow+1 );
+
+ hr = DmReadFilePartial( pTargetPath, 0, (LPBYTE)pBuffer, fileAttributes.SizeLow, &bytesRead );
+ if ( hr != XBDM_NOERR || ( bytesRead != fileAttributes.SizeLow ) )
+ {
+ Sys_Free( pBuffer );
+ return false;
+ }
+
+ // add a terminating null
+ pBuffer[fileAttributes.SizeLow] = '\0';
+
+ *pFileSize = fileAttributes.SizeLow;
+ *pData = pBuffer;
+
+ // success
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// CreateTargetPath
+//
+//-----------------------------------------------------------------------------
+bool CreateTargetPath( const char *pTargetFilename )
+{
+ // create path chain
+ char *pPath;
+ char dirPath[MAX_PATH];
+
+ // prime and skip to first seperator
+ strcpy( dirPath, pTargetFilename );
+ pPath = strchr( dirPath, '\\' );
+ while ( pPath )
+ {
+ pPath = strchr( pPath+1, '\\' );
+ if ( pPath )
+ {
+ *pPath = '\0';
+ DmMkdir( dirPath );
+ *pPath = '\\';
+ }
+ }
+
+ return true;
+}
diff --git a/utils/xbox/vxconsole/icon_connect1.ico b/utils/xbox/vxconsole/icon_connect1.ico
new file mode 100644
index 0000000..dd373b0
--- /dev/null
+++ b/utils/xbox/vxconsole/icon_connect1.ico
Binary files differ
diff --git a/utils/xbox/vxconsole/icon_connect2.ico b/utils/xbox/vxconsole/icon_connect2.ico
new file mode 100644
index 0000000..638dd28
--- /dev/null
+++ b/utils/xbox/vxconsole/icon_connect2.ico
Binary files differ
diff --git a/utils/xbox/vxconsole/icon_connect2a.ico b/utils/xbox/vxconsole/icon_connect2a.ico
new file mode 100644
index 0000000..61473ea
--- /dev/null
+++ b/utils/xbox/vxconsole/icon_connect2a.ico
Binary files differ
diff --git a/utils/xbox/vxconsole/icon_disconnect.ico b/utils/xbox/vxconsole/icon_disconnect.ico
new file mode 100644
index 0000000..2146fe3
--- /dev/null
+++ b/utils/xbox/vxconsole/icon_disconnect.ico
Binary files differ
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, &sectLoad );
+ 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;
+}
diff --git a/utils/xbox/vxconsole/mem_profile.cpp b/utils/xbox/vxconsole/mem_profile.cpp
new file mode 100644
index 0000000..d15aee3
--- /dev/null
+++ b/utils/xbox/vxconsole/mem_profile.cpp
@@ -0,0 +1,561 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// MEM_PROFILE.CPP
+//
+// Memory Profiling Display
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define PROFILE_MAXSAMPLES 512
+#define PROFILE_MEMORYHEIGHT 100
+#define PROFILE_NUMMINORTICKS 3
+#define PROFILE_LABELWIDTH 50
+#define PROFILE_SCALESTEPS 8
+#define PROFILE_MINSCALE 0.2f
+#define PROFILE_MAXSCALE 3.0f
+#define PROFILE_NUMMINORTICKS 3
+#define PROFILE_MAJORTICKMB 16
+#define PROFILE_WARNINGMB 10
+#define PROFILE_SEVEREMB 5
+
+#define ID_MEMPROFILE 1
+
+HWND g_memProfile_hWnd;
+RECT g_memProfile_WindowRect;
+int g_memProfile_tickMarks;
+int g_memProfile_colors;
+int g_memProfile_scale;
+UINT_PTR g_memProfile_Timer;
+int g_memProfile_numSamples;
+int g_memProfile_samples[PROFILE_MAXSAMPLES];
+
+//-----------------------------------------------------------------------------
+// MemProfile_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void MemProfile_SaveConfig()
+{
+ char buff[256];
+ WINDOWPLACEMENT wp;
+
+ // profile history
+ if ( g_memProfile_hWnd )
+ {
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_memProfile_hWnd, &wp );
+ g_memProfile_WindowRect = wp.rcNormalPosition;
+ sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom );
+ Sys_SetRegistryString( "MemProfileWindowRect", buff );
+ }
+
+ Sys_SetRegistryInteger( "MemProfileScale", g_memProfile_scale );
+ Sys_SetRegistryInteger( "MemProfileTickMarks", g_memProfile_tickMarks );
+ Sys_SetRegistryInteger( "MemProfileColors", g_memProfile_colors );
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void MemProfile_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ // profile history
+ Sys_GetRegistryString( "MemProfileWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_memProfile_WindowRect.left, &g_memProfile_WindowRect.top, &g_memProfile_WindowRect.right, &g_memProfile_WindowRect.bottom );
+ if ( numArgs != 4 )
+ {
+ memset( &g_memProfile_WindowRect, 0, sizeof( g_memProfile_WindowRect ) );
+ }
+
+ Sys_GetRegistryInteger( "MemProfileScale", 0, g_memProfile_scale );
+ if ( g_memProfile_scale < -PROFILE_SCALESTEPS || g_memProfile_scale > PROFILE_SCALESTEPS )
+ {
+ g_memProfile_scale = 0;
+ }
+
+ Sys_GetRegistryInteger( "MemProfileTickMarks", 1, g_memProfile_tickMarks );
+ Sys_GetRegistryInteger( "MemProfileColors", 1, g_memProfile_colors );
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_SetTitle
+//
+//-----------------------------------------------------------------------------
+void MemProfile_SetTitle()
+{
+ char titleBuff[128];
+
+ if ( g_memProfile_hWnd )
+ {
+ strcpy( titleBuff, "Free Memory Available" );
+ if ( g_memProfile_Timer )
+ {
+ strcat( titleBuff, " [ON]" );
+ }
+
+ SetWindowText( g_memProfile_hWnd, titleBuff );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_EnableProfiling
+//
+//-----------------------------------------------------------------------------
+void MemProfile_EnableProfiling( bool bEnable )
+{
+ if ( !g_memProfile_hWnd )
+ {
+ return;
+ }
+
+ UINT_PTR timer = TIMERID_MEMPROFILE;
+ if ( bEnable && !g_memProfile_Timer )
+ {
+ // run at 10Hz
+ g_memProfile_Timer = SetTimer( g_memProfile_hWnd, timer, 100, NULL );
+ }
+ else if ( !bEnable && g_memProfile_Timer )
+ {
+ KillTimer( g_memProfile_hWnd, timer );
+ g_memProfile_Timer = NULL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_UpdateWindow
+//
+//-----------------------------------------------------------------------------
+void MemProfile_UpdateWindow()
+{
+ if ( g_memProfile_hWnd && !IsIconic( g_memProfile_hWnd ) )
+ {
+ // visible - force a client repaint
+ InvalidateRect( g_memProfile_hWnd, NULL, true );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// rc_FreeMemory
+//
+//-----------------------------------------------------------------------------
+int rc_FreeMemory( char* commandPtr )
+{
+ int errCode = -1;
+ int freeMemory;
+
+ char *cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ {
+ goto cleanUp;
+ }
+ sscanf( cmdToken, "%x", &freeMemory );
+
+ g_memProfile_samples[g_memProfile_numSamples % PROFILE_MAXSAMPLES] = freeMemory;
+ g_memProfile_numSamples++;
+
+ DebugCommand( "FreeMemory( 0x%8.8x )\n", freeMemory );
+
+ MemProfile_UpdateWindow();
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_ZoomIn
+//
+//-----------------------------------------------------------------------------
+void MemProfile_ZoomIn( int& scale, int numSteps )
+{
+ scale++;
+ if ( scale > numSteps )
+ {
+ scale = numSteps;
+ return;
+ }
+ MemProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_ZoomOut
+//
+//-----------------------------------------------------------------------------
+void MemProfile_ZoomOut( int& scale, int numSteps )
+{
+ scale--;
+ if ( scale < -numSteps )
+ {
+ scale = -numSteps;
+ return;
+ }
+ MemProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_CalcScale
+//
+//-----------------------------------------------------------------------------
+float MemProfile_CalcScale( int scale, int numSteps, float min, float max )
+{
+ float t;
+
+ // from integral scale [-numSteps..numSteps] to float scale [min..max]
+ t = ( float )( scale + numSteps )/( float )( 2*numSteps );
+ t = min + t*( max-min );
+
+ return t;
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_Draw
+//
+//-----------------------------------------------------------------------------
+void MemProfile_Draw( HDC hdc, RECT* clientRect )
+{
+ char labelBuff[128];
+ HPEN hBlackPen;
+ HPEN hPenOld;
+ HPEN hNullPen;
+ HPEN hGreyPen;
+ HBRUSH hColoredBrush;
+ HBRUSH hBrushOld;
+ HFONT hFontOld;
+ int currentSample;
+ int numTicks;
+ int memoryHeight;
+ int windowWidth;
+ int windowHeight;
+ int x;
+ int y;
+ int y0;
+ int i;
+ int j;
+ int h;
+ int numbars;
+ RECT rect;
+ float t;
+ float scale;
+
+ hBlackPen = CreatePen( PS_SOLID, 1, RGB( 0,0,0 ) );
+ hGreyPen = CreatePen( PS_SOLID, 1, Sys_ColorScale( g_backgroundColor, 0.85f ) );
+ hNullPen = CreatePen( PS_NULL, 0, RGB( 0,0,0 ) );
+ hPenOld = ( HPEN )SelectObject( hdc, hBlackPen );
+ hFontOld = SelectFont( hdc, g_hProportionalFont );
+
+ // zoom
+ scale = MemProfile_CalcScale( g_memProfile_scale, PROFILE_SCALESTEPS, PROFILE_MINSCALE, PROFILE_MAXSCALE );
+ memoryHeight = ( int )( PROFILE_MEMORYHEIGHT*scale );
+ windowWidth = clientRect->right-clientRect->left;
+ windowHeight = clientRect->bottom-clientRect->top;
+
+ numTicks = windowHeight/memoryHeight + 2;
+ if ( numTicks < 0 )
+ {
+ numTicks = 1;
+ }
+ else if ( numTicks > 512/PROFILE_MAJORTICKMB + 1 )
+ {
+ numTicks = 512/PROFILE_MAJORTICKMB + 1;
+ }
+
+ SetBkColor( hdc, g_backgroundColor );
+
+ x = 0;
+ y = windowHeight;
+ for ( i=0; i<numTicks; i++ )
+ {
+ // major ticks
+ SelectObject( hdc, hBlackPen );
+ MoveToEx( hdc, 0, y, NULL );
+ LineTo( hdc, windowWidth, y );
+
+ if ( g_memProfile_tickMarks )
+ {
+ // could be very zoomed out, gap must be enough for label, otherwise don't draw
+ int gapY = memoryHeight/( PROFILE_NUMMINORTICKS+1 );
+ if ( gapY >= 10 )
+ {
+ // minor ticks
+ y0 = y;
+ SelectObject( hdc, hGreyPen );
+ for ( j=0; j<PROFILE_NUMMINORTICKS; j++ )
+ {
+ y0 += gapY;
+ MoveToEx( hdc, 0, y0, NULL );
+ LineTo( hdc, windowWidth, y0 );
+ }
+ }
+ }
+
+ // tick labels
+ if ( i )
+ {
+ rect.left = windowWidth - 50;
+ rect.right = windowWidth;
+ rect.top = y - 20;
+ rect.bottom = y;
+ sprintf( labelBuff, "%d MB", i*PROFILE_MAJORTICKMB );
+ DrawText( hdc, labelBuff, -1, &rect, DT_RIGHT|DT_SINGLELINE|DT_BOTTOM );
+ }
+
+ y -= memoryHeight;
+ }
+
+ // vertical bars
+ if ( g_memProfile_numSamples )
+ {
+ SelectObject( hdc, hNullPen );
+
+ numbars = windowWidth-PROFILE_LABELWIDTH;
+ currentSample = g_memProfile_numSamples-1;
+ for ( x=numbars-1; x>=0; x-=4 )
+ {
+ float sample = g_memProfile_samples[currentSample % PROFILE_MAXSAMPLES]/( 1024.0f * 1024.0f );
+
+ y = windowHeight;
+ t = sample/(float)PROFILE_MAJORTICKMB;
+ h = ( int )( t * ( float )memoryHeight );
+ if ( h )
+ {
+ if ( h > windowHeight )
+ h = windowHeight;
+
+ COLORREF barColor;
+ if ( sample >= PROFILE_WARNINGMB )
+ {
+ barColor = RGB( 100, 255, 100 );
+ }
+ else if ( sample >= PROFILE_SEVEREMB )
+ {
+ barColor = RGB( 255, 255, 100 );
+ }
+ else
+ {
+ barColor = RGB( 255, 0, 0 );
+ }
+
+ hColoredBrush = CreateSolidBrush( g_memProfile_colors ? barColor : RGB( 80, 80, 80 ) );
+ hBrushOld = ( HBRUSH )SelectObject( hdc, hColoredBrush );
+
+ Rectangle( hdc, x-4, y-h, x, y+1 );
+ y -= h;
+
+ SelectObject( hdc, hBrushOld );
+ DeleteObject( hColoredBrush );
+ }
+
+ currentSample--;
+ if ( currentSample < 0 )
+ {
+ // no data
+ break;
+ }
+ }
+ }
+
+ SelectObject( hdc, hFontOld );
+ SelectObject( hdc, hPenOld );
+ DeleteObject( hBlackPen );
+ DeleteObject( hGreyPen );
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_TimerProc
+//
+//-----------------------------------------------------------------------------
+void MemProfile_TimerProc( HWND hwnd, UINT_PTR idEvent )
+{
+ static bool busy = false;
+
+ if ( busy )
+ {
+ return;
+ }
+
+ busy = true;
+
+ if ( g_connectedToApp )
+ {
+ // send as async
+ DmAPI_SendCommand( VXCONSOLE_COMMAND_PREFIX "!" "__memory__ quiet", false );
+ }
+
+ busy = false;
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK MemProfile_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rect;
+ CREATESTRUCT *createStructPtr;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ // set the window identifier
+ createStructPtr = ( CREATESTRUCT* )lParam;
+ SetWindowLong( hwnd, GWL_USERDATA+0, ( LONG )createStructPtr->lpCreateParams );
+
+ // clear samples
+ g_memProfile_numSamples = 0;
+ memset( g_memProfile_samples, 0, sizeof( g_memProfile_samples ) );
+ return 0L;
+
+ case WM_DESTROY:
+ MemProfile_SaveConfig();
+ MemProfile_EnableProfiling( false );
+ g_memProfile_hWnd = NULL;
+ return 0L;
+
+ case WM_INITMENU:
+ CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_TICKMARKS, MF_BYCOMMAND | ( g_memProfile_tickMarks ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_COLORS, MF_BYCOMMAND | ( g_memProfile_colors ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_MEMPROFILE_ENABLE, MF_BYCOMMAND | ( g_memProfile_Timer != NULL ? MF_CHECKED : MF_UNCHECKED ) );
+ return 0L;
+
+ case WM_PAINT:
+ GetClientRect( hwnd, &rect );
+ hdc = BeginPaint( hwnd, &ps );
+ MemProfile_Draw( hdc, &rect );
+ EndPaint( hwnd, &ps );
+ return 0L;
+
+ case WM_SIZE:
+ // force a redraw
+ MemProfile_UpdateWindow();
+ return 0L;
+
+ case WM_TIMER:
+ if ( wID == TIMERID_MEMPROFILE )
+ {
+ MemProfile_TimerProc( hwnd, TIMERID_MEMPROFILE );
+ return 0L;
+ }
+ break;
+
+ case WM_KEYDOWN:
+ switch ( wParam )
+ {
+ case VK_INSERT:
+ MemProfile_ZoomIn( g_memProfile_scale, PROFILE_SCALESTEPS );
+ return 0L;
+
+ case VK_DELETE:
+ MemProfile_ZoomOut( g_memProfile_scale, PROFILE_SCALESTEPS );
+ return 0L;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_MEMPROFILE_TICKMARKS:
+ g_memProfile_tickMarks ^= 1;
+ MemProfile_UpdateWindow();
+ return 0L;
+
+ case IDM_MEMPROFILE_COLORS:
+ g_memProfile_colors ^= 1;
+ MemProfile_UpdateWindow();
+ return 0L;
+
+ case IDM_MEMPROFILE_ZOOMIN:
+ MemProfile_ZoomIn( g_memProfile_scale, PROFILE_SCALESTEPS );
+ return 0L;
+
+ case IDM_MEMPROFILE_ZOOMOUT:
+ MemProfile_ZoomOut( g_memProfile_scale, PROFILE_SCALESTEPS );
+ return 0L;
+
+ case IDM_MEMPROFILE_ENABLE:
+ bool bEnable = ( g_memProfile_Timer != NULL );
+ bEnable ^= 1;
+ MemProfile_EnableProfiling( bEnable );
+ MemProfile_SetTitle();
+ return 0L;
+ }
+ break;
+ }
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_Open
+//
+//-----------------------------------------------------------------------------
+void MemProfile_Open()
+{
+ HWND hWnd;
+
+ if ( g_memProfile_hWnd )
+ {
+ // only one profile instance
+ if ( IsIconic( g_memProfile_hWnd ) )
+ ShowWindow( g_memProfile_hWnd, SW_RESTORE );
+ SetForegroundWindow( g_memProfile_hWnd );
+ return;
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "MEMPROFILECLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 600,
+ 500,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ ( void* )ID_MEMPROFILE );
+ g_memProfile_hWnd = hWnd;
+
+ MemProfile_EnableProfiling( true );
+ MemProfile_SetTitle();
+
+ if ( g_memProfile_WindowRect.right && g_memProfile_WindowRect.bottom )
+ MoveWindow( g_memProfile_hWnd, g_memProfile_WindowRect.left, g_memProfile_WindowRect.top, g_memProfile_WindowRect.right-g_memProfile_WindowRect.left, g_memProfile_WindowRect.bottom-g_memProfile_WindowRect.top, FALSE );
+ ShowWindow( g_memProfile_hWnd, SHOW_OPENWINDOW );
+}
+
+//-----------------------------------------------------------------------------
+// MemProfile_Init
+//
+//-----------------------------------------------------------------------------
+bool MemProfile_Init()
+{
+ WNDCLASS wndclass;
+
+ // set up our window class
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = MemProfile_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_MEMPROFILE );
+ wndclass.lpszClassName = "MEMPROFILECLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ MemProfile_LoadConfig();
+
+ return true;
+}
diff --git a/utils/xbox/vxconsole/progress.cpp b/utils/xbox/vxconsole/progress.cpp
new file mode 100644
index 0000000..50d90f4
--- /dev/null
+++ b/utils/xbox/vxconsole/progress.cpp
@@ -0,0 +1,359 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// PROGRESS.CPP
+//
+// Progress Metering Utility.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define PROGRESS_WIDTH 425
+#define PROGRESS_HEIGHT 170
+
+#define ID_PROGRESS_STATUS1 100
+#define ID_PROGRESS_STATUS2 101
+#define ID_PROGRESS_STATUS3 102
+#define ID_PROGRESS_PERCENT 103
+#define ID_PROGRESS_METER 104
+#define ID_PROGRESS_CANCEL 105
+
+//-----------------------------------------------------------------------------
+// CProgress_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK Progress_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ CProgress *pProgress;
+ CREATESTRUCT *createStructPtr;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ createStructPtr = ( CREATESTRUCT* )lParam;
+ SetWindowLong( hwnd, GWL_USERDATA+0, ( LONG )createStructPtr->lpCreateParams );
+ return 0L;
+
+ case WM_DESTROY:
+ pProgress = ( CProgress* )GetWindowLong( hwnd, GWL_USERDATA+0 );
+ if ( pProgress )
+ pProgress->m_hWnd = NULL;
+ return 0L;
+
+ case WM_CTLCOLORSTATIC:
+ SetBkColor( ( HDC )wParam, g_backgroundColor );
+ return ( BOOL )g_hBackgroundBrush;
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case ID_PROGRESS_CANCEL:
+ pProgress = ( CProgress* )GetWindowLong( hwnd, GWL_USERDATA+0 );
+ if ( pProgress )
+ pProgress->m_bCancelPressed = true;
+ return ( TRUE );
+ }
+ break;
+ }
+
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// CProgress::Update
+//
+// Pump the message loop
+//-----------------------------------------------------------------------------
+void CProgress::Update()
+{
+ MSG msg;
+
+ while ( PeekMessage( &msg, NULL, 0, 0, PM_NOYIELD|PM_REMOVE ) )
+ {
+ if ( !TranslateAccelerator( g_hDlgMain, g_hAccel, &msg ) )
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// CProgress::IsCancel
+//
+//-----------------------------------------------------------------------------
+bool CProgress::IsCancel()
+{
+ return m_bCancelPressed;
+}
+
+//-----------------------------------------------------------------------------
+// CProgress::SetMeter
+//
+//-----------------------------------------------------------------------------
+void CProgress::SetMeter( int currentPos, int range )
+{
+ char buff[16];
+ int percent;
+
+ if ( !m_hWnd || !m_hWndPercent || !m_hWndMeter )
+ return;
+
+ if ( range >= 0 )
+ {
+ SendMessage( m_hWndMeter, PBM_SETRANGE, 0, MAKELPARAM( 0, range ) );
+ m_range = range;
+ }
+ SendMessage( m_hWndMeter, PBM_SETPOS, currentPos, 0 );
+
+ if ( m_range > 0 )
+ {
+ percent = ( int )( 100.0f*currentPos/m_range );
+ if ( percent > 100 )
+ percent = 100;
+ }
+ else
+ percent = 0;
+ sprintf( buff, "%d%%", percent );
+ SetWindowText( m_hWndPercent, buff );
+
+ Update();
+}
+
+//-----------------------------------------------------------------------------
+// CProgress::SetStatus
+//
+//-----------------------------------------------------------------------------
+void CProgress::SetStatus( const char *line1, const char *line2, const char *line3 )
+{
+ if ( !m_hWnd )
+ return;
+
+ if ( line1 )
+ SetWindowText( m_hWndStatus1, line1 );
+ if ( line2 )
+ SetWindowText( m_hWndStatus2, line2 );
+ if ( line3 )
+ SetWindowText( m_hWndStatus3, line3 );
+
+ Update();
+}
+
+//-----------------------------------------------------------------------------
+// CProgress::Open
+//
+//-----------------------------------------------------------------------------
+void CProgress::Open( const char* title, bool canCancel, bool bHasMeter )
+{
+ HWND hWnd;
+ RECT clientRect;
+ RECT parentRect;
+ int cx;
+ int cy;
+ int cw;
+ int ch;
+ int y;
+ int dialogHeight;
+
+ dialogHeight = PROGRESS_HEIGHT;
+ if ( !canCancel )
+ dialogHeight -= 25;
+ if ( !bHasMeter )
+ dialogHeight -= GetSystemMetrics( SM_CYVSCROLL );
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "PROGRESSCLASS",
+ title,
+ WS_POPUP|WS_CAPTION,
+ 0,
+ 0,
+ PROGRESS_WIDTH,
+ dialogHeight,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ ( void* )this );
+ m_hWnd = hWnd;
+ if ( !m_hWnd )
+ return;
+
+ // status text line #1
+ GetClientRect( m_hWnd, &clientRect );
+ y = 10;
+ hWnd = CreateWindowEx(
+ 0,
+ WC_STATIC,
+ "",
+ WS_VISIBLE|WS_CHILD|SS_WORDELLIPSIS,
+ 8,
+ 10,
+ clientRect.right-clientRect.left-2*8 - 50,
+ 20,
+ m_hWnd,
+ ( HMENU )ID_PROGRESS_STATUS1,
+ g_hInstance,
+ NULL );
+ m_hWndStatus1 = hWnd;
+ y += 20;
+
+ // status text line #2
+ hWnd = CreateWindowEx(
+ 0,
+ WC_STATIC,
+ "",
+ WS_VISIBLE|WS_CHILD|SS_PATHELLIPSIS,
+ 8,
+ y,
+ clientRect.right-clientRect.left-2*8 -50,
+ 20,
+ m_hWnd,
+ ( HMENU )ID_PROGRESS_STATUS2,
+ g_hInstance,
+ NULL );
+ m_hWndStatus2 = hWnd;
+ y += 20;
+
+ // status text line #3
+ hWnd = CreateWindowEx(
+ 0,
+ WC_STATIC,
+ "",
+ WS_VISIBLE|WS_CHILD|SS_PATHELLIPSIS,
+ 8,
+ y,
+ clientRect.right-clientRect.left-2*8 -50,
+ 20,
+ m_hWnd,
+ ( HMENU )ID_PROGRESS_STATUS3,
+ g_hInstance,
+ NULL );
+ m_hWndStatus3 = hWnd;
+ y += 20;
+
+ // set font
+ SendMessage( m_hWndStatus1, WM_SETFONT, ( WPARAM )g_hProportionalFont, TRUE );
+ SendMessage( m_hWndStatus2, WM_SETFONT, ( WPARAM )g_hProportionalFont, TRUE );
+ SendMessage( m_hWndStatus3, WM_SETFONT, ( WPARAM )g_hProportionalFont, TRUE );
+
+ if ( bHasMeter )
+ {
+ // percent
+ hWnd = CreateWindowEx(
+ 0,
+ WC_STATIC,
+ "0%",
+ WS_VISIBLE|WS_CHILD|SS_RIGHT,
+ ( clientRect.right-clientRect.left ) - 2*8 - 50,
+ y - 20,
+ 50,
+ 20,
+ m_hWnd,
+ ( HMENU )ID_PROGRESS_PERCENT,
+ g_hInstance,
+ NULL );
+ m_hWndPercent = hWnd;
+ SendMessage( m_hWndPercent, WM_SETFONT, ( WPARAM )g_hProportionalFont, TRUE );
+
+ // progress meter
+ ch = GetSystemMetrics( SM_CYVSCROLL );
+ cw = ( clientRect.right-clientRect.left ) - 2*8;
+ cx = ( clientRect.left + clientRect.right )/2 - cw/2;
+ cy = y;
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ PROGRESS_CLASS,
+ NULL,
+ WS_VISIBLE|WS_CHILD,
+ cx,
+ cy,
+ cw,
+ ch,
+ m_hWnd,
+ ( HMENU )ID_PROGRESS_METER,
+ g_hInstance,
+ NULL );
+ m_hWndMeter = hWnd;
+ y = cy+ch;
+
+ // ensure bar is reset
+ SendMessage( m_hWndMeter, PBM_SETRANGE, 0, 0 );
+ SendMessage( m_hWndMeter, PBM_SETPOS, 0, 0 );
+ }
+ else
+ {
+ m_hWndPercent = NULL;
+ m_hWndMeter = NULL;
+ }
+
+ m_bCancelPressed = false;
+ if ( canCancel )
+ {
+ ch = 25;
+ cw = 80;
+ cx = ( clientRect.left + clientRect.right )/2 - cw/2;
+ cy = clientRect.bottom - 8 - ch;
+
+ // cancel button
+ hWnd = CreateWindowEx(
+ 0,
+ WC_BUTTON,
+ "Cancel",
+ WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON,
+ cx,
+ cy,
+ cw,
+ ch,
+ m_hWnd,
+ ( HMENU )ID_PROGRESS_CANCEL,
+ g_hInstance,
+ NULL );
+ m_hWndCancel = hWnd;
+
+ SendMessage( m_hWndCancel, WM_SETFONT, ( WPARAM )g_hProportionalFont, TRUE );
+ }
+
+ // get parent rectangle
+ GetWindowRect( g_hDlgMain, &parentRect );
+ cx = ( parentRect.left + parentRect.right )/2 - PROGRESS_WIDTH/2;
+ cy = ( parentRect.top + parentRect.bottom )/2 - dialogHeight/2;
+
+ MoveWindow( m_hWnd, cx, cy, PROGRESS_WIDTH, dialogHeight, FALSE );
+ ShowWindow( m_hWnd, SHOW_OPENWINDOW );
+}
+
+//-----------------------------------------------------------------------------
+// CProgress::~CProgress
+//
+//-----------------------------------------------------------------------------
+CProgress::~CProgress()
+{
+ if ( !m_hWnd )
+ return;
+
+ DestroyWindow( m_hWnd );
+ m_hWnd = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// CProgress::CProgress
+//
+//-----------------------------------------------------------------------------
+CProgress::CProgress()
+{
+ // set up our window class
+ WNDCLASS wndclass;
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = Progress_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = sizeof( CProgress* );
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = "PROGRESSCLASS";
+ RegisterClass( &wndclass );
+
+ m_hWnd = 0;
+ m_bCancelPressed = false;
+}
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 );
+}
diff --git a/utils/xbox/vxconsole/resource.h b/utils/xbox/vxconsole/resource.h
new file mode 100644
index 0000000..ed5c602
--- /dev/null
+++ b/utils/xbox/vxconsole/resource.h
@@ -0,0 +1,241 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by vxconsole.rc
+//
+#define MENU_PROFILE 4
+#define MENU_CPUPROFILE 4
+#define MENU_VXCONSOLE 100
+#define IDD_VXCONSOLE 104
+#define IDD_CONFIG 111
+#define IDC_LABEL 113
+#define IDD_SYNCFILES 116
+#define MENU_SHOWTEXTURES 118
+#define MENU_TEXPROFILE 120
+#define MENU_BINDOPTIONS 122
+#define IDD_MODIFYBIND 123
+#define MENU_SHOWMATERIALS 124
+#define MENU_SHOWSOUNDS 125
+#define MENU_SHOWMEMORYDUMP 127
+#define IDD_BUG 128
+#define MENU_TIMESTAMPLOG 129
+#define IDD_EXCLUDEPATHS 131
+#define IDD_INSTALL 132
+#define MENU_MEMPROFILE 133
+#define IDI_VXCONSOLE 200
+#define IDI_DISCONNECTED 201
+#define IDI_CONNECT1_ON 202
+#define IDI_CONNECT2_ON 203
+#define IDI_CONNECT2_OFF 204
+#define IDC_COMMAND 1000
+#define IDC_OUTPUT 1010
+#define IDC_CONFIG_XBOXNAME 1015
+#define IDC_CONFIG_REMOTEPATH 1016
+#define IDC_CONFIG_LOCALPATH 1017
+#define IDC_CONFIG_PING 1018
+#define IDC_OK 1019
+#define IDC_CANCEL 1020
+#define IDC_CONFIG_CLEARONCONNECT 1021
+#define IDC_CONFIG_TARGETPATH 1022
+#define IDC_CONFIG_XBELOCALPATH 1023
+#define IDC_CONFIG_XEXLOCALPATH 1023
+#define IDC_CONFIG_XBETARGETPATH 1024
+#define IDC_CONFIG_XEXTARGETPATH 1024
+#define IDC_CONFIG_INSTALLPATH 1025
+#define IDC_CONFIG_LOADSYMBOLS 1028
+#define IDC_SYNCFILES_LOCALPATH 1029
+#define IDC_SYNCFILES_TARGETPATH 1030
+#define IDC_SYNCFILES_FORCESYNC 1035
+#define IDC_SYNCFILES_NOWRITE 1036
+#define IDC_SYNCFILES_DELETEORPHANS 1037
+#define IDC_CONFIG_SAMPLEFILE 1038
+#define IDC_SYNCFILES_VERBOSE 1038
+#define IDC_CONFIG_SAMPLELOCAL 1039
+#define IDC_SYNCFILES_ANDEXISTSONXBOX 1039
+#define IDC_CONFIG_SAMPLETARGET 1040
+#define IDC_CONFIG_XBEFORCESYNC 1045
+#define IDC_CONFIG_XEXFORCESYNC 1045
+#define IDC_CONFIG_XBESYNCONCONNECT 1046
+#define IDC_CONFIG_XEXSYNCONCONNECT 1046
+#define IDC_MODIFYBIND_MENUNAME 1050
+#define IDC_MODIFYBIND_COMMAND 1051
+#define IDC_MODIFYBIND_KEYCODE 1052
+#define IDC_CONFIG_ALWAYSAUTOCONNECT 1053
+#define IDC_CONFIG_STARTMINIMIZED 1054
+#define IDC_CONFIG_CAPTUREDEBUGSPEW 1055
+#define IDC_BUG_CLEARFORM 1056
+#define IDC_BUG_TITLE 1057
+#define IDC_BUG_DESCRIPTION 1058
+#define IDC_BUG_CLEARFORM2 1059
+#define IDC_BUG_UPDATE 1059
+#define IDC_BUG_INCLUDEBSP 1060
+#define IDC_BUG_SAVEGAME 1061
+#define IDC_BUG_INCLUDEVMF 1062
+#define IDC_BUG_TAKESHOT 1063
+#define IDC_BUG_SEVERITY 1065
+#define IDC_BUG_REPORTTYPE 1066
+#define IDC_BUG_PRIORITY 1067
+#define IDC_BUG_AREA 1068
+#define IDC_BUG_TAKESHOT_LABEL 1069
+#define IDC_BUG_SAVEGAME_LABEL 1070
+#define IDC_BUG_INCLUDEBSP_LABEL 1071
+#define IDC_BUG_INCLUDEVMF_LABEL 1072
+#define IDC_BUG_POSITION_LABEL 1073
+#define IDC_BUG_ORIENTATION_LABEL 1074
+#define IDC_BUG_MAP_LABEL 1075
+#define IDC_BUG_BUILD_LABEL 1076
+#define IDC_BUG_SUBMITTER_LABEL 1077
+#define IDC_BUG_MAPNUMBER 1078
+#define IDC_BUG_SUBMIT 1079
+#define IDC_BUG_SEVERITY2 1080
+#define IDC_BUG_OWNER 1080
+#define IDC_BUG_GAME 1082
+#define IDC_CHECK1 1083
+#define IDC_BUG_COMPRESS_SCREENSHOT 1083
+#define IDC_PATHS_LINKGAMEDIRS 1083
+#define IDC_INSTALL_FORCESYNC 1083
+#define IDC_PATHS_TREE 1085
+#define IDC_PATHS_RESCAN 1086
+#define IDC_PATHS_EXPAND 1087
+#define IDC_PATHS_COLLAPSE 1088
+#define IDC_INSTALL_LIST 1088
+#define IDC_INSTALL_REFRESH 1089
+#define IDC_CHECK2 1091
+#define IDC_INSTALL_CLEANTARGET 1091
+#define IDR_MAIN_ACCEL 3000
+#define IDM_CONNECT 40002
+#define IDM_DEBUGMONITOR 40004
+#define IDM_DEBUGCOMMANDS 40008
+#define IDM_AUTOCONNECT 40009
+#define IDM_DISCONNECT 40013
+#define IDM_EXIT 40017
+#define IDM_CONFIG 40018
+#define IDM_DEBUGMEMORY 40019
+#define IDM_FILELOG 40021
+#define IDM_CLEARLOG 40026
+#define IDM_ENABLELOG 40027
+#define IDM_REFRESHLOG 40031
+#define ID_LOG_SUMMARY 40032
+#define IDM_SUMMARYLOG 40035
+#define ID_Menu 40048
+#define IDM_PROFILESAMPLES 40064
+#define IDM_PROFILEHISTORY 40066
+#define IDM_SYNCTARGET 40073
+#define IDM_SYNCIFNEWER 40074
+#define IDM_ENABLEFILESERVING 40075
+#define ID_CONNECTION_FILESERVING 40076
+#define IDM_FILESERVING_LOCALONLY 40080
+#define IDM_FILESERVING_REMOTEONLY 40081
+#define IDM_FILESERVING_LOCALFIRST 40083
+#define IDM_FILESYNC_OFF 40088
+#define IDM_FILESYNC_ALWAYS 40089
+#define IDM_FILESYNC_IFNEWER 40090
+#define IDM_EXPORTLOG 40092
+#define ID_Menu40094 40094
+#define IDM_SYMBOLS_ADDRESS 40106
+#define IDM_SYMBOLS_FUNCTIONNAME 40110
+#define IDM_SYMBOLS_MODULEANDLINE 40112
+#define IDM_SYMBOLS_FILEPATHANDLINE 40114
+#define IDM_SYMBOLS_LOAD 40116
+#define IDM_SYNCFILES 40117
+#define IDM_SYMBOLS_DETAILS 40119
+#define IDM_OPTIONS_TREEVIEW 40121
+#define ID_Menu40123 40123
+#define IDM_SHOWMATERIALS 40124
+#define IDM_REFRESH 40127
+#define IDM_SHOWRESOURCES_TEXTURES 40130
+#define IDM_OPTIONS_CURRENTFRAME 40132
+#define IDM_OPTIONS_SUMMARY 40135
+#define IDM_OPTIONS_REFRESH 40136
+#define IDM_OPTIONS_EXPORT 40137
+#define IDM_OPTIONS_FULLPATH 40139
+#define ID_CONNECTION_PROFILING 40140
+#define ID_PROFILING_CPU 40141
+#define ID_PROFILING_TEXTURE 40142
+#define ID_CONNECTION_TEXTUREPROFILING 40147
+#define IDM_CPU_SAMPLES 40148
+#define IDM_CPU_HISTORY 40149
+#define IDM_SHOWRESOURCES_MATERIALS 40154
+#define IDM_SHOWRESOURCES_MODELS 40155
+#define ID_CONNECTION_EE 40157
+#define IDM_CPUPROFILE_TICKMARKS 40160
+#define IDM_CPUPROFILE_COLORS 40161
+#define IDM_CPUPROFILE_ZOOMIN 40162
+#define IDM_CPUPROFILE_ZOOMOUT 40163
+#define IDM_CPUPROFILE_ENABLE 40164
+#define IDM_TEXPROFILE_TICKMARKS 40166
+#define IDM_TEXPROFILE_COLORS 40168
+#define IDM_TEXPROFILE_ZOOMIN 40172
+#define IDM_TEXPROFILE_ZOOMOUT 40173
+#define IDM_TEXPROFILE_ENABLE 40174
+#define IDM_TEXPROFILE_CURRENTFRAME 40176
+#define ID_Menu40177 40177
+#define ID_VPROFILING_SHOWTEXTURE 40178
+#define ID_Menu40189 40189
+#define IDM_BINDOPTIONS_MODIFY 40192
+#define IDM_BINDOPTIONS_DELETE 40193
+#define IDM_TIMESTAMPLOG 50502
+#define IDM_CPUPROFILE_FPSLABELS 50505
+#define IDM_SHOWRESOURCES_SOUNDS 50509
+#define IDM_OPTIONS_PLAYSOUND 50513
+#define IDM_D3D_SAMPLES 50516
+#define IDM_D3D_HISTORY 50517
+#define IDM_MEMORYDUMP 50520
+#define IDM_OPTIONS_BYTES 50527
+#define IDM_OPTIONS_KILOBYTES 50530
+#define IDM_OPTIONS_MEGABYTES 50531
+#define IDM_OPTIONS_COLLAPSEOUTPUT 50533
+#define IDM_SYNCINSTALL 50535
+#define ID_Menu50536 50536
+#define IDM_FILESYNC_ANDEXISTSONTARGET 50539
+#define ID_CONNECTION_SEARCHPATHS 50540
+#define ID_SEARCHPATHS_NOZIPS 50541
+#define ID_SEARCHPATHS_PAKFILESFIRST 50542
+#define ID_SEARCHPATHS_PAKFILES 50543
+#define ID_Menu50546 50546
+#define IDM_SYNCINSTALL_TODVD 50547
+#define IDM_SYNCINSTALL_TOHDD 50548
+#define IDM_SHOWRESOURCES_BUG 50550
+#define IDM_BUG 50552
+#define IDM_SYNCXEX 50553
+#define IDM_DEBUGSPEW 50557
+#define IDM_CAPTUREGAMESPEW 50560
+#define IDM_CAPTUREDEBUGSPEW 50561
+#define ID_CONNECTION_DVDEXCLUDEPATHS 50562
+#define IDM_DVDEXCLUDEPATHS 50563
+#define IDM_EXCLUDEPATHS 50564
+#define ID_OPTIONS_SHOWTEXTURE 50565
+#define IDM_OPTIONS_SHOWTEXTURE 50566
+#define IDM_OPTIONS_DRAWTEXTURE 50567
+#define ID_OPTIONS_HIDETEXTURE 50568
+#define IDM_OPTIONS_HIDETEXTURE 50569
+#define ID_PROFILING_SHOWMEMORYUSAGE 50570
+#define IDM_SHOWMEMORYUSAGE 50571
+#define IDM_SHOWFREEMEMORY 50572
+#define ID_OPTIONS_TICKMARKS 50573
+#define ID_OPTIONS_ZOOMIN 50574
+#define ID_OPTIONS_ZOOMOUT 50575
+#define ID_OPTIONS_ENABLE 50576
+#define IDM_MEMPROFILE_TICKMARKS 50577
+#define IDM_MEMPROFILE_ZOOMIN 50578
+#define IDM_MEMPROFILE_ZOOMOUT 50579
+#define IDM_MEMPROFILE_ENABLE 50580
+#define ID_OPTIONS_COLORS 50581
+#define IDM_MEMPROFILE_COLORS 50582
+#define ID_OPTIONS_CLEAR 50583
+#define IDM_OPTIONS_CLEAR 50584
+#define ID_PROFILING_TESTINGMODE 50585
+#define IDM_PLAYTESTMODE 50586
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 134
+#define _APS_NEXT_COMMAND_VALUE 50587
+#define _APS_NEXT_CONTROL_VALUE 1092
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/utils/xbox/vxconsole/show_materials.cpp b/utils/xbox/vxconsole/show_materials.cpp
new file mode 100644
index 0000000..f57f5f9
--- /dev/null
+++ b/utils/xbox/vxconsole/show_materials.cpp
@@ -0,0 +1,575 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SHOW_MATERIALS.CPP
+//
+// Show Materials Display.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define ID_SHOWMATERIALS_LISTVIEW 100
+
+// column id
+#define ID_SM_NAME 0
+#define ID_SM_SHADER 1
+#define ID_SM_REFCOUNT 2
+
+typedef struct
+{
+ int listIndex;
+ char *pName;
+ char *pShaderName;
+ int refCount;
+ char refCountBuff[16];
+} material_t;
+
+typedef struct
+{ const CHAR* name;
+ int width;
+ int subItemIndex;
+ CHAR nameBuff[32];
+} label_t;
+
+HWND g_showMaterials_hWnd;
+HWND g_showMaterials_hWndListView;
+RECT g_showMaterials_windowRect;
+int g_showMaterials_sortColumn;
+int g_showMaterials_sortDescending;
+material_t *g_showMaterials_pMaterials;
+int g_showMaterials_numMaterials;
+int g_showMaterials_currentFrame;
+
+label_t g_showMaterials_Labels[] =
+{
+ {"Name", 300, ID_SM_NAME},
+ {"Shader", 150, ID_SM_SHADER},
+ {"RefCount", 80, ID_SM_REFCOUNT},
+};
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_SaveConfig()
+{
+ char buff[256];
+
+ Sys_SetRegistryInteger( "showMaterialsCurrentFrame", g_showMaterials_currentFrame );
+ Sys_SetRegistryInteger( "showMaterialsSortColumn", g_showMaterials_sortColumn );
+ Sys_SetRegistryInteger( "showMaterialsSortDescending", g_showMaterials_sortDescending );
+
+ WINDOWPLACEMENT wp;
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_showMaterials_hWnd, &wp );
+ g_showMaterials_windowRect = wp.rcNormalPosition;
+
+ sprintf( buff, "%d %d %d %d", g_showMaterials_windowRect.left, g_showMaterials_windowRect.top, g_showMaterials_windowRect.right, g_showMaterials_windowRect.bottom );
+ Sys_SetRegistryString( "showMaterialsWindowRect", buff );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ Sys_GetRegistryInteger( "showMaterialsCurrentFrame", false, g_showMaterials_currentFrame );
+ Sys_GetRegistryInteger( "showMaterialsSortColumn", ID_SM_NAME, g_showMaterials_sortColumn );
+ Sys_GetRegistryInteger( "showMaterialsSortDescending", false, g_showMaterials_sortDescending );
+
+ Sys_GetRegistryString( "showMaterialsWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_showMaterials_windowRect.left, &g_showMaterials_windowRect.top, &g_showMaterials_windowRect.right, &g_showMaterials_windowRect.bottom );
+ if ( numArgs != 4 || g_showMaterials_windowRect.left < 0 || g_showMaterials_windowRect.top < 0 || g_showMaterials_windowRect.right < 0 || g_showMaterials_windowRect.bottom < 0 )
+ memset( &g_showMaterials_windowRect, 0, sizeof( g_showMaterials_windowRect ) );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_Clear
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_Clear()
+{
+ // delete all the list view entries
+ if ( g_showMaterials_hWnd )
+ ListView_DeleteAllItems( g_showMaterials_hWndListView );
+
+ if ( !g_showMaterials_pMaterials )
+ return;
+
+ for ( int i=0; i<g_showMaterials_numMaterials; i++ )
+ {
+ free( g_showMaterials_pMaterials[i].pName );
+ free( g_showMaterials_pMaterials[i].pShaderName );
+ }
+
+ g_showMaterials_pMaterials = NULL;
+ g_showMaterials_numMaterials = 0;
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_Export
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_Export()
+{
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_SetTitle
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_SetTitle()
+{
+ char titleBuff[128];
+
+ if ( g_showMaterials_hWnd )
+ {
+ strcpy( titleBuff, "Materials " );
+ if ( g_showMaterials_currentFrame )
+ strcat( titleBuff, " [FRAME]" );
+
+ SetWindowText( g_showMaterials_hWnd, titleBuff );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_CompareFunc
+//
+//-----------------------------------------------------------------------------
+int CALLBACK ShowMaterials_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
+{
+ material_t* pMaterialA = ( material_t* )lParam1;
+ material_t* pMaterialB = ( material_t* )lParam2;
+
+ int sort = 0;
+ switch ( g_showMaterials_sortColumn )
+ {
+ case ID_SM_NAME:
+ sort = stricmp( pMaterialA->pName, pMaterialB->pName );
+ break;
+
+ case ID_SM_SHADER:
+ sort = stricmp( pMaterialA->pShaderName, pMaterialB->pShaderName );
+ break;
+
+ case ID_SM_REFCOUNT:
+ sort = pMaterialA->refCount - pMaterialB->refCount;
+ break;
+ }
+
+ // flip the sort order
+ if ( g_showMaterials_sortDescending )
+ sort *= -1;
+
+ return ( sort );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_SortItems
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_SortItems()
+{
+ LVITEM lvitem;
+ material_t *pMaterial;
+ int i;
+
+ if ( !g_showMaterials_hWnd )
+ {
+ // only sort if window is visible
+ return;
+ }
+
+ ListView_SortItems( g_showMaterials_hWndListView, ShowMaterials_CompareFunc, 0 );
+
+ memset( &lvitem, 0, sizeof( lvitem ) );
+ lvitem.mask = LVIF_PARAM;
+
+ // get each item and reset its list index
+ int itemCount = ListView_GetItemCount( g_showMaterials_hWndListView );
+ for ( i=0; i<itemCount; i++ )
+ {
+ lvitem.iItem = i;
+ ListView_GetItem( g_showMaterials_hWndListView, &lvitem );
+
+ pMaterial = ( material_t* )lvitem.lParam;
+ pMaterial->listIndex = i;
+ }
+
+ // update list view columns with sort key
+ for ( i=0; i<sizeof( g_showMaterials_Labels )/sizeof( g_showMaterials_Labels[0] ); i++ )
+ {
+ char symbol;
+ LVCOLUMN lvc;
+
+ if ( i == g_showMaterials_sortColumn )
+ symbol = g_showMaterials_sortDescending ? '<' : '>';
+ else
+ symbol = ' ';
+ sprintf( g_showMaterials_Labels[i].nameBuff, "%s %c", g_showMaterials_Labels[i].name, symbol );
+
+ memset( &lvc, 0, sizeof( lvc ) );
+ lvc.mask = LVCF_TEXT;
+ lvc.pszText = ( LPSTR )g_showMaterials_Labels[i].nameBuff;
+
+ ListView_SetColumn( g_showMaterials_hWndListView, i, &lvc );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_AddViewItem
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_AddViewItem( material_t* pMaterial )
+{
+ LVITEM lvi;
+
+ if ( !g_showMaterials_hWnd )
+ {
+ // only valid if log window is visible
+ return;
+ }
+
+ // update the text callback buffers
+ sprintf( pMaterial->refCountBuff, "%d", pMaterial->refCount );
+
+ int itemCount = ListView_GetItemCount( g_showMaterials_hWndListView );
+
+ // setup and insert at end of list
+ memset( &lvi, 0, sizeof( lvi ) );
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = itemCount;
+ lvi.iSubItem = 0;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = ( LPARAM )pMaterial;
+
+ // insert and set the real index
+ pMaterial->listIndex = ListView_InsertItem( g_showMaterials_hWndListView, &lvi );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_Refresh
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_Refresh()
+{
+ char command[256];
+
+ strcpy( command, "mat_material_list" );
+
+// if ( !g_showMaterials_currentFrame )
+// strcat( command, " all" );
+
+ // send the command to application which replies with list data
+ if ( g_connectedToApp )
+ ProcessCommand( command );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_SizeWindow
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_SizeWindow( HWND hwnd, int cx, int cy )
+{
+ if ( cx==0 || cy==0 )
+ {
+ RECT rcClient;
+ GetClientRect( hwnd, &rcClient );
+ cx = rcClient.right;
+ cy = rcClient.bottom;
+ }
+
+ // position the ListView
+ SetWindowPos( g_showMaterials_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK ShowMaterials_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ material_t* pMaterial;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ return 0L;
+
+ case WM_DESTROY:
+ ShowMaterials_SaveConfig();
+ g_showMaterials_hWnd = NULL;
+ return 0L;
+
+ case WM_INITMENU:
+ CheckMenuItem( ( HMENU )wParam, IDM_OPTIONS_CURRENTFRAME, MF_BYCOMMAND | ( g_showMaterials_currentFrame ? MF_CHECKED : MF_UNCHECKED ) );
+ return 0L;
+
+ case WM_SIZE:
+ ShowMaterials_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) );
+ return 0L;
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lParam )->code )
+ {
+ case LVN_COLUMNCLICK:
+ NMLISTVIEW* pnmlv;
+ pnmlv = ( NMLISTVIEW* )lParam;
+ if ( g_showMaterials_sortColumn == pnmlv->iSubItem )
+ {
+ // user has clicked on same column - flip the sort
+ g_showMaterials_sortDescending ^= 1;
+ }
+ else
+ {
+ // sort by new column
+ g_showMaterials_sortColumn = pnmlv->iSubItem;
+ }
+ ShowMaterials_SortItems();
+ return 0L;
+
+ case LVN_GETDISPINFO:
+ NMLVDISPINFO* plvdi;
+ plvdi = ( NMLVDISPINFO* )lParam;
+ pMaterial = ( material_t* )plvdi->item.lParam;
+ switch ( plvdi->item.iSubItem )
+ {
+ case ID_SM_NAME:
+ plvdi->item.pszText = pMaterial->pName;
+ return 0L;
+
+ case ID_SM_SHADER:
+ plvdi->item.pszText = pMaterial->pShaderName;
+ return 0L;
+
+ case ID_SM_REFCOUNT:
+ plvdi->item.pszText = pMaterial->refCountBuff;
+ return 0L;
+
+ default:
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_OPTIONS_REFRESH:
+ ShowMaterials_Refresh();
+ return 0L;
+
+ case IDM_OPTIONS_EXPORT:
+ ShowMaterials_Export();
+ return 0L;
+
+ case IDM_OPTIONS_CURRENTFRAME:
+ g_showMaterials_currentFrame ^= 1;
+ ShowMaterials_SetTitle();
+ ShowMaterials_Refresh();
+ return 0L;
+ }
+ break;
+ }
+
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_Init
+//
+//-----------------------------------------------------------------------------
+bool ShowMaterials_Init()
+{
+ // set up our window class
+ WNDCLASS wndclass;
+
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ShowMaterials_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_SHOWMATERIALS );
+ wndclass.lpszClassName = "SHOWMATERIALSCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ ShowMaterials_LoadConfig();
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// ShowMaterials_Open
+//
+//-----------------------------------------------------------------------------
+void ShowMaterials_Open()
+{
+ RECT clientRect;
+ HWND hWnd;
+ int i;
+
+ if ( g_showMaterials_hWnd )
+ {
+ // only one instance
+ if ( IsIconic( g_showMaterials_hWnd ) )
+ ShowWindow( g_showMaterials_hWnd, SW_RESTORE );
+ SetForegroundWindow( g_showMaterials_hWnd );
+ return;
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "SHOWMATERIALSCLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 700,
+ 400,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ NULL );
+ g_showMaterials_hWnd = hWnd;
+
+ GetClientRect( g_showMaterials_hWnd, &clientRect );
+ hWnd = CreateWindow(
+ WC_LISTVIEW,
+ "",
+ WS_VISIBLE|WS_CHILD|LVS_REPORT,
+ 0,
+ 0,
+ clientRect.right-clientRect.left,
+ clientRect.bottom-clientRect.top,
+ g_showMaterials_hWnd,
+ ( HMENU )ID_SHOWMATERIALS_LISTVIEW,
+ g_hInstance,
+ NULL );
+ g_showMaterials_hWndListView = hWnd;
+
+ // init list view columns
+ for ( i=0; i<sizeof( g_showMaterials_Labels )/sizeof( g_showMaterials_Labels[0] ); i++ )
+ {
+ LVCOLUMN lvc;
+ memset( &lvc, 0, sizeof( lvc ) );
+
+ lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
+ lvc.iSubItem = 0;
+ lvc.cx = g_showMaterials_Labels[i].width;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.pszText = ( LPSTR )g_showMaterials_Labels[i].name;
+
+ ListView_InsertColumn( g_showMaterials_hWndListView, i, &lvc );
+ }
+
+ ListView_SetBkColor( g_showMaterials_hWndListView, g_backgroundColor );
+ ListView_SetTextBkColor( g_showMaterials_hWndListView, g_backgroundColor );
+
+ DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP;
+ ListView_SetExtendedListViewStyleEx( g_showMaterials_hWndListView, style, style );
+
+ // populate list view
+ for ( i=0; i<g_showMaterials_numMaterials; i++ )
+ ShowMaterials_AddViewItem( &g_showMaterials_pMaterials[i] );
+ ShowMaterials_SortItems();
+
+ ShowMaterials_SetTitle();
+
+ if ( g_showMaterials_windowRect.right && g_showMaterials_windowRect.bottom )
+ MoveWindow( g_showMaterials_hWnd, g_showMaterials_windowRect.left, g_showMaterials_windowRect.top, g_showMaterials_windowRect.right-g_showMaterials_windowRect.left, g_showMaterials_windowRect.bottom-g_showMaterials_windowRect.top, FALSE );
+ ShowWindow( g_showMaterials_hWnd, SHOW_OPENWINDOW );
+
+ // get data from application
+ ShowMaterials_Refresh();
+}
+
+//-----------------------------------------------------------------------------
+// rc_MaterialList
+//
+// Sent from application with material list
+//-----------------------------------------------------------------------------
+int rc_MaterialList( char* commandPtr )
+{
+ char* cmdToken;
+ int numMaterials;
+ int materialList;
+ int retAddr;
+ int retVal;
+ int errCode = -1;
+ xrMaterial_t* pLocalList;
+
+ // remove old entries
+ ShowMaterials_Clear();
+
+ // get number of materials
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &numMaterials );
+
+ // get material list
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &materialList );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &retAddr );
+
+ pLocalList = new xrMaterial_t[numMaterials];
+ memset( pLocalList, 0, numMaterials*sizeof( xrMaterial_t ) );
+
+ g_showMaterials_numMaterials = numMaterials;
+ g_showMaterials_pMaterials = new material_t[numMaterials];
+ memset( g_showMaterials_pMaterials, 0, numMaterials*sizeof( material_t ) );
+
+ // get the caller's command list
+ DmGetMemory( ( void* )materialList, numMaterials*sizeof( xrMaterial_t ), pLocalList, NULL );
+
+ // build out the resident list
+ for ( int i=0; i<numMaterials; i++ )
+ {
+ // swap the structure
+ pLocalList[i].refCount = BigDWord( pLocalList[i].refCount );
+
+ g_showMaterials_pMaterials[i].pName = strdup( pLocalList[i].nameString );
+ g_showMaterials_pMaterials[i].pShaderName = strdup( pLocalList[i].shaderString );
+ g_showMaterials_pMaterials[i].refCount = pLocalList[i].refCount;
+
+ // add to list view
+ ShowMaterials_AddViewItem( &g_showMaterials_pMaterials[i] );
+ }
+
+ // return the result
+ retVal = numMaterials;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = MaterialList( 0x%8.8x, 0x%8.8x )\n", retVal, numMaterials, materialList );
+
+ delete [] pLocalList;
+
+ // update
+ ShowMaterials_SortItems();
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
diff --git a/utils/xbox/vxconsole/show_memdump.cpp b/utils/xbox/vxconsole/show_memdump.cpp
new file mode 100644
index 0000000..fc86833
--- /dev/null
+++ b/utils/xbox/vxconsole/show_memdump.cpp
@@ -0,0 +1,1440 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SHOW_MEMDUMP.CPP
+//
+// Show Mem Dump Display.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define ID_SHOWMEMDUMP_LISTVIEW 100
+
+// column id, pool mode
+#define ID_DUMPPOOL_POOL 0
+#define ID_DUMPPOOL_SIZE 1
+#define ID_DUMPPOOL_ALLOCATED 2
+#define ID_DUMPPOOL_FREE 3
+#define ID_DUMPPOOL_COMMITTED 4
+#define ID_DUMPPOOL_COMMITTEDSIZE 5
+
+// column id, detailed mode
+#define ID_DUMPDETAIL_ALLOCATION 0
+#define ID_DUMPDETAIL_CURRENTSIZE 1
+#define ID_DUMPDETAIL_PEAKSIZE 2
+#define ID_DUMPDETAIL_TOTALSIZE 3
+#define ID_DUMPDETAIL_OVERHEAD 4
+#define ID_DUMPDETAIL_PEAKOVERHEAD 5
+#define ID_DUMPDETAIL_TIME 6
+#define ID_DUMPDETAIL_CURRENTCOUNT 7
+#define ID_DUMPDETAIL_PEAKCOUNT 8
+#define ID_DUMPDETAIL_TOTALCOUNT 9
+#define ID_DUMPDETAIL_LTE16 10
+#define ID_DUMPDETAIL_LTE32 11
+#define ID_DUMPDETAIL_LTE128 12
+#define ID_DUMPDETAIL_LTE1024 13
+#define ID_DUMPDETAIL_GT1024 14
+
+#define SHOW_BYTES 0
+#define SHOW_KILOBYTES 1
+#define SHOW_MEGABYTES 2
+
+#define FORMAT_POOLS 0
+#define FORMAT_DETAILS 1
+
+struct MemoryPool_t
+{
+ int pool;
+ char poolBuff[32];
+ int size;
+ char sizeBuff[32];
+ int allocated;
+ char allocatedBuff[32];
+ int free;
+ char freeBuff[32];
+ int committed;
+ char committedBuff[32];
+ int committedSize;
+ char committedSizeBuff[32];
+};
+
+struct MemoryDetail_t
+{
+ char *pAllocationName;
+ int currentSize;
+ char currentSizeBuff[32];
+ int peakSize;
+ char peakSizeBuff[32];
+ int totalSize;
+ char totalSizeBuff[32];
+ int overheadSize;
+ char overheadSizeBuff[32];
+ int peakOverheadSize;
+ char peakOverheadSizeBuff[32];
+ int time;
+ char timeBuff[32];
+ int currentCount;
+ char currentCountBuff[32];
+ int peakCount;
+ char peakCountBuff[32];
+ int totalCount;
+ char totalCountBuff[32];
+ int lte16;
+ char lte16Buff[32];
+ int lte32;
+ char lte32Buff[32];
+ int lte128;
+ char lte128Buff[32];
+ int lte1024;
+ char lte1024Buff[32];
+ int gt1024;
+ char gt1024Buff[32];
+};
+
+struct memory_t
+{
+ int listIndex;
+ MemoryPool_t pool;
+ MemoryDetail_t detail;
+};
+
+struct label_t
+{
+ const CHAR* name;
+ int width;
+ int subItemIndex;
+ CHAR nameBuff[64];
+};
+
+HWND g_showMemDump_hWnd;
+HWND g_showMemDump_hWndListView;
+RECT g_showMemDump_windowRect;
+int g_showMemDump_sortColumn;
+int g_showMemDump_sortDescending;
+memory_t *g_showMemDump_pMemory;
+int g_showMemDump_numMemory;
+int g_showMemDump_showBytes;
+bool g_showMemDump_bCollapseOutput;
+char g_showMemDump_currentFilename[MAX_PATH];
+int g_showMemDump_format;
+
+void ShowMemDump_Parse( const char *pBuffer, int fileSize );
+
+label_t g_showMemDump_PoolLabels[] =
+{
+ {"Pool", 120, ID_DUMPPOOL_POOL},
+ {"Size", 120, ID_DUMPPOOL_SIZE},
+ {"Allocated Count", 120, ID_DUMPPOOL_ALLOCATED},
+ {"Free Count", 120, ID_DUMPPOOL_FREE},
+ {"Committed Count", 120, ID_DUMPPOOL_COMMITTED},
+ {"Committed Size", 120, ID_DUMPPOOL_COMMITTEDSIZE},
+};
+
+label_t g_showMemDump_DetailLabels[] =
+{
+ {"Allocation", 200, ID_DUMPDETAIL_ALLOCATION},
+ {"Current Size", 120, ID_DUMPDETAIL_CURRENTSIZE},
+ {"Peak Size", 120, ID_DUMPDETAIL_PEAKSIZE},
+ {"Total Allocations", 120, ID_DUMPDETAIL_TOTALSIZE},
+ {"Overhead Size", 120, ID_DUMPDETAIL_OVERHEAD},
+ {"Peak Overhead Size", 120, ID_DUMPDETAIL_PEAKOVERHEAD},
+ {"Time (ms)", 120, ID_DUMPDETAIL_TIME},
+ {"Current Count", 120, ID_DUMPDETAIL_CURRENTCOUNT},
+ {"Peak Count", 120, ID_DUMPDETAIL_PEAKCOUNT},
+ {"Total Count", 120, ID_DUMPDETAIL_TOTALCOUNT},
+ {"<=16 bytes", 100, ID_DUMPDETAIL_LTE16},
+ {"17-32 bytes", 100, ID_DUMPDETAIL_LTE32},
+ {"33-128 bytes", 100, ID_DUMPDETAIL_LTE128},
+ {"129-1024 bytes", 100, ID_DUMPDETAIL_LTE1024},
+ {"> 1024 bytes", 100, ID_DUMPDETAIL_GT1024},
+};
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_FormatSize
+//
+//-----------------------------------------------------------------------------
+char *ShowMemDump_FormatSize( int size, char *pBuff, bool bUnits )
+{
+ switch ( g_showMemDump_showBytes )
+ {
+ case SHOW_BYTES:
+ sprintf( pBuff, "%d", size );
+ break;
+
+ case SHOW_KILOBYTES:
+ sprintf( pBuff, "%.2f", (float)size/1024.0f );
+ if ( bUnits )
+ strcat( pBuff, " K");
+ break;
+
+ case SHOW_MEGABYTES:
+ sprintf( pBuff, "%.2f", (float)size/(1024.0f*1024.0f) );
+ if ( bUnits )
+ strcat( pBuff, " MB");
+ break;
+ }
+
+ return pBuff;
+}
+
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_SaveConfig()
+{
+ char buff[256];
+
+ Sys_SetRegistryInteger( "showMemDumpSortColumn", g_showMemDump_sortColumn );
+ Sys_SetRegistryInteger( "showMemDumpSortDescending", g_showMemDump_sortDescending );
+ Sys_SetRegistryInteger( "showMemDumpShowBytes", g_showMemDump_showBytes );
+
+ WINDOWPLACEMENT wp;
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_showMemDump_hWnd, &wp );
+ g_showMemDump_windowRect = wp.rcNormalPosition;
+
+ sprintf( buff, "%d %d %d %d", g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right, g_showMemDump_windowRect.bottom );
+ Sys_SetRegistryString( "showMemDumpWindowRect", buff );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ Sys_GetRegistryInteger( "showMemDumpSortColumn", 0, g_showMemDump_sortColumn );
+ Sys_GetRegistryInteger( "showMemDumpSortDescending", false, g_showMemDump_sortDescending );
+ Sys_GetRegistryInteger( "showMemDumpShowBytes", SHOW_KILOBYTES, g_showMemDump_showBytes );
+
+ Sys_GetRegistryString( "showMemDumpWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_showMemDump_windowRect.left, &g_showMemDump_windowRect.top, &g_showMemDump_windowRect.right, &g_showMemDump_windowRect.bottom );
+ if ( numArgs != 4 || g_showMemDump_windowRect.left < 0 || g_showMemDump_windowRect.top < 0 || g_showMemDump_windowRect.right < 0 || g_showMemDump_windowRect.bottom < 0 )
+ memset( &g_showMemDump_windowRect, 0, sizeof( g_showMemDump_windowRect ) );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_Clear
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_Clear()
+{
+ // delete all the list view entries
+ if ( g_showMemDump_hWnd )
+ {
+ ListView_DeleteAllItems( g_showMemDump_hWndListView );
+ }
+
+ if ( !g_showMemDump_pMemory )
+ return;
+
+ for ( int i=0; i<g_showMemDump_numMemory; i++ )
+ {
+ delete [] g_showMemDump_pMemory[i].detail.pAllocationName;
+ }
+
+ Sys_Free( g_showMemDump_pMemory );
+
+ g_showMemDump_pMemory = NULL;
+ g_showMemDump_numMemory = 0;
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_Export
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_Export()
+{
+ OPENFILENAME ofn;
+ char logFilename[MAX_PATH];
+ int retval;
+ FILE* fp;
+ int i;
+ char buff[64];
+
+ if ( g_showMemDump_format != FORMAT_DETAILS )
+ {
+ return;
+ }
+
+ memset( &ofn, 0, sizeof( ofn ) );
+ ofn.lStructSize = sizeof( ofn );
+ ofn.hwndOwner = g_showMemDump_hWnd;
+ ofn.lpstrFile = logFilename;
+ ofn.lpstrFile[0] = '\0';
+ ofn.nMaxFile = sizeof( logFilename );
+ ofn.lpstrFilter = "Excel CSV\0*.CSV\0All Files\0*.*\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = "c:\\";
+ ofn.Flags = OFN_PATHMUSTEXIST;
+
+ // display the Open dialog box.
+ retval = GetOpenFileName( &ofn );
+ if ( !retval )
+ return;
+
+ Sys_AddExtension( ".csv", logFilename, sizeof( logFilename ) );
+
+ fp = fopen( logFilename, "wt+" );
+ if ( !fp )
+ return;
+
+ // labels
+ fprintf( fp, "Allocation Type" );
+ fprintf( fp, ",Current Size" );
+ fprintf( fp, ",Peak Size" );
+ fprintf( fp, ",Total Allocations" );
+ fprintf( fp, ",Overhead Size" );
+ fprintf( fp, ",Peak Overhead Size" );
+ fprintf( fp, ",Time(ms)" );
+ fprintf( fp, ",Current Count" );
+ fprintf( fp, ",Peak Count" );
+ fprintf( fp, ",Total Count" );
+ fprintf( fp, ",<=16 Byte Allocations" );
+ fprintf( fp, ",17-32 Byte Allocations" );
+ fprintf( fp, ",33-128 Byte Allocations" );
+ fprintf( fp, ",129-1024 Byte Allocations" );
+ fprintf( fp, ",>1024 Byte Allocations" );
+ fprintf( fp, "\n" );
+
+ // dump to the log
+ for ( i=0; i<g_showMemDump_numMemory; i++ )
+ {
+ fprintf( fp, "\"%s\"", g_showMemDump_pMemory[i].detail.pAllocationName );
+ fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, buff, false ) );
+ fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, buff, false ) );
+ fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, buff, false ) );
+ fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, buff, false ) );
+ fprintf( fp, ",%s", ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, buff, false ) );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.time );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.currentCount );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.peakCount );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.totalCount );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte16 );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte32 );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte128 );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.lte1024 );
+ fprintf( fp, ",%d", g_showMemDump_pMemory[i].detail.gt1024 );
+ fprintf( fp, "\n" );
+ }
+
+ fclose( fp );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_Summary
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_Summary()
+{
+ char buff[1024];
+ int i;
+
+ if ( g_showMemDump_format != FORMAT_DETAILS )
+ {
+ return;
+ }
+
+ int currentSize = 0;
+ int peakSize = 0;
+ int totalSize = 0;
+ int overheadSize = 0;
+ int peakOverheadSize = 0;
+ int time = 0;
+ int currentCount = 0;
+ int peakCount = 0;
+ int totalCount = 0;
+ int lte16 = 0;
+ int lte32 = 0;
+ int lte128 = 0;
+ int lte1024 = 0;
+ int gt1024 = 0;
+
+ // tally the totals
+ for (i=0; i<g_showMemDump_numMemory; i++)
+ {
+ if ( !strnicmp( g_showMemDump_pMemory[i].detail.pAllocationName, "Totals,", 7 ) )
+ continue;
+
+ currentSize += g_showMemDump_pMemory[i].detail.currentSize;
+ peakSize += g_showMemDump_pMemory[i].detail.peakSize;
+ totalSize += g_showMemDump_pMemory[i].detail.totalSize;
+ overheadSize += g_showMemDump_pMemory[i].detail.overheadSize;
+ peakOverheadSize += g_showMemDump_pMemory[i].detail.peakOverheadSize;
+ time += g_showMemDump_pMemory[i].detail.time;
+ currentCount += g_showMemDump_pMemory[i].detail.currentCount;
+ peakCount += g_showMemDump_pMemory[i].detail.peakCount;
+ totalCount += g_showMemDump_pMemory[i].detail.totalCount;
+ lte16 += g_showMemDump_pMemory[i].detail.lte16;
+ lte32 += g_showMemDump_pMemory[i].detail.lte32;
+ lte128 += g_showMemDump_pMemory[i].detail.lte128;
+ lte1024 += g_showMemDump_pMemory[i].detail.lte1024;
+ gt1024 += g_showMemDump_pMemory[i].detail.gt1024;
+ }
+
+ sprintf(
+ buff,
+ "Entries:\t\t\t%d\n"
+ "Current Size:\t\t%.2f MB\n"
+ "Peak Size:\t\t%.2f MB\n"
+ "Total Size:\t\t%.2f MB\n"
+ "Overhead Size:\t\t%d\n"
+ "Peak Overhead Size:\t%d\n"
+ "Time:\t\t\t%d\n"
+ "Current Count:\t\t%d\n"
+ "Peak Count:\t\t%d\n"
+ "Total Count:\t\t%d\n"
+ "<= 16:\t\t\t%d\n"
+ "17-32:\t\t\t%d\n"
+ "33-128:\t\t\t%d\n"
+ "129-1024:\t\t%d\n"
+ "> 1024:\t\t\t%d\n",
+ g_showMemDump_numMemory,
+ (float)currentSize/( 1024.0F*1024.0F ),
+ (float)peakSize/( 1024.0F*1024.0F ),
+ (float)totalSize/( 1024.0F*1024.0F ),
+ overheadSize,
+ peakOverheadSize,
+ time,
+ currentCount,
+ peakCount,
+ totalCount,
+ lte16,
+ lte32,
+ lte128,
+ lte1024,
+ gt1024 );
+
+ MessageBox( g_showMemDump_hWnd, buff, "Memory Dump Summary", MB_OK|MB_APPLMODAL );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_SetTitle
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_SetTitle()
+{
+ if ( g_showMemDump_hWnd )
+ {
+ SetWindowText( g_showMemDump_hWnd, "Memory Dump" );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_CompareFunc
+//
+//-----------------------------------------------------------------------------
+int CALLBACK ShowMemDump_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
+{
+ memory_t* pMemoryA = (memory_t*)lParam1;
+ memory_t* pMemoryB = (memory_t*)lParam2;
+
+ int sort = 0;
+
+ if ( g_showMemDump_format == FORMAT_POOLS )
+ {
+ switch ( g_showMemDump_sortColumn )
+ {
+ case ID_DUMPPOOL_POOL:
+ sort = pMemoryA->pool.pool - pMemoryB->pool.pool;
+ break;
+
+ case ID_DUMPPOOL_SIZE:
+ sort = pMemoryA->pool.size - pMemoryB->pool.size;
+ break;
+
+ case ID_DUMPPOOL_ALLOCATED:
+ sort = pMemoryA->pool.allocated - pMemoryB->pool.allocated;
+ break;
+
+ case ID_DUMPPOOL_FREE:
+ sort = pMemoryA->pool.free - pMemoryB->pool.free;
+ break;
+
+ case ID_DUMPPOOL_COMMITTED:
+ sort = pMemoryA->pool.committed - pMemoryB->pool.committed;
+ break;
+
+ case ID_DUMPPOOL_COMMITTEDSIZE:
+ sort = pMemoryA->pool.committedSize - pMemoryB->pool.committedSize;
+ break;
+ }
+ }
+ else
+ {
+ switch ( g_showMemDump_sortColumn )
+ {
+ case ID_DUMPDETAIL_ALLOCATION:
+ sort = stricmp( pMemoryA->detail.pAllocationName, pMemoryB->detail.pAllocationName );
+ break;
+
+ case ID_DUMPDETAIL_CURRENTSIZE:
+ sort = pMemoryA->detail.currentSize - pMemoryB->detail.currentSize;
+ break;
+
+ case ID_DUMPDETAIL_PEAKSIZE:
+ sort = pMemoryA->detail.peakSize - pMemoryB->detail.peakSize;
+ break;
+
+ case ID_DUMPDETAIL_TOTALSIZE:
+ sort = pMemoryA->detail.totalSize - pMemoryB->detail.totalSize;
+ break;
+
+ case ID_DUMPDETAIL_OVERHEAD:
+ sort = pMemoryA->detail.overheadSize - pMemoryB->detail.overheadSize;
+ break;
+
+ case ID_DUMPDETAIL_PEAKOVERHEAD:
+ sort = pMemoryA->detail.peakOverheadSize - pMemoryB->detail.peakOverheadSize;
+ break;
+
+ case ID_DUMPDETAIL_TIME:
+ sort = pMemoryA->detail.time - pMemoryB->detail.time;
+ break;
+
+ case ID_DUMPDETAIL_CURRENTCOUNT:
+ sort = pMemoryA->detail.currentCount - pMemoryB->detail.currentCount;
+ break;
+
+ case ID_DUMPDETAIL_PEAKCOUNT:
+ sort = pMemoryA->detail.peakCount - pMemoryB->detail.peakCount;
+ break;
+
+ case ID_DUMPDETAIL_TOTALCOUNT:
+ sort = pMemoryA->detail.totalCount - pMemoryB->detail.totalCount;
+ break;
+
+ case ID_DUMPDETAIL_LTE16:
+ sort = pMemoryA->detail.lte16 - pMemoryB->detail.lte16;
+ break;
+
+ case ID_DUMPDETAIL_LTE32:
+ sort = pMemoryA->detail.lte32 - pMemoryB->detail.lte32;
+ break;
+
+ case ID_DUMPDETAIL_LTE128:
+ sort = pMemoryA->detail.lte128 - pMemoryB->detail.lte128;
+ break;
+
+ case ID_DUMPDETAIL_LTE1024:
+ sort = pMemoryA->detail.lte1024 - pMemoryB->detail.lte1024;
+ break;
+
+ case ID_DUMPDETAIL_GT1024:
+ sort = pMemoryA->detail.gt1024 - pMemoryB->detail.gt1024;
+ break;
+ }
+ }
+
+ // flip the sort order
+ if ( g_showMemDump_sortDescending )
+ {
+ sort *= -1;
+ }
+
+ return ( sort );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_SortItems
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_SortItems()
+{
+ LVITEM lvitem;
+ memory_t *pMemory;
+ int i;
+
+ if ( !g_showMemDump_hWnd )
+ {
+ // only sort if window is visible
+ return;
+ }
+
+ ListView_SortItems( g_showMemDump_hWndListView, ShowMemDump_CompareFunc, 0 );
+
+ memset( &lvitem, 0, sizeof( lvitem ) );
+ lvitem.mask = LVIF_PARAM;
+
+ // get each item and reset its list index
+ int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView );
+ for ( i=0; i<itemCount; i++ )
+ {
+ lvitem.iItem = i;
+ ListView_GetItem( g_showMemDump_hWndListView, &lvitem );
+
+ pMemory = (memory_t*)lvitem.lParam;
+ pMemory->listIndex = i;
+ }
+
+ int count;
+ label_t* pLabels;
+ if ( g_showMemDump_format == FORMAT_POOLS )
+ {
+ count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] );
+ pLabels = g_showMemDump_PoolLabels;
+ }
+ else
+ {
+ count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] );
+ pLabels = g_showMemDump_DetailLabels;
+ }
+
+ // update list view columns with sort key
+ for ( i = 0; i < count; i++ )
+ {
+ char symbol;
+ LVCOLUMN lvc;
+
+ if ( i == g_showMemDump_sortColumn )
+ symbol = g_showMemDump_sortDescending ? '<' : '>';
+ else
+ symbol = ' ';
+ sprintf( pLabels[i].nameBuff, "%s %c", pLabels[i].name, symbol );
+
+ memset( &lvc, 0, sizeof( lvc ) );
+ lvc.mask = LVCF_TEXT;
+ lvc.pszText = (LPSTR)pLabels[i].nameBuff;
+
+ ListView_SetColumn( g_showMemDump_hWndListView, i, &lvc );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_FormatItems
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_FormatItems()
+{
+ if ( g_showMemDump_format == FORMAT_POOLS )
+ {
+ for ( int i = 0; i < g_showMemDump_numMemory; i++ )
+ {
+ sprintf( g_showMemDump_pMemory[i].pool.sizeBuff, "%d", g_showMemDump_pMemory[i].pool.size );
+ ShowMemDump_FormatSize( g_showMemDump_pMemory[i].pool.committedSize, g_showMemDump_pMemory[i].pool.committedSizeBuff, true );
+ }
+ }
+ else
+ {
+ for ( int i = 0; i < g_showMemDump_numMemory; i++ )
+ {
+ ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.currentSize, g_showMemDump_pMemory[i].detail.currentSizeBuff, true );
+ ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakSize, g_showMemDump_pMemory[i].detail.peakSizeBuff, true );
+ ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.totalSize, g_showMemDump_pMemory[i].detail.totalSizeBuff, true );
+ ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.overheadSize, g_showMemDump_pMemory[i].detail.overheadSizeBuff, true );
+ ShowMemDump_FormatSize( g_showMemDump_pMemory[i].detail.peakOverheadSize, g_showMemDump_pMemory[i].detail.peakOverheadSizeBuff, true );
+ }
+ }
+
+ ShowMemDump_SortItems();
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_AddViewItem
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_AddViewItem( memory_t* pMemory )
+{
+ LVITEM lvi;
+
+ if ( !g_showMemDump_hWnd )
+ {
+ // only valid if log window is visible
+ return;
+ }
+
+ // update the text callback buffers
+ if ( g_showMemDump_format == FORMAT_POOLS )
+ {
+ sprintf( pMemory->pool.sizeBuff, "%d", pMemory->pool.size );
+ sprintf( pMemory->pool.poolBuff, "%d", pMemory->pool.pool );
+ sprintf( pMemory->pool.allocatedBuff, "%d", pMemory->pool.allocated );
+ sprintf( pMemory->pool.freeBuff, "%d", pMemory->pool.free );
+ sprintf( pMemory->pool.committedBuff, "%d", pMemory->pool.committed );
+ ShowMemDump_FormatSize( pMemory->pool.committedSize, pMemory->pool.committedSizeBuff, true );
+ }
+ else
+ {
+ ShowMemDump_FormatSize( pMemory->detail.currentSize, pMemory->detail.currentSizeBuff, true );
+ ShowMemDump_FormatSize( pMemory->detail.peakSize, pMemory->detail.peakSizeBuff, true );
+ ShowMemDump_FormatSize( pMemory->detail.totalSize, pMemory->detail.totalSizeBuff, true );
+ ShowMemDump_FormatSize( pMemory->detail.overheadSize, pMemory->detail.overheadSizeBuff, true );
+ ShowMemDump_FormatSize( pMemory->detail.peakOverheadSize, pMemory->detail.peakOverheadSizeBuff, true );
+ sprintf( pMemory->detail.timeBuff, "%d", pMemory->detail.time );
+ sprintf( pMemory->detail.currentCountBuff, "%d", pMemory->detail.currentCount );
+ sprintf( pMemory->detail.peakCountBuff, "%d", pMemory->detail.peakCount );
+ sprintf( pMemory->detail.totalCountBuff, "%d", pMemory->detail.totalCount );
+ sprintf( pMemory->detail.lte16Buff, "%d", pMemory->detail.lte16 );
+ sprintf( pMemory->detail.lte32Buff, "%d", pMemory->detail.lte32 );
+ sprintf( pMemory->detail.lte128Buff, "%d", pMemory->detail.lte128 );
+ sprintf( pMemory->detail.lte1024Buff, "%d", pMemory->detail.lte1024 );
+ sprintf( pMemory->detail.gt1024Buff, "%d", pMemory->detail.gt1024 );
+ }
+
+ int itemCount = ListView_GetItemCount( g_showMemDump_hWndListView );
+
+ // setup and insert at end of list
+ memset( &lvi, 0, sizeof( lvi ) );
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = itemCount;
+ lvi.iSubItem = 0;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = (LPARAM)pMemory;
+
+ // insert and set the real index
+ pMemory->listIndex = ListView_InsertItem( g_showMemDump_hWndListView, &lvi );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_Refresh
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_Refresh()
+{
+ // send the command to application which replies with list data
+ if ( g_connectedToApp )
+ {
+ ProcessCommand( "mem_dump" );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_RefreshView
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_RefreshView()
+{
+ if ( strlen( g_showMemDump_currentFilename ) == 0 )
+ {
+ // first time
+ ShowMemDump_Refresh();
+ return;
+ }
+
+ // get current file
+ int fileSize;
+ char *pBuffer;
+ bool bSuccess = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer );
+ if ( !bSuccess )
+ {
+ // stale, try again
+ ShowMemDump_Refresh();
+ return;
+ }
+
+ // parse and update view
+ ShowMemDump_Parse( pBuffer, fileSize );
+
+ Sys_Free( pBuffer );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_PopulateList
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_PopulateList()
+{
+ // delete previous labels
+ while ( 1 )
+ {
+ if ( !ListView_DeleteColumn( g_showMemDump_hWndListView, 0 ) )
+ {
+ break;
+ }
+ }
+
+ int count;
+ label_t* pLabels;
+ if ( g_showMemDump_format == FORMAT_POOLS )
+ {
+ count = sizeof( g_showMemDump_PoolLabels )/sizeof( g_showMemDump_PoolLabels[0] );
+ pLabels = g_showMemDump_PoolLabels;
+ }
+ else
+ {
+ count = sizeof( g_showMemDump_DetailLabels )/sizeof( g_showMemDump_DetailLabels[0] );
+ pLabels = g_showMemDump_DetailLabels;
+ }
+
+ // init list view columns
+ for ( int i = 0; i < count; i++ )
+ {
+ LVCOLUMN lvc;
+ memset( &lvc, 0, sizeof( lvc ) );
+
+ lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
+ lvc.iSubItem = 0;
+ lvc.cx = pLabels[i].width;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.pszText = ( LPSTR )pLabels[i].name;
+
+ ListView_InsertColumn( g_showMemDump_hWndListView, i, &lvc );
+ }
+
+ // populate list view
+ for ( int i = 0; i < g_showMemDump_numMemory; i++ )
+ {
+ ShowMemDump_AddViewItem( &g_showMemDump_pMemory[i] );
+ }
+
+ ShowMemDump_SortItems();
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_SizeWindow
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_SizeWindow( HWND hwnd, int cx, int cy )
+{
+ if ( cx==0 || cy==0 )
+ {
+ RECT rcClient;
+ GetClientRect( hwnd, &rcClient );
+ cx = rcClient.right;
+ cy = rcClient.bottom;
+ }
+
+ // position the ListView
+ SetWindowPos( g_showMemDump_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK ShowMemDump_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ memory_t* pMemory;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ return 0L;
+
+ case WM_DESTROY:
+ ShowMemDump_SaveConfig();
+
+ g_showMemDump_hWnd = NULL;
+ return 0L;
+
+ case WM_INITMENU:
+ CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_BYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_BYTES ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_KILOBYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_KILOBYTES ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_MEGABYTES, MF_BYCOMMAND | ( g_showMemDump_showBytes == SHOW_MEGABYTES ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( (HMENU)wParam, IDM_OPTIONS_COLLAPSEOUTPUT, MF_BYCOMMAND | ( g_showMemDump_bCollapseOutput ? MF_CHECKED : MF_UNCHECKED ) );
+ return 0L;
+
+ case WM_SIZE:
+ ShowMemDump_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) );
+ return 0L;
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lParam )->code )
+ {
+ case LVN_COLUMNCLICK:
+ NMLISTVIEW* pnmlv;
+ pnmlv = ( NMLISTVIEW* )lParam;
+ if ( g_showMemDump_sortColumn == pnmlv->iSubItem )
+ {
+ // user has clicked on same column - flip the sort
+ g_showMemDump_sortDescending ^= 1;
+ }
+ else
+ {
+ // sort by new column
+ g_showMemDump_sortColumn = pnmlv->iSubItem;
+ }
+ ShowMemDump_SortItems();
+ return 0L;
+
+ case LVN_GETDISPINFO:
+ NMLVDISPINFO* plvdi;
+ plvdi = (NMLVDISPINFO*)lParam;
+ pMemory = (memory_t*)plvdi->item.lParam;
+
+ if ( g_showMemDump_format == FORMAT_POOLS )
+ {
+ switch ( plvdi->item.iSubItem )
+ {
+ case ID_DUMPPOOL_POOL:
+ plvdi->item.pszText = pMemory->pool.poolBuff;
+ return 0L;
+
+ case ID_DUMPPOOL_SIZE:
+ plvdi->item.pszText = pMemory->pool.sizeBuff;
+ return 0L;
+
+ case ID_DUMPPOOL_ALLOCATED:
+ plvdi->item.pszText = pMemory->pool.allocatedBuff;
+ return 0L;
+
+ case ID_DUMPPOOL_FREE:
+ plvdi->item.pszText = pMemory->pool.freeBuff;
+ return 0L;
+
+ case ID_DUMPPOOL_COMMITTED:
+ plvdi->item.pszText = pMemory->pool.committedBuff;
+ return 0L;
+
+ case ID_DUMPPOOL_COMMITTEDSIZE:
+ plvdi->item.pszText = pMemory->pool.committedSizeBuff;
+ return 0L;
+ }
+ }
+ else
+ {
+ switch ( plvdi->item.iSubItem )
+ {
+ case ID_DUMPDETAIL_ALLOCATION:
+ plvdi->item.pszText = pMemory->detail.pAllocationName;
+ return 0L;
+
+ case ID_DUMPDETAIL_CURRENTSIZE:
+ plvdi->item.pszText = pMemory->detail.currentSizeBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_PEAKSIZE:
+ plvdi->item.pszText = pMemory->detail.peakSizeBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_TOTALSIZE:
+ plvdi->item.pszText = pMemory->detail.totalSizeBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_OVERHEAD:
+ plvdi->item.pszText = pMemory->detail.overheadSizeBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_PEAKOVERHEAD:
+ plvdi->item.pszText = pMemory->detail.peakOverheadSizeBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_TIME:
+ plvdi->item.pszText = pMemory->detail.timeBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_CURRENTCOUNT:
+ plvdi->item.pszText = pMemory->detail.currentCountBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_PEAKCOUNT:
+ plvdi->item.pszText = pMemory->detail.peakCountBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_TOTALCOUNT:
+ plvdi->item.pszText = pMemory->detail.totalCountBuff;
+ return 0L;
+
+ case ID_DUMPDETAIL_LTE16:
+ plvdi->item.pszText = pMemory->detail.lte16Buff;
+ return 0L;
+
+ case ID_DUMPDETAIL_LTE32:
+ plvdi->item.pszText = pMemory->detail.lte32Buff;
+ return 0L;
+
+ case ID_DUMPDETAIL_LTE128:
+ plvdi->item.pszText = pMemory->detail.lte128Buff;
+ return 0L;
+
+ case ID_DUMPDETAIL_LTE1024:
+ plvdi->item.pszText = pMemory->detail.lte1024Buff;
+ return 0L;
+
+ case ID_DUMPDETAIL_GT1024:
+ plvdi->item.pszText = pMemory->detail.gt1024Buff;
+ return 0L;
+
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_OPTIONS_REFRESH:
+ ShowMemDump_Refresh();
+ return 0L;
+
+ case IDM_OPTIONS_EXPORT:
+ ShowMemDump_Export();
+ return 0L;
+
+ case IDM_OPTIONS_SUMMARY:
+ ShowMemDump_Summary();
+ return 0L;
+
+ case IDM_OPTIONS_BYTES:
+ g_showMemDump_showBytes = SHOW_BYTES;
+ ShowMemDump_FormatItems();
+ return 0L;
+
+ case IDM_OPTIONS_KILOBYTES:
+ g_showMemDump_showBytes = SHOW_KILOBYTES;
+ ShowMemDump_FormatItems();
+ return 0L;
+
+ case IDM_OPTIONS_MEGABYTES:
+ g_showMemDump_showBytes = SHOW_MEGABYTES;
+ ShowMemDump_FormatItems();
+ return 0L;
+
+ case IDM_OPTIONS_COLLAPSEOUTPUT:
+ g_showMemDump_bCollapseOutput = !g_showMemDump_bCollapseOutput;
+ ShowMemDump_RefreshView();
+ return 0L;
+ }
+ break;
+ }
+
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_Init
+//
+//-----------------------------------------------------------------------------
+bool ShowMemDump_Init()
+{
+ // set up our window class
+ WNDCLASS wndclass;
+
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ShowMemDump_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_SHOWMEMORYDUMP );
+ wndclass.lpszClassName = "SHOWMEMDUMPCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ ShowMemDump_LoadConfig();
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_Open
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_Open()
+{
+ RECT clientRect;
+ HWND hWnd;
+
+ if ( g_showMemDump_hWnd )
+ {
+ // only one instance
+ if ( IsIconic( g_showMemDump_hWnd ) )
+ ShowWindow( g_showMemDump_hWnd, SW_RESTORE );
+ SetForegroundWindow( g_showMemDump_hWnd );
+ return;
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "SHOWMEMDUMPCLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 700,
+ 400,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ NULL );
+ g_showMemDump_hWnd = hWnd;
+
+ GetClientRect( g_showMemDump_hWnd, &clientRect );
+ hWnd = CreateWindow(
+ WC_LISTVIEW,
+ "",
+ WS_VISIBLE|WS_CHILD|LVS_REPORT,
+ 0,
+ 0,
+ clientRect.right-clientRect.left,
+ clientRect.bottom-clientRect.top,
+ g_showMemDump_hWnd,
+ ( HMENU )ID_SHOWMEMDUMP_LISTVIEW,
+ g_hInstance,
+ NULL );
+ g_showMemDump_hWndListView = hWnd;
+
+ ListView_SetBkColor( g_showMemDump_hWndListView, g_backgroundColor );
+ ListView_SetTextBkColor( g_showMemDump_hWndListView, g_backgroundColor );
+
+ DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP;
+ ListView_SetExtendedListViewStyleEx( g_showMemDump_hWndListView, style, style );
+
+ ShowMemDump_PopulateList();
+
+ ShowMemDump_SetTitle();
+
+ if ( g_showMemDump_windowRect.right && g_showMemDump_windowRect.bottom )
+ MoveWindow( g_showMemDump_hWnd, g_showMemDump_windowRect.left, g_showMemDump_windowRect.top, g_showMemDump_windowRect.right-g_showMemDump_windowRect.left, g_showMemDump_windowRect.bottom-g_showMemDump_windowRect.top, FALSE );
+ ShowWindow( g_showMemDump_hWnd, SHOW_OPENWINDOW );
+
+ // get data from application
+ ShowMemDump_Refresh();
+}
+
+//-----------------------------------------------------------------------------
+// MatchAllocationName
+//
+//-----------------------------------------------------------------------------
+void MatchAllocationName( memory_t *&pMemory )
+{
+ memory_t *curEntry = g_showMemDump_pMemory;
+ for ( int i=0; i<g_showMemDump_numMemory; ++i )
+ {
+ if ( !strcmp( curEntry->detail.pAllocationName, pMemory->detail.pAllocationName ) )
+ {
+ pMemory = curEntry;
+ return;
+ }
+ ++curEntry;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowMemDump_Parse
+//
+//-----------------------------------------------------------------------------
+void ShowMemDump_Parse( const char *pBuffer, int fileSize )
+{
+ char *ptr;
+ char *pToken;
+ char *pLineStart;
+ int numLines;
+ int size;
+ memory_t *pMemory;
+
+ // remove old entries
+ ShowMemDump_Clear();
+
+ if ( !pBuffer || !fileSize )
+ {
+ // no valid data
+ return;
+ }
+
+ Sys_SetScriptData( pBuffer, fileSize );
+
+ // skip first line, column headers
+ Sys_SkipRestOfLine();
+
+ Sys_SaveParser();
+
+ // count lines
+ numLines = 0;
+ while ( 1 )
+ {
+ pToken = Sys_GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+ numLines++;
+ Sys_SkipRestOfLine();
+ }
+
+ // each line represents one complete entry
+ g_showMemDump_pMemory = (memory_t *)Sys_Alloc( numLines * sizeof( memory_t ) );
+
+ Sys_RestoreParser();
+
+ pMemory = g_showMemDump_pMemory;
+
+ int format = 0;
+ if ( !V_strnicmp( g_sys_scriptptr, "pool ", 5 ) )
+ {
+ // parse as pool stats
+ format = FORMAT_POOLS;
+
+ while ( 1 )
+ {
+ // find start of relevant data
+ bool bFound = false;
+ while ( 1 )
+ {
+ pToken = Sys_GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+ if ( !V_stricmp( pToken, "size:" ) )
+ {
+ bFound = true;
+ break;
+ }
+ }
+ if ( !bFound )
+ {
+ break;
+ }
+
+ memset( pMemory, 0, sizeof( memory_t ) );
+
+ pMemory->pool.pool = g_showMemDump_numMemory;
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->pool.size = atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ if ( !V_stricmp( pToken, "allocated:" ) )
+ {
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->pool.allocated = atoi( pToken );
+ }
+ else
+ {
+ break;
+ }
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ if ( !V_stricmp( pToken, "free:" ) )
+ {
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->pool.free = atoi( pToken );
+ }
+ else
+ {
+ break;
+ }
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ if ( !V_stricmp( pToken, "committed:" ) )
+ {
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->pool.committed = atoi( pToken );
+ }
+ else
+ {
+ break;
+ }
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ if ( !V_stricmp( pToken, "committedsize:" ) )
+ {
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->pool.committedSize = atoi( pToken );
+ }
+ else
+ {
+ break;
+ }
+
+ pMemory++;
+ g_showMemDump_numMemory++;
+ if ( g_showMemDump_numMemory >= numLines )
+ break;
+ }
+ }
+ else
+ {
+ // parse as detail stats
+ format = FORMAT_DETAILS;
+
+ while ( 1 )
+ {
+ pLineStart = g_sys_scriptptr;
+
+ // can't tokenize, find start of parsable data
+ ptr = V_stristr( g_sys_scriptptr, ", line " );
+ if ( !ptr )
+ break;
+ g_sys_scriptptr = ptr + strlen( ", line " );
+
+ // advance past the expected line number
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( !g_showMemDump_bCollapseOutput )
+ {
+ size = g_sys_scriptptr-pLineStart;
+ }
+ else
+ {
+ size = ptr-pLineStart;
+ }
+
+ memset( pMemory, 0, sizeof(memory_t) );
+ memory_t *pCurRecordStart = pMemory;
+
+ pMemory->detail.pAllocationName = new char[size+1];
+ memcpy( pMemory->detail.pAllocationName, pLineStart, size );
+ pMemory->detail.pAllocationName[size] = '\0';
+ Sys_NormalizePath( pMemory->detail.pAllocationName, false );
+
+ if ( g_showMemDump_bCollapseOutput )
+ {
+ MatchAllocationName( pMemory );
+ }
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.currentSize += (int)(1024.0f*atof( pToken ));
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.peakSize += (int)(1024.0f*atof( pToken ));
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.totalSize += (int)(1024.0f*atof( pToken ));
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.overheadSize += (int)(1024.0f*atof( pToken ));
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.peakOverheadSize += (int)(1024.0f*atof( pToken ));
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.time += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.currentCount += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.peakCount += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.totalCount += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.lte16 += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.lte32 += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.lte128 += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.lte1024 += atoi( pToken );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ break;
+ pMemory->detail.gt1024 += atoi( pToken );
+
+ Sys_SkipRestOfLine();
+
+ if( pMemory == pCurRecordStart )
+ {
+ pMemory++;
+ g_showMemDump_numMemory++;
+ }
+ else
+ {
+ pMemory = pCurRecordStart;
+ }
+
+ if ( g_showMemDump_numMemory >= numLines )
+ break;
+ }
+ }
+
+ if ( g_showMemDump_format != format )
+ {
+ // format change will cause list view change
+ g_showMemDump_format = format;
+ g_showMemDump_sortColumn = 0;
+ g_showMemDump_sortDescending = 0;
+ }
+
+ ShowMemDump_PopulateList();
+}
+
+//-----------------------------------------------------------------------------
+// rc_MemDump
+//
+// Sent from application with memory dump file
+//-----------------------------------------------------------------------------
+int rc_MemDump( char *pCommand )
+{
+ char* pToken;
+ int retVal;
+ int errCode = -1;
+ int fileSize;
+ char *pBuffer;
+
+ // get name of file
+ pToken = GetToken( &pCommand );
+ if ( !pToken[0] )
+ goto cleanUp;
+
+ // get file
+ strcpy( g_showMemDump_currentFilename, pToken );
+ retVal = LoadTargetFile( g_showMemDump_currentFilename, &fileSize, (void **)&pBuffer );
+
+ DebugCommand( "0x%8.8x = MemDump( %s )\n", retVal, g_showMemDump_currentFilename );
+
+ // parse and update view
+ ShowMemDump_Parse( pBuffer, fileSize );
+
+ Sys_Free( pBuffer );
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
diff --git a/utils/xbox/vxconsole/show_sounds.cpp b/utils/xbox/vxconsole/show_sounds.cpp
new file mode 100644
index 0000000..f54be8d
--- /dev/null
+++ b/utils/xbox/vxconsole/show_sounds.cpp
@@ -0,0 +1,778 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SHOW_SOUNDS.CPP
+//
+// Show Sounds Display.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define ID_SHOWSOUNDS_LISTVIEW 100
+
+// column id
+#define ID_SS_NAME 0
+#define ID_SS_PREFIX 1
+#define ID_SS_FORMAT 2
+#define ID_SS_RATE 3
+#define ID_SS_BITS 4
+#define ID_SS_CHANNELS 5
+#define ID_SS_SIZE 6
+#define ID_SS_STREAMED 7
+#define ID_SS_LOOPED 8
+#define ID_SS_LENGTH 9
+
+typedef struct
+{
+ int listIndex;
+ char *pName;
+ char *pPrefix;
+ char *pFormat;
+ int rate;
+ char rateBuff[16];
+ int bits;
+ char bitsBuff[16];
+ int channels;
+ char channelsBuff[16];
+ int numSamples;
+ int dataSize;
+ char dataSizeBuff[16];
+ int streamed;
+ char streamedBuff[16];
+ int looped;
+ char loopedBuff[16];
+ float length;
+ char lengthBuff[16];
+} sound_t;
+
+typedef struct
+{ const CHAR* name;
+ int width;
+ int subItemIndex;
+ CHAR nameBuff[32];
+} label_t;
+
+HWND g_showSounds_hWnd;
+HWND g_showSounds_hWndListView;
+RECT g_showSounds_windowRect;
+int g_showSounds_sortColumn;
+int g_showSounds_sortDescending;
+sound_t *g_showSounds_pSounds;
+int g_showSounds_numSounds;
+int g_showSounds_currentFrame;
+
+label_t g_showSounds_Labels[] =
+{
+ {"Name", 300, ID_SS_NAME},
+ {"Prefix", 80, ID_SS_PREFIX},
+ {"Format", 80, ID_SS_FORMAT},
+ {"Rate", 80, ID_SS_RATE},
+ {"Bits", 80, ID_SS_BITS},
+ {"Channels", 80, ID_SS_CHANNELS},
+ {"Size", 80, ID_SS_SIZE},
+ {"Streamed", 80, ID_SS_STREAMED},
+ {"Looped", 80, ID_SS_LOOPED},
+ {"Length", 80, ID_SS_LENGTH},
+};
+
+//-----------------------------------------------------------------------------
+// ShowSounds_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_SaveConfig()
+{
+ char buff[256];
+
+ Sys_SetRegistryInteger( "showSoundsSortColumn", g_showSounds_sortColumn );
+ Sys_SetRegistryInteger( "showSoundsSortDescending", g_showSounds_sortDescending );
+
+ WINDOWPLACEMENT wp;
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_showSounds_hWnd, &wp );
+ g_showSounds_windowRect = wp.rcNormalPosition;
+
+ sprintf( buff, "%d %d %d %d", g_showSounds_windowRect.left, g_showSounds_windowRect.top, g_showSounds_windowRect.right, g_showSounds_windowRect.bottom );
+ Sys_SetRegistryString( "showSoundsWindowRect", buff );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ Sys_GetRegistryInteger( "showSoundsSortColumn", ID_SS_NAME, g_showSounds_sortColumn );
+ Sys_GetRegistryInteger( "showSoundsSortDescending", false, g_showSounds_sortDescending );
+
+ Sys_GetRegistryString( "showSoundsWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_showSounds_windowRect.left, &g_showSounds_windowRect.top, &g_showSounds_windowRect.right, &g_showSounds_windowRect.bottom );
+ if ( numArgs != 4 || g_showSounds_windowRect.left < 0 || g_showSounds_windowRect.top < 0 || g_showSounds_windowRect.right < 0 || g_showSounds_windowRect.bottom < 0 )
+ memset( &g_showSounds_windowRect, 0, sizeof( g_showSounds_windowRect ) );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_Clear
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_Clear()
+{
+ // delete all the list view entries
+ if ( g_showSounds_hWnd )
+ ListView_DeleteAllItems( g_showSounds_hWndListView );
+
+ if ( !g_showSounds_pSounds )
+ return;
+
+ for ( int i=0; i<g_showSounds_numSounds; i++ )
+ {
+ free( g_showSounds_pSounds[i].pName );
+ free( g_showSounds_pSounds[i].pPrefix );
+ free( g_showSounds_pSounds[i].pFormat );
+ }
+
+ g_showSounds_pSounds = NULL;
+ g_showSounds_numSounds = 0;
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_Export
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_Export()
+{
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_Summary
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_Summary()
+{
+ char buff[1024];
+
+ // tally the totals
+ int totalStreamed = 0;
+ int totalStatic = 0;
+ for ( int i=0; i<g_showSounds_numSounds; i++ )
+ {
+ if ( g_showSounds_pSounds[i].streamed )
+ {
+ totalStreamed += g_showSounds_pSounds[i].dataSize;
+ }
+ else
+ {
+ totalStatic += g_showSounds_pSounds[i].dataSize;
+ }
+ }
+
+ sprintf(
+ buff,
+ "Entries:\t\t\t%d\n"
+ "Static Memory:\t\t%.2f MB\n"
+ "Streamed Memory:\t\t%.2f MB\n",
+ g_showSounds_numSounds,
+ ( float )totalStatic/( 1024.0F*1024.0F ),
+ ( float )totalStreamed/( 1024.0F*1024.0F ) );
+
+ MessageBox( g_showSounds_hWnd, buff, "Sound Summary", MB_OK|MB_APPLMODAL );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_Play
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_Play()
+{
+ char command[256];
+ sound_t* pSound;
+ int selection;
+ LVITEM lvitem;
+
+ if ( !g_connectedToApp )
+ return;
+
+ selection = ListView_GetSelectionMark( g_showSounds_hWndListView );
+ if ( selection == -1 )
+ return;
+
+ memset( &lvitem, 0, sizeof( lvitem ) );
+ lvitem.mask = LVIF_PARAM;
+ lvitem.iItem = selection;
+ ListView_GetItem( g_showSounds_hWndListView, &lvitem );
+
+ pSound = ( sound_t* )lvitem.lParam;
+
+ sprintf( command, "play %s%s", pSound->pPrefix, pSound->pName );
+
+ // send the command to application
+ ProcessCommand( command );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_CompareFunc
+//
+//-----------------------------------------------------------------------------
+int CALLBACK ShowSounds_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
+{
+ sound_t* pSoundA = ( sound_t* )lParam1;
+ sound_t* pSoundB = ( sound_t* )lParam2;
+
+ int sort = 0;
+ switch ( g_showSounds_sortColumn )
+ {
+ case ID_SS_NAME:
+ sort = stricmp( pSoundA->pName, pSoundB->pName );
+ break;
+
+ case ID_SS_PREFIX:
+ sort = stricmp( pSoundA->pPrefix, pSoundB->pPrefix );
+ break;
+
+ case ID_SS_FORMAT:
+ sort = stricmp( pSoundA->pFormat, pSoundB->pFormat );
+ break;
+
+ case ID_SS_RATE:
+ sort = pSoundA->rate - pSoundB->rate;
+ break;
+
+ case ID_SS_BITS:
+ sort = pSoundA->bits - pSoundB->bits;
+ break;
+
+ case ID_SS_CHANNELS:
+ sort = stricmp( pSoundA->channelsBuff, pSoundB->channelsBuff );
+ break;
+
+ case ID_SS_SIZE:
+ sort = pSoundA->dataSize - pSoundB->dataSize;
+ break;
+
+ case ID_SS_STREAMED:
+ sort = stricmp( pSoundA->streamedBuff, pSoundB->streamedBuff );
+ break;
+
+ case ID_SS_LOOPED:
+ sort = stricmp( pSoundA->loopedBuff, pSoundB->loopedBuff );
+ break;
+
+ case ID_SS_LENGTH:
+ if ( pSoundA->length < pSoundB->length )
+ sort = -1;
+ else if ( pSoundA->length == pSoundB->length )
+ sort = 0;
+ else
+ sort = 1;
+ break;
+ }
+
+ // flip the sort order
+ if ( g_showSounds_sortDescending )
+ sort *= -1;
+
+ return ( sort );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_SortItems
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_SortItems()
+{
+ LVITEM lvitem;
+ sound_t *pSound;
+ int i;
+
+ if ( !g_showSounds_hWnd )
+ {
+ // only sort if window is visible
+ return;
+ }
+
+ ListView_SortItems( g_showSounds_hWndListView, ShowSounds_CompareFunc, 0 );
+
+ memset( &lvitem, 0, sizeof( lvitem ) );
+ lvitem.mask = LVIF_PARAM;
+
+ // get each item and reset its list index
+ int itemCount = ListView_GetItemCount( g_showSounds_hWndListView );
+ for ( i=0; i<itemCount; i++ )
+ {
+ lvitem.iItem = i;
+ ListView_GetItem( g_showSounds_hWndListView, &lvitem );
+
+ pSound = ( sound_t* )lvitem.lParam;
+ pSound->listIndex = i;
+ }
+
+ // update list view columns with sort key
+ for ( i=0; i<sizeof( g_showSounds_Labels )/sizeof( g_showSounds_Labels[0] ); i++ )
+ {
+ char symbol;
+ LVCOLUMN lvc;
+
+ if ( i == g_showSounds_sortColumn )
+ symbol = g_showSounds_sortDescending ? '<' : '>';
+ else
+ symbol = ' ';
+ sprintf( g_showSounds_Labels[i].nameBuff, "%s %c", g_showSounds_Labels[i].name, symbol );
+
+ memset( &lvc, 0, sizeof( lvc ) );
+ lvc.mask = LVCF_TEXT;
+ lvc.pszText = ( LPSTR )g_showSounds_Labels[i].nameBuff;
+
+ ListView_SetColumn( g_showSounds_hWndListView, i, &lvc );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_AddViewItem
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_AddViewItem( sound_t* pSound )
+{
+ LVITEM lvi;
+
+ if ( !g_showSounds_hWnd )
+ {
+ // only valid if log window is visible
+ return;
+ }
+
+ // update the text callback buffers
+ if ( pSound->rate >= 0 )
+ sprintf( pSound->rateBuff, "%5.2f KHz", ( float )pSound->rate/1000.0f );
+ else
+ strcpy( pSound->rateBuff, "???" );
+
+ if ( pSound->bits >= 0 )
+ sprintf( pSound->bitsBuff, "%d", pSound->bits );
+ else
+ strcpy( pSound->bitsBuff, "???" );
+
+ if ( pSound->channels >= 1 )
+ strcpy( pSound->channelsBuff, pSound->channels == 2 ? "Stereo" : "Mono" );
+ else
+ strcpy( pSound->channelsBuff, "???" );
+
+ if ( pSound->dataSize >= 0 )
+ sprintf( pSound->dataSizeBuff, "%d", pSound->dataSize );
+ else
+ strcpy( pSound->dataSizeBuff, "???" );
+
+ if ( pSound->streamed >= 0 )
+ strcpy( pSound->streamedBuff, pSound->streamed ? "Stream" : "Static" );
+ else
+ strcpy( pSound->streamedBuff, "???" );
+
+ if ( pSound->looped >= 0 )
+ strcpy( pSound->loopedBuff, pSound->looped ? "Looped" : "One-Shot" );
+ else
+ strcpy( pSound->loopedBuff, "???" );
+
+ sprintf( pSound->lengthBuff, "%2.2d:%2.2d:%3.3d", ( int )pSound->length/60, ( int )pSound->length%60, ( int )( 1000*( pSound->length-( int )pSound->length ) )%1000 );
+
+ int itemCount = ListView_GetItemCount( g_showSounds_hWndListView );
+
+ // setup and insert at end of list
+ memset( &lvi, 0, sizeof( lvi ) );
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = itemCount;
+ lvi.iSubItem = 0;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = ( LPARAM )pSound;
+
+ // insert and set the real index
+ pSound->listIndex = ListView_InsertItem( g_showSounds_hWndListView, &lvi );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_Refresh
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_Refresh()
+{
+ char command[256];
+
+ strcpy( command, "vx_soundlist" );
+
+ // send the command to application which replies with list data
+ if ( g_connectedToApp )
+ ProcessCommand( command );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_SizeWindow
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_SizeWindow( HWND hwnd, int cx, int cy )
+{
+ if ( cx==0 || cy==0 )
+ {
+ RECT rcClient;
+ GetClientRect( hwnd, &rcClient );
+ cx = rcClient.right;
+ cy = rcClient.bottom;
+ }
+
+ // position the ListView
+ SetWindowPos( g_showSounds_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK ShowSounds_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ sound_t* pSound;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ return 0L;
+
+ case WM_DESTROY:
+ ShowSounds_SaveConfig();
+ g_showSounds_hWnd = NULL;
+ return 0L;
+
+ case WM_INITMENU:
+ return 0L;
+
+ case WM_SIZE:
+ ShowSounds_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) );
+ return 0L;
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lParam )->code )
+ {
+ case LVN_COLUMNCLICK:
+ NMLISTVIEW* pnmlv;
+ pnmlv = ( NMLISTVIEW* )lParam;
+ if ( g_showSounds_sortColumn == pnmlv->iSubItem )
+ {
+ // user has clicked on same column - flip the sort
+ g_showSounds_sortDescending ^= 1;
+ }
+ else
+ {
+ // sort by new column
+ g_showSounds_sortColumn = pnmlv->iSubItem;
+ }
+ ShowSounds_SortItems();
+ return 0L;
+
+ case LVN_GETDISPINFO:
+ NMLVDISPINFO* plvdi;
+ plvdi = ( NMLVDISPINFO* )lParam;
+ pSound = ( sound_t* )plvdi->item.lParam;
+ switch ( plvdi->item.iSubItem )
+ {
+ case ID_SS_NAME:
+ plvdi->item.pszText = pSound->pName;
+ return 0L;
+
+ case ID_SS_PREFIX:
+ plvdi->item.pszText = pSound->pPrefix;
+ return 0L;
+
+ case ID_SS_FORMAT:
+ plvdi->item.pszText = pSound->pFormat;
+ return 0L;
+
+ case ID_SS_RATE:
+ plvdi->item.pszText = pSound->rateBuff;
+ return 0L;
+
+ case ID_SS_BITS:
+ plvdi->item.pszText = pSound->bitsBuff;
+ return 0L;
+
+ case ID_SS_CHANNELS:
+ plvdi->item.pszText = pSound->channelsBuff;
+ return 0L;
+
+ case ID_SS_SIZE:
+ plvdi->item.pszText = pSound->dataSizeBuff;
+ return 0L;
+
+ case ID_SS_STREAMED:
+ plvdi->item.pszText = pSound->streamedBuff;
+ return 0L;
+
+ case ID_SS_LOOPED:
+ plvdi->item.pszText = pSound->loopedBuff;
+ return 0L;
+
+ case ID_SS_LENGTH:
+ plvdi->item.pszText = pSound->lengthBuff;
+ return 0L;
+
+ default:
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_OPTIONS_SUMMARY:
+ ShowSounds_Summary();
+ return 0L;
+
+ case IDM_OPTIONS_REFRESH:
+ ShowSounds_Refresh();
+ return 0L;
+
+ case IDM_OPTIONS_EXPORT:
+ ShowSounds_Export();
+ return 0L;
+
+ case IDM_OPTIONS_PLAYSOUND:
+ ShowSounds_Play();
+ return 0L;
+ }
+ break;
+ }
+
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_Init
+//
+//-----------------------------------------------------------------------------
+bool ShowSounds_Init()
+{
+ // set up our window class
+ WNDCLASS wndclass;
+
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ShowSounds_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_SHOWSOUNDS );
+ wndclass.lpszClassName = "SHOWSOUNDSCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ ShowSounds_LoadConfig();
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// ShowSounds_Open
+//
+//-----------------------------------------------------------------------------
+void ShowSounds_Open()
+{
+ RECT clientRect;
+ HWND hWnd;
+ int i;
+
+ if ( g_showSounds_hWnd )
+ {
+ // only one instance
+ if ( IsIconic( g_showSounds_hWnd ) )
+ ShowWindow( g_showSounds_hWnd, SW_RESTORE );
+ SetForegroundWindow( g_showSounds_hWnd );
+ return;
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "SHOWSOUNDSCLASS",
+ "Sounds",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 700,
+ 400,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ NULL );
+ g_showSounds_hWnd = hWnd;
+
+ GetClientRect( g_showSounds_hWnd, &clientRect );
+ hWnd = CreateWindow(
+ WC_LISTVIEW,
+ "",
+ WS_VISIBLE|WS_CHILD|LVS_REPORT|LVS_SHOWSELALWAYS|LVS_SINGLESEL,
+ 0,
+ 0,
+ clientRect.right-clientRect.left,
+ clientRect.bottom-clientRect.top,
+ g_showSounds_hWnd,
+ ( HMENU )ID_SHOWSOUNDS_LISTVIEW,
+ g_hInstance,
+ NULL );
+ g_showSounds_hWndListView = hWnd;
+
+ // init list view columns
+ for ( i=0; i<sizeof( g_showSounds_Labels )/sizeof( g_showSounds_Labels[0] ); i++ )
+ {
+ LVCOLUMN lvc;
+ memset( &lvc, 0, sizeof( lvc ) );
+
+ lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
+ lvc.iSubItem = 0;
+ lvc.cx = g_showSounds_Labels[i].width;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.pszText = ( LPSTR )g_showSounds_Labels[i].name;
+
+ ListView_InsertColumn( g_showSounds_hWndListView, i, &lvc );
+ }
+
+ ListView_SetBkColor( g_showSounds_hWndListView, g_backgroundColor );
+ ListView_SetTextBkColor( g_showSounds_hWndListView, g_backgroundColor );
+
+ DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP;
+ ListView_SetExtendedListViewStyleEx( g_showSounds_hWndListView, style, style );
+
+ // populate list view
+ for ( i=0; i<g_showSounds_numSounds; i++ )
+ ShowSounds_AddViewItem( &g_showSounds_pSounds[i] );
+ ShowSounds_SortItems();
+
+ if ( g_showSounds_windowRect.right && g_showSounds_windowRect.bottom )
+ MoveWindow( g_showSounds_hWnd, g_showSounds_windowRect.left, g_showSounds_windowRect.top, g_showSounds_windowRect.right-g_showSounds_windowRect.left, g_showSounds_windowRect.bottom-g_showSounds_windowRect.top, FALSE );
+ ShowWindow( g_showSounds_hWnd, SHOW_OPENWINDOW );
+
+ // get data from application
+ ShowSounds_Refresh();
+}
+
+//-----------------------------------------------------------------------------
+// rc_SoundList
+//
+// Sent from application with sound list
+//-----------------------------------------------------------------------------
+int rc_SoundList( char* commandPtr )
+{
+ char* cmdToken;
+ int numSounds;
+ int soundList;
+ int retAddr;
+ int retVal;
+ int errCode = -1;
+ xrSound_t* pLocalList;
+ int prefixLen;
+ char *pStr;
+
+ // remove old entries
+ ShowSounds_Clear();
+
+ // get number of sounds
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &numSounds );
+
+ // get sound list
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &soundList );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &retAddr );
+
+ pLocalList = new xrSound_t[numSounds];
+ memset( pLocalList, 0, numSounds*sizeof( xrSound_t ) );
+
+ g_showSounds_numSounds = numSounds;
+ g_showSounds_pSounds = new sound_t[numSounds];
+ memset( g_showSounds_pSounds, 0, numSounds*sizeof( sound_t ) );
+
+ // get the caller's command list
+ DmGetMemory( ( void* )soundList, numSounds*sizeof( xrSound_t ), pLocalList, NULL );
+
+ // build out the resident list
+ for ( int i=0; i<numSounds; i++ )
+ {
+ // swap the structure
+ pLocalList[i].rate = BigDWord( pLocalList[i].rate );
+ pLocalList[i].bits = BigDWord( pLocalList[i].bits );
+ pLocalList[i].channels = BigDWord( pLocalList[i].channels );
+ pLocalList[i].looped = BigDWord( pLocalList[i].looped );
+ pLocalList[i].dataSize = BigDWord( pLocalList[i].dataSize );
+ pLocalList[i].numSamples = BigDWord( pLocalList[i].numSamples );
+ pLocalList[i].streamed = BigDWord( pLocalList[i].streamed );
+
+ // strip the prefix
+ pStr = pLocalList[i].nameString;
+ while ( *pStr )
+ {
+ if ( __iscsym( *pStr ) )
+ {
+ // first non-preifx character
+ break;
+ }
+ pStr++;
+ }
+ g_showSounds_pSounds[i].pName = strdup( pStr );
+
+ char prefixString[256];
+ prefixLen = pStr - pLocalList[i].nameString;
+ memcpy( prefixString, pLocalList[i].nameString, prefixLen );
+ prefixString[prefixLen] = '\0';
+ g_showSounds_pSounds[i].pPrefix = strdup( prefixString );
+
+ // get the format name
+ g_showSounds_pSounds[i].pFormat = strdup( pLocalList[i].formatString );
+
+ g_showSounds_pSounds[i].rate = pLocalList[i].rate;
+ g_showSounds_pSounds[i].bits = pLocalList[i].bits;
+ g_showSounds_pSounds[i].channels = pLocalList[i].channels;
+ g_showSounds_pSounds[i].dataSize = pLocalList[i].dataSize;
+ g_showSounds_pSounds[i].numSamples = pLocalList[i].numSamples;
+ g_showSounds_pSounds[i].streamed = pLocalList[i].streamed;
+ g_showSounds_pSounds[i].looped = pLocalList[i].looped;
+
+ // determine duration
+ // must use sample count due to compression
+ if ( g_showSounds_pSounds[i].rate > 0 )
+ g_showSounds_pSounds[i].length = ( float )g_showSounds_pSounds[i].numSamples/( float )g_showSounds_pSounds[i].rate;
+ else
+ g_showSounds_pSounds[i].length = 0;
+
+ // add to list view
+ ShowSounds_AddViewItem( &g_showSounds_pSounds[i] );
+ }
+
+ // return the result
+ retVal = numSounds;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = SoundList( 0x%8.8x, 0x%8.8x )\n", retVal, numSounds, soundList );
+
+ delete [] pLocalList;
+
+ // update
+ ShowSounds_SortItems();
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
diff --git a/utils/xbox/vxconsole/show_textures.cpp b/utils/xbox/vxconsole/show_textures.cpp
new file mode 100644
index 0000000..e8e9cbb
--- /dev/null
+++ b/utils/xbox/vxconsole/show_textures.cpp
@@ -0,0 +1,971 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SHOW_TEXTURES.CPP
+//
+// Show Textures Display.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define ID_SHOWTEXTURES_LISTVIEW 100
+
+// column id
+#define ID_ST_NAME 0
+#define ID_ST_SIZE 1
+#define ID_ST_GROUP 2
+#define ID_ST_FORMAT 3
+#define ID_ST_WIDTH 4
+#define ID_ST_HEIGHT 5
+#define ID_ST_DEPTH 6
+#define ID_ST_NUMLEVELS 7
+#define ID_ST_BINDS 8
+#define ID_ST_REFCOUNT 9
+#define ID_ST_LOAD 10
+
+typedef enum
+{
+ LS_STATIC, // surface
+ LS_PROCEDURAL, // lacks disk based bits
+ LS_SYNCHRONOUS, // loaded synchronously
+ LS_FALLBACK, // fallback version, queued hires
+ LS_HIRES, // finalized at hires
+ LS_FAILED, // failed to load
+ LS_MAX
+} loadState_e;
+
+typedef struct
+{
+ int listIndex;
+ char *pLongName;
+ char *pShortName;
+ char *pGroupName;
+ char *pFormatName;
+ int size;
+ char sizeBuff[16];
+ int width;
+ char widthBuff[16];
+ int height;
+ char heightBuff[16];
+ int depth;
+ char depthBuff[16];
+ int numLevels;
+ char numLevelsBuff[16];
+ int binds;
+ char bindsBuff[16];
+ int refCount;
+ char refCountBuff[16];
+ int loadState;
+ int edram;
+} texture_t;
+
+typedef struct
+{
+ const CHAR* name;
+ int width;
+ int subItemIndex;
+ CHAR nameBuff[32];
+} label_t;
+
+HWND g_showTextures_hWnd;
+HWND g_showTextures_hWndListView;
+RECT g_showTextures_windowRect;
+int g_showTextures_sortColumn;
+int g_showTextures_sortDescending;
+texture_t *g_showTextures_pTextures;
+int g_showTextures_numTextures;
+int g_showTextures_currentFrame;
+int g_showTextures_fullPath;
+char g_showTextures_drawTextureName[MAX_PATH];
+
+char *g_showTextures_loadStrings[LS_MAX] =
+{
+ "Static",
+ "Procedural",
+ "Synchronous",
+ "Fallback",
+ "",
+ "Failed",
+};
+
+label_t g_showTextures_Labels[] =
+{
+ {"Name", 150, ID_ST_NAME},
+ {"D3D Size", 80, ID_ST_SIZE},
+ {"Group", 150, ID_ST_GROUP},
+ {"Format", 120, ID_ST_FORMAT},
+ {"Width", 80, ID_ST_WIDTH},
+ {"Height", 80, ID_ST_HEIGHT},
+ {"Depth", 80, ID_ST_DEPTH},
+ {"NumLevels", 80, ID_ST_NUMLEVELS},
+ {"Binds", 80, ID_ST_BINDS},
+ {"RefCount", 80, ID_ST_REFCOUNT},
+ {"Load State", 120, ID_ST_LOAD},
+};
+
+//-----------------------------------------------------------------------------
+// ShowTextures_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_SaveConfig()
+{
+ char buff[256];
+
+ Sys_SetRegistryInteger( "showTexturesFullPath", g_showTextures_fullPath );
+ Sys_SetRegistryInteger( "showTexturesCurrentFrame", g_showTextures_currentFrame );
+ Sys_SetRegistryInteger( "showTexturesSortColumn", g_showTextures_sortColumn );
+ Sys_SetRegistryInteger( "showTexturesSortDescending", g_showTextures_sortDescending );
+
+ WINDOWPLACEMENT wp;
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_showTextures_hWnd, &wp );
+ g_showTextures_windowRect = wp.rcNormalPosition;
+
+ sprintf( buff, "%d %d %d %d", g_showTextures_windowRect.left, g_showTextures_windowRect.top, g_showTextures_windowRect.right, g_showTextures_windowRect.bottom );
+ Sys_SetRegistryString( "showTexturesWindowRect", buff );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ Sys_GetRegistryInteger( "showTexturesFullPath", true, g_showTextures_fullPath );
+ Sys_GetRegistryInteger( "showTexturesCurrentFrame", false, g_showTextures_currentFrame );
+ Sys_GetRegistryInteger( "showTexturesSortColumn", ID_ST_NAME, g_showTextures_sortColumn );
+ Sys_GetRegistryInteger( "showTexturesSortDescending", false, g_showTextures_sortDescending );
+
+ Sys_GetRegistryString( "showTexturesWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_showTextures_windowRect.left, &g_showTextures_windowRect.top, &g_showTextures_windowRect.right, &g_showTextures_windowRect.bottom );
+ if ( numArgs != 4 || g_showTextures_windowRect.left < 0 || g_showTextures_windowRect.top < 0 || g_showTextures_windowRect.right < 0 || g_showTextures_windowRect.bottom < 0 )
+ {
+ memset( &g_showTextures_windowRect, 0, sizeof( g_showTextures_windowRect ) );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_Clear
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_Clear()
+{
+ // delete all the list view entries
+ if ( g_showTextures_hWnd )
+ {
+ ListView_DeleteAllItems( g_showTextures_hWndListView );
+ }
+
+ if ( !g_showTextures_pTextures )
+ {
+ return;
+ }
+
+ for ( int i=0; i<g_showTextures_numTextures; i++ )
+ {
+ free( g_showTextures_pTextures[i].pLongName );
+ free( g_showTextures_pTextures[i].pShortName );
+ free( g_showTextures_pTextures[i].pGroupName );
+ free( g_showTextures_pTextures[i].pFormatName );
+ }
+
+ g_showTextures_pTextures = NULL;
+ g_showTextures_numTextures = 0;
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_Export
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_Export()
+{
+ OPENFILENAME ofn;
+ char logFilename[MAX_PATH];
+ int retval;
+ FILE* fp;
+ int i;
+ int count;
+
+ memset( &ofn, 0, sizeof( ofn ) );
+ ofn.lStructSize = sizeof( ofn );
+ ofn.hwndOwner = g_showTextures_hWnd;
+ ofn.lpstrFile = logFilename;
+ ofn.lpstrFile[0] = '\0';
+ ofn.nMaxFile = sizeof( logFilename );
+ ofn.lpstrFilter = "Excel CSV\0*.CSV\0All Files\0*.*\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = "c:\\";
+ ofn.Flags = OFN_PATHMUSTEXIST;
+
+ // display the Open dialog box.
+ retval = GetOpenFileName( &ofn );
+ if ( !retval )
+ {
+ return;
+ }
+
+ Sys_AddExtension( ".csv", logFilename, sizeof( logFilename ) );
+
+ fp = fopen( logFilename, "wt+" );
+ if ( !fp )
+ {
+ return;
+ }
+
+ // labels
+ count = sizeof( g_showTextures_Labels )/sizeof( g_showTextures_Labels[0] );
+ for ( i=0; i<count; i++ )
+ {
+ fprintf( fp, "\"%s\"", g_showTextures_Labels[i].name );
+ if ( i != count-1 )
+ {
+ fprintf( fp, "," );
+ }
+ }
+ fprintf( fp, "\n" );
+
+ // dump to the log
+ for ( i=0; i<g_showTextures_numTextures; i++ )
+ {
+ if ( g_showTextures_fullPath )
+ {
+ fprintf( fp, "\"%s\"", g_showTextures_pTextures[i].pLongName );
+ }
+ else
+ {
+ fprintf( fp, "\"%s\"", g_showTextures_pTextures[i].pShortName );
+ }
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].sizeBuff );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].pGroupName );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].pFormatName );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].widthBuff );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].heightBuff );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].depthBuff );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].numLevelsBuff );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].bindsBuff );
+ fprintf( fp, ",\"%s\"", g_showTextures_pTextures[i].refCountBuff );
+ fprintf( fp, ",\"%s\"", g_showTextures_loadStrings[g_showTextures_pTextures[i].loadState] );
+ fprintf( fp, "\n" );
+ }
+
+ fclose( fp );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_Summary
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_Summary()
+{
+ char buff[1024];
+
+ // tally the totals
+ int total = 0;
+ for ( int i=0; i<g_showTextures_numTextures; i++ )
+ {
+ if ( g_showTextures_pTextures[i].edram )
+ {
+ // edram is does not affect system memory total
+ continue;
+ }
+ total += g_showTextures_pTextures[i].size;
+ }
+
+ sprintf(
+ buff,
+ "Entries:\t\t\t%d\n"
+ "System D3D Memory:\t%.2f MB\n",
+ g_showTextures_numTextures,
+ ( float )total/( 1024.0F*1024.0F ) );
+
+ MessageBox( g_showTextures_hWnd, buff, "Texture Summary", MB_OK|MB_APPLMODAL );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_DrawTexture
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_DrawTexture()
+{
+ char command[256];
+ texture_t* pTexture;
+ int selection;
+ LVITEM lvitem;
+
+ if ( !g_connectedToApp )
+ return;
+
+ selection = ListView_GetSelectionMark( g_showTextures_hWndListView );
+ if ( selection == -1 )
+ return;
+
+ memset( &lvitem, 0, sizeof( lvitem ) );
+ lvitem.mask = LVIF_PARAM;
+ lvitem.iItem = selection;
+ ListView_GetItem( g_showTextures_hWndListView, &lvitem );
+
+ pTexture = ( texture_t* )lvitem.lParam;
+
+ if ( !V_stricmp( g_showTextures_drawTextureName, pTexture->pLongName ) )
+ {
+ // hide
+ sprintf( command, "mat_drawTexture \"\"" );
+ g_showTextures_drawTextureName[0] = '\0';
+ }
+ else
+ {
+ // show
+ sprintf( command, "mat_drawTexture %s", pTexture->pLongName );
+ V_strncpy( g_showTextures_drawTextureName, pTexture->pLongName, sizeof( g_showTextures_drawTextureName ) );
+ }
+
+ // send the command to application
+ ProcessCommand( command );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_SetTitle
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_SetTitle()
+{
+ char titleBuff[128];
+
+ if ( g_showTextures_hWnd )
+ {
+ strcpy( titleBuff, "Textures " );
+ if ( g_showTextures_currentFrame )
+ {
+ strcat( titleBuff, " [FRAME]" );
+ }
+ if ( g_showTextures_fullPath )
+ {
+ strcat( titleBuff, " [FULL PATH]" );
+ }
+
+ SetWindowText( g_showTextures_hWnd, titleBuff );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_CompareFunc
+//
+//-----------------------------------------------------------------------------
+int CALLBACK ShowTextures_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
+{
+ texture_t* pTextureA = ( texture_t* )lParam1;
+ texture_t* pTextureB = ( texture_t* )lParam2;
+
+ int sort = 0;
+ switch ( g_showTextures_sortColumn )
+ {
+ case ID_ST_NAME:
+ if ( g_showTextures_fullPath )
+ {
+ sort = stricmp( pTextureA->pLongName, pTextureB->pLongName );
+ }
+ else
+ {
+ sort = stricmp( pTextureA->pShortName, pTextureB->pShortName );
+ }
+ break;
+
+ case ID_ST_GROUP:
+ sort = stricmp( pTextureA->pGroupName, pTextureB->pGroupName );
+ break;
+
+ case ID_ST_FORMAT:
+ sort = stricmp( pTextureA->pFormatName, pTextureB->pFormatName );
+ break;
+
+ case ID_ST_SIZE:
+ sort = pTextureA->size - pTextureB->size;
+ break;
+
+ case ID_ST_WIDTH:
+ sort = pTextureA->width - pTextureB->width;
+ break;
+
+ case ID_ST_HEIGHT:
+ sort = pTextureA->height - pTextureB->height;
+ break;
+
+ case ID_ST_DEPTH:
+ sort = pTextureA->depth - pTextureB->depth;
+ break;
+
+ case ID_ST_NUMLEVELS:
+ sort = pTextureA->numLevels - pTextureB->numLevels;
+ break;
+
+ case ID_ST_BINDS:
+ sort = pTextureA->binds - pTextureB->binds;
+ break;
+
+ case ID_ST_REFCOUNT:
+ sort = pTextureA->refCount - pTextureB->refCount;
+ break;
+
+ case ID_ST_LOAD:
+ sort = stricmp( g_showTextures_loadStrings[pTextureA->loadState], g_showTextures_loadStrings[pTextureB->loadState] );
+ break;
+ }
+
+ // flip the sort order
+ if ( g_showTextures_sortDescending )
+ {
+ sort *= -1;
+ }
+
+ return ( sort );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_SortItems
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_SortItems()
+{
+ LVITEM lvitem;
+ texture_t *pTexture;
+ int i;
+
+ if ( !g_showTextures_hWnd )
+ {
+ // only sort if window is visible
+ return;
+ }
+
+ ListView_SortItems( g_showTextures_hWndListView, ShowTextures_CompareFunc, 0 );
+
+ memset( &lvitem, 0, sizeof( lvitem ) );
+ lvitem.mask = LVIF_PARAM;
+
+ // get each item and reset its list index
+ int itemCount = ListView_GetItemCount( g_showTextures_hWndListView );
+ for ( i=0; i<itemCount; i++ )
+ {
+ lvitem.iItem = i;
+ ListView_GetItem( g_showTextures_hWndListView, &lvitem );
+
+ pTexture = ( texture_t* )lvitem.lParam;
+ pTexture->listIndex = i;
+ }
+
+ // update list view columns with sort key
+ for ( i=0; i<sizeof( g_showTextures_Labels )/sizeof( g_showTextures_Labels[0] ); i++ )
+ {
+ char symbol;
+ LVCOLUMN lvc;
+
+ if ( i == g_showTextures_sortColumn )
+ {
+ symbol = g_showTextures_sortDescending ? '<' : '>';
+ }
+ else
+ {
+ symbol = ' ';
+ }
+ sprintf( g_showTextures_Labels[i].nameBuff, "%s %c", g_showTextures_Labels[i].name, symbol );
+
+ memset( &lvc, 0, sizeof( lvc ) );
+ lvc.mask = LVCF_TEXT;
+ lvc.pszText = ( LPSTR )g_showTextures_Labels[i].nameBuff;
+
+ ListView_SetColumn( g_showTextures_hWndListView, i, &lvc );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_AddViewItem
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_AddViewItem( texture_t* pTexture )
+{
+ LVITEM lvi;
+
+ if ( !g_showTextures_hWnd )
+ {
+ // only valid if log window is visible
+ return;
+ }
+
+ // update the text callback buffers
+ sprintf( pTexture->sizeBuff, "%d", pTexture->size );
+ sprintf( pTexture->widthBuff, "%d", pTexture->width );
+ sprintf( pTexture->heightBuff, "%d", pTexture->height );
+ sprintf( pTexture->depthBuff, "%d", pTexture->depth );
+ sprintf( pTexture->numLevelsBuff, "%d", pTexture->numLevels );
+ sprintf( pTexture->bindsBuff, "%d", pTexture->binds );
+ sprintf( pTexture->refCountBuff, "%d", pTexture->refCount );
+
+ int itemCount = ListView_GetItemCount( g_showTextures_hWndListView );
+
+ // setup and insert at end of list
+ memset( &lvi, 0, sizeof( lvi ) );
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = itemCount;
+ lvi.iSubItem = 0;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = ( LPARAM )pTexture;
+
+ // insert and set the real index
+ pTexture->listIndex = ListView_InsertItem( g_showTextures_hWndListView, &lvi );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_Refresh
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_Refresh()
+{
+ char command[256];
+
+ strcpy( command, "mat_get_textures" );
+
+ if ( !g_showTextures_currentFrame )
+ {
+ strcat( command, " all" );
+ }
+
+ // send the command to application which replies with list data
+ if ( g_connectedToApp )
+ {
+ ProcessCommand( command );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_SizeWindow
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_SizeWindow( HWND hwnd, int cx, int cy )
+{
+ if ( cx==0 || cy==0 )
+ {
+ RECT rcClient;
+ GetClientRect( hwnd, &rcClient );
+ cx = rcClient.right;
+ cy = rcClient.bottom;
+ }
+
+ // position the ListView
+ SetWindowPos( g_showTextures_hWndListView, NULL, 0, 0, cx, cy, SWP_NOZORDER );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK ShowTextures_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ texture_t* pTexture;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ return 0L;
+
+ case WM_DESTROY:
+ ShowTextures_SaveConfig();
+ g_showTextures_hWnd = NULL;
+ return 0L;
+
+ case WM_INITMENU:
+ CheckMenuItem( ( HMENU )wParam, IDM_OPTIONS_CURRENTFRAME, MF_BYCOMMAND | ( g_showTextures_currentFrame ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_OPTIONS_FULLPATH, MF_BYCOMMAND | ( g_showTextures_fullPath ? MF_CHECKED : MF_UNCHECKED ) );
+ return 0L;
+
+ case WM_SIZE:
+ ShowTextures_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) );
+ return 0L;
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lParam )->code )
+ {
+ case LVN_COLUMNCLICK:
+ NMLISTVIEW* pnmlv;
+ pnmlv = ( NMLISTVIEW* )lParam;
+ if ( g_showTextures_sortColumn == pnmlv->iSubItem )
+ {
+ // user has clicked on same column - flip the sort
+ g_showTextures_sortDescending ^= 1;
+ }
+ else
+ {
+ // sort by new column
+ g_showTextures_sortColumn = pnmlv->iSubItem;
+ }
+ ShowTextures_SortItems();
+ return 0L;
+
+ case LVN_GETDISPINFO:
+ NMLVDISPINFO* plvdi;
+ plvdi = ( NMLVDISPINFO* )lParam;
+ pTexture = ( texture_t* )plvdi->item.lParam;
+ switch ( plvdi->item.iSubItem )
+ {
+ case ID_ST_NAME:
+ if ( g_showTextures_fullPath )
+ plvdi->item.pszText = pTexture->pLongName;
+ else
+ plvdi->item.pszText = pTexture->pShortName;
+ return 0L;
+
+ case ID_ST_GROUP:
+ plvdi->item.pszText = pTexture->pGroupName;
+ return 0L;
+
+ case ID_ST_FORMAT:
+ plvdi->item.pszText = pTexture->pFormatName;
+ return 0L;
+
+ case ID_ST_SIZE:
+ plvdi->item.pszText = pTexture->sizeBuff;
+ return 0L;
+
+ case ID_ST_WIDTH:
+ plvdi->item.pszText = pTexture->widthBuff;
+ return 0L;
+
+ case ID_ST_HEIGHT:
+ plvdi->item.pszText = pTexture->heightBuff;
+ return 0L;
+
+ case ID_ST_DEPTH:
+ plvdi->item.pszText = pTexture->depthBuff;
+ return 0L;
+
+ case ID_ST_NUMLEVELS:
+ plvdi->item.pszText = pTexture->numLevelsBuff;
+ return 0L;
+
+ case ID_ST_BINDS:
+ plvdi->item.pszText = pTexture->bindsBuff;
+ return 0L;
+
+ case ID_ST_LOAD:
+ plvdi->item.pszText = g_showTextures_loadStrings[pTexture->loadState];
+ return 0L;
+
+ case ID_ST_REFCOUNT:
+ plvdi->item.pszText = pTexture->refCountBuff;
+ return 0L;
+
+ default:
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_OPTIONS_SUMMARY:
+ ShowTextures_Summary();
+ return 0L;
+
+ case IDM_OPTIONS_REFRESH:
+ ShowTextures_Refresh();
+ return 0L;
+
+ case IDM_OPTIONS_EXPORT:
+ ShowTextures_Export();
+ return 0L;
+
+ case IDM_OPTIONS_CURRENTFRAME:
+ g_showTextures_currentFrame ^= 1;
+ ShowTextures_SetTitle();
+ ShowTextures_Refresh();
+ return 0L;
+
+ case IDM_OPTIONS_FULLPATH:
+ g_showTextures_fullPath ^= 1;
+ ShowTextures_SetTitle();
+ ShowTextures_SortItems();
+ return 0L;
+
+ case IDM_OPTIONS_DRAWTEXTURE:
+ ShowTextures_DrawTexture();
+ return 0L;
+ }
+ break;
+ }
+
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_Init
+//
+//-----------------------------------------------------------------------------
+bool ShowTextures_Init()
+{
+ // set up our window class
+ WNDCLASS wndclass;
+
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = ShowTextures_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_SHOWTEXTURES );
+ wndclass.lpszClassName = "SHOWTEXTURESCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ ShowTextures_LoadConfig();
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// ShowTextures_Open
+//
+//-----------------------------------------------------------------------------
+void ShowTextures_Open()
+{
+ RECT clientRect;
+ HWND hWnd;
+ int i;
+
+ if ( g_showTextures_hWnd )
+ {
+ // only one instance
+ if ( IsIconic( g_showTextures_hWnd ) )
+ {
+ ShowWindow( g_showTextures_hWnd, SW_RESTORE );
+ }
+ SetForegroundWindow( g_showTextures_hWnd );
+ return;
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "SHOWTEXTURESCLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 700,
+ 400,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ NULL );
+ g_showTextures_hWnd = hWnd;
+
+ GetClientRect( g_showTextures_hWnd, &clientRect );
+ hWnd = CreateWindow(
+ WC_LISTVIEW,
+ "",
+ WS_VISIBLE|WS_CHILD|LVS_REPORT,
+ 0,
+ 0,
+ clientRect.right-clientRect.left,
+ clientRect.bottom-clientRect.top,
+ g_showTextures_hWnd,
+ ( HMENU )ID_SHOWTEXTURES_LISTVIEW,
+ g_hInstance,
+ NULL );
+ g_showTextures_hWndListView = hWnd;
+
+ // init list view columns
+ for ( i=0; i<sizeof( g_showTextures_Labels )/sizeof( g_showTextures_Labels[0] ); i++ )
+ {
+ LVCOLUMN lvc;
+ memset( &lvc, 0, sizeof( lvc ) );
+
+ lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
+ lvc.iSubItem = 0;
+ lvc.cx = g_showTextures_Labels[i].width;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.pszText = ( LPSTR )g_showTextures_Labels[i].name;
+ ListView_InsertColumn( g_showTextures_hWndListView, i, &lvc );
+ }
+
+ ListView_SetBkColor( g_showTextures_hWndListView, g_backgroundColor );
+ ListView_SetTextBkColor( g_showTextures_hWndListView, g_backgroundColor );
+
+ DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP;
+ ListView_SetExtendedListViewStyleEx( g_showTextures_hWndListView, style, style );
+
+ // populate list view
+ for ( i=0; i<g_showTextures_numTextures; i++ )
+ {
+ ShowTextures_AddViewItem( &g_showTextures_pTextures[i] );
+ }
+ ShowTextures_SortItems();
+
+ ShowTextures_SetTitle();
+
+ if ( g_showTextures_windowRect.right && g_showTextures_windowRect.bottom )
+ {
+ MoveWindow( g_showTextures_hWnd, g_showTextures_windowRect.left, g_showTextures_windowRect.top, g_showTextures_windowRect.right-g_showTextures_windowRect.left, g_showTextures_windowRect.bottom-g_showTextures_windowRect.top, FALSE );
+ }
+ ShowWindow( g_showTextures_hWnd, SHOW_OPENWINDOW );
+
+ // get data from application
+ ShowTextures_Refresh();
+}
+
+//-----------------------------------------------------------------------------
+// rc_TextureList
+//
+// Sent from application with texture list
+//-----------------------------------------------------------------------------
+int rc_TextureList( char* commandPtr )
+{
+ int errCode = -1;
+ char* cmdToken;
+ int numTextures;
+ int textureList;
+ int retAddr;
+ int retVal;
+ xrTexture_t* pLocalList;
+
+ // remove old entries
+ ShowTextures_Clear();
+
+ // get number of textures
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &numTextures );
+
+ // get texture list
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &textureList );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &retAddr );
+
+ pLocalList = new xrTexture_t[numTextures];
+ memset( pLocalList, 0, numTextures*sizeof( xrTexture_t ) );
+
+ g_showTextures_numTextures = numTextures;
+ g_showTextures_pTextures = new texture_t[numTextures];
+ memset( g_showTextures_pTextures, 0, numTextures*sizeof( texture_t ) );
+
+ // get the caller's command list
+ DmGetMemory( ( void* )textureList, numTextures*sizeof( xrTexture_t ), pLocalList, NULL );
+
+ // build out the resident list
+ for ( int i=0; i<numTextures; i++ )
+ {
+ // swap the structure
+ pLocalList[i].size = BigDWord( pLocalList[i].size );
+ pLocalList[i].width = BigDWord( pLocalList[i].width );
+ pLocalList[i].height = BigDWord( pLocalList[i].height );
+ pLocalList[i].depth = BigDWord( pLocalList[i].depth );
+ pLocalList[i].numLevels = BigDWord( pLocalList[i].numLevels );
+ pLocalList[i].binds = BigDWord( pLocalList[i].binds );
+ pLocalList[i].refCount = BigDWord( pLocalList[i].refCount );
+ pLocalList[i].sRGB = BigDWord( pLocalList[i].sRGB );
+ pLocalList[i].edram = BigDWord( pLocalList[i].edram );
+ pLocalList[i].procedural = BigDWord( pLocalList[i].procedural );
+ pLocalList[i].fallback = BigDWord( pLocalList[i].fallback );
+ pLocalList[i].final = BigDWord( pLocalList[i].final );
+ pLocalList[i].failed = BigDWord( pLocalList[i].failed );
+
+ // get the name
+ g_showTextures_pTextures[i].pLongName = strdup( pLocalList[i].nameString );
+
+ CHAR shortName[MAX_PATH];
+ Sys_StripPath( g_showTextures_pTextures[i].pLongName, shortName, sizeof( shortName ) );
+ g_showTextures_pTextures[i].pShortName = strdup( shortName );
+
+ // get the group name
+ g_showTextures_pTextures[i].pGroupName = strdup( pLocalList[i].groupString );
+
+ // get the format name
+ const char *pFormatName = pLocalList[i].formatString;
+ if ( !strnicmp( pFormatName, "D3DFMT_", 7 ) )
+ {
+ // strip D3DFMT_
+ pFormatName += 7;
+ }
+ char tempName[MAX_PATH];
+ if ( pLocalList[i].sRGB )
+ {
+ strcpy( tempName, pFormatName );
+ strcat( tempName, " (SRGB)" );
+ pFormatName = tempName;
+ }
+ g_showTextures_pTextures[i].pFormatName = strdup( pFormatName );
+
+ g_showTextures_pTextures[i].size = pLocalList[i].size;
+ g_showTextures_pTextures[i].width = pLocalList[i].width;
+ g_showTextures_pTextures[i].height = pLocalList[i].height;
+ g_showTextures_pTextures[i].depth = pLocalList[i].depth;
+ g_showTextures_pTextures[i].numLevels = pLocalList[i].numLevels;
+ g_showTextures_pTextures[i].binds = pLocalList[i].binds;
+ g_showTextures_pTextures[i].refCount = pLocalList[i].refCount;
+ g_showTextures_pTextures[i].edram = pLocalList[i].edram;
+
+ loadState_e loadState;
+ if ( pLocalList[i].edram || V_stristr( g_showTextures_pTextures[i].pGroupName, "RenderTarget" ) )
+ {
+ loadState = LS_STATIC;
+ }
+ else if ( pLocalList[i].procedural )
+ {
+ loadState = LS_PROCEDURAL;
+ }
+ else if ( pLocalList[i].final )
+ {
+ loadState = LS_HIRES;
+ }
+ else if ( pLocalList[i].failed )
+ {
+ loadState = LS_FAILED;
+ }
+ else if ( pLocalList[i].fallback )
+ {
+ loadState = LS_FALLBACK;
+ }
+ else
+ {
+ loadState = LS_SYNCHRONOUS;
+ }
+ g_showTextures_pTextures[i].loadState = loadState;
+
+ // add to list view
+ ShowTextures_AddViewItem( &g_showTextures_pTextures[i] );
+ }
+
+ // return the result
+ retVal = numTextures;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = TextureList( 0x%8.8x, 0x%8.8x )\n", retVal, numTextures, textureList );
+
+ delete [] pLocalList;
+
+ // update
+ ShowTextures_SortItems();
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return errCode;
+}
diff --git a/utils/xbox/vxconsole/sync_files.cpp b/utils/xbox/vxconsole/sync_files.cpp
new file mode 100644
index 0000000..facb395
--- /dev/null
+++ b/utils/xbox/vxconsole/sync_files.cpp
@@ -0,0 +1,942 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SYNC_FILES.CPP
+//
+// Sync Files Routines.
+//=====================================================================================//
+#include "vxconsole.h"
+
+char g_syncfiles_localPath[MAX_PATH];
+char g_syncfiles_targetPath[MAX_PATH];
+fileNode_t *g_syncfiles_targetFiles;
+int g_syncfiles_numTargetFiles;
+CProgress *g_syncFiles_progress;
+BOOL g_syncFiles_noWrite;
+BOOL g_syncFiles_force;
+BOOL g_syncFiles_verbose;
+
+struct dvdimage_t
+{
+ char szString[MAX_PATH];
+ CUtlString installPath;
+ CUtlString versionDetailString;
+};
+CUtlVector< dvdimage_t> g_install_dvdImages;
+int g_install_Selection;
+bool g_install_bForceSync;
+bool g_install_bCleanTarget;
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_Validate
+//
+//-----------------------------------------------------------------------------
+bool SyncFilesDlg_Validate()
+{
+ if ( !g_connectedToXBox )
+ {
+ Sys_MessageBox( "Sync Error", "Cannot sync until connected to XBox." );
+ return false;
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_Setup
+//
+//-----------------------------------------------------------------------------
+void SyncFilesDlg_Setup( HWND hWnd )
+{
+ SetDlgItemText( hWnd, IDC_SYNCFILES_LOCALPATH, g_syncfiles_localPath );
+ SetDlgItemText( hWnd, IDC_SYNCFILES_TARGETPATH, g_syncfiles_targetPath );
+
+ CheckDlgButton( hWnd, IDC_SYNCFILES_FORCESYNC, g_syncFiles_force ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hWnd, IDC_SYNCFILES_NOWRITE, g_syncFiles_noWrite ? BST_CHECKED : BST_UNCHECKED );
+ CheckDlgButton( hWnd, IDC_SYNCFILES_VERBOSE, g_syncFiles_verbose ? BST_CHECKED : BST_UNCHECKED );
+}
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_GetChanges
+//
+//-----------------------------------------------------------------------------
+bool SyncFilesDlg_GetChanges( HWND hwnd )
+{
+ char localPath[MAX_PATH];
+ char targetPath[MAX_PATH];
+
+ localPath[0] = '\0';
+ targetPath[0] = '\0';
+
+ GetDlgItemText( hwnd, IDC_SYNCFILES_LOCALPATH, localPath, MAX_PATH );
+ GetDlgItemText( hwnd, IDC_SYNCFILES_TARGETPATH, targetPath, MAX_PATH );
+
+ strcpy( g_syncfiles_localPath, localPath );
+ Sys_NormalizePath( g_syncfiles_localPath, true );
+
+ strcpy( g_syncfiles_targetPath, targetPath );
+ Sys_NormalizePath( g_syncfiles_targetPath, true );
+
+ g_syncFiles_force = IsDlgButtonChecked( hwnd, IDC_SYNCFILES_FORCESYNC ) != 0;
+ g_syncFiles_noWrite = IsDlgButtonChecked( hwnd, IDC_SYNCFILES_NOWRITE ) != 0;
+ g_syncFiles_verbose = IsDlgButtonChecked( hwnd, IDC_SYNCFILES_VERBOSE ) != 0;
+
+ // success
+ return ( true );
+}
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_Proc
+//
+//-----------------------------------------------------------------------------
+BOOL CALLBACK SyncFilesDlg_Proc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ SyncFilesDlg_Setup( hwnd );
+ return ( TRUE );
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_OK:
+ if ( !SyncFilesDlg_GetChanges( hwnd ) )
+ break;
+ EndDialog( hwnd, wParam );
+ return ( TRUE );
+
+ case IDCANCEL:
+ case IDC_CANCEL:
+ EndDialog( hwnd, wParam );
+ return ( TRUE );
+ }
+ break;
+ }
+ return ( FALSE );
+}
+
+//-----------------------------------------------------------------------------
+// SyncFiles_FreeTargetList
+//
+//-----------------------------------------------------------------------------
+void SyncFiles_FreeTargetList()
+{
+ g_syncfiles_numTargetFiles = 0;
+
+ FreeTargetFileList( g_syncfiles_targetFiles );
+ g_syncfiles_targetFiles = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// SyncFiles_DoUpdates
+//
+//-----------------------------------------------------------------------------
+bool SyncFiles_DoUpdates()
+{
+ WIN32_FILE_ATTRIBUTE_DATA localAttributes;
+ fileNode_t *nodePtr;
+ char sourceFilename[MAX_PATH];
+ char statusBuff1[MAX_PATH];
+ char statusBuff2[MAX_PATH];
+ int targetPathLen;
+ char *ptr;
+ int progress;
+ int fileSyncMode;
+ int numSynced;
+ int retVal;
+
+ g_syncFiles_progress->SetStatus( "Syncing Target Files...", "", "" );
+ g_syncFiles_progress->SetMeter( 0, g_syncfiles_numTargetFiles );
+
+ fileSyncMode = FSYNC_ANDEXISTSONTARGET;
+ if ( g_syncFiles_force )
+ fileSyncMode |= FSYNC_ALWAYS;
+ else
+ fileSyncMode |= FSYNC_IFNEWER;
+
+ targetPathLen = strlen( g_syncfiles_targetPath );
+
+ numSynced = 0;
+ progress = 0;
+ nodePtr = g_syncfiles_targetFiles;
+ while ( nodePtr )
+ {
+ ptr = nodePtr->filename+targetPathLen;
+ if ( *ptr == '\\' )
+ ptr++;
+
+ // replace with source path head
+ strcpy( sourceFilename, g_syncfiles_localPath );
+ Sys_AddFileSeperator( sourceFilename, sizeof( sourceFilename ) );
+ strcat( sourceFilename, ptr );
+
+ float sourceFileSize = 0;
+ if ( GetFileAttributesEx( sourceFilename, GetFileExInfoStandard, &localAttributes ) )
+ {
+ sourceFileSize = (float)localAttributes.nFileSizeLow / (1024.0f * 1024.0f);
+ }
+
+ _snprintf( statusBuff1, sizeof( statusBuff1 ), "Local File: %s (%.2f MB)", sourceFilename, sourceFileSize );
+ statusBuff1[sizeof( statusBuff1 ) - 1] = '\0';
+ _snprintf( statusBuff2, sizeof( statusBuff2 ), "Target File: %s", nodePtr->filename );
+ statusBuff1[sizeof( statusBuff2 ) - 1] = '\0';
+ g_syncFiles_progress->SetStatus( NULL, statusBuff1, statusBuff2 );
+
+ retVal = FileSyncEx( sourceFilename, nodePtr->filename, fileSyncMode, g_syncFiles_verbose != FALSE, g_syncFiles_noWrite != FALSE);
+ if ( retVal == 1 )
+ {
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Sync: %s -> %s\n", sourceFilename, nodePtr->filename );
+ numSynced++;
+ }
+
+ progress++;
+ g_syncFiles_progress->SetMeter( progress, -1 );
+ if ( g_syncFiles_progress->IsCancel() )
+ {
+ return false;
+ }
+
+ nodePtr = nodePtr->nextPtr;
+ }
+
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Synced %d/%d Files.\n", numSynced, g_syncfiles_numTargetFiles );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// SyncFiles_GetTargetList
+//
+//-----------------------------------------------------------------------------
+bool SyncFiles_GetTargetList( char* pTargetPath )
+{
+ g_syncFiles_progress->SetStatus( "Getting Target Files...", "", "" );
+ g_syncFiles_progress->SetMeter( 0, 100 );
+
+ if ( !GetTargetFileList_r( pTargetPath, true, FA_NORMAL|FA_READONLY, 0, &g_syncfiles_targetFiles ) )
+ {
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "Bad Target Path '%s'\n", pTargetPath );
+ return false;
+ }
+
+ fileNode_t* pFileNode;
+ for ( pFileNode = g_syncfiles_targetFiles; pFileNode; pFileNode = pFileNode->nextPtr )
+ {
+ g_syncfiles_numTargetFiles++;
+ }
+
+ // success
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void SyncFilesDlg_SaveConfig()
+{
+ Sys_SetRegistryString( "syncfiles_localPath", g_syncfiles_localPath );
+ Sys_SetRegistryString( "syncfiles_targetPath", g_syncfiles_targetPath );
+ Sys_SetRegistryInteger( "syncfiles_force", g_syncFiles_force );
+ Sys_SetRegistryInteger( "syncfiles_noWrite", g_syncFiles_noWrite );
+ Sys_SetRegistryInteger( "syncfiles_verbose", g_syncFiles_verbose );
+}
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_Open
+//
+//-----------------------------------------------------------------------------
+void SyncFilesDlg_Open( void )
+{
+ int result;
+ bool bError;
+ bool bValid;
+
+ result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_SYNCFILES ), g_hDlgMain, ( DLGPROC )SyncFilesDlg_Proc );
+ if ( LOWORD( result ) != IDC_OK )
+ return;
+
+ SyncFilesDlg_SaveConfig();
+
+ if ( !SyncFilesDlg_Validate() )
+ return;
+
+ g_syncFiles_progress = new CProgress;
+ g_syncFiles_progress->Open( "Sync Files...", true, true );
+
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\nSyncing Files From '%s' to '%s'\n", g_syncfiles_localPath, g_syncfiles_targetPath );
+
+ bError = true;
+
+ // get a file listing from target
+ bValid = SyncFiles_GetTargetList( g_syncfiles_targetPath );
+ if ( !bValid )
+ goto cleanUp;
+
+ // mark all files needing update
+ bValid = SyncFiles_DoUpdates();
+ if ( !bValid )
+ goto cleanUp;
+
+ bError = false;
+
+cleanUp:
+ delete g_syncFiles_progress;
+ g_syncFiles_progress = NULL;
+
+ if ( bError )
+ ConsoleWindowPrintf( XBX_CLR_RED, "Aborted.\n" );
+ else
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Finished.\n" );
+
+ SyncFiles_FreeTargetList();
+}
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void SyncFilesDlg_LoadConfig()
+{
+ // get our config
+ Sys_GetRegistryString( "syncfiles_localPath", g_syncfiles_localPath, g_localPath, sizeof( g_syncfiles_localPath ) );
+ Sys_GetRegistryString( "syncfiles_targetPath", g_syncfiles_targetPath, g_targetPath, sizeof( g_syncfiles_targetPath ) );
+ Sys_GetRegistryInteger( "syncfiles_force", false, g_syncFiles_force );
+ Sys_GetRegistryInteger( "syncfiles_noWrite", false, g_syncFiles_noWrite );
+ Sys_GetRegistryInteger( "syncfiles_verbose", false, g_syncFiles_verbose );
+}
+
+//-----------------------------------------------------------------------------
+// SyncFilesDlg_Init
+//
+//-----------------------------------------------------------------------------
+bool SyncFilesDlg_Init()
+{
+ SyncFilesDlg_LoadConfig();
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// InstallDlg_InstallImage
+//
+//-----------------------------------------------------------------------------
+void InstallDlg_InstallImage( const char *pInstallPath, bool bForce, bool bCleanTarget )
+{
+ int errCode;
+ char *pToken;
+ char arg1[MAXTOKEN];
+ char arg2[MAXTOKEN];
+ char sourceFilename[MAX_PATH];
+ char sourcePath[MAX_PATH];
+ char targetFilename[MAX_PATH];
+ char filename[MAX_PATH];
+ WIN32_FIND_DATA findData;
+ HANDLE h;
+
+ if ( !pInstallPath[0] )
+ {
+ return;
+ }
+
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\nSyncing From Install Depot: %s\n", pInstallPath );
+
+ // get the install script
+ char szScriptPath[MAX_PATH];
+ V_ComposeFileName( pInstallPath, "../dvd_install.txt", szScriptPath, sizeof( szScriptPath ) );
+ if ( !Sys_Exists( szScriptPath ) )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Failed to open: %s\n", szScriptPath );
+ return;
+ }
+
+ // sanity check
+ // DVD image auto-build failure prevents the presence of the default.xex
+ char szTempFilename[MAX_PATH];
+ V_ComposeFileName( pInstallPath, "default.xex", szTempFilename, sizeof( szTempFilename ) );
+ if ( !Sys_Exists( szTempFilename ) )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Cancelled Installation! DVD Image Auto-Build Process Failed - Missing default.xex!\n" );
+ return;
+ }
+
+ // get the version detail
+ char szVersionPath[MAX_PATH];
+ char *pVersionDetailString = NULL;
+ V_ComposeFileName( pInstallPath, "version.txt", szVersionPath, sizeof( szVersionPath ) );
+ if ( Sys_LoadFile( szVersionPath, (void**)&pVersionDetailString ) <= 0 )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Cancelled Installation! DVD Image Auto-Build Process Failed! - Missing version.txt\n" );
+ return;
+ }
+
+ Sys_LoadScriptFile( szScriptPath );
+
+ CProgress* pProgress = new CProgress;
+ pProgress->Open( "Installing DVD Image...", true, false );
+
+ int numFailed = 0;
+ int numSkipped = 0;
+ int numUpdated = 0;
+ int version = 0;
+
+ bool bFailed = true;
+ bool bSyntaxError = false;
+ bool bCancelled = false;
+ while ( 1 )
+ {
+ pToken = Sys_GetToken( true );
+ if ( !pToken || !pToken[0] )
+ break;
+
+ if ( pProgress->IsCancel() )
+ {
+ bCancelled = true;
+ break;
+ }
+
+ if ( !stricmp( pToken, "$version" ) )
+ {
+ // version <num> <targetroot>
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ bSyntaxError = true;
+ break;
+ }
+ version = atoi( pToken );
+ if ( version < 0 )
+ {
+ version = 0;
+ }
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ bSyntaxError = true;
+ break;
+ }
+ Sys_StripQuotesFromToken( pToken );
+ V_FixSlashes( pToken );
+ if ( pToken[0] == CORRECT_PATH_SEPARATOR )
+ {
+ // remove initial slash
+ memcpy( pToken, pToken+1, strlen( pToken ) );
+ }
+
+ char szRootPath[MAX_PATH];
+ V_ComposeFileName( g_targetPath, pToken, szRootPath, sizeof( szRootPath ) );
+
+ if ( bCleanTarget )
+ {
+ // delete any exisiting files at target
+ DM_FILE_ATTRIBUTES fileAttributes;
+ HRESULT hr = DmGetFileAttributes( szRootPath, &fileAttributes );
+ if ( hr == XBDM_NOERR )
+ {
+ // delete all files at valid target
+ V_ComposeFileName( szRootPath, "*.*", szTempFilename, sizeof( szTempFilename ) );
+ char *pArgs[3];
+ pArgs[0] = "*del";
+ pArgs[1] = szTempFilename;
+ pArgs[2] = "/s";
+ if ( !lc_del( 3, pArgs ) )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Failed To Delete Files At '%s'.\n", szRootPath );
+ break;
+ }
+ }
+ }
+
+ char szTargetVersionPath[MAX_PATH];
+ V_ComposeFileName( szRootPath, "version.txt", szTargetVersionPath, sizeof( szTargetVersionPath ) );
+
+ if ( !bForce )
+ {
+ int fileSize;
+ char *pTargetVersionDetailString;
+ if ( !LoadTargetFile( szTargetVersionPath, &fileSize, (void**)&pTargetVersionDetailString ) )
+ {
+ // expected version does not exist
+ // force full install
+ bForce = true;
+ }
+ else if ( strcmp( pVersionDetailString, pTargetVersionDetailString ) != 0 )
+ {
+ // different versions
+ bForce = true;
+ }
+ Sys_Free( pTargetVersionDetailString );
+ }
+
+ if ( bForce && !FileSyncEx( szVersionPath, szTargetVersionPath, FSYNC_ALWAYS, true, false ) )
+ {
+ numFailed++;
+ break;
+ }
+ }
+ else if ( !stricmp( pToken, "$print" ) )
+ {
+ // print <string>
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ bSyntaxError = true;
+ break;
+ }
+ Sys_StripQuotesFromToken( pToken );
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s\n", pToken );
+ }
+ else if ( !stricmp( pToken, "$copy" ) )
+ {
+ // copy <source> <target>
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ bSyntaxError = true;
+ break;
+ }
+ Sys_StripQuotesFromToken( pToken );
+ V_FixSlashes( pToken );
+ if ( !V_strnicmp( pToken, "DVD\\", 4 ) )
+ {
+ // skip past DVD, used as a placeholder
+ pToken += 4;
+ }
+ V_ComposeFileName( pInstallPath, pToken, arg1, sizeof( arg1 ) );
+
+ pToken = Sys_GetToken( false );
+ if ( !pToken || !pToken[0] )
+ {
+ bSyntaxError = true;
+ break;
+ }
+ Sys_StripQuotesFromToken( pToken );
+ V_FixSlashes( pToken );
+ if ( pToken[0] == CORRECT_PATH_SEPARATOR )
+ {
+ // remove initial slash
+ memcpy( pToken, pToken+1, strlen( pToken ) );
+ }
+ V_ComposeFileName( g_targetPath, pToken, arg2, sizeof( arg2 ) );
+
+ Sys_StripFilename( arg1, sourcePath, sizeof( sourcePath ) );
+
+ h = FindFirstFile( arg1, &findData );
+ if ( h != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( pProgress->IsCancel() )
+ {
+ bCancelled = true;
+ break;
+ }
+
+ if ( !stricmp( findData.cFileName, "." ) || !stricmp( findData.cFileName, ".." ) )
+ {
+ continue;
+ }
+ if ( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+ {
+ continue;
+ }
+
+ strcpy( sourceFilename, sourcePath );
+ Sys_AddFileSeperator( sourceFilename, sizeof( sourceFilename ) );
+ strcat( sourceFilename, findData.cFileName );
+ Sys_NormalizePath( sourceFilename, false );
+
+ Sys_StripPath( arg2, filename, sizeof( filename ) );
+ if ( filename[0] )
+ {
+ // target filename is specified
+ strcpy( targetFilename, arg2 );
+ }
+ else
+ {
+ // target filename is path
+ strcpy( targetFilename, arg2 );
+ Sys_AddFileSeperator( targetFilename, sizeof( targetFilename ) );
+ strcat( targetFilename, findData.cFileName );
+ Sys_NormalizePath( targetFilename, false );
+ }
+
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "\nCopying: %s -> %s\n", sourceFilename, targetFilename );
+
+ WIN32_FILE_ATTRIBUTE_DATA localAttributes;
+ float sourceFileSize = 0;
+ if ( GetFileAttributesEx( sourceFilename, GetFileExInfoStandard, &localAttributes ) )
+ {
+ sourceFileSize = (float)localAttributes.nFileSizeLow / (1024.0f * 1024.0f);
+ }
+
+ char statusBuff1[MAX_PATH];
+ V_snprintf( statusBuff1, sizeof( statusBuff1 ), "Copying (%.2f MB) ... Please Wait", sourceFileSize );
+ pProgress->SetStatus( statusBuff1, sourceFilename, targetFilename );
+
+ int fileSyncMode = bForce ? FSYNC_ALWAYS : FSYNC_IFNEWER;
+ errCode = FileSyncEx( sourceFilename, targetFilename, fileSyncMode, true, false );
+ if ( errCode < 0 )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Sync Failure!\n" );
+ numFailed++;
+ }
+ else if ( errCode == 0 )
+ {
+ ConsoleWindowPrintf( XBX_CLR_BLUE, "Sync Skipped!\n" );
+ numSkipped++;
+ }
+ else if ( errCode == 1 )
+ {
+ ConsoleWindowPrintf( XBX_CLR_GREEN, "Sync Completed!\n" );
+ numUpdated++;
+ }
+ }
+ while ( FindNextFile( h, &findData ) );
+
+ FindClose( h );
+ }
+ }
+ else if ( !stricmp( pToken, "$end" ) )
+ {
+ bFailed = false;
+ break;
+ }
+ else
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Unknown token: '%s' in '%s'\n", pToken, szScriptPath );
+ bSyntaxError = true;
+ break;
+ }
+ }
+
+ if ( bSyntaxError )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Syntax Error in '%s'.\n", szScriptPath );
+ }
+
+ if ( bCancelled )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Cancelled Installation!\n" );
+ }
+ else if ( bFailed )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "Failed Installation!\n" );
+ }
+ else
+ {
+ char *pCRLF = V_stristr( pVersionDetailString, "\r\n" );
+ if ( pCRLF )
+ {
+ *pCRLF = '\0';
+ }
+
+ // spew stats
+ ConsoleWindowPrintf( XBX_CLR_BLACK, "\n" );
+ ConsoleWindowPrintf( XBX_CLR_BLACK, "Installation Completed.\n" );
+ ConsoleWindowPrintf( XBX_CLR_BLACK, "-----------------------\n" );
+ ConsoleWindowPrintf( XBX_CLR_BLACK, "Version: %s\n", pVersionDetailString ? pVersionDetailString : "???" );
+
+ if ( numFailed )
+ {
+ ConsoleWindowPrintf( XBX_CLR_RED, "%d Failures.\n", numFailed );
+ }
+ ConsoleWindowPrintf( XBX_CLR_BLACK, "%d Files In Sync.\n", numSkipped );
+ ConsoleWindowPrintf( XBX_CLR_BLACK, "%d Files Updated.\n", numUpdated );
+ }
+
+ delete pProgress;
+ Sys_Free( pVersionDetailString );
+ Sys_FreeScriptFile();
+}
+
+//-----------------------------------------------------------------------------
+// InstallDlg_GetChanges
+//
+//-----------------------------------------------------------------------------
+bool InstallDlg_GetChanges( HWND hWnd )
+{
+ g_install_bForceSync = IsDlgButtonChecked( hWnd, IDC_INSTALL_FORCESYNC ) != 0;
+ g_install_bCleanTarget = IsDlgButtonChecked( hWnd, IDC_INSTALL_CLEANTARGET ) != 0;
+
+ g_install_Selection = -1;
+ for ( int i = 0; i < g_install_dvdImages.Count(); i++ )
+ {
+ int state = ListView_GetItemState( GetDlgItem( hWnd, IDC_INSTALL_LIST ), i, LVIS_FOCUSED|LVIS_SELECTED );
+ if ( state == ( LVIS_FOCUSED|LVIS_SELECTED ) )
+ {
+ g_install_Selection = i;
+ break;
+ }
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// SortDVDImages
+//
+//-----------------------------------------------------------------------------
+int SortDVDImages( const dvdimage_t *pA, const dvdimage_t *pB )
+{
+ char szStringA[256];
+ char szStringB[256];
+
+ V_strncpy( szStringA, pA->szString, sizeof( szStringA ) );
+ V_strncpy( szStringB, pB->szString, sizeof( szStringB ) );
+
+ // sort staging first
+ char *pCommentA = V_stristr( szStringA, " (" );
+ char *pCommentB = V_stristr( szStringB, " (" );
+ if ( pCommentA )
+ {
+ *pCommentA = '\0';
+ }
+ if ( pCommentB )
+ {
+ *pCommentB = '\0';
+ }
+
+ return stricmp( szStringB, szStringA );
+}
+
+//-----------------------------------------------------------------------------
+// InstallDlg_Populate
+//
+//-----------------------------------------------------------------------------
+void InstallDlg_Populate( HWND hWnd )
+{
+ HWND hWndListView = GetDlgItem( hWnd, IDC_INSTALL_LIST );
+
+ ListView_DeleteAllItems( hWndListView );
+ g_install_dvdImages.Purge();
+
+ // get list of DVD images
+ char szPath[MAX_PATH];
+ V_ComposeFileName( g_installPath, "DVD_*", szPath, sizeof( szPath ) );
+ WIN32_FIND_DATA findData;
+ HANDLE h = FindFirstFile( szPath, &findData );
+ if ( h != INVALID_HANDLE_VALUE )
+ {
+ do
+ {
+ if ( !stricmp( findData.cFileName, "." ) || !stricmp( findData.cFileName, ".." ) )
+ {
+ continue;
+ }
+ if ( !( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
+ {
+ // skip files
+ continue;
+ }
+
+ char szInstallPath[MAX_PATH];
+ V_strncpy( szInstallPath, g_installPath, sizeof( szInstallPath ) );
+ V_AppendSlash( szInstallPath, sizeof( szInstallPath ) );
+ V_strncat( szInstallPath, findData.cFileName, sizeof( szInstallPath ) );
+
+ // qualify dvd dirs that are images
+ char szBooterPath[MAX_PATH];
+ V_ComposeFileName( szInstallPath, "default.xex", szBooterPath, sizeof( szBooterPath ) );
+ if ( !Sys_Exists( szBooterPath ) )
+ {
+ continue;
+ }
+ char szVersionPath[MAX_PATH];
+ V_ComposeFileName( szInstallPath, "version.txt", szVersionPath, sizeof( szVersionPath ) );
+ char *pVersionDetailString = NULL;
+ if ( Sys_LoadFile( szVersionPath, (void**)&pVersionDetailString ) == -1 )
+ {
+ continue;
+ }
+
+ char *pCRLF = V_stristr( pVersionDetailString, "\r\n" );
+ if ( pCRLF )
+ {
+ *pCRLF = '\0';
+ }
+
+ dvdimage_t image;
+
+ int year = 0;
+ int month = 0;
+ int day = 0;
+ int hour = 0;
+ int minute = 0;
+ char timeOfDay[256];
+ sscanf( findData.cFileName, "DVD_%d_%d_%d_%d_%d_%s", &year, &month, &day, &hour, &minute, timeOfDay );
+
+ const char *pInfoString = timeOfDay;
+ if ( !V_strnicmp( timeOfDay, "PM", 2 ) )
+ {
+ if ( hour != 12 )
+ {
+ // 24 hour time for correct sorting
+ hour += 12;
+ }
+ pInfoString += 2;
+ }
+ else if ( !V_strnicmp( timeOfDay, "AM", 2 ) )
+ {
+ if ( hour == 12 )
+ {
+ // 24 hour time for correct sorting
+ hour = 0;
+ }
+ pInfoString += 2;
+ }
+
+ char szCommentBuff[128];
+ if ( pInfoString[0] == '_' )
+ {
+ // optional info after AM/PM
+ pInfoString++;
+ V_snprintf( szCommentBuff, sizeof( szCommentBuff ), " (%s)", pInfoString );
+ }
+ else
+ {
+ szCommentBuff[0] = '\0';
+ }
+
+ V_snprintf( image.szString, sizeof( image.szString ), "%2.2d/%2.2d/%4.4d %2.2d:%2.2d%s", month, day, year, hour, minute, szCommentBuff );
+
+ image.installPath = szInstallPath;
+ image.versionDetailString = pVersionDetailString;
+ g_install_dvdImages.AddToTail( image );
+ Sys_Free( pVersionDetailString );
+ }
+ while ( FindNextFile( h, &findData ) );
+ FindClose( h );
+ }
+
+ // current image will be at head
+ g_install_dvdImages.Sort( SortDVDImages );
+
+ for ( int i = 0; i < g_install_dvdImages.Count(); i++ )
+ {
+ // setup and insert at end of list
+ LVITEM lvi;
+ memset( &lvi, 0, sizeof( lvi ) );
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = i;
+ lvi.iSubItem = 0;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = (LPARAM)i;
+
+ ListView_InsertItem( hWndListView, &lvi );
+ }
+
+ if ( g_install_dvdImages.Count() )
+ {
+ ListView_SetItemState( hWndListView, 0, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// InstallDlg_Setup
+//
+//-----------------------------------------------------------------------------
+void InstallDlg_Setup( HWND hWnd )
+{
+ g_install_Selection = -1;
+ g_install_bForceSync = false;
+ g_install_bCleanTarget = false;
+
+ HWND hWndListView = GetDlgItem( hWnd, IDC_INSTALL_LIST );
+
+ // initialize columns
+ LVCOLUMN lvc;
+ memset( &lvc, 0, sizeof( lvc ) );
+ lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
+ lvc.iSubItem = 0;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.cx = 200;
+ lvc.pszText = ( LPSTR )"Date Built:";
+ ListView_InsertColumn( hWndListView, 0, &lvc );
+ lvc.iSubItem = 0;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.cx = 500;
+ lvc.pszText = ( LPSTR )"Perforce Changelist:";
+ ListView_InsertColumn( hWndListView, 1, &lvc );
+
+ ListView_SetBkColor( hWndListView, g_backgroundColor );
+ ListView_SetTextBkColor( hWndListView, g_backgroundColor );
+
+ DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES;
+ ListView_SetExtendedListViewStyleEx( hWndListView, style, style );
+
+ InstallDlg_Populate( hWnd );
+}
+
+//-----------------------------------------------------------------------------
+// InstallDlg_Proc
+//
+//-----------------------------------------------------------------------------
+BOOL CALLBACK InstallDlg_Proc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ switch ( message )
+ {
+ case WM_INITDIALOG:
+ InstallDlg_Setup( hWnd );
+ return ( TRUE );
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lParam )->code )
+ {
+ case LVN_GETDISPINFO:
+ NMLVDISPINFO* plvdi;
+ plvdi = (NMLVDISPINFO*)lParam;
+ int item = (int)plvdi->item.lParam;
+ switch ( plvdi->item.iSubItem )
+ {
+ case 0:
+ plvdi->item.pszText = g_install_dvdImages[item].szString;
+ return TRUE;
+ case 1:
+ plvdi->item.pszText = (LPSTR)g_install_dvdImages[item].versionDetailString.String();
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( LOWORD( wParam ) )
+ {
+ case IDC_OK:
+ InstallDlg_GetChanges( hWnd );
+ EndDialog( hWnd, wParam );
+ return ( TRUE );
+
+ case IDC_INSTALL_REFRESH:
+ InstallDlg_Populate( hWnd );
+ return TRUE;
+
+ case IDCANCEL:
+ case IDC_CANCEL:
+ EndDialog( hWnd, wParam );
+ return ( TRUE );
+ }
+ break;
+ }
+ return ( FALSE );
+}
+
+//-----------------------------------------------------------------------------
+// InstallDlg_Open
+//
+//-----------------------------------------------------------------------------
+void InstallDlg_Open( void )
+{
+ int result = DialogBox( g_hInstance, MAKEINTRESOURCE( IDD_INSTALL ), g_hDlgMain, ( DLGPROC )InstallDlg_Proc );
+ if ( LOWORD( result ) == IDC_OK && g_install_Selection != -1 )
+ {
+ InstallDlg_InstallImage(
+ g_install_dvdImages[g_install_Selection].installPath.String(),
+ g_install_bForceSync,
+ g_install_bCleanTarget );
+ }
+
+ g_install_dvdImages.Purge();
+}
diff --git a/utils/xbox/vxconsole/sys_scriptlib.cpp b/utils/xbox/vxconsole/sys_scriptlib.cpp
new file mode 100644
index 0000000..e52729c
--- /dev/null
+++ b/utils/xbox/vxconsole/sys_scriptlib.cpp
@@ -0,0 +1,292 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SYS_SCRIPTLIB.CPP
+//
+//
+//=====================================================================================//
+#include "vxconsole.h"
+
+char g_sys_token[MAXTOKEN];
+char* g_sys_scriptbuff;
+char* g_sys_scriptptr;
+char* g_sys_scriptendptr;
+int g_sys_scriptsize;
+int g_sys_scriptline;
+bool g_sys_endofscript;
+bool g_sys_tokenready;
+int g_sys_oldscriptline;
+char* g_sys_oldscriptptr;
+
+//-----------------------------------------------------------------------------
+// Sys_FreeScriptFile
+//
+//-----------------------------------------------------------------------------
+void Sys_FreeScriptFile(void)
+{
+ if (g_sys_scriptbuff)
+ {
+ Sys_Free(g_sys_scriptbuff);
+ g_sys_scriptbuff = NULL;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Sys_LoadScriptFile
+//
+//-----------------------------------------------------------------------------
+void Sys_LoadScriptFile(const char* filename)
+{
+ g_sys_scriptsize = Sys_LoadFile(filename,(void **)&g_sys_scriptbuff);
+
+ Sys_ResetParser();
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SetScriptData
+//
+//-----------------------------------------------------------------------------
+void Sys_SetScriptData(const char* data, int length)
+{
+ g_sys_scriptbuff = (char *)data;
+ g_sys_scriptsize = length;
+
+ Sys_ResetParser();
+}
+
+//-----------------------------------------------------------------------------
+// Sys_UnGetToken
+//
+//-----------------------------------------------------------------------------
+void Sys_UnGetToken(void)
+{
+ g_sys_tokenready = true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_GetToken
+//
+//-----------------------------------------------------------------------------
+char* Sys_GetToken(bool crossline)
+{
+ char* tokenptr;
+
+ if (g_sys_tokenready)
+ {
+ g_sys_tokenready = false;
+ return (g_sys_token);
+ }
+
+ g_sys_token[0] = '\0';
+
+ if (g_sys_scriptptr >= g_sys_scriptendptr)
+ {
+ g_sys_endofscript = true;
+ return (NULL);
+ }
+
+skipspace:
+ while (*g_sys_scriptptr <= ' ')
+ {
+ if (g_sys_scriptptr >= g_sys_scriptendptr)
+ {
+ g_sys_endofscript = true;
+ return (NULL);
+ }
+
+ if (*g_sys_scriptptr++ == '\n')
+ {
+ if (!crossline)
+ {
+ // unexpected newline at g_sys_scriptline
+ return (NULL);
+ }
+
+ g_sys_scriptline++;
+ }
+ }
+
+ if (g_sys_scriptptr >= g_sys_scriptendptr)
+ {
+ g_sys_endofscript = true;
+ return (NULL);
+ }
+
+ // skip commented line
+ if ((g_sys_scriptptr[0] == ';') || (g_sys_scriptptr[0] == '/' && g_sys_scriptptr[1] == '/'))
+ {
+ if (!crossline)
+ {
+ // unexpected newline at g_sys_scriptline
+ return (NULL);
+ }
+
+ while (*g_sys_scriptptr++ != '\n')
+ {
+ if (g_sys_scriptptr >= g_sys_scriptendptr)
+ {
+ g_sys_endofscript = true;
+ return (NULL);
+ }
+ }
+
+ g_sys_scriptline++;
+ goto skipspace;
+ }
+
+ tokenptr = g_sys_token;
+ if (g_sys_scriptptr[0] == '\"' && g_sys_scriptptr[1])
+ {
+ // copy quoted token
+ do
+ {
+ *tokenptr++ = *g_sys_scriptptr++;
+ if (g_sys_scriptptr == g_sys_scriptendptr)
+ break;
+
+ if (tokenptr == &g_sys_token[MAXTOKEN])
+ {
+ // token too large
+ return NULL;
+ }
+ }
+ while (*g_sys_scriptptr >= ' ' && *g_sys_scriptptr != '\"');
+
+ if (g_sys_scriptptr[0] == '\"')
+ *tokenptr++ = *g_sys_scriptptr++;
+ }
+ else
+ {
+ // copy token
+ while (*g_sys_scriptptr > ' ' && *g_sys_scriptptr != ';' && *g_sys_scriptptr != '\"')
+ {
+ *tokenptr++ = *g_sys_scriptptr++;
+ if (g_sys_scriptptr == g_sys_scriptendptr)
+ break;
+
+ if (tokenptr == &g_sys_token[MAXTOKEN])
+ {
+ // token too large
+ return NULL;
+ }
+ }
+ }
+
+ *tokenptr = '\0';
+
+ return (g_sys_token);
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SkipRestOfLine
+//
+//-----------------------------------------------------------------------------
+void Sys_SkipRestOfLine(void)
+{
+ while (*g_sys_scriptptr++ != '\n')
+ {
+ if (g_sys_scriptptr >= g_sys_scriptendptr)
+ {
+ break;
+ }
+ }
+
+ g_sys_scriptline++;
+
+ // flush any queued token
+ g_sys_tokenready = false;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_TokenAvailable
+//
+// Returns (TRUE) if token available on line.
+//-----------------------------------------------------------------------------
+bool Sys_TokenAvailable (void)
+{
+ char* ptr;
+
+ ptr = g_sys_scriptptr;
+ while (*ptr <= ' ')
+ {
+ if (ptr >= g_sys_scriptendptr)
+ {
+ g_sys_endofscript = true;
+ return (false);
+ }
+
+ if (*ptr++ == '\n')
+ return (false);
+ }
+
+ return (true);
+}
+
+
+//-----------------------------------------------------------------------------
+// Sys_EndOfScript
+//
+// Returns (TRUE) at end of script
+//-----------------------------------------------------------------------------
+bool Sys_EndOfScript(void)
+{
+ if (g_sys_scriptptr >= g_sys_scriptendptr)
+ {
+ g_sys_endofscript = true;
+ return (true);
+ }
+
+ return (false);
+}
+
+//-----------------------------------------------------------------------------
+// Sys_ResetParser
+//
+//-----------------------------------------------------------------------------
+void Sys_ResetParser(void)
+{
+ g_sys_scriptptr = g_sys_scriptbuff;
+ g_sys_scriptendptr = g_sys_scriptptr + g_sys_scriptsize;
+ g_sys_scriptline = 1;
+ g_sys_endofscript = false;
+ g_sys_tokenready = false;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SaveParser
+//
+//-----------------------------------------------------------------------------
+void Sys_SaveParser(void)
+{
+ g_sys_oldscriptline = g_sys_scriptline;
+ g_sys_oldscriptptr = g_sys_scriptptr;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_RestoreParser
+//
+//-----------------------------------------------------------------------------
+void Sys_RestoreParser(void)
+{
+ g_sys_scriptline = g_sys_oldscriptline;
+ g_sys_scriptptr = g_sys_oldscriptptr;
+ g_sys_tokenready = false;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_StripQuotesFromToken
+//
+//-----------------------------------------------------------------------------
+void Sys_StripQuotesFromToken( char *pToken )
+{
+ int len;
+
+ len = strlen( pToken );
+ if ( len >= 2 && pToken[0] == '\"' )
+ {
+ memcpy( pToken, pToken+1, len-1 );
+ pToken[len-2] = '\0';
+ }
+}
+
+
+
diff --git a/utils/xbox/vxconsole/sys_scriptlib.h b/utils/xbox/vxconsole/sys_scriptlib.h
new file mode 100644
index 0000000..a019f83
--- /dev/null
+++ b/utils/xbox/vxconsole/sys_scriptlib.h
@@ -0,0 +1,34 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SYS_SCRIPTLIB.H
+//
+// System Utilities.
+//=====================================================================================//
+#pragma once
+
+#include "vxconsole.h"
+
+#define MAXTOKEN 128
+
+extern void Sys_LoadScriptFile(const char* filename);
+extern void Sys_SetScriptData(const char* data, int length);
+extern void Sys_FreeScriptFile(void);
+extern char* Sys_GetToken(bool crossline);
+extern char* Sys_GetQuotedToken(bool crossline);
+extern void Sys_UnGetToken(void);
+extern bool Sys_TokenAvailable(void);
+extern void Sys_SaveParser(void);
+extern void Sys_RestoreParser(void);
+extern void Sys_ResetParser(void);
+extern void Sys_SkipRestOfLine(void);
+extern bool Sys_EndOfScript(void);
+extern char* Sys_GetRawToken(void);
+extern void Sys_StripQuotesFromToken( char *pToken );
+
+extern char g_sys_token[MAXTOKEN];
+extern char* g_sys_scriptbuffer;
+extern char* g_sys_scriptptr;
+extern char* g_sys_scriptendptr;
+extern int g_sys_scriptsize;
+extern int g_sys_scriptline;
+extern bool g_sys_endofscript;
diff --git a/utils/xbox/vxconsole/sys_utils.cpp b/utils/xbox/vxconsole/sys_utils.cpp
new file mode 100644
index 0000000..d8bf23c
--- /dev/null
+++ b/utils/xbox/vxconsole/sys_utils.cpp
@@ -0,0 +1,1090 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SYS_UTILS.C
+//
+//=====================================================================================//
+#include "vxconsole.h"
+
+CHAR g_szRegistryPrefix[256];
+
+//-----------------------------------------------------------------------------
+// Sys_SetRegistryPrefix
+//
+//-----------------------------------------------------------------------------
+void Sys_SetRegistryPrefix( const CHAR *pPrefix )
+{
+ _snprintf_s( g_szRegistryPrefix, sizeof( g_szRegistryPrefix ), _TRUNCATE, pPrefix );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SplitRegistryKey
+//
+//-----------------------------------------------------------------------------
+static BOOL Sys_SplitRegistryKey( const CHAR *key, CHAR *key0, int key0Len, CHAR *key1, int key1Len )
+{
+ if ( !key )
+ {
+ return false;
+ }
+
+ int len = (int)strlen( key );
+ if ( !len )
+ {
+ return false;
+ }
+
+ int Start = -1;
+ for ( int i=len-1; i>=0; i-- )
+ {
+ if ( key[i] == '\\' )
+ break;
+ else
+ Start=i;
+ }
+
+ if ( Start == -1 )
+ return false;
+
+ _snprintf_s( key0, Start, _TRUNCATE, key );
+ _snprintf_s( key1, ( len-Start )+1, _TRUNCATE, key+Start );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SetRegistryString
+//
+//-----------------------------------------------------------------------------
+BOOL Sys_SetRegistryString( const CHAR *keyName, const CHAR *value )
+{
+ HKEY hKey;
+ CHAR key0[256];
+ CHAR key1[256];
+ CHAR keyBuff[256];
+ CHAR *key;
+
+ strcpy_s( keyBuff, sizeof( keyBuff ), g_szRegistryPrefix );
+ strcat_s( keyBuff, sizeof( keyBuff ), keyName );
+ key = keyBuff;
+
+ HKEY hSlot = HKEY_CURRENT_USER;
+ if ( !strncmp( key, "HKEY_LOCAL_MACHINE", 18 ) )
+ {
+ hSlot = HKEY_LOCAL_MACHINE;
+ key += 19;
+ }
+ else if ( !strncmp( key, "HKEY_CURRENT_USER", 17 ) )
+ {
+ hSlot = HKEY_CURRENT_USER;
+ key += 18;
+ }
+
+ if ( !Sys_SplitRegistryKey( key, key0, sizeof( key0 ), key1, sizeof( key1 ) ) )
+ return false;
+
+ if ( RegCreateKeyEx( hSlot,key0,NULL,NULL,REG_OPTION_NON_VOLATILE, value ? KEY_WRITE : KEY_ALL_ACCESS,NULL,&hKey,NULL )!=ERROR_SUCCESS )
+ return false;
+
+ if ( RegSetValueEx( hKey, key1, NULL, REG_SZ, ( UCHAR* )value, (int)strlen( value ) + 1 ) != ERROR_SUCCESS )
+ {
+ RegCloseKey( hKey );
+ return false;
+ }
+
+ // success
+ RegCloseKey( hKey );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_GetRegistryString
+//
+//-----------------------------------------------------------------------------
+BOOL Sys_GetRegistryString( const CHAR *keyName, CHAR *value, const CHAR* defValue, int valueLen )
+{
+ HKEY hKey;
+ CHAR key0[256];
+ CHAR key1[256];
+ CHAR keyBuff[256];
+ CHAR *key;
+
+ strcpy_s( keyBuff, sizeof( keyBuff ), g_szRegistryPrefix );
+ strcat_s( keyBuff, sizeof( keyBuff ), keyName );
+ key = keyBuff;
+
+ if ( defValue )
+ {
+ _snprintf_s( value, valueLen, _TRUNCATE, defValue );
+ }
+
+ HKEY hSlot = HKEY_CURRENT_USER;
+ if ( !strncmp( key, "HKEY_LOCAL_MACHINE", 18 ) )
+ {
+ hSlot = HKEY_LOCAL_MACHINE;
+ key += 19;
+ }
+ else if ( !strncmp( key, "HKEY_CURRENT_USER", 17 ) )
+ {
+ hSlot = HKEY_CURRENT_USER;
+ key += 18;
+ }
+
+ if ( !Sys_SplitRegistryKey( key,key0,256,key1,256 ) )
+ return false;
+
+ if ( RegOpenKeyEx( hSlot,key0,NULL,KEY_READ,&hKey )!=ERROR_SUCCESS )
+ return false;
+
+ unsigned long len=valueLen;
+ if ( RegQueryValueEx( hKey,key1,NULL,NULL,( UCHAR* )value,&len )!=ERROR_SUCCESS )
+ {
+ RegCloseKey( hKey );
+ return false;
+ }
+
+ // success
+ RegCloseKey( hKey );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SetRegistryInteger
+//
+//-----------------------------------------------------------------------------
+BOOL Sys_SetRegistryInteger( const CHAR *keyName, int value )
+{
+ HKEY hKey;
+ CHAR key0[256];
+ CHAR key1[256];
+ CHAR keyBuff[256];
+ CHAR *key;
+
+ strcpy_s( keyBuff, sizeof( keyBuff ), g_szRegistryPrefix );
+ strcat_s( keyBuff, sizeof( keyBuff ), keyName );
+ key = keyBuff;
+
+ HKEY hSlot = HKEY_CURRENT_USER;
+ if ( !strncmp( key, "HKEY_LOCAL_MACHINE", 18 ) )
+ {
+ hSlot = HKEY_LOCAL_MACHINE;
+ key += 19;
+ }
+ else if ( !strncmp( key, "HKEY_CURRENT_USER", 17 ) )
+ {
+ hSlot = HKEY_CURRENT_USER;
+ key += 18;
+ }
+
+ if ( !Sys_SplitRegistryKey( key,key0,256,key1,256 ) )
+ return false;
+
+ if ( RegCreateKeyEx( hSlot, key0, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL )!=ERROR_SUCCESS )
+ return false;
+
+ if ( RegSetValueEx( hKey, key1, NULL, REG_DWORD, ( UCHAR* )&value, 4 )!=ERROR_SUCCESS )
+ {
+ RegCloseKey( hKey );
+ return false;
+ }
+
+ // success
+ RegCloseKey( hKey );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_GetRegistryInteger
+//
+//-----------------------------------------------------------------------------
+BOOL Sys_GetRegistryInteger( const CHAR *keyName, int defValue, int &value )
+{
+ HKEY hKey;
+ CHAR key0[256];
+ CHAR key1[256];
+ CHAR keyBuff[256];
+ CHAR *key;
+
+ strcpy_s( keyBuff, sizeof( keyBuff ), g_szRegistryPrefix );
+ strcat_s( keyBuff, sizeof( keyBuff ), keyName );
+ key = keyBuff;
+
+ value = defValue;
+
+ HKEY hSlot = HKEY_CURRENT_USER;
+ if ( !strncmp( key, "HKEY_LOCAL_MACHINE", 18 ) )
+ {
+ hSlot = HKEY_LOCAL_MACHINE;
+ key += 19;
+ }
+ else if ( !strncmp( key, "HKEY_CURRENT_USER", 17 ) )
+ {
+ hSlot = HKEY_CURRENT_USER;
+ key += 18;
+ }
+
+ if ( !Sys_SplitRegistryKey( key, key0, 256, key1, 256 ) )
+ return false;
+
+ if ( RegOpenKeyEx( hSlot, key0, NULL, KEY_READ, &hKey ) != ERROR_SUCCESS )
+ return false;
+
+ unsigned long len=4;
+ if ( RegQueryValueEx( hKey, key1, NULL, NULL, ( UCHAR* )&value, &len ) != ERROR_SUCCESS )
+ {
+ RegCloseKey( hKey );
+ return false;
+ }
+
+ // success
+ RegCloseKey( hKey );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_MessageBox
+//
+//-----------------------------------------------------------------------------
+void Sys_MessageBox( const CHAR* title, const CHAR* format, ... )
+{
+ CHAR msg[2048];
+ va_list argptr;
+
+ va_start( argptr, format );
+ vsprintf_s( msg, sizeof( msg ), format, argptr );
+ va_end( argptr );
+
+ MessageBox( NULL, msg, title, MB_OK|MB_TASKMODAL|MB_TOPMOST );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_CopyString
+//
+//-----------------------------------------------------------------------------
+CHAR* Sys_CopyString( const CHAR* str )
+{
+ int len = (int)strlen( str );
+ CHAR *ptr = ( CHAR* )Sys_Alloc( len+1 );
+ memcpy( ptr,str,len+1 );
+
+ return ( ptr );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_Alloc
+//
+//-----------------------------------------------------------------------------
+void* Sys_Alloc( int size )
+{
+ int* ptr;
+
+ if ( !size )
+ {
+ Sys_Error( "Sys_Alloc(): zero size" );
+ }
+
+ size = AlignValue( size, 4 );
+
+ // allocate fixed zero init block
+ ptr = ( int* )malloc( size );
+ if ( !ptr )
+ {
+ Sys_Error( "Sys_Alloc(): %d bytes not available",size );
+ }
+
+ V_memset( ptr, 0, size );
+
+ return ptr;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_Free
+//
+//-----------------------------------------------------------------------------
+void Sys_Free( void* ptr )
+{
+ if ( !ptr )
+ {
+ // already freed - easier for me, not really an error
+ return;
+ }
+
+ free( ptr );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_Error
+//
+//-----------------------------------------------------------------------------
+void Sys_Error( const CHAR* format, ... )
+{
+ va_list argptr;
+ CHAR msg[MAX_SYSPRINTMSG];
+
+ va_start( argptr, format );
+ vsprintf_s( msg, sizeof( msg ), format, argptr );
+ va_end( argptr );
+
+ MessageBox( NULL, msg, "FATAL ERROR", MB_OK|MB_ICONHAND );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_LoadFile
+//
+//-----------------------------------------------------------------------------
+int Sys_LoadFile( const CHAR* filename, void** bufferptr, bool bText )
+{
+ int handle;
+ long length;
+ CHAR* buffer;
+
+ *bufferptr = NULL;
+
+ if ( !Sys_Exists( filename ) )
+ {
+ return ( -1 );
+ }
+
+ int openFlags = bText ? _O_TEXT : _O_BINARY;
+ _sopen_s( &handle, filename, _O_RDONLY|openFlags, _SH_DENYWR, _S_IREAD );
+ if ( handle == -1 )
+ {
+ char szError[MAX_PATH];
+ strerror_s( szError, sizeof( szError ), errno );
+ Sys_Error( "Sys_LoadFile(): Error opening %s: %s", filename, szError );
+ }
+
+ // allocate a buffer with an auto null terminator
+ length = Sys_FileLength( handle );
+ buffer = ( CHAR* )Sys_Alloc( length+1 );
+
+ int numBytesRead = _read( handle, buffer, length );
+ _close( handle );
+
+ if ( bText )
+ {
+ length = numBytesRead;
+ }
+ else if ( length != numBytesRead )
+ {
+ Sys_Error( "Sys_LoadFile(): read failure" );
+ }
+
+ // for parsing
+ buffer[length] = '\0';
+
+ *bufferptr = ( void* )buffer;
+
+ return ( length );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SaveFile
+//
+//-----------------------------------------------------------------------------
+bool Sys_SaveFile( const CHAR* filename, void* buffer, long count, bool bText )
+{
+ int handle;
+ int status;
+
+ int openFlags = bText ? _O_TEXT : _O_BINARY;
+ _sopen_s( &handle, filename, _O_RDWR|_O_CREAT|_O_TRUNC|openFlags, _SH_DENYNO, _S_IREAD|_S_IWRITE );
+ if ( handle == -1 )
+ {
+ char szError[MAX_PATH];
+ strerror_s( szError, sizeof( szError ), errno );
+ Sys_Error( "Sys_SaveFile(): Error opening %s: %s", filename, szError );
+ return false;
+ }
+
+ status = _write( handle, buffer, count );
+ if ( status != count )
+ {
+ Sys_Error( "Sys_SaveFile(): write failure %d, errno=%d", status, errno );
+ return false;
+ }
+
+ _close( handle );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_FileLength
+//
+//-----------------------------------------------------------------------------
+long Sys_FileLength( const CHAR* filename, bool bText )
+{
+ long length;
+
+ if ( filename )
+ {
+ int handle;
+ int openFlags = bText ? _O_TEXT : _O_BINARY;
+ _sopen_s( &handle, filename, _O_RDONLY|openFlags, _SH_DENYWR, _S_IREAD );
+ if ( handle == -1 )
+ {
+ // file does not exist
+ return -1;
+ }
+
+ length = _lseek( handle, 0, SEEK_END );
+ _close( handle );
+ }
+ else
+ {
+ return -1;
+ }
+
+ return length;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_FileLength
+//
+//-----------------------------------------------------------------------------
+long Sys_FileLength( int handle )
+{
+ long pos;
+ long length;
+
+ if ( handle != -1 )
+ {
+ pos = _lseek( handle, 0, SEEK_CUR );
+ length = _lseek( handle, 0, SEEK_END );
+ _lseek( handle, pos, SEEK_SET );
+ }
+ else
+ {
+ return -1;
+ }
+
+ return length;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_NormalizePath
+//
+//-----------------------------------------------------------------------------
+void Sys_NormalizePath( CHAR* path, bool forceToLower )
+{
+ int i;
+ int srclen;
+
+ srclen = (int)strlen( path );
+ for ( i=0; i<srclen; i++ )
+ {
+ if ( path[i] == '/' )
+ path[i] = '\\';
+ else if ( forceToLower && ( path[i] >= 'A' && path[i] <= 'Z' ) )
+ path[i] = path[i] - 'A' + 'a';
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Sys_AddFileSeperator
+//
+//-----------------------------------------------------------------------------
+void Sys_AddFileSeperator( CHAR* path, int pathLen )
+{
+ int srclen;
+
+ if ( !path[0] )
+ {
+ strcpy_s( path, pathLen, ".\\" );
+ return;
+ }
+
+ srclen = (int)strlen( path );
+ if ( path[srclen-1] == '\\' )
+ {
+ return;
+ }
+
+ strcat_s( path, pathLen, "\\" );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_StripFilename
+//
+// Removes filename from path.
+//-----------------------------------------------------------------------------
+void Sys_StripFilename( const CHAR* inpath, CHAR* outpath, int outPathLen )
+{
+ int length;
+
+ strcpy_s( outpath, outPathLen, inpath );
+
+ length = (int)strlen( outpath )-1;
+ while ( ( length > 0 ) && ( outpath[length] != '\\' ) && ( outpath[length] != '/' ) && ( outpath[length] != ':' ) )
+ length--;
+
+ // leave possible seperator
+ if ( !length )
+ outpath[0] = '\0';
+ else
+ outpath[length+1] = '\0';
+}
+
+//-----------------------------------------------------------------------------
+// Sys_StripExtension
+//
+// Removes extension from path.
+//-----------------------------------------------------------------------------
+void Sys_StripExtension( const CHAR* inpath, CHAR* outpath, int outPathLen )
+{
+ int length;
+
+ strcpy_s( outpath, outPathLen, inpath );
+
+ length = (int)strlen( outpath )-1;
+ while ( length > 0 && outpath[length] != '.' )
+ {
+ length--;
+ }
+
+ if ( length && outpath[length] == '.' )
+ {
+ outpath[length] = '\0';
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Sys_StripPath
+//
+// Removes path from full path.
+//-----------------------------------------------------------------------------
+void Sys_StripPath( const CHAR* inpath, CHAR* outpath, int outPathLen )
+{
+ const CHAR* src;
+
+ src = inpath + strlen( inpath );
+ while ( ( src != inpath ) && ( *( src-1 ) != '\\' ) && ( *( src-1 ) != '/' ) && ( *( src-1 ) != ':' ) )
+ {
+ src--;
+ }
+
+ strcpy_s( outpath, outPathLen, src );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_GetExtension
+//
+// Gets any extension from the full path.
+//-----------------------------------------------------------------------------
+void Sys_GetExtension( const CHAR* inpath, CHAR* outpath, int outPathLen )
+{
+ const CHAR* src;
+
+ src = inpath + strlen( inpath ) - 1;
+
+ // back up until a . or the start
+ while ( src != inpath && *( src-1 ) != '.' )
+ {
+ src--;
+ }
+
+ if ( src == inpath )
+ {
+ *outpath = '\0'; // no extension
+ return;
+ }
+
+ strcpy_s( outpath, outPathLen, src );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_AddExtension
+//
+// Adds extension to end of path.
+//-----------------------------------------------------------------------------
+void Sys_AddExtension( const CHAR* extension, CHAR* outpath, int outPathLen )
+{
+ CHAR* src;
+
+ if ( outpath[0] )
+ {
+ src = outpath + strlen( outpath ) - 1;
+ while ( ( src != outpath ) && ( *src != '\\' ) && ( *src != '/' ) )
+ {
+ if ( *src == '.' )
+ return;
+ src--;
+ }
+ }
+
+ strcat_s( outpath, outPathLen, extension );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_TempFilename
+//
+// Make a temporary filename at specified path.
+//-----------------------------------------------------------------------------
+void Sys_TempFilename( CHAR* temppath, int tempPathLen )
+{
+ CHAR* ptr;
+
+ ptr = _tempnam( "c:\\", "tmp" );
+ strcpy_s( temppath, tempPathLen, ptr );
+ free( ptr );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_Exists
+//
+// Returns TRUE if file exists.
+//-----------------------------------------------------------------------------
+BOOL Sys_Exists( const CHAR* filename )
+{
+ FILE* test;
+
+ fopen_s( &test, filename, "rb" );
+ if ( test == NULL )
+ {
+ return false;
+ }
+
+ fclose( test );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SkipWhitespace
+//
+//-----------------------------------------------------------------------------
+CHAR* Sys_SkipWhitespace( CHAR *data, BOOL *hasNewLines, int* numlines )
+{
+ int c;
+
+ while( ( c = *data ) <= ' ' )
+ {
+ if ( c == '\n' )
+ {
+ if ( numlines )
+ ( *numlines )++;
+
+ if ( hasNewLines )
+ *hasNewLines = true;
+ }
+ else if ( !c )
+ return ( NULL );
+
+ data++;
+ }
+
+ return ( data );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_GetToken
+//
+//-----------------------------------------------------------------------------
+CHAR* Sys_GetToken( CHAR** dataptr, BOOL allowLineBreaks, int* numlines )
+{
+ CHAR c;
+ int len;
+ BOOL hasNewLines;
+ CHAR* data;
+ static CHAR token[MAX_SYSTOKENCHARS];
+
+ if ( numlines )
+ *numlines = 0;
+
+ c = 0;
+ data = *dataptr;
+ len = 0;
+ token[0] = 0;
+ hasNewLines = false;
+
+ // make sure incoming data is valid
+ if ( !data )
+ {
+ *dataptr = NULL;
+ return ( token );
+ }
+
+ for ( ;; )
+ {
+ // skip whitespace
+ data = Sys_SkipWhitespace( data,&hasNewLines,numlines );
+ if ( !data )
+ {
+ *dataptr = NULL;
+ return ( token );
+ }
+
+ if ( hasNewLines && !allowLineBreaks )
+ {
+ *dataptr = data;
+ return ( token );
+ }
+
+ c = *data;
+
+ // skip double slash comments
+ if ( c == '/' && data[1] == '/' )
+ {
+ data += 2;
+ while ( *data && *data != '\n' )
+ data++;
+ }
+ // skip /* */ comments
+ else if ( c =='/' && data[1] == '*' )
+ {
+ data += 2;
+ while ( *data && ( *data != '*' || data[1] != '/' ) )
+ data++;
+
+ if ( *data )
+ data += 2;
+ }
+ else
+ break;
+ }
+
+ // handle quoted strings
+ if ( c == '\"' )
+ {
+ data++;
+ for ( ;; )
+ {
+ c = *data++;
+ if ( c == '\"' || !c )
+ {
+ token[len] = 0;
+ *dataptr = ( CHAR* )data;
+ return ( token );
+ }
+ if ( len < MAX_SYSTOKENCHARS )
+ token[len++] = c;
+ }
+ }
+
+ // parse a regular word
+ do
+ {
+ if ( len < MAX_SYSTOKENCHARS )
+ token[len++] = c;
+
+ data++;
+ c = *data;
+ if ( c == '\n' && numlines )
+ ( *numlines )++;
+ } while ( c > ' ' );
+
+ if ( len >= MAX_SYSTOKENCHARS )
+ len = 0;
+
+ token[len] = '\0';
+ *dataptr = ( CHAR* ) data;
+
+ return ( token );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SkipBracedSection
+//
+// The next token should be an open brace.
+// Skips until a matching close brace is found.
+// Internal brace depths are properly skipped.
+//-----------------------------------------------------------------------------
+void Sys_SkipBracedSection( CHAR** dataptr, int* numlines )
+{
+ CHAR* token;
+ int depth;
+
+ depth = 0;
+ do
+ {
+ token = Sys_GetToken( dataptr, true, numlines );
+ if ( token[1] == '\0' )
+ {
+ if ( token[0] == '{' )
+ depth++;
+ else if ( token[0] == '}' )
+ depth--;
+ }
+ }
+ while( depth && *dataptr );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_SkipRestOfLine
+//
+//-----------------------------------------------------------------------------
+void Sys_SkipRestOfLine( CHAR** dataptr, int* numlines )
+{
+ CHAR* p;
+ int c;
+
+ p = *dataptr;
+ while ( ( c = *p++ ) != '\0' )
+ {
+ if ( c == '\n' )
+ {
+ if ( numlines )
+ ( *numlines )++;
+ break;
+ }
+ }
+ *dataptr = p;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_FileTime
+//
+// Returns a file's last write time
+//-----------------------------------------------------------------------------
+BOOL Sys_FileTime( CHAR* filename, FILETIME* time )
+{
+ HANDLE hFile;
+
+ hFile = CreateFile(
+ filename,
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL );
+
+ if ( hFile == INVALID_HANDLE_VALUE )
+ return ( false );
+
+ // Retrieve the file times for the file.
+ if ( !GetFileTime( hFile, NULL, NULL, time ) )
+ {
+ CloseHandle( hFile );
+ return ( false );
+ }
+
+ CloseHandle( hFile );
+ return ( true );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_GetSystemTime
+//
+// Current time marker in milliseconds
+//-----------------------------------------------------------------------------
+DWORD Sys_GetSystemTime( void )
+{
+ LARGE_INTEGER qwTime;
+ LARGE_INTEGER qwTicksPerSec;
+ float msecsPerTick;
+
+ // Get the frequency of the timer
+ QueryPerformanceFrequency( &qwTicksPerSec );
+ msecsPerTick = 1000.0f/( FLOAT )qwTicksPerSec.QuadPart;
+
+ QueryPerformanceCounter( &qwTime );
+ return ( ( DWORD )( msecsPerTick * ( FLOAT )qwTime.QuadPart ) );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_ColorScale
+//
+//-----------------------------------------------------------------------------
+COLORREF Sys_ColorScale( COLORREF color, float scale )
+{
+ int r;
+ int g;
+ int b;
+
+ r = color & 0xFF;
+ g = ( color >> 8 ) & 0xFF;
+ b = ( color >> 16 ) & 0xFF;
+
+ r = ( int )( ( float )r * scale );
+ g = ( int )( ( float )g * scale );
+ b = ( int )( ( float )b * scale );
+
+ if ( r > 255 )
+ r = 255;
+ if ( g > 255 )
+ g = 255;
+ if ( b > 255 )
+ b = 255;
+
+ color = RGB( r, g, b );
+ return ( color );
+}
+
+//-----------------------------------------------------------------------------
+// Sys_IsWildcardMatch
+//
+// See if a string matches a wildcard specification that uses * or ?
+//-----------------------------------------------------------------------------
+bool Sys_IsWildcardMatch( const CHAR *wildcardString, const CHAR *stringToCheck, bool caseSensitive )
+{
+ CHAR wcChar;
+ CHAR strChar;
+
+ if ( !_stricmp( wildcardString, "*.*" ) || !_stricmp( wildcardString, "*" ) )
+ {
+ // matches everything
+ return true;
+ }
+
+ // use the starMatchesZero variable to determine whether an asterisk
+ // matches zero or more characters ( TRUE ) or one or more characters
+ // ( FALSE )
+ bool starMatchesZero = true;
+
+ for ( ;; )
+ {
+ strChar = *stringToCheck;
+ if ( !strChar )
+ {
+ break;
+ }
+
+ wcChar = *wildcardString;
+ if ( !wcChar )
+ {
+ break;
+ }
+
+ // we only want to advance the pointers if we successfully assigned
+ // both of our char variables, so we'll do it here rather than in the
+ // loop condition itself
+ *stringToCheck++;
+ *wildcardString++;
+
+ // if this isn't a case-sensitive match, make both chars uppercase
+ // ( thanks to David John Fielder ( Konan ) at http://innuendo.ev.ca
+ // for pointing out an error here in the original code )
+ if ( !caseSensitive )
+ {
+ wcChar = (CHAR)toupper( wcChar );
+ strChar = (CHAR)toupper( strChar );
+ }
+
+ // check the wcChar against our wildcard list
+ switch ( wcChar )
+ {
+ // an asterisk matches zero or more characters
+ case '*' :
+ // do a recursive call against the rest of the string,
+ // until we've either found a match or the string has
+ // ended
+ if ( starMatchesZero )
+ *stringToCheck--;
+
+ while ( *stringToCheck )
+ {
+ if ( Sys_IsWildcardMatch( wildcardString, stringToCheck++, caseSensitive ) )
+ return true;
+ }
+
+ break;
+
+ // a question mark matches any single character
+ case '?' :
+ break;
+
+ // if we fell through, we want an exact match
+ default :
+ if ( wcChar != strChar )
+ return false;
+ break;
+ }
+ }
+
+ // if we have any asterisks left at the end of the wildcard string, we can
+ // advance past them if starMatchesZero is TRUE ( so "blah*" will match "blah" )
+ while ( ( *wildcardString ) && ( starMatchesZero ) )
+ {
+ if ( *wildcardString == '*' )
+ wildcardString++;
+ else
+ break;
+ }
+
+ // if we got to the end but there's still stuff left in either of our strings,
+ // return false; otherwise, we have a match
+ if ( ( *stringToCheck ) || ( *wildcardString ) )
+ return false;
+ else
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_NumberToCommaString
+//
+// Add commas to number
+//-----------------------------------------------------------------------------
+char *Sys_NumberToCommaString( __int64 number, char *buffer, int bufferSize )
+{
+ char temp[256];
+ char temp2[256];
+ int inLen;
+ char *inPtr;
+ char *outPtr;
+ int i;
+
+ sprintf_s( temp, sizeof( temp ), "%I64d", number );
+
+ // build string backwards
+ inLen = (int)strlen( temp );
+ inPtr = temp+inLen-1;
+ outPtr = temp2;
+ while ( inLen > 0 )
+ {
+ for ( i=0; i<3 && inLen > 0; i++, inLen-- )
+ {
+ *outPtr++ = *inPtr--;
+ }
+ if ( inLen > 0 )
+ *outPtr++ = ',';
+ }
+ *outPtr++ = '\0';
+
+ // reverse string
+ inLen = (int)strlen( temp2 );
+ inPtr = temp2;
+ outPtr = temp;
+ for ( i=inLen-1; i>=0; i-- )
+ {
+ *outPtr++ = inPtr[i];
+ }
+ *outPtr++ = '\0';
+
+ _snprintf_s( buffer, bufferSize, _TRUNCATE, temp );
+
+ return buffer;
+}
+
+//-----------------------------------------------------------------------------
+// Sys_CreatePath
+//
+//-----------------------------------------------------------------------------
+void Sys_CreatePath( const char* pInPath )
+{
+ char* ptr;
+ char dirPath[MAX_PATH];
+
+ // prime and skip to first seperator
+ strcpy_s( dirPath, sizeof( dirPath ), pInPath );
+
+ if ( dirPath[0] == '\\' && dirPath[1] == '\\' )
+ {
+ ptr = strchr( dirPath+1, '\\' );
+ }
+ else
+ {
+ ptr = strchr( dirPath, '\\' );
+ }
+
+ while ( ptr )
+ {
+ ptr = strchr( ptr+1, '\\' );
+ if ( ptr )
+ {
+ *ptr = '\0';
+ CreateDirectory( dirPath, NULL );
+ *ptr = '\\';
+ }
+ }
+}
+
diff --git a/utils/xbox/vxconsole/sys_utils.h b/utils/xbox/vxconsole/sys_utils.h
new file mode 100644
index 0000000..a91c208
--- /dev/null
+++ b/utils/xbox/vxconsole/sys_utils.h
@@ -0,0 +1,65 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// SYS_UTILS.H
+//
+// System Utilities.
+//=====================================================================================//
+#pragma once
+
+#include "vxconsole.h"
+
+#pragma warning(disable : 4100) // warning C4100: unreferenced formal parameter
+
+#define MAX_SYSPRINTMSG 1024
+#define MAX_SYSTOKENCHARS 1024
+
+#define MAKEINT64( hiword, loword ) ( ( __int64 )( ( ( ( __int64 )( hiword ) ) << 32 ) | ( __int64 )( loword ) ) )
+
+extern void Sys_MessageBox( const CHAR *title, const CHAR *format, ... );
+extern void Sys_Error( const CHAR *format, ... );
+
+extern void *Sys_Alloc( int size );
+extern void Sys_Free( void *ptr );
+extern CHAR *Sys_CopyString( const CHAR *str );
+
+extern int Sys_LoadFile( const CHAR *filename, void **bufferptr, bool bText = false );
+extern bool Sys_SaveFile( const CHAR *filename, void *buffer, long count, bool bText = false );
+extern long Sys_FileLength( const CHAR *filename, bool bText = false );
+extern long Sys_FileLength( int handle );
+extern BOOL Sys_FileTime( CHAR *filename, FILETIME *time );
+extern void Sys_CreatePath( const char* pInPath );
+
+extern void Sys_AddFileSeperator( CHAR *path, int outPathLen );
+extern void Sys_NormalizePath( CHAR *path, bool forceToLower );
+extern void Sys_StripFilename( const CHAR *path, CHAR *outpath, int outPathLen );
+extern void Sys_StripExtension( const CHAR *path, CHAR *outpath, int outPathLen );
+extern void Sys_StripPath( const CHAR *path, CHAR *outpath, int outPathLen );
+extern void Sys_GetExtension( const CHAR *path, CHAR *outpath, int outPathLen );
+extern void Sys_AddExtension( const CHAR *extension, CHAR *outpath, int outPathLen );
+extern void Sys_TempFilename( CHAR *outpath, int outPathLen );
+extern BOOL Sys_Exists( const CHAR *filename );
+
+extern CHAR *Sys_GetToken( CHAR **dataptr, BOOL crossline, int *numlines );
+extern CHAR *Sys_SkipWhitespace( CHAR *data, BOOL *hasNewLines, int *numlines );
+extern void Sys_SkipBracedSection( CHAR **dataptr, int *numlines );
+extern void Sys_SkipRestOfLine( CHAR **dataptr, int *numlines );
+
+extern void Sys_SetRegistryPrefix( const CHAR *pPrefix );
+extern BOOL Sys_SetRegistryString( const CHAR *key, const CHAR *value );
+extern BOOL Sys_GetRegistryString( const CHAR *key, CHAR *value, const CHAR *defValue, int valueLen );
+extern BOOL Sys_SetRegistryInteger( const CHAR *key, int value );
+extern BOOL Sys_GetRegistryInteger( const CHAR *key, int defValue, int &value );
+
+extern DWORD Sys_GetSystemTime( void );
+extern COLORREF Sys_ColorScale( COLORREF color, float scale );
+extern bool Sys_IsWildcardMatch( const CHAR *wildcardString, const CHAR *stringToCheck, bool caseSensitive );
+extern char *Sys_NumberToCommaString( __int64 number, char *buffer, int bufferSize );
+
+
+
+
+
+
+
+
+
diff --git a/utils/xbox/vxconsole/tex_profile.cpp b/utils/xbox/vxconsole/tex_profile.cpp
new file mode 100644
index 0000000..8c3ddf1
--- /dev/null
+++ b/utils/xbox/vxconsole/tex_profile.cpp
@@ -0,0 +1,993 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// TEX_PROFILE.CPP
+//
+// Texture Profiling Display.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define TEXPROFILE_MAXCOUNTERS 64
+#define TEXPROFILE_MAXSAMPLES 512
+
+#define TEXPROFILE_MAJORTICKSIZE 4
+#define TEXPROFILE_MAJORTICKBYTES ( TEXPROFILE_MAJORTICKSIZE*1024.0f*1024.0f )
+
+#define TEXPROFILE_HISTORY_MAJORTICKHEIGHT 100
+#define TEXPROFILE_HISTORY_NUMMINORTICKS 3
+#define TEXPROFILE_HISTORY_LABELWIDTH 50
+#define TEXPROFILE_HISTORY_SCALESTEPS 5
+#define TEXPROFILE_HISTORY_MINSCALE 0.3f
+#define TEXPROFILE_HISTORY_MAXSCALE 3.0f
+
+#define TEXPROFILE_SAMPLES_ITEMHEIGHT 15
+#define TEXPROFILE_SAMPLES_BARHEIGHT 10
+#define TEXPROFILE_SAMPLES_MAJORTICKWIDTH 200
+#define TEXPROFILE_SAMPLES_LABELWIDTH 150
+#define TEXPROFILE_SAMPLES_LABELGAP 5
+#define TEXPROFILE_SAMPLES_NUMMINORTICKS 3
+#define TEXPROFILE_SAMPLES_PEAKHOLDTIME 3000
+#define TEXPROFILE_SAMPLES_SCALESTEPS 10
+#define TEXPROFILE_SAMPLES_MINSCALE 0.3f
+#define TEXPROFILE_SAMPLES_MAXSCALE 3.0f
+
+#define ID_TEXPROFILE_SAMPLES 1
+#define ID_TEXPROFILE_HISTORY 2
+
+typedef struct
+{
+ unsigned int samples[TEXPROFILE_MAXSAMPLES];
+ unsigned int peakSample;
+ char label[64];
+ COLORREF color;
+} profileCounter_t;
+
+HWND g_texProfile_hWndSamples;
+HWND g_texProfile_hWndHistory;
+int g_texProfile_numCounters;
+profileCounter_t g_texProfile_counters[TEXPROFILE_MAXCOUNTERS];
+RECT g_texProfile_samplesWindowRect;
+RECT g_texProfile_historyWindowRect;
+DWORD g_texProfile_lastPeakTime;
+bool g_texProfile_history_tickMarks = true;
+bool g_texProfile_history_colors = true;
+int g_texProfile_history_scale;
+bool g_texProfile_samples_tickMarks = true;
+bool g_texProfile_samples_colors = true;
+int g_texProfile_samples_scale;
+int g_texProfile_numSamples;
+int g_texProfile_currentFrame;
+
+//-----------------------------------------------------------------------------
+// TexProfile_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void TexProfile_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ // profile samples
+ Sys_GetRegistryString( "texProfileSamplesWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_texProfile_samplesWindowRect.left, &g_texProfile_samplesWindowRect.top, &g_texProfile_samplesWindowRect.right, &g_texProfile_samplesWindowRect.bottom );
+ if ( numArgs != 4 || g_texProfile_samplesWindowRect.left < 0 || g_texProfile_samplesWindowRect.top < 0 || g_texProfile_samplesWindowRect.right < 0 || g_texProfile_samplesWindowRect.bottom < 0 )
+ memset( &g_texProfile_samplesWindowRect, 0, sizeof( g_texProfile_samplesWindowRect ) );
+ Sys_GetRegistryInteger( "texProfileSamplesScale", 0, g_texProfile_samples_scale );
+ if ( g_texProfile_samples_scale < -TEXPROFILE_SAMPLES_SCALESTEPS || g_texProfile_samples_scale > TEXPROFILE_SAMPLES_SCALESTEPS )
+ g_texProfile_samples_scale = 0;
+
+ // profile history
+ Sys_GetRegistryString( "texProfileHistoryWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_texProfile_historyWindowRect.left, &g_texProfile_historyWindowRect.top, &g_texProfile_historyWindowRect.right, &g_texProfile_historyWindowRect.bottom );
+ if ( numArgs != 4 || g_texProfile_historyWindowRect.left < 0 || g_texProfile_historyWindowRect.top < 0 || g_texProfile_historyWindowRect.right < 0 || g_texProfile_historyWindowRect.bottom < 0 )
+ memset( &g_texProfile_historyWindowRect, 0, sizeof( g_texProfile_historyWindowRect ) );
+ Sys_GetRegistryInteger( "texProfileHistoryScale", 0, g_texProfile_history_scale );
+ if ( g_texProfile_history_scale < -TEXPROFILE_HISTORY_SCALESTEPS || g_texProfile_history_scale > TEXPROFILE_HISTORY_SCALESTEPS )
+ g_texProfile_history_scale = 0;
+
+ Sys_GetRegistryInteger( "texProfileCurrentFrame", 0, g_texProfile_currentFrame );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void TexProfile_SaveConfig()
+{
+ char buff[256];
+ WINDOWPLACEMENT wp;
+
+ // profile samples
+ if ( g_texProfile_hWndSamples )
+ {
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_texProfile_hWndSamples, &wp );
+ g_texProfile_samplesWindowRect = wp.rcNormalPosition;
+ sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom );
+ Sys_SetRegistryString( "texProfileSamplesWindowRect", buff );
+ }
+ Sys_SetRegistryInteger( "texProfileSamplesScale", g_texProfile_samples_scale );
+
+ // profile history
+ if ( g_texProfile_hWndHistory )
+ {
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_texProfile_hWndHistory, &wp );
+ g_texProfile_historyWindowRect = wp.rcNormalPosition;
+ sprintf( buff, "%d %d %d %d", wp.rcNormalPosition.left, wp.rcNormalPosition.top, wp.rcNormalPosition.right, wp.rcNormalPosition.bottom );
+ Sys_SetRegistryString( "texProfileHistoryWindowRect", buff );
+ }
+ Sys_SetRegistryInteger( "texProfileHistoryScale", g_texProfile_history_scale );
+
+ Sys_SetRegistryInteger( "texProfileCurrentFrame", g_texProfile_currentFrame );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_SetTitle
+//
+//-----------------------------------------------------------------------------
+void TexProfile_SetTitle()
+{
+ char titleBuff[128];
+
+ if ( g_texProfile_hWndSamples )
+ {
+ strcpy( titleBuff, "D3D Usage Snapshot" );
+ if ( VProf_GetState() == VPROF_TEXTURE || VProf_GetState() == VPROF_TEXTUREFRAME )
+ strcat( titleBuff, " [ON]" );
+ if ( g_texProfile_currentFrame )
+ strcat( titleBuff, " [FRAME]" );
+
+ SetWindowText( g_texProfile_hWndSamples, titleBuff );
+ }
+
+ if ( g_texProfile_hWndHistory )
+ {
+ strcpy( titleBuff, "D3D Usage History" );
+ if ( VProf_GetState() == VPROF_TEXTURE || VProf_GetState() == VPROF_TEXTUREFRAME )
+ strcat( titleBuff, " [ON]" );
+ if ( g_texProfile_currentFrame )
+ strcat( titleBuff, " [FRAME]" );
+
+ SetWindowText( g_texProfile_hWndHistory, titleBuff );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_UpdateWindow
+//
+//-----------------------------------------------------------------------------
+void TexProfile_UpdateWindow()
+{
+ if ( g_texProfile_hWndSamples && !IsIconic( g_texProfile_hWndSamples ) )
+ {
+ // visible - force a client repaint
+ InvalidateRect( g_texProfile_hWndSamples, NULL, true );
+ }
+
+ if ( g_texProfile_hWndHistory && !IsIconic( g_texProfile_hWndHistory ) )
+ {
+ // visible - force a client repaint
+ InvalidateRect( g_texProfile_hWndHistory, NULL, true );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// rc_SetTexProfile
+//
+//-----------------------------------------------------------------------------
+int rc_SetTexProfile( char* commandPtr )
+{
+ int i;
+ char* cmdToken;
+ int retAddr;
+ int retVal;
+ int errCode = -1;
+ xrProfile_t* localList;
+ int profileList;
+ int numProfiles;
+
+ // get numProfiles
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken,"%x",&numProfiles );
+
+ // get profile attributes
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &profileList );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken,"%x",&retAddr );
+
+ localList = new xrProfile_t[numProfiles];
+ memset( localList, 0, numProfiles*sizeof( xrProfile_t ) );
+
+ // get the caller's profile list
+ DmGetMemory( ( void* )profileList, numProfiles*sizeof( xrProfile_t ), localList, NULL );
+
+ g_texProfile_numCounters = numProfiles;
+ if ( g_texProfile_numCounters > TEXPROFILE_MAXCOUNTERS-1 )
+ g_texProfile_numCounters = TEXPROFILE_MAXCOUNTERS-1;
+
+ for ( i=0; i<g_texProfile_numCounters; i++ )
+ {
+ // swap the structure
+ localList[i].color = BigDWord( localList[i].color );
+
+ // clear the old counter
+ memset( &g_texProfile_counters[i], 0, sizeof( profileCounter_t ) );
+
+ V_strncpy( g_texProfile_counters[i].label, localList[i].labelString, sizeof( g_texProfile_counters[i].label ) );
+ g_texProfile_counters[i].color = localList[i].color;
+ }
+
+ // build out the reserved last counter as total count
+ memset( &g_texProfile_counters[g_texProfile_numCounters], 0, sizeof( profileCounter_t ) );
+ strcpy( g_texProfile_counters[g_texProfile_numCounters].label, "Total" );
+ g_texProfile_counters[i].color = RGB( 255,255,255 );
+ g_texProfile_numCounters++;
+
+ // set the return code
+ retVal = g_texProfile_numCounters-1;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = SetTexProfile( 0x%8.8x, 0x%8.8x )\n", retVal, numProfiles, profileList );
+
+ delete [] localList;
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
+
+//-----------------------------------------------------------------------------
+// rc_SetTexProfileData
+//
+//-----------------------------------------------------------------------------
+int rc_SetTexProfileData( char* commandPtr )
+{
+ int i;
+ char* cmdToken;
+ int errCode = -1;
+ int counters;
+ int currentSample;
+ int total;
+ bool newPeaks;
+ unsigned int localCounters[TEXPROFILE_MAXCOUNTERS];
+ DWORD newTime;
+
+ // get profiles
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &counters );
+
+ // get the caller's profile list
+ if ( g_texProfile_numCounters )
+ DmGetMemory( ( void* )counters, ( g_texProfile_numCounters-1 )*sizeof( int ), localCounters, NULL );
+
+ // timeout peaks
+ newTime = Sys_GetSystemTime();
+ if ( newTime - g_texProfile_lastPeakTime > TEXPROFILE_SAMPLES_PEAKHOLDTIME )
+ {
+ g_texProfile_lastPeakTime = newTime;
+ newPeaks = true;
+ }
+ else
+ newPeaks = false;
+
+ // next sample
+ currentSample = g_texProfile_numSamples % TEXPROFILE_MAXSAMPLES;
+ g_texProfile_numSamples++;
+
+ total = 0;
+ for ( i=0; i<g_texProfile_numCounters; i++ )
+ {
+ if ( i != g_texProfile_numCounters-1 )
+ {
+ g_texProfile_counters[i].samples[currentSample] = localCounters[i];
+ total += localCounters[i];
+ }
+ else
+ {
+ // reserved total counter
+ g_texProfile_counters[i].samples[currentSample] = total;
+ }
+
+ if ( newPeaks || g_texProfile_counters[i].peakSample < g_texProfile_counters[i].samples[currentSample] )
+ g_texProfile_counters[i].peakSample = g_texProfile_counters[i].samples[currentSample];
+ }
+
+ DebugCommand( "SetTexProfileData( 0x%8.8x )\n", counters );
+
+ TexProfile_UpdateWindow();
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_ZoomIn
+//
+//-----------------------------------------------------------------------------
+void TexProfile_ZoomIn( int& scale, int numSteps )
+{
+ scale++;
+ if ( scale > numSteps )
+ {
+ scale = numSteps;
+ return;
+ }
+ TexProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_ZoomOut
+//
+//-----------------------------------------------------------------------------
+void TexProfile_ZoomOut( int& scale, int numSteps )
+{
+ scale--;
+ if ( scale < -numSteps )
+ {
+ scale = -numSteps;
+ return;
+ }
+ TexProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_CalcScale
+//
+//-----------------------------------------------------------------------------
+float TexProfile_CalcScale( int scale, int numSteps, float min, float max )
+{
+ float t;
+
+ // from integral scale [-numSteps..numSteps] to float scale [min..max]
+ t = ( float )( scale + numSteps )/( float )( 2*numSteps );
+ t = min + t*( max-min );
+
+ return t;
+}
+
+//-----------------------------------------------------------------------------
+// TexProfileSamples_Draw
+//
+//-----------------------------------------------------------------------------
+void TexProfileSamples_Draw( HDC hdc, RECT* clientRect )
+{
+ int i;
+ int j;
+ int x;
+ int y;
+ int x0;
+ int y0;
+ int w;
+ float t;
+ float scale;
+ float sample;
+ char labelBuff[128];
+ HPEN hBlackPen;
+ HPEN hPenOld;
+ HPEN hGreyPen;
+ HBRUSH hColoredBrush;
+ HBRUSH hbrushOld;
+ HFONT hFontOld;
+ RECT rect;
+ int currentSample;
+ int numTicks;
+ int tickWidth;
+ int windowWidth;
+ int windowHeight;
+
+ hBlackPen = CreatePen( PS_SOLID, 1, RGB( 0,0,0 ) );
+ hGreyPen = CreatePen( PS_SOLID, 1, Sys_ColorScale( g_backgroundColor, 0.85f ) );
+ hPenOld = ( HPEN )SelectObject( hdc, hBlackPen );
+ hFontOld = SelectFont( hdc, g_hProportionalFont );
+
+ SetBkColor( hdc, g_backgroundColor );
+
+ // zoom
+ scale = TexProfile_CalcScale( g_texProfile_samples_scale, TEXPROFILE_SAMPLES_SCALESTEPS, TEXPROFILE_SAMPLES_MINSCALE, TEXPROFILE_SAMPLES_MAXSCALE );
+ tickWidth = ( int )( TEXPROFILE_SAMPLES_MAJORTICKWIDTH*scale );
+ windowWidth = clientRect->right-clientRect->left;
+ windowHeight = clientRect->bottom-clientRect->top;
+
+ numTicks = ( windowWidth-TEXPROFILE_SAMPLES_LABELWIDTH )/tickWidth + 1;
+ if ( numTicks < 0 )
+ numTicks = 1;
+
+ rect.left = 0;
+ rect.right = TEXPROFILE_SAMPLES_LABELWIDTH;
+ rect.top = 0;
+ rect.bottom = TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ DrawText( hdc, "Name", -1, &rect, DT_LEFT );
+
+ // draw size ticks
+ x = TEXPROFILE_SAMPLES_LABELWIDTH;
+ y = 0;
+ for ( i=0; i<numTicks; i++ )
+ {
+ // tick labels
+ rect.left = x-40;
+ rect.right = x+40;
+ rect.top = y;
+ rect.bottom = y+TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ sprintf( labelBuff, "%dMB", i*TEXPROFILE_MAJORTICKSIZE );
+ DrawText( hdc, labelBuff, -1, &rect, DT_CENTER );
+
+ // major ticks
+ x0 = x;
+ y0 = y + TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ SelectObject( hdc, hBlackPen );
+ MoveToEx( hdc, x0, y0, NULL );
+ LineTo( hdc, x0, y0+windowHeight );
+
+ if ( g_texProfile_samples_tickMarks && g_texProfile_samples_scale > -TEXPROFILE_SAMPLES_SCALESTEPS )
+ {
+ // minor ticks
+ x0 = x;
+ y0 = y + TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ SelectObject( hdc, hGreyPen );
+ for ( j=0; j<TEXPROFILE_SAMPLES_NUMMINORTICKS; j++ )
+ {
+ x0 += tickWidth/( TEXPROFILE_SAMPLES_NUMMINORTICKS+1 );
+
+ MoveToEx( hdc, x0, y0, NULL );
+ LineTo( hdc, x0, y0+windowHeight );
+ }
+ }
+ x += tickWidth;
+ }
+
+ // seperator
+ SelectObject( hdc, hBlackPen );
+ MoveToEx( hdc, 0, TEXPROFILE_SAMPLES_ITEMHEIGHT, NULL );
+ LineTo( hdc, windowWidth, TEXPROFILE_SAMPLES_ITEMHEIGHT );
+
+ // draw labels
+ x = 0;
+ y = TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ for ( i=0; i<g_texProfile_numCounters; i++ )
+ {
+ if ( !g_texProfile_counters[i].label )
+ continue;
+
+ rect.left = x;
+ rect.right = x+TEXPROFILE_SAMPLES_LABELWIDTH-TEXPROFILE_SAMPLES_LABELGAP;
+ rect.top = y;
+ rect.bottom = y+TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ DrawText( hdc, g_texProfile_counters[i].label, -1, &rect, DT_VCENTER|DT_RIGHT|DT_SINGLELINE|DT_END_ELLIPSIS|DT_MODIFYSTRING );
+
+ // draw the under line
+ MoveToEx( hdc, x, y+TEXPROFILE_SAMPLES_ITEMHEIGHT, NULL );
+ LineTo( hdc, x+TEXPROFILE_SAMPLES_LABELWIDTH, y+TEXPROFILE_SAMPLES_ITEMHEIGHT );
+
+ y += TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ }
+
+ // draw bars
+ SelectObject( hdc, hBlackPen );
+ x = TEXPROFILE_SAMPLES_LABELWIDTH;
+ y = TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ currentSample = g_texProfile_numSamples-1;
+ if ( currentSample < 0 )
+ currentSample = 0;
+ else
+ currentSample %= TEXPROFILE_MAXSAMPLES;
+ for ( i=0; i<g_texProfile_numCounters; i++ )
+ {
+ if ( !g_texProfile_counters[i].label )
+ continue;
+
+ hColoredBrush = CreateSolidBrush( g_texProfile_samples_colors ? g_texProfile_counters[i].color : g_backgroundColor );
+ hbrushOld = ( HBRUSH )SelectObject( hdc, hColoredBrush );
+
+ // bar - count is in bytes, scale to major tick
+ t = ( float )g_texProfile_counters[i].samples[currentSample]/TEXPROFILE_MAJORTICKBYTES;
+ w = ( int )( t * ( float )tickWidth );
+ if ( w > windowWidth )
+ w = windowWidth;
+ x0 = x;
+ y0 = y + ( TEXPROFILE_SAMPLES_ITEMHEIGHT-TEXPROFILE_SAMPLES_BARHEIGHT )/2 + 1;
+ Rectangle( hdc, x0, y0, x0 + w, y0 + TEXPROFILE_SAMPLES_BARHEIGHT );
+
+ // peak
+ t = ( float )g_texProfile_counters[i].peakSample/TEXPROFILE_MAJORTICKBYTES;
+ w = ( int )( t * ( float )tickWidth );
+ if ( w > windowWidth )
+ w = windowWidth;
+ x0 = x + w;
+ y0 = y + TEXPROFILE_SAMPLES_ITEMHEIGHT/2 + 1;
+
+ POINT points[4];
+ points[0].x = x0;
+ points[0].y = y0-4;
+ points[1].x = x0+4;
+ points[1].y = y0;
+ points[2].x = x0;
+ points[2].y = y0+4;
+ points[3].x = x0-4;
+ points[3].y = y0;
+ Polygon( hdc, points, 4 );
+
+ SelectObject( hdc, hbrushOld );
+ DeleteObject( hColoredBrush );
+
+ // draw peak sizes
+ sample = ( float )g_texProfile_counters[i].peakSample/1024.0f;
+ if ( sample >= 0.01F )
+ {
+ sprintf( labelBuff, "%.2f MB", sample/1024.0f );
+ rect.left = x0 + 8;
+ rect.right = x0 + 8 + 100;
+ rect.top = y;
+ rect.bottom = y + TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ DrawText( hdc, labelBuff, -1, &rect, DT_VCENTER|DT_LEFT|DT_SINGLELINE );
+ }
+
+ y += TEXPROFILE_SAMPLES_ITEMHEIGHT;
+ }
+
+ SelectObject( hdc, hFontOld );
+ SelectObject( hdc, hPenOld );
+ DeleteObject( hBlackPen );
+ DeleteObject( hGreyPen );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfileHistory_Draw
+//
+//-----------------------------------------------------------------------------
+void TexProfileHistory_Draw( HDC hdc, RECT* clientRect )
+{
+ char labelBuff[128];
+ HPEN hBlackPen;
+ HPEN hPenOld;
+ HPEN hNullPen;
+ HPEN hGreyPen;
+ HBRUSH hColoredBrush;
+ HBRUSH hBrushOld;
+ HFONT hFontOld;
+ int currentSample;
+ int numTicks;
+ int tickHeight;
+ int windowWidth;
+ int windowHeight;
+ int x;
+ int y;
+ int y0;
+ int i;
+ int j;
+ int h;
+ int numbars;
+ RECT rect;
+ float t;
+ float scale;
+
+ hBlackPen = CreatePen( PS_SOLID, 1, RGB( 0,0,0 ) );
+ hGreyPen = CreatePen( PS_SOLID, 1, Sys_ColorScale( g_backgroundColor, 0.85f ) );
+ hNullPen = CreatePen( PS_NULL, 0, RGB( 0,0,0 ) );
+ hPenOld = ( HPEN )SelectObject( hdc, hBlackPen );
+ hFontOld = SelectFont( hdc, g_hProportionalFont );
+
+ // zoom
+ scale = TexProfile_CalcScale( g_texProfile_history_scale, TEXPROFILE_HISTORY_SCALESTEPS, TEXPROFILE_HISTORY_MINSCALE, TEXPROFILE_HISTORY_MAXSCALE );
+ tickHeight = ( int )( TEXPROFILE_HISTORY_MAJORTICKHEIGHT*scale );
+ windowWidth = clientRect->right-clientRect->left;
+ windowHeight = clientRect->bottom-clientRect->top;
+
+ numTicks = windowHeight/tickHeight + 2;
+ if ( numTicks < 0 )
+ numTicks = 1;
+
+ SetBkColor( hdc, g_backgroundColor );
+
+ x = 0;
+ y = windowHeight;
+ for ( i=0; i<numTicks; i++ )
+ {
+ // major ticks
+ SelectObject( hdc, hBlackPen );
+ MoveToEx( hdc, 0, y, NULL );
+ LineTo( hdc, windowWidth, y );
+
+ if ( g_texProfile_history_tickMarks && g_texProfile_history_scale > -TEXPROFILE_HISTORY_SCALESTEPS )
+ {
+ // minor ticks
+ y0 = y;
+ SelectObject( hdc, hGreyPen );
+ for ( j=0; j<TEXPROFILE_HISTORY_NUMMINORTICKS; j++ )
+ {
+ y0 += tickHeight/( TEXPROFILE_SAMPLES_NUMMINORTICKS+1 );
+ MoveToEx( hdc, 0, y0, NULL );
+ LineTo( hdc, windowWidth, y0 );
+ }
+ }
+
+ // tick labels
+ if ( i )
+ {
+ rect.left = windowWidth-50;
+ rect.right = windowWidth;
+ rect.top = y-20;
+ rect.bottom = y;
+ sprintf( labelBuff, "%dMB", i*TEXPROFILE_MAJORTICKSIZE );
+ DrawText( hdc, labelBuff, -1, &rect, DT_RIGHT|DT_SINGLELINE|DT_BOTTOM );
+ }
+
+ y -= tickHeight;
+ }
+
+ // vertical bars
+ if ( g_texProfile_numSamples )
+ {
+ SelectObject( hdc, hNullPen );
+
+ numbars = windowWidth-TEXPROFILE_HISTORY_LABELWIDTH;
+ currentSample = g_texProfile_numSamples-1;
+ for ( x=numbars-1; x>=0; x-=4 )
+ {
+ // all the counters at this sample
+ y = windowHeight;
+ for ( j=0; j<g_texProfile_numCounters-1; j++ )
+ {
+ if ( !g_texProfile_counters[j].label )
+ continue;
+
+ t = ( float )g_texProfile_counters[j].samples[currentSample % TEXPROFILE_MAXSAMPLES]/TEXPROFILE_MAJORTICKBYTES;
+ h = ( int )( t * ( float )tickHeight );
+ if ( h )
+ {
+ if ( h > windowHeight )
+ h = windowHeight;
+
+ hColoredBrush = CreateSolidBrush( g_texProfile_history_colors ? g_texProfile_counters[j].color : RGB( 80,80,80 ) );
+ hBrushOld = ( HBRUSH )SelectObject( hdc, hColoredBrush );
+
+ Rectangle( hdc, x-4, y-h, x, y+1 );
+ y -= h;
+
+ SelectObject( hdc, hBrushOld );
+ DeleteObject( hColoredBrush );
+ }
+ }
+ currentSample--;
+ if ( currentSample < 0 )
+ {
+ // no data
+ break;
+ }
+ }
+ }
+
+ SelectObject( hdc, hFontOld );
+ SelectObject( hdc, hPenOld );
+ DeleteObject( hBlackPen );
+ DeleteObject( hGreyPen );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK TexProfile_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ HDC hdc;
+ PAINTSTRUCT ps;
+ RECT rect;
+ int id;
+ bool bIsSamples;
+ bool bIsHistory;
+ CREATESTRUCT *createStructPtr;
+ bool bIsEnabled;
+
+ // identify window
+ id = ( int )GetWindowLong( hwnd, GWL_USERDATA+0 );
+ bIsSamples = ( id == ID_TEXPROFILE_SAMPLES );
+ bIsHistory = ( id == ID_TEXPROFILE_HISTORY );
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ // set the window identifier
+ createStructPtr = ( CREATESTRUCT* )lParam;
+ SetWindowLong( hwnd, GWL_USERDATA+0, ( LONG )createStructPtr->lpCreateParams );
+
+ // reset peaks
+ g_texProfile_lastPeakTime = 0;
+ return 0L;
+
+ case WM_DESTROY:
+ TexProfile_SaveConfig();
+
+ if ( bIsSamples )
+ g_texProfile_hWndSamples = NULL;
+ else if ( bIsHistory )
+ g_texProfile_hWndHistory = NULL;
+
+ if ( VProf_GetState() == VPROF_TEXTURE || VProf_GetState() == VPROF_TEXTUREFRAME )
+ {
+ VProf_Enable( VPROF_OFF );
+ }
+ return 0L;
+
+ case WM_INITMENU:
+ if ( bIsSamples )
+ {
+ CheckMenuItem( ( HMENU )wParam, IDM_TEXPROFILE_TICKMARKS, MF_BYCOMMAND | ( g_texProfile_samples_tickMarks ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_TEXPROFILE_COLORS, MF_BYCOMMAND | ( g_texProfile_samples_colors ? MF_CHECKED : MF_UNCHECKED ) );
+ }
+ else if ( bIsHistory )
+ {
+ CheckMenuItem( ( HMENU )wParam, IDM_TEXPROFILE_TICKMARKS, MF_BYCOMMAND | ( g_texProfile_history_tickMarks ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_TEXPROFILE_COLORS, MF_BYCOMMAND | ( g_texProfile_history_colors ? MF_CHECKED : MF_UNCHECKED ) );
+ }
+ CheckMenuItem( ( HMENU )wParam, IDM_TEXPROFILE_ENABLE, MF_BYCOMMAND | ( ( VProf_GetState() == VPROF_TEXTURE || VProf_GetState() == VPROF_TEXTUREFRAME ) ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_TEXPROFILE_CURRENTFRAME, MF_BYCOMMAND | ( g_texProfile_currentFrame ? MF_CHECKED : MF_UNCHECKED ) );
+ return 0L;
+
+ case WM_PAINT:
+ GetClientRect( hwnd, &rect );
+ hdc = BeginPaint( hwnd, &ps );
+ if ( bIsSamples )
+ TexProfileSamples_Draw( hdc, &rect );
+ else if ( bIsHistory )
+ TexProfileHistory_Draw( hdc, &rect );
+ EndPaint( hwnd, &ps );
+ return 0L;
+
+ case WM_SIZE:
+ // force a redraw
+ TexProfile_UpdateWindow();
+ return 0L;
+
+ case WM_KEYDOWN:
+ switch ( wParam )
+ {
+ case VK_INSERT:
+ if ( bIsSamples )
+ TexProfile_ZoomIn( g_texProfile_samples_scale, TEXPROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ TexProfile_ZoomIn( g_texProfile_history_scale, TEXPROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+
+ case VK_DELETE:
+ if ( bIsSamples )
+ TexProfile_ZoomOut( g_texProfile_samples_scale, TEXPROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ TexProfile_ZoomOut( g_texProfile_history_scale, TEXPROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_TEXPROFILE_TICKMARKS:
+ if ( bIsSamples )
+ g_texProfile_samples_tickMarks ^= 1;
+ else if ( bIsHistory )
+ g_texProfile_history_tickMarks ^= 1;
+ TexProfile_UpdateWindow();
+ return 0L;
+
+ case IDM_TEXPROFILE_COLORS:
+ if ( bIsSamples )
+ g_texProfile_samples_colors ^= 1;
+ else if ( bIsHistory )
+ g_texProfile_history_colors ^= 1;
+ TexProfile_UpdateWindow();
+ return 0L;
+
+ case IDM_TEXPROFILE_ZOOMIN:
+ if ( bIsSamples )
+ TexProfile_ZoomIn( g_texProfile_samples_scale, TEXPROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ TexProfile_ZoomIn( g_texProfile_history_scale, TEXPROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+
+ case IDM_TEXPROFILE_ZOOMOUT:
+ if ( bIsSamples )
+ TexProfile_ZoomOut( g_texProfile_samples_scale, TEXPROFILE_SAMPLES_SCALESTEPS );
+ else if ( bIsHistory )
+ TexProfile_ZoomOut( g_texProfile_history_scale, TEXPROFILE_HISTORY_SCALESTEPS );
+ return 0L;
+
+ case IDM_TEXPROFILE_ENABLE:
+ bIsEnabled = ( VProf_GetState() == VPROF_TEXTURE || VProf_GetState() == VPROF_TEXTUREFRAME );
+ bIsEnabled ^= 1;
+ if ( !bIsEnabled )
+ VProf_Enable( VPROF_OFF );
+ else
+ {
+ if ( !g_texProfile_currentFrame )
+ VProf_Enable( VPROF_TEXTURE );
+ else
+ VProf_Enable( VPROF_TEXTUREFRAME );
+ }
+ TexProfile_SetTitle();
+ return 0L;
+
+ case IDM_TEXPROFILE_CURRENTFRAME:
+ bIsEnabled = ( VProf_GetState() == VPROF_TEXTURE || VProf_GetState() == VPROF_TEXTUREFRAME );
+ g_texProfile_currentFrame ^= 1;
+ if ( bIsEnabled )
+ {
+ if ( !g_texProfile_currentFrame )
+ VProf_Enable( VPROF_TEXTURE );
+ else
+ VProf_Enable( VPROF_TEXTUREFRAME );
+ }
+ TexProfile_SetTitle();
+ return 0L;
+ }
+ break;
+ }
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfileHistory_Open
+//
+//-----------------------------------------------------------------------------
+void TexProfileHistory_Open()
+{
+ HWND hWnd;
+
+ if ( g_texProfile_hWndHistory )
+ {
+ // only one profile instance
+ if ( IsIconic( g_texProfile_hWndHistory ) )
+ ShowWindow( g_texProfile_hWndHistory, SW_RESTORE );
+ SetForegroundWindow( g_texProfile_hWndHistory );
+ return;
+ }
+
+ if ( VProf_GetState() == VPROF_OFF )
+ {
+ if ( !g_texProfile_currentFrame )
+ VProf_Enable( VPROF_TEXTURE );
+ else
+ VProf_Enable( VPROF_TEXTUREFRAME );
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "TEXPROFILEHISTORYCLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 600,
+ 500,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ ( void* )ID_TEXPROFILE_HISTORY );
+ g_texProfile_hWndHistory = hWnd;
+
+ TexProfile_SetTitle();
+
+ if ( g_texProfile_historyWindowRect.right && g_texProfile_historyWindowRect.bottom )
+ MoveWindow( g_texProfile_hWndHistory, g_texProfile_historyWindowRect.left, g_texProfile_historyWindowRect.top, g_texProfile_historyWindowRect.right-g_texProfile_historyWindowRect.left, g_texProfile_historyWindowRect.bottom-g_texProfile_historyWindowRect.top, FALSE );
+ ShowWindow( g_texProfile_hWndHistory, SHOW_OPENWINDOW );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfileSamples_Open
+//
+//-----------------------------------------------------------------------------
+void TexProfileSamples_Open()
+{
+ HWND hWnd;
+
+ if ( g_texProfile_hWndSamples )
+ {
+ // only one profile instance
+ if ( IsIconic( g_texProfile_hWndSamples ) )
+ ShowWindow( g_texProfile_hWndSamples, SW_RESTORE );
+ SetForegroundWindow( g_texProfile_hWndSamples );
+ return;
+ }
+
+ if ( VProf_GetState() == VPROF_OFF )
+ {
+ if ( !g_texProfile_currentFrame )
+ VProf_Enable( VPROF_TEXTURE );
+ else
+ VProf_Enable( VPROF_TEXTUREFRAME );
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "TEXPROFILESAMPLESCLASS",
+ "",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 600,
+ 500,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ ( void* )ID_TEXPROFILE_SAMPLES );
+ g_texProfile_hWndSamples = hWnd;
+
+ TexProfile_SetTitle();
+
+ if ( g_texProfile_samplesWindowRect.right && g_texProfile_samplesWindowRect.bottom )
+ MoveWindow( g_texProfile_hWndSamples, g_texProfile_samplesWindowRect.left, g_texProfile_samplesWindowRect.top, g_texProfile_samplesWindowRect.right-g_texProfile_samplesWindowRect.left, g_texProfile_samplesWindowRect.bottom-g_texProfile_samplesWindowRect.top, FALSE );
+ ShowWindow( g_texProfile_hWndSamples, SHOW_OPENWINDOW );
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_Clear
+//
+//-----------------------------------------------------------------------------
+void TexProfile_Clear()
+{
+ // clear counters and history
+ g_texProfile_numCounters = 0;
+ g_texProfile_numSamples = 0;
+
+ TexProfile_UpdateWindow();
+}
+
+//-----------------------------------------------------------------------------
+// TexProfile_Init
+//
+//-----------------------------------------------------------------------------
+bool TexProfile_Init()
+{
+ WNDCLASS wndclass;
+
+ // set up our window class
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = TexProfile_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_TEXPROFILE );
+ wndclass.lpszClassName = "TEXPROFILESAMPLESCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ // set up our window class
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = TexProfile_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_TEXPROFILE );
+ wndclass.lpszClassName = "TEXPROFILEHISTORYCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ TexProfile_LoadConfig();
+
+ return true;
+} \ No newline at end of file
diff --git a/utils/xbox/vxconsole/timestamp_log.cpp b/utils/xbox/vxconsole/timestamp_log.cpp
new file mode 100644
index 0000000..1cc45ef
--- /dev/null
+++ b/utils/xbox/vxconsole/timestamp_log.cpp
@@ -0,0 +1,623 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// TIMESTAMP_LOG.CPP
+//
+// TimeStamp Log Display.
+//=====================================================================================//
+#include "vxconsole.h"
+
+#define ID_TIMESTAMPLOG_LISTVIEW 100
+
+// column id
+#define ID_TSL_TIME 0
+#define ID_TSL_DELTATIME 1
+#define ID_TSL_MEMORY 2
+#define ID_TSL_DELTAMEMORY 3
+#define ID_TSL_MESSAGE 4
+
+typedef struct
+{ const CHAR* name;
+ int width;
+ int subItemIndex;
+ CHAR nameBuff[32];
+} label_t;
+
+struct timeStampLogNode_t
+{
+ int index;
+ float time;
+ float deltaTime;
+ int memory;
+ int deltaMemory;
+ char timeBuff[32];
+ char deltaTimeBuff[32];
+ char memoryBuff[32];
+ char deltaMemoryBuff[32];
+ char *pMessage;
+ timeStampLogNode_t *pNext;
+};
+
+HWND g_timeStampLog_hWnd;
+HWND g_timeStampLog_hWndListView;
+RECT g_timeStampLog_windowRect;
+timeStampLogNode_t *g_timeStampLog_pNodes;
+int g_timeStampLog_sortColumn;
+int g_timeStampLog_sortDescending;
+
+label_t g_timeStampLog_Labels[] =
+{
+ {"Time", 100, ID_TSL_TIME},
+ {"Delta Time", 100, ID_TSL_DELTATIME},
+ {"Memory", 100, ID_TSL_MEMORY},
+ {"Delta Memory", 100, ID_TSL_DELTAMEMORY},
+ {"Message", 400, ID_TSL_MESSAGE},
+};
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_CompareFunc
+//
+//-----------------------------------------------------------------------------
+int CALLBACK TimeStampLog_CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
+{
+ timeStampLogNode_t* pNodeA = ( timeStampLogNode_t* )lParam1;
+ timeStampLogNode_t* pNodeB = ( timeStampLogNode_t* )lParam2;
+
+ int sort = 0;
+ switch ( g_timeStampLog_sortColumn )
+ {
+ case ID_TSL_TIME:
+ sort = ( int )( 1000.0f*pNodeA->time - 1000.0f*pNodeB->time );
+ break;
+
+ case ID_TSL_DELTATIME:
+ sort = ( int )( 1000.0f*pNodeA->deltaTime - 1000.0f*pNodeB->deltaTime );
+ break;
+
+ case ID_TSL_MEMORY:
+ sort = pNodeA->memory - pNodeB->memory;
+ break;
+
+ case ID_TSL_DELTAMEMORY:
+ sort = pNodeA->deltaMemory - pNodeB->deltaMemory;
+ break;
+
+ case ID_TSL_MESSAGE:
+ sort = stricmp( pNodeA->pMessage, pNodeB->pMessage );
+ break;
+ }
+
+ // flip the sort order
+ if ( g_timeStampLog_sortDescending )
+ sort *= -1;
+
+ return ( sort );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_SortItems
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_SortItems()
+{
+ LVITEM lvitem;
+ timeStampLogNode_t *pNode;
+ int i;
+
+ if ( !g_timeStampLog_hWnd )
+ {
+ // only sort if window is visible
+ return;
+ }
+
+ ListView_SortItems( g_timeStampLog_hWndListView, TimeStampLog_CompareFunc, 0 );
+
+ memset( &lvitem, 0, sizeof( lvitem ) );
+ lvitem.mask = LVIF_PARAM;
+
+ // get each item and reset its list index
+ int itemCount = ListView_GetItemCount( g_timeStampLog_hWndListView );
+ for ( i=0; i<itemCount; i++ )
+ {
+ lvitem.iItem = i;
+ ListView_GetItem( g_timeStampLog_hWndListView, &lvitem );
+
+ pNode = ( timeStampLogNode_t* )lvitem.lParam;
+ pNode->index = i;
+ }
+
+ // update list view columns with sort key
+ for ( i=0; i<sizeof( g_timeStampLog_Labels )/sizeof( g_timeStampLog_Labels[0] ); i++ )
+ {
+ char symbol;
+ LVCOLUMN lvc;
+
+ if ( i == g_timeStampLog_sortColumn )
+ symbol = g_timeStampLog_sortDescending ? '<' : '>';
+ else
+ symbol = ' ';
+ sprintf( g_timeStampLog_Labels[i].nameBuff, "%s %c", g_timeStampLog_Labels[i].name, symbol );
+
+ memset( &lvc, 0, sizeof( lvc ) );
+ lvc.mask = LVCF_TEXT;
+ lvc.pszText = ( LPSTR )g_timeStampLog_Labels[i].nameBuff;
+
+ ListView_SetColumn( g_timeStampLog_hWndListView, i, &lvc );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_AddViewItem
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_AddViewItem( timeStampLogNode_t* pNode )
+{
+ LVITEM lvi;
+
+ if ( !g_timeStampLog_hWnd )
+ {
+ // only valid if log window is visible
+ return;
+ }
+
+ // update the text callback buffers
+ sprintf( pNode->timeBuff, "%2.2d:%2.2d:%2.2d:%3.3d", ( int )pNode->time/3600, ( ( int )pNode->time/60 )%60, ( int )pNode->time%60, ( int )( 1000*( pNode->time-( int )pNode->time ) )%1000 );
+ sprintf( pNode->deltaTimeBuff, "%.3f", pNode->deltaTime );
+ sprintf( pNode->memoryBuff, "%.2f MB", pNode->memory/( 1024.0f*1024.0f ) );
+ sprintf( pNode->deltaMemoryBuff, "%d", pNode->deltaMemory );
+
+ int itemCount = ListView_GetItemCount( g_timeStampLog_hWndListView );
+
+ // setup and insert at end of list
+ memset( &lvi, 0, sizeof( lvi ) );
+ lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
+ lvi.iItem = itemCount;
+ lvi.iSubItem = 0;
+ lvi.state = 0;
+ lvi.stateMask = 0;
+ lvi.pszText = LPSTR_TEXTCALLBACK;
+ lvi.lParam = ( LPARAM )pNode;
+
+ // insert
+ pNode->index = ListView_InsertItem( g_timeStampLog_hWndListView, &lvi );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_AddItem
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_AddItem( float time, float deltaTime, int memory, int deltaMemory, const char* pMessage )
+{
+ timeStampLogNode_t* pNode;
+
+ // create and init
+ pNode = new timeStampLogNode_t;
+ memset( pNode, 0, sizeof( timeStampLogNode_t ) );
+
+ pNode->time = time;
+ pNode->deltaTime = deltaTime;
+ pNode->memory = memory;
+ pNode->deltaMemory = deltaMemory;
+ pNode->pMessage = Sys_CopyString( pMessage ? pMessage : "" );
+
+ // link in
+ pNode->pNext = g_timeStampLog_pNodes;
+ g_timeStampLog_pNodes = pNode;
+
+ TimeStampLog_AddViewItem( pNode );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_Clear
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_Clear()
+{
+ timeStampLogNode_t* pNode;
+ timeStampLogNode_t* pNextNode;
+
+ // delete all the list view entries
+ if ( g_timeStampLog_hWnd )
+ ListView_DeleteAllItems( g_timeStampLog_hWndListView );
+
+ // delete nodes in chain
+ pNode = g_timeStampLog_pNodes;
+ while ( pNode )
+ {
+ pNextNode = pNode->pNext;
+
+ Sys_Free( pNode->pMessage );
+ delete pNode;
+
+ pNode = pNextNode;
+ }
+ g_timeStampLog_pNodes = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_SaveConfig
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_SaveConfig()
+{
+ char buff[256];
+
+ Sys_SetRegistryInteger( "timeStampLogSortColumn", g_timeStampLog_sortColumn );
+ Sys_SetRegistryInteger( "timeStampLogSortDescending", g_timeStampLog_sortDescending );
+
+ WINDOWPLACEMENT wp;
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_timeStampLog_hWnd, &wp );
+ g_timeStampLog_windowRect = wp.rcNormalPosition;
+
+ sprintf( buff, "%d %d %d %d", g_timeStampLog_windowRect.left, g_timeStampLog_windowRect.top, g_timeStampLog_windowRect.right, g_timeStampLog_windowRect.bottom );
+ Sys_SetRegistryString( "timeStampLogWindowRect", buff );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_LoadConfig
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_LoadConfig()
+{
+ int numArgs;
+ char buff[256];
+
+ Sys_GetRegistryInteger( "timeStampLogSortColumn", ID_TSL_TIME, g_timeStampLog_sortColumn );
+ Sys_GetRegistryInteger( "timeStampLogSortDescending", false, g_timeStampLog_sortDescending );
+
+ Sys_GetRegistryString( "timeStampLogWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_timeStampLog_windowRect.left, &g_timeStampLog_windowRect.top, &g_timeStampLog_windowRect.right, &g_timeStampLog_windowRect.bottom );
+ if ( numArgs != 4 || g_timeStampLog_windowRect.left < 0 || g_timeStampLog_windowRect.top < 0 || g_timeStampLog_windowRect.right < 0 || g_timeStampLog_windowRect.bottom < 0 )
+ memset( &g_timeStampLog_windowRect, 0, sizeof( g_timeStampLog_windowRect ) );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_SizeWindow
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_SizeWindow( HWND hwnd, int width, int height )
+{
+ if ( width==0 || height==0 )
+ {
+ RECT rcClient;
+ GetClientRect( hwnd, &rcClient );
+ width = rcClient.right;
+ height = rcClient.bottom;
+ }
+
+ // position the ListView
+ SetWindowPos( g_timeStampLog_hWndListView, NULL, 0, 0, width, height, SWP_NOZORDER );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_Export
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_Export()
+{
+ OPENFILENAME ofn;
+ char logFilename[MAX_PATH];
+ int retval;
+ FILE* fp;
+ int i;
+ int count;
+
+ memset( &ofn, 0, sizeof( ofn ) );
+ ofn.lStructSize = sizeof( ofn );
+ ofn.hwndOwner = g_timeStampLog_hWnd;
+ ofn.lpstrFile = logFilename;
+ ofn.lpstrFile[0] = '\0';
+ ofn.nMaxFile = sizeof( logFilename );
+ ofn.lpstrFilter = "Excel CSV\0*.CSV\0All Files\0*.*\0";
+ ofn.nFilterIndex = 1;
+ ofn.lpstrFileTitle = NULL;
+ ofn.nMaxFileTitle = 0;
+ ofn.lpstrInitialDir = "c:\\";
+ ofn.Flags = OFN_PATHMUSTEXIST;
+
+ // display the open dialog box
+ retval = GetOpenFileName( &ofn );
+ if ( !retval )
+ return;
+
+ Sys_AddExtension( ".csv", logFilename, sizeof( logFilename ) );
+
+ fp = fopen( logFilename, "wt+" );
+ if ( !fp )
+ return;
+
+ // labels
+ count = ARRAYSIZE( g_timeStampLog_Labels );
+ for ( i=0; i<count; i++ )
+ {
+ fprintf( fp, "\"%s\"", g_timeStampLog_Labels[i].name );
+ if ( i != count-1 )
+ fprintf( fp, "," );
+ }
+ fprintf( fp, "\n" );
+
+ // build a list for easy reverse traversal
+ CUtlVector< timeStampLogNode_t* > nodeList;
+ timeStampLogNode_t *pNode;
+ pNode = g_timeStampLog_pNodes;
+ while ( pNode )
+ {
+ nodeList.AddToTail( pNode );
+ pNode = pNode->pNext;
+ }
+
+ // dump to the log
+ for ( int i=nodeList.Count()-1; i>=0; i-- )
+ {
+ pNode = nodeList[i];
+
+ fprintf( fp, "\"%s\"", pNode->timeBuff );
+ fprintf( fp, ",\"%s\"", pNode->deltaTimeBuff );
+ fprintf( fp, ",\"%s\"", pNode->memoryBuff );
+ fprintf( fp, ",\"%s\"", pNode->deltaMemoryBuff );
+ fprintf( fp, ",\"%s\"", pNode->pMessage );
+ fprintf( fp, "\n" );
+ }
+
+ fclose( fp );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_WndProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK TimeStampLog_WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ timeStampLogNode_t *pNode;
+
+ switch ( message )
+ {
+ case WM_CREATE:
+ return 0L;
+
+ case WM_DESTROY:
+ TimeStampLog_SaveConfig();
+ g_timeStampLog_hWnd = NULL;
+ return 0L;
+
+ case WM_SIZE:
+ TimeStampLog_SizeWindow( hwnd, LOWORD( lParam ), HIWORD( lParam ) );
+ return 0L;
+
+ case WM_NOTIFY:
+ switch ( ( ( LPNMHDR )lParam )->code )
+ {
+ case LVN_COLUMNCLICK:
+ NMLISTVIEW* pnmlv;
+ pnmlv = ( NMLISTVIEW* )lParam;
+ if ( g_timeStampLog_sortColumn == pnmlv->iSubItem )
+ {
+ // user has clicked on same column - flip the sort
+ g_timeStampLog_sortDescending ^= 1;
+ }
+ else
+ {
+ // sort by new column
+ g_timeStampLog_sortColumn = pnmlv->iSubItem;
+ }
+ TimeStampLog_SortItems();
+ return 0L;
+
+ case LVN_GETDISPINFO:
+ NMLVDISPINFO* plvdi;
+ plvdi = ( NMLVDISPINFO* )lParam;
+ pNode = ( timeStampLogNode_t * )plvdi->item.lParam;
+ switch ( plvdi->item.iSubItem )
+ {
+ case ID_TSL_TIME:
+ plvdi->item.pszText = pNode->timeBuff;
+ return 0L;
+
+ case ID_TSL_DELTATIME:
+ plvdi->item.pszText = pNode->deltaTimeBuff;
+ return 0L;
+
+ case ID_TSL_MEMORY:
+ plvdi->item.pszText = pNode->memoryBuff;
+ return 0L;
+
+ case ID_TSL_DELTAMEMORY:
+ plvdi->item.pszText = pNode->deltaMemoryBuff;
+ return 0L;
+
+ case ID_TSL_MESSAGE:
+ plvdi->item.pszText = pNode->pMessage;
+ return 0L;
+
+ default:
+ break;
+ }
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDM_OPTIONS_CLEAR:
+ TimeStampLog_Clear();
+ return 0L;
+
+ case IDM_OPTIONS_EXPORT:
+ TimeStampLog_Export();
+ return 0L;
+ }
+ break;
+ }
+
+ return ( DefWindowProc( hwnd, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_Init
+//
+//-----------------------------------------------------------------------------
+bool TimeStampLog_Init()
+{
+ // set up our window class
+ WNDCLASS wndclass;
+
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = TimeStampLog_WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_APPLICATION];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_TIMESTAMPLOG );
+ wndclass.lpszClassName = "TIMESTAMPLOGCLASS";
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ TimeStampLog_LoadConfig();
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// TimeStampLog_Open
+//
+//-----------------------------------------------------------------------------
+void TimeStampLog_Open()
+{
+ RECT clientRect;
+ HWND hWnd;
+ int i;
+ timeStampLogNode_t *pNode;
+
+ if ( g_timeStampLog_hWnd )
+ {
+ // only one file log instance
+ if ( IsIconic( g_timeStampLog_hWnd ) )
+ ShowWindow( g_timeStampLog_hWnd, SW_RESTORE );
+ SetForegroundWindow( g_timeStampLog_hWnd );
+ return;
+ }
+
+ hWnd = CreateWindowEx(
+ WS_EX_CLIENTEDGE,
+ "TIMESTAMPLOGCLASS",
+ "TimeStamp Log",
+ WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_SIZEBOX|WS_MINIMIZEBOX|WS_MAXIMIZEBOX,
+ 0,
+ 0,
+ 600,
+ 300,
+ g_hDlgMain,
+ NULL,
+ g_hInstance,
+ NULL );
+ g_timeStampLog_hWnd = hWnd;
+
+ GetClientRect( g_timeStampLog_hWnd, &clientRect );
+ hWnd = CreateWindow(
+ WC_LISTVIEW,
+ "",
+ WS_VISIBLE|WS_CHILD|LVS_REPORT,
+ 0,
+ 0,
+ clientRect.right-clientRect.left,
+ clientRect.bottom-clientRect.top,
+ g_timeStampLog_hWnd,
+ ( HMENU )ID_TIMESTAMPLOG_LISTVIEW,
+ g_hInstance,
+ NULL );
+ g_timeStampLog_hWndListView = hWnd;
+
+ // init list view columns
+ for ( i=0; i<sizeof( g_timeStampLog_Labels )/sizeof( g_timeStampLog_Labels[0] ); i++ )
+ {
+ LVCOLUMN lvc;
+ memset( &lvc, 0, sizeof( lvc ) );
+
+ lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
+ lvc.iSubItem = 0;
+ lvc.cx = g_timeStampLog_Labels[i].width;
+ lvc.fmt = LVCFMT_LEFT;
+ lvc.pszText = ( LPSTR )g_timeStampLog_Labels[i].name;
+
+ ListView_InsertColumn( g_timeStampLog_hWndListView, i, &lvc );
+ }
+
+ ListView_SetBkColor( g_timeStampLog_hWndListView, g_backgroundColor );
+ ListView_SetTextBkColor( g_timeStampLog_hWndListView, g_backgroundColor );
+
+ DWORD style = LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP;
+ ListView_SetExtendedListViewStyleEx( g_timeStampLog_hWndListView, style, style );
+
+ // populate list view
+ pNode = g_timeStampLog_pNodes;
+ while ( pNode )
+ {
+ TimeStampLog_AddViewItem( pNode );
+ pNode = pNode->pNext;
+ }
+ TimeStampLog_SortItems();
+
+ if ( g_timeStampLog_windowRect.right && g_timeStampLog_windowRect.bottom )
+ MoveWindow( g_timeStampLog_hWnd, g_timeStampLog_windowRect.left, g_timeStampLog_windowRect.top, g_timeStampLog_windowRect.right-g_timeStampLog_windowRect.left, g_timeStampLog_windowRect.bottom-g_timeStampLog_windowRect.top, FALSE );
+ ShowWindow( g_timeStampLog_hWnd, SHOW_OPENWINDOW );
+}
+
+
+//-----------------------------------------------------------------------------
+// rc_TimeStampLog
+//
+// Sent from application with time stamp log
+//-----------------------------------------------------------------------------
+int rc_TimeStampLog( char* commandPtr )
+{
+ char *cmdToken;
+ int timeStampAddr;
+ int retAddr;
+ int retVal;
+ int errCode = -1;
+ xrTimeStamp_t timeStamp;
+
+ // get data
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &timeStampAddr );
+
+ // get retAddr
+ cmdToken = GetToken( &commandPtr );
+ if ( !cmdToken[0] )
+ goto cleanUp;
+ sscanf( cmdToken, "%x", &retAddr );
+
+ // get the caller's data
+ DmGetMemory( ( void* )timeStampAddr, sizeof( xrTimeStamp_t ), &timeStamp, NULL );
+
+ // swap the structure
+ BigFloat( &timeStamp.time, &timeStamp.time );
+ BigFloat( &timeStamp.deltaTime, &timeStamp.deltaTime );
+ timeStamp.memory = BigDWord( timeStamp.memory );
+ timeStamp.deltaMemory = BigDWord( timeStamp.deltaMemory );
+
+ // add to log
+ TimeStampLog_AddItem( timeStamp.time, timeStamp.deltaTime, timeStamp.memory, timeStamp.deltaMemory, timeStamp.messageString );
+ TimeStampLog_SortItems();
+
+ // return the result
+ retVal = 0;
+ int xboxRetVal = BigDWord( retVal );
+ DmSetMemory( ( void* )retAddr, sizeof( int ), &xboxRetVal, NULL );
+
+ DebugCommand( "0x%8.8x = TimeStampLog( 0x%8.8x )\n", retVal, timeStampAddr );
+
+ // success
+ errCode = 0;
+
+cleanUp:
+ return ( errCode );
+}
diff --git a/utils/xbox/vxconsole/vxconsole.cpp b/utils/xbox/vxconsole/vxconsole.cpp
new file mode 100644
index 0000000..976f3da
--- /dev/null
+++ b/utils/xbox/vxconsole/vxconsole.cpp
@@ -0,0 +1,1528 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// VXCONSOLE.CPP
+//
+// Valve XBox Console.
+//=====================================================================================//
+#include "vxconsole.h"
+
+HWND g_hDlgMain;
+HWND g_hwndCommandCombo;
+HWND g_hwndOutputWindow;
+HWND g_hwndCommandHint;
+WNDPROC g_hwndCommandSubclassed;
+BOOL g_connectedToXBox;
+BOOL g_connectedToApp;
+PDMN_SESSION g_pdmnSession;
+PDM_CONNECTION g_pdmConnection;
+printQueue_t g_PrintQueue;
+UINT_PTR g_autoConnectTimer;
+BOOL g_autoConnect;
+BOOL g_debugCommands;
+BOOL g_captureDebugSpew;
+BOOL g_captureGameSpew = TRUE;
+CHAR g_xboxName[MAX_XBOXNAMELEN];
+DWORD g_xboxAddress;
+HINSTANCE g_hInstance;
+HICON g_hIcons[MAX_ICONS];
+HBRUSH g_hBackgroundBrush;
+HFONT g_hFixedFont;
+BOOL g_reboot;
+char* g_rebootArgv[MAX_ARGVELEMS];
+int g_rebootArgc;
+COLORREF g_backgroundColor;
+TEXTMETRIC g_fixedFontMetrics;
+int g_connectCount;
+int g_currentIcon = -1;
+HACCEL g_hAccel;
+HMODULE g_hRichEdit;
+DWORD g_connectedTime;
+RECT g_mainWindowRect;
+HFONT g_hProportionalFont;
+HANDLE g_hCommandReadyEvent;
+int g_currentCommandSelection;
+int g_connectFailure;
+int g_configID;
+bool g_bSuppressBlink = false;
+BOOL g_bPlayTestMode = TRUE;
+
+LRESULT CALLBACK Main_DlgProc( HWND, UINT, WPARAM, LPARAM );
+LRESULT CALLBACK CommandWindow_SubclassedProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
+
+bool ParseCommandLineArg( const char *pCmdLine, const char *pKey, char *pValueBuff, int valueBuffSize )
+{
+ const char* pArg = V_stristr( (char*)pCmdLine, pKey );
+ if ( !pArg )
+ {
+ return false;
+ }
+
+ if ( pValueBuff )
+ {
+ // caller wants next token
+ pArg += strlen( pKey );
+
+ int i;
+ for ( i=0; i<valueBuffSize; i++ )
+ {
+ pValueBuff[i] = *pArg;
+ if ( *pArg == '\0' || *pArg == ' ' )
+ {
+ break;
+ }
+ pArg++;
+ }
+ pValueBuff[i] = '\0';
+ }
+
+ return true;
+}
+
+void MakeConfigString( const char *pString, int configID, char *pOutBuff, int outBuffSize )
+{
+ if ( configID <= 0 )
+ {
+ // as-is, undecorated
+ V_snprintf( pOutBuff, outBuffSize, "%s", pString );
+ return;
+ }
+
+ int len = strlen( pString );
+ bool bAddTerminalSlash = ( len > 1 && pString[len-1] == '\\' );
+
+ V_snprintf( pOutBuff, outBuffSize, "%s_%d", pString, configID );
+
+ if ( bAddTerminalSlash )
+ {
+ V_strncat( pOutBuff, "\\", outBuffSize );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// LoadConfig
+//
+//-----------------------------------------------------------------------------
+void LoadConfig()
+{
+ char buff[256];
+ int numArgs;
+
+ ConfigDlg_LoadConfig();
+
+ // initial menu state is from persisted config
+ g_captureDebugSpew = g_captureDebugSpew_StartupState;
+
+ Sys_GetRegistryString( "mainWindowRect", buff, "", sizeof( buff ) );
+ numArgs = sscanf( buff, "%d %d %d %d", &g_mainWindowRect.left, &g_mainWindowRect.top, &g_mainWindowRect.right, &g_mainWindowRect.bottom );
+ if ( numArgs != 4 || g_mainWindowRect.left < 0 || g_mainWindowRect.top < 0 || g_mainWindowRect.right < 0 || g_mainWindowRect.bottom < 0 )
+ memset( &g_mainWindowRect, 0, sizeof( g_mainWindowRect ) );
+}
+
+//-----------------------------------------------------------------------------
+// SaveConfig
+//
+//-----------------------------------------------------------------------------
+void SaveConfig()
+{
+ char buff[256];
+
+ // get window placement
+ WINDOWPLACEMENT wp;
+ memset( &wp, 0, sizeof( wp ) );
+ wp.length = sizeof( WINDOWPLACEMENT );
+ GetWindowPlacement( g_hDlgMain, &wp );
+ g_mainWindowRect = wp.rcNormalPosition;
+
+ sprintf( buff, "%d %d %d %d", g_mainWindowRect.left, g_mainWindowRect.top, g_mainWindowRect.right, g_mainWindowRect.bottom );
+ Sys_SetRegistryString( "mainWindowRect", buff );
+}
+
+//-----------------------------------------------------------------------------
+// SetConnectionIcon
+//
+//-----------------------------------------------------------------------------
+void SetConnectionIcon( int icon )
+{
+ if ( g_currentIcon == icon )
+ return;
+
+ g_currentIcon = icon;
+ SetClassLongPtr( g_hDlgMain, GCLP_HICON, ( LONG_PTR )g_hIcons[icon] );
+}
+
+//-----------------------------------------------------------------------------
+// SetMainWindowTitle
+//
+//-----------------------------------------------------------------------------
+void SetMainWindowTitle()
+{
+ if ( !g_hDlgMain )
+ {
+ return;
+ }
+
+ char titleBuff[128];
+ if ( !g_xboxTargetName[0] )
+ {
+ strcpy( titleBuff, VXCONSOLE_TITLE );
+ }
+ else
+ {
+ sprintf( titleBuff, "%s: %s", VXCONSOLE_TITLE, g_xboxTargetName );
+ if ( g_configID )
+ {
+ char configBuff[32];
+ sprintf( configBuff, " (%d)", g_configID );
+ V_strncat( titleBuff, configBuff, sizeof( titleBuff ) );
+ }
+ }
+ SetWindowText( g_hDlgMain, titleBuff );
+}
+
+//-----------------------------------------------------------------------------
+// DmAPI_DisplayError
+//
+//-----------------------------------------------------------------------------
+VOID DmAPI_DisplayError( const CHAR* message, HRESULT hr )
+{
+ CHAR strError[128];
+
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "%s\n", message );
+
+ HRESULT hrError = DmTranslateError( hr, strError, sizeof( strError ) );
+ if ( !FAILED( hrError ) && strError[0] )
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "Reason: '%s'\n", strError );
+ else
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "Reason: 0x%08lx\n", hr );
+}
+
+//-----------------------------------------------------------------------------
+// DmAPI_SendCommand
+//
+// Send the specified string across the debugger channel to the application
+//-----------------------------------------------------------------------------
+HRESULT DmAPI_SendCommand( const char* strCommand, bool wait )
+{
+ DWORD dwResponseLen;
+ CHAR strResponse[MAX_PATH];
+ int retval;
+ bool bIgnorePingResponse;
+ char* ptr;
+
+ retval = WaitForSingleObject( g_hCommandReadyEvent, wait ? INFINITE : 0 );
+ if ( retval != WAIT_OBJECT_0 )
+ {
+ // cannot send command
+ // some other previous command has not responded and signaled the release
+ // testing has shown DmSendCommand() is not re-entrant and callers get
+ // their responses out of sync
+ return XBDM_UNDEFINED;
+ }
+
+ // clear the event mutex until ready
+ ResetEvent( g_hCommandReadyEvent );
+
+ bIgnorePingResponse = false;
+ dwResponseLen = sizeof( strResponse );
+ strResponse[0] = '\0';
+
+ if ( strCommand[0] == '*' )
+ {
+ // skip past internal command identifier
+ strCommand++;
+ }
+ else if ( !stricmp( strCommand, VXCONSOLE_COMMAND_PREFIX "!" ) )
+ {
+ // empty ping command
+ // must be done as a synchronous command with a response because there
+ // is no way to bind an asynch response to the owner
+ bIgnorePingResponse = true;
+ }
+
+ HRESULT hr = DmSendCommand( g_pdmConnection, strCommand, strResponse, &dwResponseLen );
+ if ( !FAILED( hr ) )
+ {
+ // success
+ switch ( hr )
+ {
+ case XBDM_NOERR:
+ if ( !bIgnorePingResponse )
+ {
+ // skip past possible ack prefix
+ ptr = strstr( strResponse, VXCONSOLE_COMMAND_ACK );
+ if ( ptr )
+ {
+ ptr += strlen( VXCONSOLE_COMMAND_ACK );
+
+ // ignore remote acknowledge response
+ if ( !stricmp( ptr, "OK" ) )
+ break;
+ }
+ else
+ {
+ ptr = strResponse;
+ }
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s\n", ptr );
+ }
+ break;
+
+ case XBDM_MULTIRESPONSE:
+ // multi-line response - loop, looking for end of response
+ while ( 1 )
+ {
+ dwResponseLen = sizeof( strResponse );
+
+ hr = DmReceiveSocketLine( g_pdmConnection, strResponse, &dwResponseLen );
+ if ( FAILED( hr ) || strResponse[0] == '.' )
+ break;
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "%s\n", strResponse );
+ }
+ break;
+
+ case XBDM_BINRESPONSE:
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Binary response - not implemented\n" );
+ break;
+
+ case XBDM_READYFORBIN:
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "Ready for binary - not implemented\n" );
+ break;
+
+ default:
+ ConsoleWindowPrintf( XBX_CLR_RED, "Unknown Response: ( %s ).\n", strResponse );
+ break;
+ }
+ }
+
+ SetEvent( g_hCommandReadyEvent );
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// PrintToQueue
+//
+// Formats the string and adds it to the print queue
+//-----------------------------------------------------------------------------
+void PrintToQueue( COLORREF rgb, LPCTSTR strFormat, ... )
+{
+ char buffer[MAX_QUEUEDSTRINGLEN];
+
+ // enter critical section so we don't try to process the list
+ EnterCriticalSection( &g_PrintQueue.CriticalSection );
+
+ assert( g_PrintQueue.numMessages <= MAX_QUEUEDSTRINGS );
+
+ // when the queue is full, the main thread is probably blocked and not dequeing
+ if ( !g_captureGameSpew || g_PrintQueue.numMessages == MAX_QUEUEDSTRINGS )
+ {
+ LeaveCriticalSection( &g_PrintQueue.CriticalSection );
+ return;
+ }
+
+ va_list arglist;
+ va_start( arglist, strFormat );
+ int len = _vsnprintf( buffer, MAX_QUEUEDSTRINGLEN, strFormat, arglist );
+ if ( len == -1 )
+ {
+ buffer[sizeof(buffer)-1] = '\0';
+ }
+ va_end( arglist );
+
+ // queue the message into the next slot
+ g_PrintQueue.pMessages[g_PrintQueue.numMessages] = Sys_CopyString( buffer );
+ g_PrintQueue.aColors[g_PrintQueue.numMessages++] = rgb;
+
+ // ensure we post a message to process the print queue
+ if ( g_PrintQueue.numMessages == 1 )
+ PostMessage( g_hDlgMain, WM_USER, 0, 0 );
+
+ // the main thread can now safely process the list
+ LeaveCriticalSection( &g_PrintQueue.CriticalSection );
+}
+
+//-----------------------------------------------------------------------------
+// ProcessPrintQueue
+//
+//-----------------------------------------------------------------------------
+void ProcessPrintQueue()
+{
+ // enter critical section so we don't try to add anything while we're processing
+ EnterCriticalSection( &g_PrintQueue.CriticalSection );
+
+ // dequeue all entries
+ for ( int i = 0; i < g_PrintQueue.numMessages; i++ )
+ {
+ ConsoleWindowPrintf( g_PrintQueue.aColors[i], "%s", g_PrintQueue.pMessages[i] );
+ Sys_Free( g_PrintQueue.pMessages[i] );
+ }
+
+ g_PrintQueue.numMessages = 0;
+
+ // now we can safely add to the list
+ LeaveCriticalSection( &g_PrintQueue.CriticalSection );
+}
+
+//-----------------------------------------------------------------------------
+// ConsoleWindowPrintf
+//
+// Writes out a string directly to the console window
+//-----------------------------------------------------------------------------
+int ConsoleWindowPrintf( COLORREF rgb, LPCTSTR strFormat, ... )
+{
+ int dwStrLen;
+ char strTemp[512];
+ va_list arglist;
+ CHARRANGE cr = { -1, -2 };
+
+ if ( rgb != XBX_CLR_DEFAULT )
+ {
+ // set whatever colors, etc. they want
+ CHARFORMAT cf = {0};
+ cf.cbSize = sizeof( cf );
+ cf.dwMask = CFM_COLOR;
+ cf.dwEffects = 0;
+ cf.crTextColor = rgb;
+ SendDlgItemMessage( g_hDlgMain, IDC_OUTPUT, EM_SETCHARFORMAT, SCF_SELECTION, ( LPARAM )&cf );
+ }
+
+ // Get our string to print
+ va_start( arglist, strFormat );
+ dwStrLen = _vsnprintf( strTemp, sizeof( strTemp ), strFormat, arglist );
+ va_end( arglist );
+
+ // Move the selection to the end
+ SendDlgItemMessage( g_hDlgMain, IDC_OUTPUT, EM_EXSETSEL, 0, ( LPARAM )&cr );
+
+ // Add the text and scroll it into view
+ SendDlgItemMessage( g_hDlgMain, IDC_OUTPUT, EM_REPLACESEL, 0, ( LONG )( LPSTR )strTemp );
+ SendDlgItemMessage( g_hDlgMain, IDC_OUTPUT, EM_SCROLLCARET, 0, 0L );
+
+ if ( g_bPlayTestMode )
+ {
+ char szLogPath[MAX_PATH];
+ char szLogName[MAX_PATH];
+ V_snprintf( szLogName, sizeof( szLogName ), "vxconsole_%s.log", g_xboxTargetName );
+ V_ComposeFileName( g_localPath, szLogName, szLogPath, sizeof( szLogPath ) );
+ FILE *fp = fopen( szLogPath, "at+" );
+ if ( fp )
+ {
+ fprintf( fp, strTemp );
+ fclose( fp );
+ }
+ }
+
+ return dwStrLen;
+}
+
+//-----------------------------------------------------------------------------
+// ProcessCommand
+//
+//-----------------------------------------------------------------------------
+bool ProcessCommand( const char* strCmdIn )
+{
+ char strRemoteCmd[MAX_PATH + 10];
+ TCHAR strCmdBak[MAX_PATH];
+ char strCmd[MAX_PATH];
+ char* argv[MAX_ARGVELEMS];
+ BOOL isXCommand = FALSE;
+ BOOL isLocal = FALSE;
+ BOOL isRemote = FALSE;
+ int iIndex;
+
+ // local copy for destructive purposes
+ strcpy( strCmd, strCmdIn );
+
+ // copy of the original command string
+ lstrcpyA( strCmdBak, strCmdIn );
+
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "] %s\n", strCmd );
+
+ // parse argstring into components
+ int argc = CmdToArgv( strCmd, argv, MAX_ARGVELEMS );
+ if ( !argc )
+ {
+ // empty command
+ return true;
+ }
+
+ if ( ( iIndex = ComboBox_GetCount( g_hwndCommandCombo ) ) >= MAX_COMMANDHISTORY )
+ {
+ // Limit the history of items, purge oldest
+ ComboBox_DeleteString( g_hwndCommandCombo, 0 );
+ }
+
+ // add to end of list
+ iIndex = ComboBox_InsertItemData( g_hwndCommandCombo, -1, strCmdBak );
+ ComboBox_SetCurSel( g_hwndCommandCombo, -1 );
+
+ // find command in local list
+ for ( int i=0; i<g_numLocalCommands; i++ )
+ {
+ if ( lstrcmpiA( g_localCommands[i].strCommand, argv[0] ) )
+ {
+ // no match
+ continue;
+ }
+
+ isLocal = TRUE;
+ if ( !g_localCommands[i].pfnHandler )
+ {
+ // no handler, remote xcommand
+ isXCommand = TRUE;
+ }
+
+ if ( ( g_localCommands[i].flags & FN_XBOX ) && !g_connectedToXBox )
+ {
+ // not allowed yet
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "'%s' is not available until connected to XBox.\n", argv[0] );
+ return true;
+ }
+ else if ( ( g_localCommands[i].flags & FN_APP ) && !g_connectedToApp )
+ {
+ // not allowed yet
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "'%s' is not available until connected to Application.\n", argv[0] );
+ return true;
+ }
+
+ if ( isXCommand )
+ break;
+
+ // do local command
+ g_localCommands[i].pfnHandler( argc, argv );
+ return true;
+ }
+
+ // find command in remote list
+ if ( !isLocal && !isXCommand && g_connectedToApp )
+ {
+ for ( int i=0; i<g_numRemoteCommands; i++ )
+ {
+ if ( lstrcmpiA( g_remoteCommands[i]->strCommand, argv[0] ) )
+ {
+ // no match
+ continue;
+ }
+
+ isRemote = TRUE;
+
+ if ( !g_connectedToApp )
+ {
+ // not allowed yet
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "'%s' is not available until connected to Application.\n", argv[0] );
+ return true;
+ }
+ break;
+ }
+ }
+
+ if ( !isLocal && !isXCommand && !isRemote )
+ {
+ if ( !g_connectedToApp || g_numRemoteCommands != 0 )
+ {
+ // unrecognized
+ ConsoleWindowPrintf( RGB( 255,0,0 ), "'%s' is not a recognized command.\n", argv[0] );
+ return true;
+ }
+ }
+
+ if ( isXCommand )
+ {
+ // send the xcommand directly
+ lstrcpyA( strRemoteCmd, strCmdBak );
+ }
+ else
+ {
+ // add remote command prefix
+ lstrcpyA( strRemoteCmd, VXCONSOLE_COMMAND_PREFIX "!" );
+ lstrcatA( strRemoteCmd, strCmdBak );
+ }
+
+ // send the command to the Xbox
+ HRESULT hr = DmAPI_SendCommand( strRemoteCmd, true );
+ if ( FAILED( hr ) )
+ {
+ DmAPI_DisplayError( "DmSendCommand", hr );
+ return false;
+ }
+
+ return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// CommandWindow_HandleKey
+//
+// Handle a WM_KEYDOWN in our RTF cmd window
+//-----------------------------------------------------------------------------
+BOOL CommandWindow_HandleKey( WPARAM wParam )
+{
+ BOOL bHandled = FALSE;
+ int curSel;
+ int numItems;
+
+ if ( wParam >= VK_F1 && wParam <= VK_F12 )
+ {
+ if ( Bindings_TranslateKey( wParam ) )
+ {
+ // handled
+ return true;
+ }
+ }
+
+ switch ( wParam )
+ {
+ case VK_TAB:
+ case VK_UP:
+ case VK_DOWN:
+ if ( IsWindowVisible( g_hwndCommandHint ) )
+ {
+ // hint window open
+ char hintCmd[MAX_PATH];
+ char userCmd[MAX_PATH];
+
+ // scroll through the hint selections
+ curSel = SendMessage( g_hwndCommandHint, (UINT)LB_GETCURSEL, NULL, NULL );
+ SendMessage( g_hwndCommandHint, (UINT)LB_GETTEXT, (WPARAM)curSel, (LPARAM)hintCmd );
+
+ numItems = SendMessage( g_hwndCommandHint, (UINT)LB_GETCOUNT, NULL, NULL );
+ if ( numItems < 0 )
+ numItems = 0;
+
+ if ( wParam == VK_TAB )
+ {
+ // get command typed so far
+ ComboBox_GetText( g_hwndCommandCombo, userCmd, MAX_PATH );
+
+ // strip the auto-space off the end
+ int len = Q_strlen(userCmd);
+ if ( userCmd[len-1] == ' ' )
+ {
+ userCmd[len-1] = '\0';
+ }
+
+ if ( !stricmp( userCmd, hintCmd ) )
+ {
+ // cycle to next or prev command with tab or shift-tab
+ if ( GetKeyState(VK_SHIFT) < 0 )
+ {
+ wParam = VK_UP;
+ }
+ else
+ {
+ wParam = VK_DOWN;
+ }
+ }
+ }
+
+ // move the selection
+ if ( wParam == VK_UP )
+ curSel--;
+ else if ( wParam == VK_DOWN )
+ curSel++;
+ if ( curSel < 0 )
+ curSel = numItems - 1;
+ else if ( curSel > numItems-1 )
+ curSel = 0;
+ if ( curSel < 0 )
+ curSel = 0;
+
+ // set the selection and get highlighted command
+ SendMessage( g_hwndCommandHint, (UINT)LB_SETCURSEL, (WPARAM)curSel, NULL );
+ SendMessage( g_hwndCommandHint, (UINT)LB_GETTEXT, (WPARAM)curSel, (LPARAM)hintCmd );
+
+ // add a space to the end for easier parameter setting
+ Q_strncat( hintCmd, " ", sizeof(hintCmd), 1 );
+
+ // replace command string
+ ComboBox_SetText( g_hwndCommandCombo, hintCmd );
+
+ // set cursor to end of command
+ SendMessage( g_hwndCommandCombo, (UINT)CB_SETEDITSEL, (WPARAM)0, MAKELONG( MAX_PATH,MAX_PATH ) );
+
+ bHandled = TRUE;
+ }
+ else
+ {
+ curSel = SendMessage( g_hwndCommandCombo, (UINT)CB_GETCURSEL, NULL, NULL );
+ if ( curSel < 0 )
+ {
+ // combo box has no selection
+ // override combo box behavior and set selection
+ numItems = SendMessage( g_hwndCommandCombo, (UINT)CB_GETCOUNT, NULL, NULL );
+ if ( numItems > 0 )
+ {
+ if ( wParam == VK_UP )
+ {
+ // set to bottom of list
+ curSel = numItems-1;
+ }
+ else if ( wParam == VK_DOWN )
+ {
+ // set to top of list
+ curSel = 0;
+ }
+
+ SendMessage( g_hwndCommandCombo, (UINT)CB_SETCURSEL, (WPARAM)curSel, NULL );
+ bHandled = TRUE;
+ }
+ }
+ }
+ break;
+
+ case VK_RETURN:
+ // user hit return in the combo box
+ if ( ComboBox_GetDroppedState( g_hwndCommandCombo ) )
+ {
+ ComboBox_ShowDropdown( g_hwndCommandCombo, FALSE );
+ }
+ else
+ {
+ PostMessage( g_hDlgMain, WM_APP, 0, 0 );
+ bHandled = TRUE;
+ }
+ break;
+ }
+
+ return bHandled;
+}
+
+//-----------------------------------------------------------------------------
+// CommandWindow_SubclassedProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK CommandWindow_SubclassedProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+ switch ( msg )
+ {
+ case WM_SYSKEYDOWN:
+ case WM_KEYDOWN:
+ if ( CommandWindow_HandleKey( wParam ) )
+ return 0;
+ break;
+
+ case WM_CHAR:
+ if ( wParam == VK_RETURN )
+ return 0;
+ break;
+ }
+
+ return CallWindowProc( g_hwndCommandSubclassed, hDlg, msg, wParam, lParam );
+}
+
+//-----------------------------------------------------------------------------
+// Main_SizeWindow
+//
+// Handles a WM_SIZE message by resizing all our child windows to match the main window
+//-----------------------------------------------------------------------------
+void Main_SizeWindow( HWND hDlg, UINT wParam, int cx, int cy )
+{
+ if ( cx==0 || cy==0 )
+ {
+ RECT rcClient;
+ GetClientRect( hDlg, &rcClient );
+ cx = rcClient.right;
+ cy = rcClient.bottom;
+ }
+
+ // if we're big enough, position our child windows
+ if ( g_hwndCommandCombo && cx > 64 && cy > 64 )
+ {
+ RECT rcCmd;
+ RECT rcHint;
+ RECT rcOut;
+
+ // fit the "command" combo box into our window
+ GetWindowRect( g_hwndCommandCombo, &rcCmd );
+ ScreenToClient( hDlg, ( LPPOINT )&rcCmd );
+ ScreenToClient( hDlg, ( LPPOINT )&rcCmd + 1 );
+ int x = rcCmd.left;
+ int dx = cx - 8 - x;
+ int dy = rcCmd.bottom - rcCmd.top;
+ int y = cy - 8 - dy;
+ SetWindowPos(
+ g_hwndCommandCombo,
+ NULL,
+ x,
+ y,
+ dx,
+ dy,
+ SWP_NOZORDER );
+
+ // position the "hint popup" window above the "command" window
+ GetWindowRect( g_hwndCommandHint, &rcHint );
+ ScreenToClient( g_hDlgMain, ( LPPOINT )&rcHint );
+ ScreenToClient( g_hDlgMain, ( LPPOINT )&rcHint + 1 );
+ SetWindowPos(
+ g_hwndCommandHint,
+ NULL,
+ rcCmd.left,
+ ( rcCmd.top - 4 ) - ( rcHint.bottom - rcHint.top + 1 ),
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER );
+
+ // position the "Cmd" label
+ RECT rcStaticCmd;
+ HWND hStaticCmd = GetDlgItem( g_hDlgMain, IDC_LABEL );
+ GetWindowRect( hStaticCmd, &rcStaticCmd );
+ ScreenToClient( hDlg, ( LPPOINT )&rcStaticCmd );
+ ScreenToClient( hDlg, ( LPPOINT )&rcStaticCmd + 1 );
+ SetWindowPos(
+ hStaticCmd,
+ NULL,
+ 8,
+ y + ( dy - ( rcStaticCmd.bottom - rcStaticCmd.top ) ) / 2 - 1,
+ 0,
+ 0,
+ SWP_NOSIZE | SWP_NOZORDER );
+
+ // position the "output" window
+ GetWindowRect( g_hwndOutputWindow, &rcOut );
+ ScreenToClient( hDlg, ( LPPOINT )&rcOut );
+ int dwWidth = cx - rcOut.left - 8;
+ int dwHeight = y - rcOut.top - 8;
+ SetWindowPos( g_hwndOutputWindow, NULL, 0, 0, dwWidth, dwHeight, SWP_NOMOVE | SWP_NOZORDER );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// _SortCommands
+//
+//-----------------------------------------------------------------------------
+int _SortCommands( const void* a, const void* b )
+{
+ const char* strA = *( const char** )a;
+ const char* strB = *( const char** )b;
+
+ return ( stricmp( strA, strB ) );
+}
+
+//-----------------------------------------------------------------------------
+// EnableCommandHint
+//
+// Open/Close the command hint popup
+//-----------------------------------------------------------------------------
+void EnableCommandHint( bool enable )
+{
+ int w = 0;
+ int h = 0;
+ int itemHeight;
+ int i;
+ int maxLen;
+ int len;
+ const char* cmds[256];
+ int numLocalCommands;
+ int numRemoteCommands;
+ int curSel;
+
+ if ( !enable )
+ goto cleanUp;
+
+ // get the current command
+ char strCmd[MAX_PATH];
+ ComboBox_GetText( g_hwndCommandCombo, strCmd, MAX_PATH );
+ if ( !strCmd[0] )
+ {
+ // user has typed nothing
+ enable = false;
+ goto cleanUp;
+ }
+
+ SendMessage( g_hwndCommandHint, ( UINT )LB_RESETCONTENT, NULL, NULL );
+
+ // get a list of possible matches
+ maxLen = 0;
+ numLocalCommands = MatchLocalCommands( strCmd, cmds, 256 );
+ numRemoteCommands = MatchRemoteCommands( strCmd, cmds+numLocalCommands, 256-numLocalCommands );
+ for ( i=0; i<numLocalCommands+numRemoteCommands; i++ )
+ {
+ len = strlen( cmds[i] );
+ if ( maxLen < len )
+ maxLen = len;
+ }
+ if ( !maxLen )
+ {
+ // no matches
+ enable = false;
+ goto cleanUp;
+ }
+
+ // sort the list ( eschew listbox's autosorting )
+ qsort( cmds, numLocalCommands+numRemoteCommands, sizeof( const char* ), _SortCommands );
+
+ curSel = -1;
+ len = strlen( strCmd );
+ for ( i=0; i<numLocalCommands+numRemoteCommands; i++ )
+ {
+ // populate the listbox
+ SendMessage( g_hwndCommandHint, ( UINT )LB_ADDSTRING, 0, ( LPARAM )cmds[i] );
+
+ // determine first best match
+ if ( curSel == -1 && !strnicmp( strCmd, cmds[i], len ) )
+ curSel = i;
+ }
+
+ if ( curSel != -1 )
+ {
+ // set the selection to the first best string
+ // ensure the top string is shown ( avoids odd auto-vscroll choices )
+ SendMessage( g_hwndCommandHint, ( UINT )LB_SETCURSEL, ( WPARAM )curSel, NULL );
+ if ( !curSel )
+ SendMessage( g_hwndCommandHint, ( UINT )LB_SETTOPINDEX, 0, NULL );
+ }
+
+ RECT rcCmd;
+ GetWindowRect( g_hwndCommandCombo, &rcCmd );
+ ScreenToClient( g_hDlgMain, ( LPPOINT )&rcCmd );
+ ScreenToClient( g_hDlgMain, ( LPPOINT )&rcCmd + 1 );
+
+ // clamp listbox height to client space
+ itemHeight = SendMessage( g_hwndCommandHint, ( UINT )LB_GETITEMHEIGHT, 0, NULL );
+ if ( itemHeight <= 0 )
+ {
+ // oops, shouldn't happen
+ enable = false;
+ goto cleanUp;
+ }
+
+ h = ( numLocalCommands + numRemoteCommands )*itemHeight + 2;
+ if ( h > rcCmd.top - 8)
+ {
+ h = rcCmd.top - 8;
+ }
+
+ // clamp listbox width
+ w = ( maxLen + 5 ) * g_fixedFontMetrics.tmMaxCharWidth;
+
+ // position the "hint popup" window above the "command" window
+ SetWindowPos(
+ g_hwndCommandHint,
+ NULL,
+ rcCmd.left,
+ ( rcCmd.top - 4 ) - h,
+ w,
+ h,
+ SWP_NOZORDER );
+
+cleanUp:
+ BOOL isVisible = IsWindowVisible( g_hwndCommandHint );
+ if ( !enable && isVisible )
+ ShowWindow( g_hwndCommandHint, SW_HIDE );
+ else if ( enable && !isVisible )
+ ShowWindow( g_hwndCommandHint, SW_SHOWNA );
+}
+
+//-----------------------------------------------------------------------------
+// Main_DlgProc
+//
+//-----------------------------------------------------------------------------
+LRESULT CALLBACK Main_DlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ WORD wID = LOWORD( wParam );
+ BOOL isConnect;
+
+ switch ( message )
+ {
+ case WM_APP:
+ // user has pressed enter
+ // take the string from the command window and process it
+ // extra room for \r\n
+ char strCmd[MAX_PATH + 3];
+ ComboBox_GetText( g_hwndCommandCombo, strCmd, MAX_PATH );
+ ProcessCommand( strCmd );
+ ComboBox_SetText( g_hwndCommandCombo, "" );
+ EnableCommandHint( false );
+ break;
+
+ case WM_USER:
+ ProcessPrintQueue();
+ break;
+
+ case WM_TIMER:
+ // Don't do auto-connect stuff while the Assert dialog is up
+ // (it uses a synchronous command, so calling 'Dm' funcs here can cause a lockup)
+ if ( !g_AssertDialogActive )
+ {
+ if ( wID == TIMERID_AUTOCONNECT )
+ {
+ AutoConnectTimerProc( hDlg, TIMERID_AUTOCONNECT );
+ return 0L;
+ }
+ }
+ break;
+
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLOREDIT:
+ SetBkColor( ( HDC )wParam,g_backgroundColor );
+ return ( BOOL )g_hBackgroundBrush;
+
+ case WM_SIZE:
+ Main_SizeWindow( hDlg, wParam, LOWORD( lParam ), HIWORD( lParam ) );
+ break;
+
+ case WM_SYSCOMMAND:
+ if ( wID == SC_CLOSE )
+ {
+ PostMessage( hDlg, WM_CLOSE, 0, 0 );
+ return 0L;
+ }
+ break;
+
+ case WM_CLOSE:
+ // disconnect before closing
+ lc_disconnect( 0, NULL );
+
+ SaveConfig();
+ DestroyWindow( hDlg );
+ break;
+
+ case WM_DESTROY:
+ SubclassWindow( g_hwndCommandCombo, g_hwndCommandSubclassed );
+ PostQuitMessage( 0 );
+ return 0L;
+
+ case WM_INITMENU:
+ isConnect = g_connectedToXBox || g_connectedToApp;
+ CheckMenuItem( ( HMENU )wParam, IDM_AUTOCONNECT, MF_BYCOMMAND | ( g_autoConnect ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_CAPTUREGAMESPEW, MF_BYCOMMAND | ( g_captureGameSpew ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_CAPTUREDEBUGSPEW, MF_BYCOMMAND | ( g_captureDebugSpew ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_DEBUGCOMMANDS, MF_BYCOMMAND | ( g_debugCommands ? MF_CHECKED : MF_UNCHECKED ) );
+ CheckMenuItem( ( HMENU )wParam, IDM_PLAYTESTMODE, MF_BYCOMMAND | ( g_bPlayTestMode ? MF_CHECKED : MF_UNCHECKED ) );
+ EnableMenuItem( ( HMENU )wParam, IDM_SYNCFILES, MF_BYCOMMAND | ( g_connectedToXBox ? MF_ENABLED : MF_GRAYED ) );
+ EnableMenuItem( ( HMENU )wParam, IDM_SYNCINSTALL, MF_BYCOMMAND | ( g_connectedToXBox ? MF_ENABLED : MF_GRAYED ) );
+ return 0L;
+
+ case WM_COMMAND:
+ switch ( wID )
+ {
+ case IDC_COMMAND:
+ switch ( HIWORD( wParam ) )
+ {
+ case CBN_EDITCHANGE:
+ case CBN_SETFOCUS:
+ EnableCommandHint( true );
+ break;
+
+ case CBN_KILLFOCUS:
+ EnableCommandHint( false );
+ break;
+ }
+ break;
+
+ case IDM_CONFIG:
+ ConfigDlg_Open();
+ return 0L;
+
+ case IDM_CAPTUREGAMESPEW:
+ g_captureGameSpew ^= 1;
+ return 0L;
+
+ case IDM_CAPTUREDEBUGSPEW:
+ g_captureDebugSpew ^= 1;
+ return 0L;
+
+ case IDM_DEBUGCOMMANDS:
+ g_debugCommands ^= 1;
+ return 0L;
+
+ case IDM_BUG:
+ BugDlg_Open();
+ return 0L;
+
+ case IDM_MEMORYDUMP:
+ ShowMemDump_Open();
+ return 0L;
+
+ case IDM_TIMESTAMPLOG:
+ TimeStampLog_Open();
+ return 0L;
+
+ case IDM_SYNCFILES:
+ SyncFilesDlg_Open();
+ return 0L;
+
+ case IDM_SYNCINSTALL:
+ InstallDlg_Open();
+ return 0L;
+
+ case IDM_EXCLUDEPATHS:
+ ExcludePathsDlg_Open();
+ return 0L;
+
+ case IDM_CPU_SAMPLES:
+ CpuProfileSamples_Open();
+ return 0L;
+
+ case IDM_CPU_HISTORY:
+ CpuProfileHistory_Open();
+ return 0L;
+
+ case IDM_D3D_SAMPLES:
+ TexProfileSamples_Open();
+ return 0L;
+
+ case IDM_D3D_HISTORY:
+ TexProfileHistory_Open();
+ return 0L;
+
+ case IDM_SHOWMEMORYUSAGE:
+ MemProfile_Open();
+ return 0L;
+
+ case IDM_PLAYTESTMODE:
+ g_bPlayTestMode ^= 1;
+ return 0L;
+
+ case IDM_SHOWRESOURCES_TEXTURES:
+ ShowTextures_Open();
+ return 0L;
+
+ case IDM_SHOWRESOURCES_MATERIALS:
+ ShowMaterials_Open();
+ return 0L;
+
+ case IDM_SHOWRESOURCES_SOUNDS:
+ ShowSounds_Open();
+ return 0L;
+
+ case IDM_SHOWRESOURCES_MODELS:
+ NotImplementedYet();
+ return 0L;
+
+ case IDM_AUTOCONNECT:
+ if ( g_connectedToXBox || g_connectedToApp || g_autoConnect )
+ lc_disconnect( 0, NULL );
+ else
+ lc_autoConnect( 0, NULL );
+ return 0L;
+
+ case IDM_BINDINGS_EDIT:
+ Bindings_Open();
+ return 0L;
+
+ case IDM_BINDINGS_BIND1:
+ case IDM_BINDINGS_BIND2:
+ case IDM_BINDINGS_BIND3:
+ case IDM_BINDINGS_BIND4:
+ case IDM_BINDINGS_BIND5:
+ case IDM_BINDINGS_BIND6:
+ case IDM_BINDINGS_BIND7:
+ case IDM_BINDINGS_BIND8:
+ case IDM_BINDINGS_BIND9:
+ case IDM_BINDINGS_BIND10:
+ case IDM_BINDINGS_BIND11:
+ case IDM_BINDINGS_BIND12:
+ Bindings_MenuSelection( wID );
+ return 0L;
+
+ case IDM_EXIT:
+ PostMessage( hDlg, WM_CLOSE, 0, 0 );
+ return 0L;
+ }
+ break;
+ }
+
+ return ( DefDlgProc( hDlg, message, wParam, lParam ) );
+}
+
+//-----------------------------------------------------------------------------
+// CmdToArgv
+//
+// Parses a string into argv and return # of args.
+//-----------------------------------------------------------------------------
+int CmdToArgv( char* str, char* argv[], int maxargs )
+{
+ int argc = 0;
+ int argcT = 0;
+ char* strNil = str + lstrlenA( str );
+
+ while ( argcT < maxargs )
+ {
+ // Eat whitespace
+ while ( *str && ( *str==' ' ) )
+ str++;
+
+ if ( !*str )
+ {
+ argv[argcT++] = strNil;
+ }
+ else
+ {
+ // Find the end of this arg
+ char chEnd = ( *str == '"' || *str == '\'' ) ? *str++ : ' ';
+ char* strArgEnd = str;
+ while ( *strArgEnd && ( *strArgEnd != chEnd ) )
+ strArgEnd++;
+
+ // Record this argument
+ argv[argcT++] = str;
+ argc = argcT;
+
+ // Move strArg to the next argument ( or not, if we hit the end )
+ str = *strArgEnd ? strArgEnd + 1 : strArgEnd;
+ *strArgEnd = 0;
+ }
+ }
+
+ return argc;
+}
+
+//-----------------------------------------------------------------------------
+// CreateCommandHint
+//
+//-----------------------------------------------------------------------------
+void CreateCommandHint()
+{
+ // create the "hint" popup
+ g_hwndCommandHint = CreateWindowEx(
+ WS_EX_NOPARENTNOTIFY,
+ "LISTBOX",
+ "",
+ WS_BORDER|WS_CHILD|LBS_HASSTRINGS|WS_VSCROLL,
+ 0, 0, 100, 0,
+ g_hDlgMain,
+ ( HMENU )IDC_COMMANDHINT,
+ g_hInstance,
+ NULL );
+
+ // force the popup to head of z-order
+ // to draw over all other children
+ BringWindowToTop( g_hwndCommandHint );
+
+ // set font
+ SendDlgItemMessage( g_hDlgMain, IDC_COMMANDHINT, WM_SETFONT, ( WPARAM )g_hFixedFont, TRUE );
+}
+
+//-----------------------------------------------------------------------------
+// CreateResources
+//
+//-----------------------------------------------------------------------------
+bool CreateResources()
+{
+ LOGFONT lf;
+ HFONT hFontOld;
+ HDC hDC;
+ int i;
+
+ // pull in common controls
+ INITCOMMONCONTROLSEX initCommon;
+ initCommon.dwSize = sizeof( INITCOMMONCONTROLSEX );
+ initCommon.dwICC = ICC_LISTVIEW_CLASSES|ICC_USEREX_CLASSES;
+ if ( !InitCommonControlsEx( &initCommon ) )
+ return false;
+
+ // pull in rich edit controls
+ g_hRichEdit = LoadLibrary( "Riched32.dll" );
+ if ( !g_hRichEdit )
+ return false;
+
+ g_backgroundColor = XBX_CLR_LTGREY;
+ g_hBackgroundBrush = CreateSolidBrush( g_backgroundColor );
+
+ // get icons
+ g_hIcons[ICON_APPLICATION] = LoadIcon( g_hInstance, MAKEINTRESOURCE( IDI_VXCONSOLE ) );
+ g_hIcons[ICON_DISCONNECTED] = LoadIcon( g_hInstance, MAKEINTRESOURCE( IDI_DISCONNECTED ) );
+ g_hIcons[ICON_CONNECTED_XBOX] = LoadIcon( g_hInstance, MAKEINTRESOURCE( IDI_CONNECT1_ON ) );
+ g_hIcons[ICON_CONNECTED_APP0] = LoadIcon( g_hInstance, MAKEINTRESOURCE( IDI_CONNECT2_OFF ) );
+ g_hIcons[ICON_CONNECTED_APP1] = LoadIcon( g_hInstance, MAKEINTRESOURCE( IDI_CONNECT2_ON ) );
+ for ( i=0; i<MAX_ICONS; i++ )
+ {
+ if ( !g_hIcons[i] )
+ return false;
+ }
+
+ // get the font feight
+ hDC = GetWindowDC( NULL );
+ int nHeight = -MulDiv( VXCONSOLE_FONTSIZE, GetDeviceCaps( hDC, LOGPIXELSY ), 72 );
+ ReleaseDC( NULL, hDC );
+
+ // create fixed font
+ memset( &lf, 0, sizeof( LOGFONT ) );
+ lf.lfHeight = nHeight;
+ lf.lfWeight = 400;
+ strcpy( lf.lfFaceName, VXCONSOLE_FONT );
+ g_hFixedFont = CreateFontIndirect( &lf );
+ if ( !g_hFixedFont )
+ return false;
+
+ // create proportional font
+ memset( &lf, 0, sizeof( LOGFONT ) );
+ lf.lfHeight = -11;
+ lf.lfWeight = 400;
+ strcpy( lf.lfFaceName, "Tahoma" );
+ g_hProportionalFont = CreateFontIndirect( &lf );
+ if ( !g_hProportionalFont )
+ return false;
+
+ // get the font metrics
+ hDC = GetWindowDC( NULL );
+ hFontOld = ( HFONT )SelectObject( hDC, g_hFixedFont );
+ GetTextMetrics( hDC, &g_fixedFontMetrics );
+ SelectObject( hDC, hFontOld );
+ ReleaseDC( NULL, hDC );
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Shutdown
+//
+// Free all resources
+//-----------------------------------------------------------------------------
+void Shutdown()
+{
+ BugReporter_FreeInterfaces();
+
+ if ( g_PrintQueue.bInit )
+ {
+ DeleteCriticalSection( &g_PrintQueue.CriticalSection );
+ g_PrintQueue.bInit = false;
+ }
+
+ if ( g_hCommandReadyEvent )
+ {
+ CloseHandle( g_hCommandReadyEvent );
+ g_hCommandReadyEvent = 0;
+ }
+
+ if ( g_hRichEdit )
+ {
+ FreeLibrary( g_hRichEdit );
+ g_hRichEdit = 0;
+ }
+
+ if ( g_hBackgroundBrush )
+ {
+ DeleteObject( g_hBackgroundBrush );
+ g_hBackgroundBrush = 0;
+ }
+
+ if ( g_hFixedFont )
+ {
+ DeleteObject( g_hFixedFont );
+ g_hFixedFont = 0;
+ }
+
+ if ( g_hProportionalFont )
+ {
+ DeleteObject( g_hProportionalFont );
+ g_hProportionalFont = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Startup
+//
+//-----------------------------------------------------------------------------
+bool Startup()
+{
+ // Load the xenon debugging dll (xbdm.dll) manually due to its absence from system path
+ const char *pPath = getenv( "path" );
+ const char *pXEDKDir = getenv( "xedk" );
+ if ( !pXEDKDir )
+ pXEDKDir = "";
+
+ int len = strlen( pPath ) + strlen( pXEDKDir ) + 256;
+ char *pNewPath = (char*)_alloca( len );
+ sprintf( pNewPath, "path=%s;%s\\bin\\win32", pPath, pXEDKDir );
+ _putenv( pNewPath );
+
+ HMODULE hXBDM = LoadLibrary( TEXT( "xbdm.dll" ) );
+ if ( !hXBDM )
+ {
+ if ( pXEDKDir[0] )
+ Sys_Error( "Couldn't load xbdm.dll" );
+ else
+ Sys_Error( "Couldn't load xbdm.dll\nXEDK environment variable not set." );
+ }
+
+ LoadConfig();
+
+ if ( !CreateResources() )
+ return false;
+
+ // set up our print queue
+ InitializeCriticalSection( &g_PrintQueue.CriticalSection );
+ g_PrintQueue.bInit = true;
+
+ // manual reset, initially signaled
+ g_hCommandReadyEvent = CreateEvent( NULL, TRUE, TRUE, NULL );
+
+ // set up our window class
+ WNDCLASS wndclass;
+ memset( &wndclass, 0, sizeof( wndclass ) );
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = Main_DlgProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = VXCONSOLE_WINDOWBYTES;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = g_hIcons[ICON_DISCONNECTED];
+ wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );
+ wndclass.hbrBackground = g_hBackgroundBrush;
+ wndclass.lpszMenuName = MAKEINTRESOURCE( MENU_VXCONSOLE );
+ wndclass.lpszClassName = VXCONSOLE_CLASSNAME;
+ if ( !RegisterClass( &wndclass ) )
+ return false;
+
+ g_hAccel = LoadAccelerators( g_hInstance, MAKEINTRESOURCE( IDR_MAIN_ACCEL ) );
+ if ( !g_hAccel )
+ return false;
+
+ // Create our main dialog
+ g_hDlgMain = CreateDialog( g_hInstance, MAKEINTRESOURCE( IDD_VXCONSOLE ), 0, NULL );
+ if ( !g_hDlgMain )
+ return false;
+ SetWindowLong( g_hDlgMain, VXCONSOLE_CONFIGID, g_configID );
+
+ if ( !BugDlg_Init() )
+ return false;
+
+ if ( !CpuProfile_Init() )
+ return false;
+
+ if ( !TexProfile_Init() )
+ return false;
+
+ if ( !MemProfile_Init() )
+ return false;
+
+ if ( !Bindings_Init() )
+ return false;
+
+ if ( !SyncFilesDlg_Init() )
+ return false;
+
+ if ( !ShowMaterials_Init() )
+ return false;
+
+ if ( !ShowTextures_Init() )
+ return false;
+
+ if ( !ShowSounds_Init() )
+ return false;
+
+ if ( !ShowMemDump_Init() )
+ return false;
+
+ if ( !TimeStampLog_Init() )
+ return false;
+
+ if ( !ExcludePathsDlg_Init() )
+ return false;
+
+ g_hwndOutputWindow = GetDlgItem( g_hDlgMain, IDC_OUTPUT );
+ g_hwndCommandCombo = GetDlgItem( g_hDlgMain, IDC_COMMAND );
+
+ CreateCommandHint();
+
+ // subclass our dropdown command listbox to handle return key
+ g_hwndCommandSubclassed = SubclassWindow( GetWindow( g_hwndCommandCombo, GW_CHILD ), CommandWindow_SubclassedProc );
+
+ // Change the font type of the output window to courier
+ CHARFORMAT cf;
+ cf.cbSize = sizeof( CHARFORMAT );
+ SendMessage( g_hwndOutputWindow, EM_GETCHARFORMAT, 0, ( LPARAM )&cf );
+ cf.dwMask &= ~CFM_COLOR;
+ cf.yHeight = VXCONSOLE_FONTSIZE*20;
+ lstrcpyA( cf.szFaceName, VXCONSOLE_FONT );
+ SendMessage( g_hwndOutputWindow, EM_SETCHARFORMAT, SCF_ALL, ( LPARAM )&cf );
+ SendMessage( g_hwndOutputWindow, EM_SETBKGNDCOLOR, 0, g_backgroundColor );
+
+ // ensure the output window adheres to its z ordering
+ LONG style = GetWindowLong( g_hwndOutputWindow, GWL_STYLE );
+ style |= WS_CLIPSIBLINGS;
+ SetWindowLong( g_hwndOutputWindow, GWL_STYLE, style );
+
+ // change the font of the command and its hint window to courier
+ SendDlgItemMessage( g_hDlgMain, IDC_COMMAND, WM_SETFONT, ( WPARAM )g_hFixedFont, TRUE );
+
+ // set the window title
+ SetMainWindowTitle();
+
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "VXConsole %s [%s Build: %s %s] [Protocol: %d]\n", VXCONSOLE_VERSION, VXCONSOLE_BUILDTYPE, __DATE__, __TIME__, VXCONSOLE_PROTOCOL_VERSION );
+ ConsoleWindowPrintf( XBX_CLR_DEFAULT, "type '*help' for list of commands...\n\n" );
+
+ g_currentIcon = -1;
+ SetConnectionIcon( ICON_DISCONNECTED );
+
+ if ( g_alwaysAutoConnect)
+ {
+ // user wants to auto-connect at startup
+ lc_autoConnect( 0, NULL );
+ }
+
+ if ( g_mainWindowRect.right && g_mainWindowRect.bottom )
+ MoveWindow( g_hDlgMain, g_mainWindowRect.left, g_mainWindowRect.top, g_mainWindowRect.right-g_mainWindowRect.left, g_mainWindowRect.bottom-g_mainWindowRect.top, FALSE );
+
+ // ready for display
+ int cmdShow = SW_SHOWNORMAL;
+ if ( g_startMinimized )
+ cmdShow = SW_SHOWMINIMIZED;
+ ShowWindow( g_hDlgMain, cmdShow );
+
+ // success
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// WinMain
+//
+// Entry point for program
+//-----------------------------------------------------------------------------
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow )
+{
+ bool error = true;
+ MSG msg = {0};
+
+ g_hInstance = hInstance;
+
+ g_bSuppressBlink = ParseCommandLineArg( pCmdLine, "-noblink", NULL, 0 );
+
+ // optional -config <ID> can specify a specific configuration
+ char buff[128];
+ buff[0] = '\0';
+ ParseCommandLineArg( pCmdLine, "-config ", buff, sizeof( buff ) );
+ g_configID = atoi( buff );
+
+ MakeConfigString( VXCONSOLE_REGISTRY, g_configID, buff, sizeof( buff ) );
+ Sys_SetRegistryPrefix( buff );
+
+ HWND hwnd = FindWindow( VXCONSOLE_CLASSNAME, NULL );
+ if ( hwnd && GetWindowLong( hwnd, VXCONSOLE_CONFIGID ) == g_configID )
+ {
+ // single instance only
+ // bring other version to foreground
+ if ( IsIconic( hwnd ) )
+ ShowWindow( hwnd, SW_RESTORE );
+ SetForegroundWindow( hwnd );
+ return ( FALSE );
+ }
+
+ if ( !Startup() )
+ goto cleanUp;
+
+ // message pump
+ while ( GetMessage( &msg, NULL, 0, 0 ) )
+ {
+ if ( !TranslateAccelerator( g_hDlgMain, g_hAccel, &msg ) )
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+
+ // no-error, end of app
+ error = false;
+
+cleanUp:
+ if ( error )
+ {
+ char str[255];
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, str, 255, NULL );
+ MessageBox( NULL, str, NULL, MB_OK );
+ }
+
+ Shutdown();
+
+ return ( msg.wParam );
+}
+
+
diff --git a/utils/xbox/vxconsole/vxconsole.h b/utils/xbox/vxconsole/vxconsole.h
new file mode 100644
index 0000000..6ff1afc
--- /dev/null
+++ b/utils/xbox/vxconsole/vxconsole.h
@@ -0,0 +1,479 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// VXCONSOLE.H
+//
+// Master Header.
+//=====================================================================================//
+#pragma once
+
+#include "tier0/platform.h"
+
+#include <winsock2.h>
+#include <windows.h>
+#include <windowsx.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string.h>
+#include <share.h>
+#include <richedit.h>
+#include <assert.h>
+#include <xbdm.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#include "resource.h"
+#include "assert_resource.h"
+#include "sys_utils.h"
+#include "sys_scriptlib.h"
+#include "bugreporter/bugreporter.h"
+#include "jpeglib/jpeglib.h"
+#include "UtlBuffer.h"
+#include "strtools.h"
+#include "xbox/xbox_vxconsole.h"
+#include "UtlRBTree.h"
+#include "UtlSymbol.h"
+#include "UtlVector.h"
+#include "UtlString.h"
+
+#define VXCONSOLE_VERSION "1.2"
+#define VXCONSOLE_CLASSNAME "VXConsole"
+#define VXCONSOLE_TITLE "VXConsole"
+#define VXCONSOLE_FONT "Courier"
+#define VXCONSOLE_FONTSIZE 10
+#define VXCONSOLE_MAGIC "3\\"
+#define VXCONSOLE_REGISTRY "HKEY_CURRENT_USER\\Software\\VXConsole\\" VXCONSOLE_MAGIC
+#ifdef _DEBUG
+#define VXCONSOLE_BUILDTYPE "Debug"
+#else
+#define VXCONSOLE_BUILDTYPE "Release"
+#endif
+
+#define VXCONSOLE_WINDOWBYTES ( DLGWINDOWEXTRA + 4 )
+#define VXCONSOLE_CONFIGID ( VXCONSOLE_WINDOWBYTES - 4 )
+
+#define MAX_QUEUEDSTRINGS 4096
+#define MAX_QUEUEDSTRINGLEN 512
+#define MAX_RCMDNAMELEN 32
+#define MAX_RCMDS 4096
+#define MAX_TOKENCHARS 256
+#define MAX_XBOXNAMELEN 64
+#define MAX_ARGVELEMS 20
+#define MAX_COMMANDHISTORY 25
+
+#define TIMERID_AUTOCONNECT 0x1000
+#define TIMERID_MEMPROFILE 0x1001
+
+#define IDC_COMMANDHINT 666
+
+#define XBX_CLR_RED ( RGB( 255,0,0 ) )
+#define XBX_CLR_GREEN ( RGB( 0,255,0 ) )
+#define XBX_CLR_WHITE ( RGB( 255,255,255 ) )
+#define XBX_CLR_BLACK ( RGB( 0,0,0 ) )
+#define XBX_CLR_BLUE ( RGB( 0,0,255 ) )
+#define XBX_CLR_YELLOW ( RGB( 255,255,0 ) )
+#define XBX_CLR_LTGREY ( RGB( 180,180,180 ) )
+#define XBX_CLR_DEFAULT XBX_CLR_BLACK
+
+// The command prefix that is prepended to all communication between the Xbox
+// app and the debug console app
+#define VXCONSOLE_PRINT_PREFIX "XPRT"
+#define VXCONSOLE_COMMAND_PREFIX "XCMD"
+#define VXCONSOLE_COMMAND_ACK "XACK"
+#define VXCONSOLE_COLOR_PREFIX "XCLR"
+
+#define ICON_APPLICATION 0
+#define ICON_DISCONNECTED 1
+#define ICON_CONNECTED_XBOX 2
+#define ICON_CONNECTED_APP0 3
+#define ICON_CONNECTED_APP1 4
+#define MAX_ICONS 5
+
+typedef BOOL ( *cmdHandler_t )( int argc, char* argv[] );
+
+#define IDM_BINDINGS 50000
+#define IDM_BINDINGS_EDIT ( IDM_BINDINGS+1 )
+#define IDM_BINDINGS_BIND1 ( IDM_BINDINGS+2 )
+#define IDM_BINDINGS_BIND2 ( IDM_BINDINGS+3 )
+#define IDM_BINDINGS_BIND3 ( IDM_BINDINGS+4 )
+#define IDM_BINDINGS_BIND4 ( IDM_BINDINGS+5 )
+#define IDM_BINDINGS_BIND5 ( IDM_BINDINGS+6 )
+#define IDM_BINDINGS_BIND6 ( IDM_BINDINGS+7 )
+#define IDM_BINDINGS_BIND7 ( IDM_BINDINGS+8 )
+#define IDM_BINDINGS_BIND8 ( IDM_BINDINGS+9 )
+#define IDM_BINDINGS_BIND9 ( IDM_BINDINGS+10 )
+#define IDM_BINDINGS_BIND10 ( IDM_BINDINGS+11 )
+#define IDM_BINDINGS_BIND11 ( IDM_BINDINGS+12 )
+#define IDM_BINDINGS_BIND12 ( IDM_BINDINGS+13 )
+#define MAX_BINDINGS ( VK_F12-VK_F1+1 )
+
+// file serving
+#define FSERVE_LOCALONLY 0
+#define FSERVE_REMOTEONLY 1
+#define FSERVE_LOCALFIRST 2
+
+// file sync
+#define FSYNC_OFF 0x00000000
+#define FSYNC_ALWAYS 0x00000001
+#define FSYNC_IFNEWER 0x00000002
+#define FSYNC_TYPEMASK 0x0000000F
+#define FSYNC_ANDEXISTSONTARGET 0x80000000
+
+// track function invocations
+typedef enum
+{
+ FL_INVALID,
+ FL_STAT,
+ FL_FOPEN,
+ FL_FSEEK,
+ FL_FTELL,
+ FL_FREAD,
+ FL_FWRITE,
+ FL_FCLOSE,
+ FL_FEOF,
+ FL_FERROR,
+ FL_FFLUSH,
+ FL_FGETS,
+ FL_MAXFUNCTIONCOUNTS,
+} fileLogFunctions_e;
+
+typedef enum
+{
+ VPROF_OFF = 0,
+ VPROF_CPU,
+ VPROF_TEXTURE,
+ VPROF_TEXTUREFRAME,
+} vprofState_e;
+
+// funtion command types
+#define FN_CONSOLE 0x00 // command runs at console
+#define FN_XBOX 0x01 // command requires xbox
+#define FN_APP 0x02 // command requires application
+
+// shorthand
+#define FA_NORMAL FILE_ATTRIBUTE_NORMAL
+#define FA_DIRECTORY FILE_ATTRIBUTE_DIRECTORY
+#define FA_READONLY FILE_ATTRIBUTE_READONLY
+
+typedef struct
+{
+ const CHAR* strCommand;
+ int flags;
+ cmdHandler_t pfnHandler;
+ const CHAR* strHelp;
+} localCommand_t;
+
+typedef struct
+{
+ char* strCommand;
+ char* strHelp;
+} remoteCommand_t;
+
+typedef struct
+{
+ CRITICAL_SECTION CriticalSection;
+ int numMessages;
+ bool bInit;
+ COLORREF aColors[MAX_QUEUEDSTRINGS];
+ CHAR *pMessages[MAX_QUEUEDSTRINGS];
+} printQueue_t;
+
+class CProgress
+{
+public:
+ CProgress();
+ ~CProgress();
+ void Open( const char* title, bool canCancel, bool bHasMeter );
+ void SetStatus( const char *line1, const char *line2, const char *line3 );
+ void SetMeter( int currentPos, int range );
+ bool IsCancel();
+ HWND m_hWnd;
+ HWND m_hWndStatus1;
+ HWND m_hWndStatus2;
+ HWND m_hWndStatus3;
+ HWND m_hWndPercent;
+ HWND m_hWndMeter;
+ HWND m_hWndCancel;
+ bool m_bCancelPressed;
+ int m_range;
+
+private:
+ void Update();
+};
+
+typedef struct fileNode_s
+{
+ char *filename;
+ FILETIME creationTime;
+ FILETIME changeTime;
+ DWORD sizeHigh;
+ DWORD sizeLow;
+ DWORD attributes;
+ int level;
+ struct fileNode_s *nextPtr;
+ bool needsUpdate;
+}
+fileNode_t;
+
+//-----------------------------------------------------------------------------
+// FILEIO.CPP
+//-----------------------------------------------------------------------------
+extern void RemoteToLocalFilename( const char* inFilename, char* outFilename, int outSize );
+extern void RemoteToTargetFilename( const char* inFilename, char* outFilename, int outSize );
+extern void FreeTargetFileList( fileNode_t* pFileList );
+extern bool GetTargetFileList_r( char* targetPath, bool recurse, int attributes, int level, fileNode_t** pFileList );
+extern char *SystemTimeToString( SYSTEMTIME *systemTime, char *buffer, int bufferSize );
+extern bool CreateTargetPath( const char *pTargetFilename );
+
+//-----------------------------------------------------------------------------
+// BINDINGS.CPP
+//-----------------------------------------------------------------------------
+extern bool Bindings_TranslateKey( int vkKeyCode );
+extern bool Bindings_MenuSelection( int wID );
+extern void Bindings_LoadConfig();
+extern void Bindings_SaveConfig();
+extern void Bindings_Open();
+extern bool Bindings_Init();
+
+//-----------------------------------------------------------------------------
+// COMMON.CPP
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// VXCONSOLE.CPP
+//-----------------------------------------------------------------------------
+extern void SetConnectionIcon( int icon );
+extern void PrintToQueue( COLORREF color, const CHAR* strFormat, ... );
+extern void ProcessPrintQueue();
+extern void DmAPI_DisplayError( const char* strApiName, HRESULT hr );
+extern int ConsoleWindowPrintf( COLORREF rgb, LPCTSTR lpFmt, ... );
+extern int CmdToArgv( char* str, char* argv[], int maxargs );
+extern char* GetToken( char** tokenStreamPtr );
+extern void DebugCommand( const char* strFormat, ... );
+extern bool ProcessCommand( const char* strCmd );
+extern HRESULT DmAPI_SendCommand( const char* strCommand, bool wait );
+extern void NotImplementedYet();
+extern void SetMainWindowTitle();
+extern HWND g_hDlgMain;
+extern HWND g_hwndOutputWindow;
+extern UINT_PTR g_autoConnectTimer;
+extern BOOL g_autoConnect;
+extern CHAR g_xboxName[];
+extern DWORD g_xboxAddress;
+extern CHAR g_remotePath[];
+extern CHAR g_localPath[];
+extern CHAR g_targetPath[];
+extern CHAR g_installPath[];
+extern CHAR g_xboxTargetName[];
+extern BOOL g_connectedToApp;
+extern BOOL g_connectedToXBox;
+extern PDMN_SESSION g_pdmnSession;
+extern PDM_CONNECTION g_pdmConnection;
+extern BOOL g_debugCommands;
+extern BOOL g_captureDebugSpew;
+extern HINSTANCE g_hInstance;
+extern HICON g_hIcons[];
+extern BOOL g_reboot;
+extern int g_rebootArgc;
+extern char* g_rebootArgv[];
+extern int g_connectCount;
+extern int g_currentIcon;
+extern BOOL g_clsOnConnect;
+extern DWORD g_connectedTime;
+extern HBRUSH g_hBackgroundBrush;
+extern COLORREF g_backgroundColor;
+extern HFONT g_hFixedFont;
+extern HFONT g_hProportionalFont;
+extern HANDLE g_hCommandReadyEvent;
+extern BOOL g_loadSymbolsOnConnect;
+extern HACCEL g_hAccel;
+extern BOOL g_alwaysAutoConnect;
+extern BOOL g_startMinimized;
+extern int g_connectFailure;
+extern BOOL g_captureDebugSpew_StartupState;
+extern bool g_bSuppressBlink;
+extern BOOL g_bPlayTestMode;
+
+//-----------------------------------------------------------------------------
+// LOCAL_CMDS.CPP
+//-----------------------------------------------------------------------------
+extern BOOL lc_bug( int argc, char* argv[] );
+extern BOOL lc_dir( int argc, char* argv[] );
+extern BOOL lc_del( int argc, char* argv[] );
+extern BOOL lc_memory( int argc, char* argv[] );
+extern BOOL lc_screenshot( int argc, char* argv[] );
+extern BOOL lc_help( int argc, char* argv[] );
+extern BOOL lc_cls( int argc, char* argv[] );
+extern BOOL lc_connect( int argc, char* argv[] );
+extern BOOL lc_autoConnect( int argc, char* argv[] );
+extern BOOL lc_disconnect( int argc, char* argv[] );
+extern BOOL lc_quit( int argc, char* argv[] );
+extern BOOL lc_crashdump( int argc, char* argv[] );
+extern BOOL lc_listen( int argc, char* argv[] );
+extern BOOL lc_run( int argc, char* argv[] );
+extern BOOL lc_reset( int argc, char* argv[] );
+extern BOOL lc_modules( int argc, char* argv[] );
+extern BOOL lc_sections( int argc, char* argv[] );
+extern BOOL lc_threads( int argc, char* argv[] );
+extern BOOL lc_ClearConfigs( int argc, char* argv[] );
+extern void AutoConnectTimerProc( HWND hwnd, UINT_PTR idEvent );
+extern int MatchLocalCommands( char* cmdStr, const char* cmdList[], int maxCmds );
+extern void DoDisconnect( BOOL bKeepConnection, int waitTime = 15 );
+extern localCommand_t g_localCommands[];
+extern const int g_numLocalCommands;
+
+//-----------------------------------------------------------------------------
+// REMOTE_CMDS.CPP
+//-----------------------------------------------------------------------------
+extern int rc_AddCommands( char* commandPtr );
+extern void Remote_DeleteCommands();
+extern DWORD __stdcall Remote_NotifyDebugString( ULONG dwNotification, DWORD dwParam );
+extern DWORD __stdcall Remote_NotifyPrintFunc( const CHAR* strNotification );
+extern DWORD __stdcall Remote_NotifyCommandFunc( const CHAR* strNotification );
+extern int MatchRemoteCommands( char* cmdStr, const char* cmdList[], int maxCmds );
+extern remoteCommand_t* g_remoteCommands[];
+extern int g_numRemoteCommands;
+
+//-----------------------------------------------------------------------------
+// BUG.CPP
+//-----------------------------------------------------------------------------
+extern bool BugDlg_Init( void );
+extern void BugDlg_Open( void );
+extern void BugReporter_FreeInterfaces();
+extern int rc_MapInfo( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// CONFIG.CPP
+//-----------------------------------------------------------------------------
+extern void ConfigDlg_Open( void );
+extern void ConfigDlg_LoadConfig();
+
+//-----------------------------------------------------------------------------
+// FILELOG.CPP
+//-----------------------------------------------------------------------------
+extern void FileLog_Open();
+extern bool FileLog_Init();
+extern void FileLog_Clear();
+extern unsigned int FileLog_AddItem( const char* filename, unsigned int fp );
+extern void FileLog_UpdateItem( unsigned int log, unsigned int fp, fileLogFunctions_e functionId, int value );
+extern void FileLog_SaveConfig();
+extern void FileLog_LoadConfig();
+extern bool g_fileLogEnable;
+
+//-----------------------------------------------------------------------------
+// CPU_PROFILE.CPP
+//-----------------------------------------------------------------------------
+extern void CpuProfileSamples_Open();
+extern void CpuProfileHistory_Open();
+extern void CpuProfile_SetTitle();
+extern bool CpuProfile_Init();
+extern void CpuProfile_Clear();
+extern int rc_SetCpuProfile( char* commandPtr );
+extern int rc_SetCpuProfileData( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// TEX_PROFILE.CPP
+//-----------------------------------------------------------------------------
+extern void TexProfile_SetTitle();
+extern void TexProfileSamples_Open();
+extern void TexProfileHistory_Open();
+extern bool TexProfile_Init();
+extern int rc_SetTexProfile( char* commandPtr );
+extern int rc_SetTexProfileData( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// MEM_PROFILE.CPP
+//-----------------------------------------------------------------------------
+extern void MemProfile_Open();
+extern void MemProfile_SetTitle();
+extern bool MemProfile_Init();
+extern void MemProfile_Clear();
+extern int rc_FreeMemory( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// MEMLOG.CPP
+//-----------------------------------------------------------------------------
+extern void MemoryLog_Open();
+extern bool MemoryLog_Init();
+extern void MemoryLog_Clear();
+extern void MemoryLog_SaveConfig();
+extern void MemoryLog_LoadConfig();
+extern void MemoryLog_TreeView( bool enable );
+extern void MemoryLog_RefreshItems();
+extern int rc_MemoryLog( char* commandPtr );
+extern bool g_memoryLog_enable;
+
+//-----------------------------------------------------------------------------
+// SYNC_FILES.CPP
+//-----------------------------------------------------------------------------
+extern int FileSyncEx( const char* localFilename, const char* remoteFilename, int fileSyncMode, bool bVerbose, bool bNoWrite );
+extern bool SyncFilesDlg_Init( void );
+extern void SyncFilesDlg_Open( void );
+extern void InstallDlg_Open( void );
+
+//-----------------------------------------------------------------------------
+// FILEIO.CPP
+//-----------------------------------------------------------------------------
+extern int CompareFileTimes_NTFStoFATX( FILETIME* ntfsFileTime, char *ntfsTimeString, int ntfsStringSize, FILETIME* fatxFileTime, char *fatxTimeString, int fatxStringSize );
+extern bool LoadTargetFile( const char *pTargetPath, int *pFileSize, void **pData );
+
+//-----------------------------------------------------------------------------
+// PROGRESS.CPP
+//-----------------------------------------------------------------------------
+extern bool Progress_Init();
+
+//-----------------------------------------------------------------------------
+// SHOW_TEXTURES.CPP
+//-----------------------------------------------------------------------------
+extern void ShowTextures_Open();
+extern bool ShowTextures_Init();
+extern int rc_TextureList( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// TIMESTAMP_LOG.CPP
+//-----------------------------------------------------------------------------
+extern void TimeStampLog_Open();
+extern bool TimeStampLog_Init();
+extern void TimeStampLog_Clear();
+extern int rc_TimeStampLog( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// COMMON.CPP
+//-----------------------------------------------------------------------------
+extern vprofState_e VProf_GetState();
+extern void VProf_Enable( vprofState_e state );
+
+//-----------------------------------------------------------------------------
+// SHOW_MATERIALS.CPP
+//-----------------------------------------------------------------------------
+extern void ShowMaterials_Open();
+extern bool ShowMaterials_Init();
+extern int rc_MaterialList( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// SHOW_SOUNDS.CPP
+//-----------------------------------------------------------------------------
+extern void ShowSounds_Open();
+extern bool ShowSounds_Init();
+extern int rc_SoundList( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// SHOW_MEMDUMP.CPP
+//-----------------------------------------------------------------------------
+extern void ShowMemDump_Open();
+extern bool ShowMemDump_Init();
+extern int rc_MemDump( char* commandPtr );
+
+//-----------------------------------------------------------------------------
+// EXCLUDE_PATHS.CPP
+//-----------------------------------------------------------------------------
+extern bool ExcludePathsDlg_Init( void );
+extern void ExcludePathsDlg_Open( void );
+
+//-----------------------------------------------------------------------------
+// ASSERT_DIALOG.CPP
+//-----------------------------------------------------------------------------
+extern bool g_AssertDialogActive;
+int rc_Assert( char *commandPtr );
diff --git a/utils/xbox/vxconsole/vxconsole.ico b/utils/xbox/vxconsole/vxconsole.ico
new file mode 100644
index 0000000..48c0d4c
--- /dev/null
+++ b/utils/xbox/vxconsole/vxconsole.ico
Binary files differ
diff --git a/utils/xbox/vxconsole/vxconsole.rc b/utils/xbox/vxconsole/vxconsole.rc
new file mode 100644
index 0000000..2e62120
--- /dev/null
+++ b/utils/xbox/vxconsole/vxconsole.rc
@@ -0,0 +1,557 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_VXCONSOLE ICON "VXConsole.ico"
+IDI_CONNECT1_ON ICON "icon_connect1.ico"
+IDI_DISCONNECTED ICON "icon_disconnect.ico"
+IDI_CONNECT2_OFF ICON "icon_connect2.ico"
+IDI_CONNECT2_ON ICON "icon_connect2a.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_VXCONSOLE DIALOGEX 7, 18, 416, 203
+STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+EXSTYLE WS_EX_CLIENTEDGE
+MENU MENU_VXCONSOLE
+CLASS "VXConsole"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ COMBOBOX IDC_COMMAND,26,182,386,130,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Cmd:",IDC_LABEL,5,184,17,8,SS_CENTERIMAGE
+ CONTROL "",IDC_OUTPUT,"RichEdit20A",ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_NOHIDESEL | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_HSCROLL,5,7,404,170
+END
+
+IDD_CONFIG DIALOGEX 0, 0, 412, 151
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDC_OK,355,130,50,14
+ PUSHBUTTON "Cancel",IDC_CANCEL,296,130,50,14
+ LTEXT "Target XBox Name:",IDC_STATIC,7,7,126,9
+ EDITTEXT IDC_CONFIG_XBOXNAME,7,18,148,13,ES_AUTOHSCROLL
+ PUSHBUTTON "Ping",IDC_CONFIG_PING,163,18,43,13
+ CONTROL "Clear Log On Connect",IDC_CONFIG_CLEARONCONNECT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,17,149,12
+ CONTROL "Always Auto-Connect At Startup",IDC_CONFIG_ALWAYSAUTOCONNECT,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,33,149,12
+ CONTROL "Start Minimized",IDC_CONFIG_STARTMINIMIZED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,49,149,12
+ EDITTEXT IDC_CONFIG_INSTALLPATH,7,117,199,13,ES_AUTOHSCROLL
+ LTEXT "PC Local Game Path: (Example: u:\\dev\\game)",IDC_STATIC,7,37,199,9
+ EDITTEXT IDC_CONFIG_LOCALPATH,7,49,199,13,ES_AUTOHSCROLL
+ LTEXT "XBox Target HDD Path: (Example: e:\\valve)",IDC_STATIC,7,70,199,9
+ EDITTEXT IDC_CONFIG_TARGETPATH,7,81,199,13,ES_AUTOHSCROLL
+ LTEXT "Installation Depot:",IDC_STATIC,7,105,116,9
+ CONTROL "Enable Capture Debug Spew At Startup",IDC_CONFIG_CAPTUREDEBUGSPEW,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,223,65,149,12
+END
+
+IDD_SYNCFILES DIALOGEX 0, 0, 227, 154
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Sync Files"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "Sync",IDC_OK,170,132,50,14
+ PUSHBUTTON "Cancel",IDC_CANCEL,111,132,50,14
+ LTEXT "XBox Target Path (To):",IDC_STATIC,7,39,116,9
+ EDITTEXT IDC_SYNCFILES_TARGETPATH,7,51,213,13,ES_AUTOHSCROLL
+ LTEXT "PC Source Path (From):",IDC_STATIC,7,7,142,9
+ EDITTEXT IDC_SYNCFILES_LOCALPATH,7,19,213,13,ES_AUTOHSCROLL
+ CONTROL "Force Sync",IDC_SYNCFILES_FORCESYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,89,116,10
+ CONTROL "Skip Writing Files (Test Mode)",IDC_SYNCFILES_NOWRITE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,105,116,10
+ CONTROL "Verbose",IDC_SYNCFILES_VERBOSE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,73,116,10
+END
+
+IDD_MODIFYBIND DIALOGEX 0, 0, 260, 106
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDC_OK,202,86,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,144,86,50,14
+ LTEXT "Key:",IDC_STATIC,7,7,16,8
+ LTEXT "Static",IDC_MODIFYBIND_KEYCODE,28,7,51,8
+ LTEXT "Menu Name:",IDC_STATIC,7,21,41,8
+ EDITTEXT IDC_MODIFYBIND_MENUNAME,7,31,245,14,ES_AUTOHSCROLL
+ LTEXT "Command:",IDC_STATIC,7,50,35,8
+ EDITTEXT IDC_MODIFYBIND_COMMAND,7,60,243,14,ES_AUTOHSCROLL
+END
+
+IDD_BUG DIALOGEX 0, 0, 441, 375
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Bug Reporter"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ EDITTEXT IDC_BUG_TITLE,70,7,361,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_BUG_DESCRIPTION,70,26,361,90,ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL
+ PUSHBUTTON "Take Shot",IDC_BUG_TAKESHOT,7,122,56,14
+ PUSHBUTTON "Save Game",IDC_BUG_SAVEGAME,7,141,56,14
+ PUSHBUTTON "Include .bsp",IDC_BUG_INCLUDEBSP,7,159,56,14
+ PUSHBUTTON "Include .vmf",IDC_BUG_INCLUDEVMF,7,178,56,14
+ CONTROL "Compress Screenshot",IDC_BUG_COMPRESS_SCREENSHOT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,70,298,104,10
+ COMBOBOX IDC_BUG_OWNER,282,202,152,195,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_BUG_SEVERITY,282,221,152,77,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_BUG_REPORTTYPE,282,240,152,76,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_BUG_PRIORITY,282,259,152,76,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_BUG_GAME,282,278,152,195,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_BUG_AREA,282,297,152,125,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX IDC_BUG_MAPNUMBER,282,316,152,84,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "Clear Form",IDC_BUG_CLEARFORM,7,354,50,14
+ PUSHBUTTON "Update",IDC_BUG_UPDATE,67,354,50,14
+ PUSHBUTTON "Cancel",IDC_CANCEL,321,354,50,14
+ DEFPUSHBUTTON "Submit",IDC_BUG_SUBMIT,384,354,50,14
+ LTEXT "Title:",IDC_STATIC,7,7,45,8
+ LTEXT "Description:",IDC_STATIC,7,26,45,8
+ LTEXT "Position:",IDC_STATIC,7,204,44,8
+ LTEXT "Orientation:",IDC_STATIC,7,223,44,8
+ LTEXT "Map:",IDC_STATIC,7,242,44,8
+ LTEXT "Build:",IDC_STATIC,7,261,44,8
+ LTEXT "Submitter:",IDC_STATIC,7,280,40,8
+ LTEXT "",IDC_BUG_POSITION_LABEL,70,201,152,14,SS_SUNKEN
+ LTEXT "",IDC_BUG_ORIENTATION_LABEL,70,220,152,14,SS_SUNKEN
+ LTEXT "",IDC_BUG_MAP_LABEL,70,239,152,14,SS_SUNKEN
+ LTEXT "",IDC_BUG_BUILD_LABEL,70,258,152,14,SS_SUNKEN
+ LTEXT "",IDC_BUG_SUBMITTER_LABEL,70,277,152,14,SS_SUNKEN
+ LTEXT "Owner:",IDC_STATIC,232,204,40,8
+ LTEXT "Severity:",IDC_STATIC,232,223,40,8
+ LTEXT "Report Type:",IDC_STATIC,232,242,44,8
+ LTEXT "Priority:",IDC_STATIC,232,261,26,8
+ LTEXT "Game:",IDC_STATIC,231,280,40,8
+ LTEXT "Area:",IDC_STATIC,232,299,19,8
+ LTEXT "Map Number:",IDC_STATIC,232,318,44,8
+ LTEXT "",IDC_BUG_TAKESHOT_LABEL,70,122,364,14,SS_SUNKEN | SS_PATHELLIPSIS
+ LTEXT "",IDC_BUG_SAVEGAME_LABEL,70,141,364,14,SS_SUNKEN | SS_PATHELLIPSIS
+ LTEXT "",IDC_BUG_INCLUDEBSP_LABEL,70,159,364,14,SS_SUNKEN | SS_PATHELLIPSIS
+ LTEXT "",IDC_BUG_INCLUDEVMF_LABEL,70,178,364,14,SS_SUNKEN | SS_PATHELLIPSIS
+END
+
+IDD_EXCLUDEPATHS DIALOGEX 0, 0, 412, 313
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Exclude Xbox HDD Paths"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_PATHS_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_CHECKBOXES | WS_BORDER | WS_TABSTOP,7,7,398,276,WS_EX_CLIENTEDGE
+ PUSHBUTTON "Re-Scan",IDC_PATHS_RESCAN,7,292,50,14
+ PUSHBUTTON "Expand All",IDC_PATHS_EXPAND,64,292,50,14
+ PUSHBUTTON "Collapse All",IDC_PATHS_COLLAPSE,122,292,50,14
+ PUSHBUTTON "Cancel",IDC_CANCEL,294,292,50,14
+ DEFPUSHBUTTON "OK",IDC_OK,355,292,50,14
+ CONTROL "Link Game Directories",IDC_PATHS_LINKGAMEDIRS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,188,294,91,10
+END
+
+IDD_INSTALL DIALOGEX 0, 0, 492, 261
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Sync to DVD Image"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_INSTALL_LIST,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,477,215
+ PUSHBUTTON "Refresh",IDC_INSTALL_REFRESH,7,234,50,14
+ CONTROL "Force Sync",IDC_INSTALL_FORCESYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,122,236,51,10
+ CONTROL "Exact Image (Deletes Unrelated Files)",IDC_INSTALL_CLEANTARGET,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,185,236,137,10
+ PUSHBUTTON "Cancel",IDC_CANCEL,373,234,50,14
+ DEFPUSHBUTTON "OK",IDC_OK,434,234,50,14
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_MAIN_ACCEL ACCELERATORS
+BEGIN
+ "X", IDM_AUTOCONNECT, VIRTKEY, CONTROL, NOINVERT
+ "H", IDM_PROFILEHISTORY, VIRTKEY, CONTROL, NOINVERT
+ "S", IDM_PROFILESAMPLES, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+MENU_VXCONSOLE MENU
+BEGIN
+ POPUP "Main"
+ BEGIN
+ MENUITEM "Configuration..", IDM_CONFIG
+ MENUITEM SEPARATOR
+ MENUITEM "Exit", IDM_EXIT
+ END
+ POPUP "Connection"
+ BEGIN
+ MENUITEM "Capture Game Spew", IDM_CAPTUREGAMESPEW
+ MENUITEM "Capture Debug Spew", IDM_CAPTUREDEBUGSPEW
+ MENUITEM "Show Remote Command Traffic", IDM_DEBUGCOMMANDS
+ MENUITEM SEPARATOR
+ MENUITEM "Bug Reporter...", IDM_BUG
+ MENUITEM SEPARATOR
+ MENUITEM "Sync Xbox HDD Files...", IDM_SYNCFILES
+ MENUITEM "Sync Xbox HDD To DVD Image...", IDM_SYNCINSTALL
+ MENUITEM SEPARATOR
+ MENUITEM "Exclude Xbox HDD Paths...", IDM_EXCLUDEPATHS
+ MENUITEM SEPARATOR
+ MENUITEM "&Auto Connect\tCtrl+X", IDM_AUTOCONNECT
+ END
+ POPUP "Profiling"
+ BEGIN
+ MENUITEM "TimeStamp Log", IDM_TIMESTAMPLOG
+ MENUITEM "Memory Dump", IDM_MEMORYDUMP
+ MENUITEM SEPARATOR
+ POPUP "Show CPU Usage"
+ BEGIN
+ MENUITEM "Snapshot", IDM_CPU_SAMPLES
+ MENUITEM " History", IDM_CPU_HISTORY
+ END
+ POPUP "Show D3D Usage"
+ BEGIN
+ MENUITEM "Snapshot", IDM_D3D_SAMPLES
+ MENUITEM "History", IDM_D3D_HISTORY
+ END
+ MENUITEM "Show Memory Usage", IDM_SHOWMEMORYUSAGE
+ MENUITEM SEPARATOR
+ MENUITEM "Playtest Mode", IDM_PLAYTESTMODE
+ END
+ POPUP "Resources"
+ BEGIN
+ MENUITEM "List Materials", IDM_SHOWRESOURCES_MATERIALS
+ MENUITEM "List Models", IDM_SHOWRESOURCES_MODELS
+ MENUITEM "List Textures", IDM_SHOWRESOURCES_TEXTURES
+ MENUITEM "List Sounds", IDM_SHOWRESOURCES_SOUNDS
+ END
+END
+
+MENU_CPUPROFILE MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Tick Marks", IDM_CPUPROFILE_TICKMARKS
+ MENUITEM "Colors", IDM_CPUPROFILE_COLORS
+ MENUITEM "FPS", IDM_CPUPROFILE_FPSLABELS
+ MENUITEM SEPARATOR
+ MENUITEM "Zoom In\tINS", IDM_CPUPROFILE_ZOOMIN
+ MENUITEM "Zoom Out\tDEL", IDM_CPUPROFILE_ZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "Enable", IDM_CPUPROFILE_ENABLE
+ END
+END
+
+MENU_SHOWTEXTURES MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Summary...", IDM_OPTIONS_SUMMARY
+ MENUITEM "Refresh", IDM_OPTIONS_REFRESH
+ MENUITEM "Export...", IDM_OPTIONS_EXPORT
+ MENUITEM SEPARATOR
+ MENUITEM "Current Frame", IDM_OPTIONS_CURRENTFRAME
+ MENUITEM "Full Path", IDM_OPTIONS_FULLPATH
+ MENUITEM SEPARATOR
+ MENUITEM "Draw Texture", IDM_OPTIONS_DRAWTEXTURE
+ END
+END
+
+MENU_TEXPROFILE MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Tick Marks", IDM_TEXPROFILE_TICKMARKS
+ MENUITEM "Colors", IDM_TEXPROFILE_COLORS
+ MENUITEM SEPARATOR
+ MENUITEM "Zoom In\tINS", IDM_TEXPROFILE_ZOOMIN
+ MENUITEM "Zoom Out\tDEL", IDM_TEXPROFILE_ZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "Current Frame", IDM_TEXPROFILE_CURRENTFRAME
+ MENUITEM "Enable", IDM_TEXPROFILE_ENABLE
+ END
+END
+
+MENU_BINDOPTIONS MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Modify...", IDM_BINDOPTIONS_MODIFY
+ MENUITEM "Delete", IDM_BINDOPTIONS_DELETE
+ END
+END
+
+MENU_SHOWMATERIALS MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Refresh", IDM_OPTIONS_REFRESH
+ MENUITEM "Export", IDM_OPTIONS_EXPORT
+ MENUITEM SEPARATOR
+ MENUITEM "Current Frame", IDM_OPTIONS_CURRENTFRAME
+ END
+END
+
+MENU_SHOWSOUNDS MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Summary...", IDM_OPTIONS_SUMMARY
+ MENUITEM "Refresh", IDM_OPTIONS_REFRESH
+ MENUITEM "Export...", IDM_OPTIONS_EXPORT
+ MENUITEM SEPARATOR
+ MENUITEM "Play", IDM_OPTIONS_PLAYSOUND
+ END
+END
+
+MENU_SHOWMEMORYDUMP MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Refresh", IDM_OPTIONS_REFRESH
+ MENUITEM "Export...", IDM_OPTIONS_EXPORT
+ MENUITEM "Summary...", IDM_OPTIONS_SUMMARY
+ MENUITEM SEPARATOR
+ MENUITEM "Size as Bytes", IDM_OPTIONS_BYTES
+ MENUITEM "Size as KB", IDM_OPTIONS_KILOBYTES
+ MENUITEM "Size as MB", IDM_OPTIONS_MEGABYTES
+ MENUITEM "Collapse Output", IDM_OPTIONS_COLLAPSEOUTPUT
+ END
+END
+
+MENU_TIMESTAMPLOG MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Clear", IDM_OPTIONS_CLEAR
+ MENUITEM "Export", IDM_OPTIONS_EXPORT
+ END
+END
+
+MENU_MEMPROFILE MENU
+BEGIN
+ POPUP "Options"
+ BEGIN
+ MENUITEM "Tick Marks", IDM_MEMPROFILE_TICKMARKS
+ MENUITEM "Colors", IDM_MEMPROFILE_COLORS
+ MENUITEM SEPARATOR
+ MENUITEM "Zoom In\tINS", IDM_MEMPROFILE_ZOOMIN
+ MENUITEM "Zoom Out\t INS", IDM_MEMPROFILE_ZOOMOUT
+ MENUITEM SEPARATOR
+ MENUITEM "Enable", IDM_MEMPROFILE_ENABLE
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_CONFIG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 405
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 144
+ END
+
+ IDD_SYNCFILES, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 220
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 146
+ END
+
+ IDD_MODIFYBIND, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 252
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 99
+ END
+
+ IDD_BUG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 434
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 368
+ END
+
+ IDD_EXCLUDEPATHS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 405
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 306
+ END
+
+ IDD_INSTALL, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 485
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 254
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ 10004 "Interrupted system call."
+ 10009 "Bad file number."
+ 10013 "Permission denied."
+ 10014 "Bad address."
+END
+
+STRINGTABLE
+BEGIN
+ 10022 "Invalid argument."
+ 10024 "Too many open files."
+END
+
+STRINGTABLE
+BEGIN
+ 10035 "Operation would block."
+ 10036 "Operation now in progress."
+ 10037 "Operation already in progress."
+ 10038 "Socket operation on nonsocket."
+ 10039 "Destination address required."
+ 10040 "Message too long."
+ 10041 "Protocol wrong type for socket."
+ 10042 "Protocol not available."
+ 10043 "Protocol not supported."
+ 10044 "Socket type not supported."
+ 10045 "Operation not supported on socket."
+ 10046 "Protocol family not supported."
+ 10047 "Address family not supported by protocol family."
+END
+
+STRINGTABLE
+BEGIN
+ 10048 "Address already in use."
+ 10049 "Cannot assign requested address."
+ 10050 "Network is down."
+ 10051 "Network is unreachable."
+ 10052 "Network dropped connection on reset."
+ 10053 "Software caused connection abort."
+ 10054 "Connection reset by peer."
+ 10055 "No buffer space available."
+ 10056 "Socket is already connected."
+ 10057 "Socket is not connected."
+ 10058 "Cannot send after socket shutdown."
+ 10059 "Too many references: cannot splice."
+ 10060 "Connection timed out."
+ 10061 "Connection refused."
+ 10062 "Too many levels of symbolic links."
+ 10063 "File name too long."
+END
+
+STRINGTABLE
+BEGIN
+ 10064 "Host is down."
+ 10065 "No route to host."
+END
+
+STRINGTABLE
+BEGIN
+ 10091 "The network subsystem is unusable."
+ 10092 "The Windows Sockets DLL cannot support this application."
+ 10093 "Winsock not initialized."
+END
+
+STRINGTABLE
+BEGIN
+ 10101 "Disconnect."
+END
+
+STRINGTABLE
+BEGIN
+ 11001 "Host not found."
+ 11002 "Nonauthoritative host not found. Name service maybe not be functioning."
+ 11003 "Nonrecoverable error. Name service maybe not be functioning."
+ 11004 "Valid name, no data record of requested type."
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/utils/xbox/vxconsole/vxconsole.vpc b/utils/xbox/vxconsole/vxconsole.vpc
new file mode 100644
index 0000000..5e9424c
--- /dev/null
+++ b/utils/xbox/vxconsole/vxconsole.vpc
@@ -0,0 +1,85 @@
+//-----------------------------------------------------------------------------
+// VXCONSOLE.VPC
+//
+// Project Script
+//-----------------------------------------------------------------------------
+
+$Macro SRCDIR "..\..\.."
+$Macro OUTBINDIR "$SRCDIR\..\game\bin"
+
+$Include "$SRCDIR\vpc_scripts\source_exe_win_win32_base.vpc"
+
+$Configuration
+{
+ $Compiler
+ {
+ $AdditionalIncludeDirectories "$BASE;$SRCDIR\x360xdk\include\win32\vs2005"
+ }
+
+ $Linker
+ {
+ $AdditionalDependencies "wsock32.lib comctl32.lib odbc32.lib odbccp32.lib xbdm.lib"
+ $AdditionalLibraryDirectories "$SRCDIR\x360xdk\lib\win32\vs2005"
+ $DelayLoadedDLLs "xbdm.dll"
+ }
+}
+
+$Project "VXConsole"
+{
+ $Folder "Source Files"
+ {
+ $File "bindings.cpp"
+ $File "bug.cpp"
+ $File "common.cpp"
+ $File "config.cpp"
+ $File "cpu_profile.cpp"
+ $File "exclude_paths.cpp"
+ $File "fileio.cpp"
+ $File "local_cmds.cpp"
+ $File "progress.cpp"
+ $File "remote_cmds.cpp"
+ $File "show_materials.cpp"
+ $File "show_memdump.cpp"
+ $File "show_sounds.cpp"
+ $File "show_textures.cpp"
+ $File "sync_files.cpp"
+ $File "sys_scriptlib.cpp"
+ $File "sys_utils.cpp"
+ $File "tex_profile.cpp"
+ $File "timestamp_log.cpp"
+ $File "vxconsole.cpp"
+ $File "assert_dialog.cpp"
+ $File "mem_profile.cpp"
+ }
+
+ $Folder "Header Files"
+ {
+ $File "$SRCDIR\common\bugreporter\bugreporter.h"
+ $File "$SRCDIR\common\xbox\xbox_vxconsole.h"
+ $File "$SRCDIR\public\tier1\interface.h"
+ $File "$SRCDIR\public\jpeglib\jpeglib.h"
+ $File "$SRCDIR\public\tier0\platform.h"
+ $File "$SRCDIR\public\tier1\strtools.h"
+ $File "resource.h"
+ $File "assert_resource.h"
+ $File "sys_scriptlib.h"
+ $File "sys_utils.h"
+ $File "vxconsole.h"
+ }
+
+ $Folder "Resource Files"
+ {
+ $File "icon_connect1.ico"
+ $File "icon_connect2.ico"
+ $File "icon_connect2a.ico"
+ $File "icon_disconnect.ico"
+ $File "vxconsole.ico"
+ $File "vxconsole.rc"
+ $File "assert_dialog.rc"
+ }
+
+ $Folder "Link Libraries"
+ {
+ $DynamicFile "$SRCDIR\lib\common\jpeglib.lib"
+ }
+}