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