//// ここから呼んでる ///////////////////////////////////////////////////////////////
DialogBox( hInst, ( LPCTSTR) IDD_CONTROLS, hWnd, ( DLGPROC) Controls) ;
//// ダイアログの処理全部 ///////////////////////////////////////////////////////////////
LRESULT CALLBACK Controls( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
static HBITMAP hbm = 0 ;
static int curDevice = 0 ;
static HWND tabs = NULL ;
switch ( message)
{
case WM_INITDIALOG:
W32Util:: CenterWindow ( hDlg) ;
{
// TODO: connect to keyboard device instead
{
HBITMAP hResBM = LoadImageFromResource( hInst, MAKEINTRESOURCE( IDB_IMAGE_PSP) , "IMAGE" ) ;
HDC hDC = GetDC( hDlg) ;
RECT clientRect;
GetClientRect( hDlg, & clientRect) ;
//TabCtrl_AdjustRect(, TRUE, &clientRect);
HBITMAP hMemBM = CreateCompatibleBitmap( hDC, clientRect.right , clientRect.bottom ) ;
HDC hResDC = CreateCompatibleDC( hDC) ;
HDC hMemDC = CreateCompatibleDC( hDC) ;
SelectObject( hResDC, hResBM) ;
SelectObject( hMemDC, hMemBM) ;
BITMAP bm;
GetObject( hResBM, sizeof ( BITMAP) , & bm) ;
SetStretchBltMode( hMemDC, HALFTONE) ;
StretchBlt( hMemDC, clientRect.left , clientRect.top , ( clientRect.right - clientRect.left ) ,
( clientRect.bottom - clientRect.top ) , hResDC, 0 , 0 , bm.bmWidth , bm.bmHeight , SRCCOPY) ;
if ( hbm)
DeleteObject( hbm) ;
hbm = hMemBM;
DeleteDC( hMemDC) ;
DeleteDC( hResDC) ;
ReleaseDC( hDlg, hDC) ;
DeleteObject( hResBM) ;
}
int key_pad_size = ( IDC_EDIT_KEYRIGHT - IDC_EDIT_KEY_TURBO + 1 ) ;
for ( u32 i = 0 ; i <= IDC_EDIT_KEY_ANALOG_RIGHT - IDC_EDIT_KEY_TURBO; i++ ) {
HWND hEdit = GetDlgItem( hDlg, IDC_EDIT_KEY_TURBO + i) ;
if ( IDC_EDIT_KEY_TURBO + i <= IDC_EDIT_KEYRIGHT)
control_map[ i] = key_pad_map[ i * 2 ] ;
else
control_map[ i] = analog_ctrl_map[ ( i - key_pad_size) * 2 ] ;
SetWindowTextA( hEdit, getVirtualKeyName( control_map[ i] ) ) ;
}
ComboBox_AddString( GetDlgItem( hDlg, IDC_FORCE_INPUT_DEVICE) , "None" ) ;
ComboBox_AddString( GetDlgItem( hDlg, IDC_FORCE_INPUT_DEVICE) , "XInput" ) ;
ComboBox_AddString( GetDlgItem( hDlg, IDC_FORCE_INPUT_DEVICE) , "DirectInput" ) ;
if ( ( g_Config.iForceInputDevice < 0 ) || ( g_Config.iForceInputDevice > 1 ) )
{
ComboBox_SetCurSel( GetDlgItem( hDlg, IDC_FORCE_INPUT_DEVICE) , 0 ) ;
}
else
{
ComboBox_SetCurSel( GetDlgItem( hDlg, IDC_FORCE_INPUT_DEVICE) , ( g_Config.iForceInputDevice + 1 ) ) ;
}
tabs = GetDlgItem( hDlg, IDC_CONTROLTAB) ;
TCITEM tcItem;
ZeroMemory( & tcItem, sizeof ( tcItem) ) ;
tcItem.mask = TCIF_TEXT;
tcItem.dwState = 0 ;
tcItem.pszText = "Keyboard" ;
tcItem.cchTextMax = ( int ) strlen ( tcItem.pszText ) + 1 ;
tcItem.iImage = 0 ;
TabCtrl_InsertItem( tabs, TabCtrl_GetItemCount( tabs) ,& tcItem) ;
tcItem.pszText = "DirectInput" ;
tcItem.cchTextMax = ( int ) strlen ( tcItem.pszText ) + 1 ;
TabCtrl_InsertItem( tabs, TabCtrl_GetItemCount( tabs) ,& tcItem) ;
tcItem.pszText = "XInput" ;
tcItem.cchTextMax = ( int ) strlen ( tcItem.pszText ) + 1 ;
TabCtrl_InsertItem( tabs, TabCtrl_GetItemCount( tabs) ,& tcItem) ;
DWORD dwThreadID = GetWindowThreadProcessId( hDlg, NULL ) ;
pKeydownHook = SetWindowsHookEx( WH_KEYBOARD,KeyboardProc, NULL , dwThreadID) ;
}
return TRUE;
case WM_NOTIFY:
{
switch ( ( ( NMHDR * ) lParam) - > code) {
case TCN_SELCHANGE:
//InvalidateRect(hDlg, NULL, TRUE);
curDevice = TabCtrl_GetCurSel( tabs) ;
break ;
case TCN_SELCHANGING:
curDevice = TabCtrl_GetCurSel( tabs) ;
break ;
default :
break ;
}
break ;
}
case WM_PAINT:
{
PAINTSTRUCT pst;
HDC hdc = BeginPaint( hDlg, & pst) ;
BITMAP bm;
GetObject( hbm, sizeof ( BITMAP) , & bm) ;
//RECT rect;
//GetClientRect(hDlg, &rect);
RECT rect = { 0 , 0 , bm.bmWidth , bm.bmHeight } ;
//TabCtrl_AdjustRect(hDlg, TRUE, &rect);
BitBlt( hbm, hdc, rect.left , rect.top , rect.right - rect.left , rect.bottom - rect.top , 0 , 0 ) ;
//BitBlt(hbm, hdc, 0, 0, bm.bmWidth, bm.bmHeight, 0 , 0);
EndPaint( hDlg, & pst) ;
return TRUE;
}
case WM_CTLCOLORSTATIC:
{
HDC hdc= ( HDC) wParam;
SetBkMode( hdc, TRANSPARENT) ;
return ( LRESULT) GetStockObject( NULL_BRUSH) ;
}
case WM_CTLCOLOREDIT:
{
if ( ( HWND) lParam == GetDlgItem( hDlg, IDC_FORCE_INPUT_DEVICE) )
return FALSE;
HDC hdc = ( HDC) wParam;
SetBkMode( hdc, TRANSPARENT) ;
SetTextColor( hdc, RGB( 255 , 0 , 0 ) ) ;
HWND hEdit = ( HWND) lParam;
RECT rc = getRedrawRect( hEdit) ;
RECT clientrc;
GetClientRect( hEdit, & clientrc) ;
BitBlt( hbm, hdc, 0 , 0 , rc.right - rc.left , rc.bottom - rc.top , rc.left , rc.top ) ;
char str[ 11 ] ;
GetWindowTextA( hEdit, str, 10 ) ;
DrawTextA( hdc, str, ( int ) strlen ( str) , & clientrc, DT_CENTER| DT_SINGLELINE) ;
return ( LRESULT) GetStockObject( NULL_BRUSH) ;
}
case WM_COMMAND:
if ( LOWORD( wParam) == IDOK || LOWORD( wParam) == IDCANCEL)
{
if ( LOWORD( wParam) == IDOK) {
g_Config.iForceInputDevice = ( ComboBox_GetCurSel( GetDlgItem( hDlg, IDC_FORCE_INPUT_DEVICE) ) - 1 ) ;
int key_pad_size = ( IDC_EDIT_KEYRIGHT - IDC_EDIT_KEY_TURBO + 1 ) ;
for ( u32 i = 0 ; i <= IDC_EDIT_KEY_ANALOG_RIGHT - IDC_EDIT_KEY_TURBO; i++ ) {
if ( IDC_EDIT_KEY_TURBO + i <= IDC_EDIT_KEYRIGHT)
key_pad_map[ i * 2 ] = control_map[ i] ;
else
analog_ctrl_map[ ( i - key_pad_size) * 2 ] = control_map[ i] ;
}
saveControlsToFile( ) ;
}
UnhookWindowsHookEx( pKeydownHook) ;
EndDialog( hDlg, LOWORD( wParam) ) ;
curDevice = 0 ;
tabs = NULL ;
if ( hbm) {
DeleteObject( hbm) ;
hbm = 0 ;
}
return TRUE;
}
break ;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////
// *.rc
IDD_CONTROLS DIALOGEX 0 , 0 , 495 , 239
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Controls"
FONT 9 , "MS Shell Dlg" , 0 , 0 , 0x1
BEGIN
DEFPUSHBUTTON "OK" ,IDOK,188 ,217 ,50 ,14
PUSHBUTTON "Cancel" ,IDCANCEL,242 ,217 ,50 ,14
LTEXT "Turbo Mode:" ,IDC_STATIC,386 ,220 ,42 ,8
EDITTEXT IDC_EDIT_KEYUP,56 ,79 ,34 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEYLEFT,34 ,100 ,34 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEYRIGHT,78 ,100 ,34 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEYDOWN,56 ,123 ,34 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_TRIANGLE,406 ,73 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_RECTANGLE,380 ,100 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_CIRCLE,433 ,100 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_CROSS,406 ,126 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_LEFT_THUMB,55 ,24 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_RIGHT_THUMB,406 ,24 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_SELECT,326 ,192 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_START,356 ,192 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_ANALOG_UP,57 ,145 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_ANALOG_LEFT,40 ,159 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_ANALOG_RIGHT,75 ,159 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_ANALOG_DOWN,57 ,173 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
EDITTEXT IDC_EDIT_KEY_TURBO,430 ,220 ,33 ,14 ,ES_CENTER | ES_AUTOHSCROLL | NOT WS_BORDER
LTEXT "Force device:" ,IDC_STATIC,14 ,220 ,45 ,11
COMBOBOX IDC_FORCE_INPUT_DEVICE,62 ,218 ,84 ,140 ,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "" ,IDC_CONTROLTAB,"SysTabControl32" , TCS_FORCEICONLEFT | TCS_FIXEDWIDTH,0 ,0 ,495 ,239 ,WS_EX_TRANSPARENT
END
//////////////////////////////////////////////////////////////////////
Ly8vLyDjgZPjgZPjgYvjgonlkbzjgpPjgafjgosgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCkRpYWxvZ0JveChoSW5zdCwgKExQQ1RTVFIpSUREX0NPTlRST0xTLCBoV25kLCAoRExHUFJPQylDb250cm9scyk7Ci8vLy8g44OA44Kk44Ki44Ot44Kw44Gu5Yem55CG5YWo6YOoIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoJTFJFU1VMVCBDQUxMQkFDSyBDb250cm9scyhIV05EIGhEbGcsIFVJTlQgbWVzc2FnZSwgV1BBUkFNIHdQYXJhbSwgTFBBUkFNIGxQYXJhbSkKCXsKCQlzdGF0aWMgSEJJVE1BUCBoYm0gPSAwOwoJCXN0YXRpYyBpbnQgY3VyRGV2aWNlID0gMDsKCQlzdGF0aWMgSFdORCB0YWJzID0gTlVMTDsKCQlzd2l0Y2ggKG1lc3NhZ2UpCgkJewoJCWNhc2UgV01fSU5JVERJQUxPRzoKCQkJVzMyVXRpbDo6Q2VudGVyV2luZG93KGhEbGcpOwoJCQl7CgkJCQkvLyBUT0RPOiBjb25uZWN0IHRvIGtleWJvYXJkIGRldmljZSBpbnN0ZWFkCgkJCQl7CgkJCQkJCgkJCQkJSEJJVE1BUCBoUmVzQk0gPSBMb2FkSW1hZ2VGcm9tUmVzb3VyY2UoaEluc3QsIE1BS0VJTlRSRVNPVVJDRShJREJfSU1BR0VfUFNQKSwgIklNQUdFIik7CgkJCQkJSERDIGhEQyA9IEdldERDKGhEbGcpOwoJCQkJCVJFQ1QgY2xpZW50UmVjdDsKCQkJCQlHZXRDbGllbnRSZWN0KGhEbGcsICZjbGllbnRSZWN0KTsKCQkJCQkvL1RhYkN0cmxfQWRqdXN0UmVjdCgsIFRSVUUsICZjbGllbnRSZWN0KTsKCQkJCQlIQklUTUFQIGhNZW1CTSA9IENyZWF0ZUNvbXBhdGlibGVCaXRtYXAoaERDLCBjbGllbnRSZWN0LnJpZ2h0LCBjbGllbnRSZWN0LmJvdHRvbSk7CgkJCQkJSERDIGhSZXNEQyA9IENyZWF0ZUNvbXBhdGlibGVEQyhoREMpOwoJCQkJCUhEQyBoTWVtREMgPSBDcmVhdGVDb21wYXRpYmxlREMoaERDKTsKCQkJCQlTZWxlY3RPYmplY3QoaFJlc0RDLCBoUmVzQk0pOwoJCQkJCVNlbGVjdE9iamVjdChoTWVtREMsIGhNZW1CTSk7CgoJCQkJCUJJVE1BUCBibTsKCQkJCQlHZXRPYmplY3QoaFJlc0JNLCBzaXplb2YoQklUTUFQKSwgJmJtKTsKCQkJCQlTZXRTdHJldGNoQmx0TW9kZShoTWVtREMsIEhBTEZUT05FKTsKCQkJCQlTdHJldGNoQmx0KGhNZW1EQywgY2xpZW50UmVjdC5sZWZ0LCBjbGllbnRSZWN0LnRvcCwgKGNsaWVudFJlY3QucmlnaHQgLSBjbGllbnRSZWN0LmxlZnQpLAoJCQkJCQkoY2xpZW50UmVjdC5ib3R0b20gLSBjbGllbnRSZWN0LnRvcCksIGhSZXNEQywgMCwgMCwgYm0uYm1XaWR0aCwgYm0uYm1IZWlnaHQsIFNSQ0NPUFkpOyAKCQkJCQlpZiAoaGJtKQoJCQkJCQlEZWxldGVPYmplY3QoaGJtKTsKCQkJCQloYm0gPSBoTWVtQk07CgoJCQkJCURlbGV0ZURDKGhNZW1EQyk7CgkJCQkJRGVsZXRlREMoaFJlc0RDKTsKCQkJCQlSZWxlYXNlREMoaERsZywgaERDKTsKCQkJCQlEZWxldGVPYmplY3QoaFJlc0JNKTsKCQkJCX0KCgkJCQlpbnQga2V5X3BhZF9zaXplID0gKElEQ19FRElUX0tFWVJJR0hUIC0gSURDX0VESVRfS0VZX1RVUkJPICsgMSk7CgkJCQlmb3IgKHUzMiBpID0gMDsgaSA8PSBJRENfRURJVF9LRVlfQU5BTE9HX1JJR0hUIC0gSURDX0VESVRfS0VZX1RVUkJPOyBpKyspIHsKCQkJCQlIV05EIGhFZGl0ID0gR2V0RGxnSXRlbShoRGxnLCBJRENfRURJVF9LRVlfVFVSQk8gKyBpKTsKCQkJCQlpZiAoSURDX0VESVRfS0VZX1RVUkJPICsgaSA8PSBJRENfRURJVF9LRVlSSUdIVCkKCQkJCQkJY29udHJvbF9tYXBbaV0gPSBrZXlfcGFkX21hcFtpICogMl07CgkJCQkJZWxzZQoJCQkJCQljb250cm9sX21hcFtpXSA9IGFuYWxvZ19jdHJsX21hcFsoaSAtIGtleV9wYWRfc2l6ZSkgKiAyXTsKCQkJCQlTZXRXaW5kb3dUZXh0QShoRWRpdCwgZ2V0VmlydHVhbEtleU5hbWUoY29udHJvbF9tYXBbaV0pKTsKCQkJCX0KCQkJCUNvbWJvQm94X0FkZFN0cmluZyhHZXREbGdJdGVtKGhEbGcsIElEQ19GT1JDRV9JTlBVVF9ERVZJQ0UpLCAiTm9uZSIpOwoJCQkJQ29tYm9Cb3hfQWRkU3RyaW5nKEdldERsZ0l0ZW0oaERsZywgSURDX0ZPUkNFX0lOUFVUX0RFVklDRSksICJYSW5wdXQiKTsKCQkJCUNvbWJvQm94X0FkZFN0cmluZyhHZXREbGdJdGVtKGhEbGcsIElEQ19GT1JDRV9JTlBVVF9ERVZJQ0UpLCAiRGlyZWN0SW5wdXQiKTsKCQkJCWlmICgoZ19Db25maWcuaUZvcmNlSW5wdXREZXZpY2UgPCAwKSB8fCAoZ19Db25maWcuaUZvcmNlSW5wdXREZXZpY2UgPiAxKSkKCQkJCXsKCQkJCQlDb21ib0JveF9TZXRDdXJTZWwoR2V0RGxnSXRlbShoRGxnLCBJRENfRk9SQ0VfSU5QVVRfREVWSUNFKSwgMCk7CgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJQ29tYm9Cb3hfU2V0Q3VyU2VsKEdldERsZ0l0ZW0oaERsZywgSURDX0ZPUkNFX0lOUFVUX0RFVklDRSksIChnX0NvbmZpZy5pRm9yY2VJbnB1dERldmljZSArIDEpKTsKCQkJCX0KCQkJCXRhYnMgPSBHZXREbGdJdGVtKGhEbGcsIElEQ19DT05UUk9MVEFCKTsKCQkJCVRDSVRFTSB0Y0l0ZW07CgkJCQlaZXJvTWVtb3J5KCZ0Y0l0ZW0sIHNpemVvZih0Y0l0ZW0pKTsKCQkJCXRjSXRlbS5tYXNrCQkJPSBUQ0lGX1RFWFQ7CgkJCQl0Y0l0ZW0uZHdTdGF0ZQkJPSAwOwoJCQkJdGNJdGVtLnBzelRleHQJCT0gIktleWJvYXJkIjsKCQkJCXRjSXRlbS5jY2hUZXh0TWF4CT0gKGludClzdHJsZW4odGNJdGVtLnBzelRleHQpKzE7CgkJCQl0Y0l0ZW0uaUltYWdlCQk9IDA7CgkJCQlUYWJDdHJsX0luc2VydEl0ZW0odGFicywgVGFiQ3RybF9HZXRJdGVtQ291bnQodGFicyksJnRjSXRlbSk7CgkJCQl0Y0l0ZW0ucHN6VGV4dAkJPSAiRGlyZWN0SW5wdXQiOwoJCQkJdGNJdGVtLmNjaFRleHRNYXgJPSAoaW50KXN0cmxlbih0Y0l0ZW0ucHN6VGV4dCkrMTsKCQkJCVRhYkN0cmxfSW5zZXJ0SXRlbSh0YWJzLCBUYWJDdHJsX0dldEl0ZW1Db3VudCh0YWJzKSwmdGNJdGVtKTsKCQkJCXRjSXRlbS5wc3pUZXh0CQk9ICJYSW5wdXQiOwoJCQkJdGNJdGVtLmNjaFRleHRNYXgJPSAoaW50KXN0cmxlbih0Y0l0ZW0ucHN6VGV4dCkrMTsKCQkJCVRhYkN0cmxfSW5zZXJ0SXRlbSh0YWJzLCBUYWJDdHJsX0dldEl0ZW1Db3VudCh0YWJzKSwmdGNJdGVtKTsKCQkJCQoKCQkJCURXT1JEIGR3VGhyZWFkSUQgPSBHZXRXaW5kb3dUaHJlYWRQcm9jZXNzSWQoaERsZywgTlVMTCk7CgkJCQlwS2V5ZG93bkhvb2sgPSBTZXRXaW5kb3dzSG9va0V4KFdIX0tFWUJPQVJELEtleWJvYXJkUHJvYywgTlVMTCwgZHdUaHJlYWRJRCk7CgkJCX0KCQkJcmV0dXJuIFRSVUU7CgkJY2FzZSBXTV9OT1RJRlk6CgkJCXsKCQkJCXN3aXRjaCAoKChOTUhEUiAqKWxQYXJhbSktPmNvZGUpIHsKCQkJCQljYXNlIFRDTl9TRUxDSEFOR0U6CgkJCQkJCS8vSW52YWxpZGF0ZVJlY3QoaERsZywgTlVMTCwgVFJVRSk7CgkJCQkJCWN1ckRldmljZSA9IFRhYkN0cmxfR2V0Q3VyU2VsKHRhYnMpOwoJCQkJCQlicmVhazsKCQkJCQljYXNlIFRDTl9TRUxDSEFOR0lORzoKCQkJCQkJY3VyRGV2aWNlID0gVGFiQ3RybF9HZXRDdXJTZWwodGFicyk7CgkJCQkJCWJyZWFrOwoJCQkJCWRlZmF1bHQ6CgkJCQkJCWJyZWFrOwoJCQkJfQoJCQkJYnJlYWs7CgkJCX0KCQljYXNlIFdNX1BBSU5UOgoJCQl7CgkJCQkKCQkJCVBBSU5UU1RSVUNUIHBzdDsJCgkJCQlIREMgaGRjID0gQmVnaW5QYWludChoRGxnLCAmcHN0KTsKCQkJCQoJCQkJQklUTUFQIGJtOwoJCQkJR2V0T2JqZWN0KGhibSwgc2l6ZW9mKEJJVE1BUCksICZibSk7CgkJCQkvL1JFQ1QgcmVjdDsKCQkJCS8vR2V0Q2xpZW50UmVjdChoRGxnLCAmcmVjdCk7CgkJCQlSRUNUIHJlY3QgPSB7MCwgMCwgYm0uYm1XaWR0aCwgYm0uYm1IZWlnaHR9OwoJCQkJLy9UYWJDdHJsX0FkanVzdFJlY3QoaERsZywgVFJVRSwgJnJlY3QpOwoJCQkJQml0Qmx0KGhibSwgaGRjLCByZWN0LmxlZnQsIHJlY3QudG9wLCByZWN0LnJpZ2h0IC0gcmVjdC5sZWZ0LCByZWN0LmJvdHRvbSAtIHJlY3QudG9wLCAwLCAwKTsKCQkJCS8vQml0Qmx0KGhibSwgaGRjLCAwLCAwLCBibS5ibVdpZHRoLCBibS5ibUhlaWdodCwgMCAsIDApOwoJCQkJRW5kUGFpbnQoaERsZywgJnBzdCk7CgkJCQkKCQkJCXJldHVybiBUUlVFOwoJCQl9CgkJY2FzZSBXTV9DVExDT0xPUlNUQVRJQzoKCQkJewoJCQkJSERDIGhkYz0oSERDKXdQYXJhbTsKCQkJCVNldEJrTW9kZShoZGMsIFRSQU5TUEFSRU5UKTsKCQkJCXJldHVybiAoTFJFU1VMVClHZXRTdG9ja09iamVjdChOVUxMX0JSVVNIKTsgCgkJCX0KCQljYXNlIFdNX0NUTENPTE9SRURJVDoKCQkJewoJCQkJaWYgKChIV05EKWxQYXJhbSA9PSBHZXREbGdJdGVtKGhEbGcsIElEQ19GT1JDRV9JTlBVVF9ERVZJQ0UpKQoJCQkJCXJldHVybiBGQUxTRTsKCQkJCUhEQyBoZGMgPSAoSERDKXdQYXJhbTsKCQkJCVNldEJrTW9kZShoZGMsIFRSQU5TUEFSRU5UKTsKCQkJCVNldFRleHRDb2xvcihoZGMsIFJHQigyNTUsIDAsIDApKTsKCQkJCUhXTkQgaEVkaXQgPSAoSFdORClsUGFyYW07CgkJCQlSRUNUIHJjID0gZ2V0UmVkcmF3UmVjdChoRWRpdCk7CgkJCQlSRUNUIGNsaWVudHJjOwoJCQkJR2V0Q2xpZW50UmVjdChoRWRpdCwgJmNsaWVudHJjKTsKCQkJCUJpdEJsdChoYm0sIGhkYywgMCwgMCwgcmMucmlnaHQgLSByYy5sZWZ0LCByYy5ib3R0b20gLSByYy50b3AsIHJjLmxlZnQsIHJjLnRvcCk7CgkJCQljaGFyIHN0clsxMV07CgkJCQlHZXRXaW5kb3dUZXh0QShoRWRpdCwgc3RyLCAxMCk7CgkJCQlEcmF3VGV4dEEoaGRjLCBzdHIsIChpbnQpc3RybGVuKHN0ciksICZjbGllbnRyYywgRFRfQ0VOVEVSfERUX1NJTkdMRUxJTkUpOwoJCQkJcmV0dXJuIChMUkVTVUxUKUdldFN0b2NrT2JqZWN0KE5VTExfQlJVU0gpOwoJCQl9CgkJY2FzZSBXTV9DT01NQU5EOgoJCQlpZiAoTE9XT1JEKHdQYXJhbSkgPT0gSURPSyB8fCBMT1dPUkQod1BhcmFtKSA9PSBJRENBTkNFTCkgCgkJCXsKCQkJCWlmIChMT1dPUkQod1BhcmFtKSA9PSBJRE9LKSB7CgkJCQkJZ19Db25maWcuaUZvcmNlSW5wdXREZXZpY2UgPSAoQ29tYm9Cb3hfR2V0Q3VyU2VsKEdldERsZ0l0ZW0oaERsZywgSURDX0ZPUkNFX0lOUFVUX0RFVklDRSkpIC0gMSk7CgkJCQkJaW50IGtleV9wYWRfc2l6ZSA9IChJRENfRURJVF9LRVlSSUdIVCAtIElEQ19FRElUX0tFWV9UVVJCTyArIDEpOwoJCQkJCWZvciAodTMyIGkgPSAwOyBpIDw9IElEQ19FRElUX0tFWV9BTkFMT0dfUklHSFQgLSBJRENfRURJVF9LRVlfVFVSQk87IGkrKykgewoJCQkJCQlpZiAoSURDX0VESVRfS0VZX1RVUkJPICsgaSA8PSBJRENfRURJVF9LRVlSSUdIVCkKCQkJCQkJCWtleV9wYWRfbWFwW2kgKiAyXSA9IGNvbnRyb2xfbWFwW2ldOwoJCQkJCWVsc2UKCQkJCQkJYW5hbG9nX2N0cmxfbWFwWyhpIC0ga2V5X3BhZF9zaXplKSAqIDJdID0gY29udHJvbF9tYXBbaV07CgkJCQkJfQoJCQkJCXNhdmVDb250cm9sc1RvRmlsZSgpOwoJCQkJfQoJCQkJVW5ob29rV2luZG93c0hvb2tFeChwS2V5ZG93bkhvb2spOwoJCQkJRW5kRGlhbG9nKGhEbGcsIExPV09SRCh3UGFyYW0pKTsKCQkJCWN1ckRldmljZSA9IDA7CgkJCQl0YWJzID0gTlVMTDsKCQkJCWlmIChoYm0pIHsKCQkJCQlEZWxldGVPYmplY3QoaGJtKTsKCQkJCQloYm0gPSAwOwoJCQkJfQoJCQkJcmV0dXJuIFRSVUU7CgkJCX0KCQkJYnJlYWs7CgkJfQoJCXJldHVybiBGQUxTRTsKCX0KLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovLyAqLnJjCklERF9DT05UUk9MUyBESUFMT0dFWCAwLCAwLCA0OTUsIDIzOQpTVFlMRSBEU19TRVRGT05UIHwgRFNfTU9EQUxGUkFNRSB8IERTX0ZJWEVEU1lTIHwgV1NfUE9QVVAgfCBXU19DQVBUSU9OIHwgV1NfU1lTTUVOVQpDQVBUSU9OICJDb250cm9scyIKRk9OVCA5LCAiTVMgU2hlbGwgRGxnIiwgMCwgMCwgMHgxCkJFR0lOCiAgICBERUZQVVNIQlVUVE9OICAgIk9LIixJRE9LLDE4OCwyMTcsNTAsMTQKICAgIFBVU0hCVVRUT04gICAgICAiQ2FuY2VsIixJRENBTkNFTCwyNDIsMjE3LDUwLDE0CiAgICBMVEVYVCAgICAgICAgICAgIlR1cmJvIE1vZGU6IixJRENfU1RBVElDLDM4NiwyMjAsNDIsOAogICAgRURJVFRFWFQgICAgICAgIElEQ19FRElUX0tFWVVQLDU2LDc5LDM0LDE0LEVTX0NFTlRFUiB8IEVTX0FVVE9IU0NST0xMIHwgTk9UIFdTX0JPUkRFUgogICAgRURJVFRFWFQgICAgICAgIElEQ19FRElUX0tFWUxFRlQsMzQsMTAwLDM0LDE0LEVTX0NFTlRFUiB8IEVTX0FVVE9IU0NST0xMIHwgTk9UIFdTX0JPUkRFUgogICAgRURJVFRFWFQgICAgICAgIElEQ19FRElUX0tFWVJJR0hULDc4LDEwMCwzNCwxNCxFU19DRU5URVIgfCBFU19BVVRPSFNDUk9MTCB8IE5PVCBXU19CT1JERVIKICAgIEVESVRURVhUICAgICAgICBJRENfRURJVF9LRVlET1dOLDU2LDEyMywzNCwxNCxFU19DRU5URVIgfCBFU19BVVRPSFNDUk9MTCB8IE5PVCBXU19CT1JERVIKICAgIEVESVRURVhUICAgICAgICBJRENfRURJVF9LRVlfVFJJQU5HTEUsNDA2LDczLDMzLDE0LEVTX0NFTlRFUiB8IEVTX0FVVE9IU0NST0xMIHwgTk9UIFdTX0JPUkRFUgogICAgRURJVFRFWFQgICAgICAgIElEQ19FRElUX0tFWV9SRUNUQU5HTEUsMzgwLDEwMCwzMywxNCxFU19DRU5URVIgfCBFU19BVVRPSFNDUk9MTCB8IE5PVCBXU19CT1JERVIKICAgIEVESVRURVhUICAgICAgICBJRENfRURJVF9LRVlfQ0lSQ0xFLDQzMywxMDAsMzMsMTQsRVNfQ0VOVEVSIHwgRVNfQVVUT0hTQ1JPTEwgfCBOT1QgV1NfQk9SREVSCiAgICBFRElUVEVYVCAgICAgICAgSURDX0VESVRfS0VZX0NST1NTLDQwNiwxMjYsMzMsMTQsRVNfQ0VOVEVSIHwgRVNfQVVUT0hTQ1JPTEwgfCBOT1QgV1NfQk9SREVSCiAgICBFRElUVEVYVCAgICAgICAgSURDX0VESVRfS0VZX0xFRlRfVEhVTUIsNTUsMjQsMzMsMTQsRVNfQ0VOVEVSIHwgRVNfQVVUT0hTQ1JPTEwgfCBOT1QgV1NfQk9SREVSCiAgICBFRElUVEVYVCAgICAgICAgSURDX0VESVRfS0VZX1JJR0hUX1RIVU1CLDQwNiwyNCwzMywxNCxFU19DRU5URVIgfCBFU19BVVRPSFNDUk9MTCB8IE5PVCBXU19CT1JERVIKICAgIEVESVRURVhUICAgICAgICBJRENfRURJVF9LRVlfU0VMRUNULDMyNiwxOTIsMzMsMTQsRVNfQ0VOVEVSIHwgRVNfQVVUT0hTQ1JPTEwgfCBOT1QgV1NfQk9SREVSCiAgICBFRElUVEVYVCAgICAgICAgSURDX0VESVRfS0VZX1NUQVJULDM1NiwxOTIsMzMsMTQsRVNfQ0VOVEVSIHwgRVNfQVVUT0hTQ1JPTEwgfCBOT1QgV1NfQk9SREVSCiAgICBFRElUVEVYVCAgICAgICAgSURDX0VESVRfS0VZX0FOQUxPR19VUCw1NywxNDUsMzMsMTQsRVNfQ0VOVEVSIHwgRVNfQVVUT0hTQ1JPTEwgfCBOT1QgV1NfQk9SREVSCiAgICBFRElUVEVYVCAgICAgICAgSURDX0VESVRfS0VZX0FOQUxPR19MRUZULDQwLDE1OSwzMywxNCxFU19DRU5URVIgfCBFU19BVVRPSFNDUk9MTCB8IE5PVCBXU19CT1JERVIKICAgIEVESVRURVhUICAgICAgICBJRENfRURJVF9LRVlfQU5BTE9HX1JJR0hULDc1LDE1OSwzMywxNCxFU19DRU5URVIgfCBFU19BVVRPSFNDUk9MTCB8IE5PVCBXU19CT1JERVIKICAgIEVESVRURVhUICAgICAgICBJRENfRURJVF9LRVlfQU5BTE9HX0RPV04sNTcsMTczLDMzLDE0LEVTX0NFTlRFUiB8IEVTX0FVVE9IU0NST0xMIHwgTk9UIFdTX0JPUkRFUgogICAgRURJVFRFWFQgICAgICAgIElEQ19FRElUX0tFWV9UVVJCTyw0MzAsMjIwLDMzLDE0LEVTX0NFTlRFUiB8IEVTX0FVVE9IU0NST0xMIHwgTk9UIFdTX0JPUkRFUgogICAgTFRFWFQgICAgICAgICAgICJGb3JjZSBkZXZpY2U6IixJRENfU1RBVElDLDE0LDIyMCw0NSwxMQogICAgQ09NQk9CT1ggICAgICAgIElEQ19GT1JDRV9JTlBVVF9ERVZJQ0UsNjIsMjE4LDg0LDE0MCxDQlNfRFJPUERPV05MSVNUIHwgV1NfVlNDUk9MTCB8IFdTX1RBQlNUT1AKICAgIENPTlRST0wgICAgICAgICAiIixJRENfQ09OVFJPTFRBQiwiU3lzVGFiQ29udHJvbDMyIiwgVENTX0ZPUkNFSUNPTkxFRlQgfCBUQ1NfRklYRURXSURUSCwwLDAsNDk1LDIzOSxXU19FWF9UUkFOU1BBUkVOVApFTkQKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLw==