From c74939e16ec24c61f308151add02d78c3756a0e6 Mon Sep 17 00:00:00 2001 From: pcca-matrix Date: Fri, 6 Jun 2025 06:30:37 +0200 Subject: [PATCH] NRage plugin enhancements (#2469) * Updated NRage plugin - sensitivity adjustment - stick Visualizer - respect for the N64 octagonal shape - adjustable stick range and N64 range - XInput axis inversion support - Virtual corners in octagon - Small UI fixes * Update default Xinput settings * Typo error --- Source/nragev20/DirectInput.cpp | 73 ++--- Source/nragev20/FileAccess.cpp | 15 ++ Source/nragev20/FileAccess.h | 6 + Source/nragev20/Interface.cpp | 342 ++++++++++++++++++++++-- Source/nragev20/NRagePluginV2.cpp | 92 +++++++ Source/nragev20/NRagePluginV2.h | 30 ++- Source/nragev20/NRagePluginV2.rc | 117 ++++---- Source/nragev20/XInputController.cpp | 162 ++++++----- Source/nragev20/XInputController.h | 3 +- Source/nragev20/configs/Controller1.cpf | 5 +- Source/nragev20/resource.h | 17 +- 11 files changed, 652 insertions(+), 210 deletions(-) diff --git a/Source/nragev20/DirectInput.cpp b/Source/nragev20/DirectInput.cpp index 584c84173..5f14e1e65 100644 --- a/Source/nragev20/DirectInput.cpp +++ b/Source/nragev20/DirectInput.cpp @@ -149,7 +149,6 @@ bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) *pdwData = 0; WORD w_Buttons = 0; // WORD w_Axes = 0; - LPCONTROLLER pcController = &g_pcControllers[indexController]; // Still needs to be here, but not as important (comment by rabid) bool b_Value; @@ -157,11 +156,9 @@ bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) long lAxisValueX = ZEROVALUE; long lAxisValueY = ZEROVALUE; - // Take this info from the N64 controller struct, regardless of input devices - float d_ModifierX = (float)pcController->bStickRange / 100.0f; - float d_ModifierY = (float)pcController->bStickRange / 100.0f; - + float d_ModifierX = 0; + float d_ModifierY = 0; int i; // Do N64-Buttons / modifiers @@ -210,8 +207,8 @@ bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) case MDT_MOVE: { LPMODSPEC_MOVE args = (LPMODSPEC_MOVE)&pcController->pModifiers[i].dwSpecific; - d_ModifierX *= args->XModification / 100.0f; - d_ModifierY *= args->YModification / 100.0f; + d_ModifierX = args->XModification / 100.0f; + d_ModifierY = args->YModification / 100.0f; } break; case MDT_MACRO: @@ -228,7 +225,7 @@ bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) if(!args->fPrevFireState) // This round, a firing is needed { w_Buttons |= args->aButtons; - if( args->fAnalogRight ) + if( args->fAnalogRight ) lAxisValueX += MAXAXISVALUE; else if( args->fAnalogLeft ) lAxisValueX -= MAXAXISVALUE; @@ -324,9 +321,6 @@ bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) w_Buttons |= (((WORD)b_Value) << i); } // End N64 buttons for - long lDeadZoneValue = pcController->bPadDeadZone * RANGERELATIVE / 100; - float fDeadZoneRelation = (float)RANGERELATIVE / (float)( RANGERELATIVE - lDeadZoneValue ); - // Do N64 joystick axes for ( i = 0; i < 4; i++ ) { @@ -350,21 +344,16 @@ bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) case DT_JOYSLIDER: case DT_JOYAXE: l_Value = plRawState[btnButton.bOffset] - ZEROVALUE; - if( btnButton.bAxisID ) // Negative range { fNegInput = !fNegInput; - - b_Value = ( l_Value <= -lDeadZoneValue ); - if( b_Value ) - l_Value = (long) ((float)(l_Value + lDeadZoneValue ) * fDeadZoneRelation ); + b_Value = ( l_Value <= -ZEROVALUE ); } else { - b_Value = ( l_Value >= lDeadZoneValue ); - if( b_Value ) - l_Value = (long) ((float)(l_Value - lDeadZoneValue ) * fDeadZoneRelation ); + b_Value = ( l_Value >= ZEROVALUE ); } + break; case DT_JOYPOV: @@ -517,44 +506,18 @@ bool GetNControllerInput ( const int indexController, LPDWORD pdwData ) } } - if( pcController->fRealN64Range && ( lAxisValueX || lAxisValueY )) + if( ( lAxisValueX || lAxisValueY ) ) { - long lAbsoluteX = ( lAxisValueX > 0 ) ? lAxisValueX : -lAxisValueX; - long lAbsoluteY = ( lAxisValueY > 0 ) ? lAxisValueY : -lAxisValueY; + float LX, LY; + float modX = lAxisValueX * (d_ModifierX == 0 ? d_ModifierX = 1 : d_ModifierX); + float modY = lAxisValueY * (d_ModifierY == 0 ? d_ModifierY = 1 : d_ModifierY); + lAxisValueX = (min( max( MINAXISVALUE, modX), MAXAXISVALUE)); + lAxisValueY = (min( max( MINAXISVALUE, modY), MAXAXISVALUE)); + processStickInput(pcController, lAxisValueX , lAxisValueY, LX, LY); - long lRangeX; - long lRangeY; - - if( lAbsoluteX > lAbsoluteY ) - { - lRangeX = MAXAXISVALUE; - lRangeY = lRangeX * lAbsoluteY / lAbsoluteX; - } - else - { - lRangeY = MAXAXISVALUE; - lRangeX = lRangeY * lAbsoluteX / lAbsoluteY; - } - - // TODO: We should optimize this (comment by rabid) - double dRangeDiagonal = sqrt((double)(lRangeX * lRangeX + lRangeY * lRangeY)); -// __asm{ -// fld fRangeDiagonal -// fsqrt -// fstp fRangeDiagonal -// fwait -// } - double dRel = MAXAXISVALUE / dRangeDiagonal; - - *pdwData = MAKELONG(w_Buttons, - MAKEWORD( (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX * dRel )), MAXAXISVALUE) / N64DIVIDER ), - (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY * dRel )), MAXAXISVALUE) / N64DIVIDER ))); - } - else - { - *pdwData = MAKELONG(w_Buttons, - MAKEWORD( (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueX * d_ModifierX )), MAXAXISVALUE) / N64DIVIDER ), - (BYTE)(min( max( MINAXISVALUE, (long)(lAxisValueY * d_ModifierY )), MAXAXISVALUE) / N64DIVIDER ))); + *pdwData = MAKELONG(w_Buttons, MAKEWORD( LX * pcController->bN64Range / MAXAXISVALUE, LY * pcController->bN64Range / MAXAXISVALUE) ); + }else{ + *pdwData = MAKELONG(w_Buttons, MAKEWORD(ZEROVALUE, ZEROVALUE)); } return true; diff --git a/Source/nragev20/FileAccess.cpp b/Source/nragev20/FileAccess.cpp index 01dbd743a..f21d5b575 100644 --- a/Source/nragev20/FileAccess.cpp +++ b/Source/nragev20/FileAccess.cpp @@ -307,6 +307,18 @@ bool ProcessKey( DWORD dwKey, DWORD dwSection, LPCSTR pszLine, LPTSTR pszFFDevic if (pController) pController->bPadDeadZone = atoi(pszLine); break; + case CHK_SENSITIVITY: + if (pController) + pController->bPadSensitivity = atoi(pszLine); + break; + case CHK_VIRTUALCORNERS: + if (pController) + pController->bVirtualCorners = atoi(pszLine); + break; + case CHK_N64RANGE: + if (pController) + pController->bN64Range = atoi(pszLine); + break; case CHK_MOUSESENSITIVITYX: if (pController) pController->wMouseSensitivityX = atoi(pszLine); @@ -1501,6 +1513,8 @@ void DumpControllerSettings(FILE * fFile, int i, bool bIsINI) fprintf(fFile, STRING_INI_RAPIDFIREENABLED "=%u\n", g_ivConfig->Controllers[i].bRapidFireEnabled); fprintf(fFile, STRING_INI_RAPIDFIRERATE "=%u\n", g_ivConfig->Controllers[i].bRapidFireRate); fprintf(fFile, STRING_INI_STICKRANGE "=%u\n", g_ivConfig->Controllers[i].bStickRange); + fprintf(fFile, STRING_INI_N64RANGE "=%u\n", g_ivConfig->Controllers[i].bN64Range); + fprintf(fFile, STRING_INI_VIRTUALCORNERS "=%u\n", g_ivConfig->Controllers[i].bVirtualCorners); fprintf(fFile, STRING_INI_MOUSEMOVEX "=%u\n", g_ivConfig->Controllers[i].bMouseMoveX); fprintf(fFile, STRING_INI_MOUSEMOVEY "=%u\n", g_ivConfig->Controllers[i].bMouseMoveY); fprintf(fFile, STRING_INI_AXISSET "=%u\n", g_ivConfig->Controllers[i].bAxisSet); @@ -1512,6 +1526,7 @@ void DumpControllerSettings(FILE * fFile, int i, bool bIsINI) fprintf(fFile, STRING_INI_RUMBLETYPE "=%u\n", g_ivConfig->Controllers[i].bRumbleTyp); fprintf(fFile, STRING_INI_RUMBLESTRENGTH "=%u\n", g_ivConfig->Controllers[i].bRumbleStrength); fprintf(fFile, STRING_INI_VISUALRUMBLE "=%u\n", g_ivConfig->Controllers[i].fVisualRumble); + fprintf(fFile, STRING_INI_SENSITIVITY "=%u\n", g_ivConfig->Controllers[i].bPadSensitivity); if (bIsINI) { diff --git a/Source/nragev20/FileAccess.h b/Source/nragev20/FileAccess.h index d1164bff7..f844294a5 100644 --- a/Source/nragev20/FileAccess.h +++ b/Source/nragev20/FileAccess.h @@ -101,6 +101,9 @@ unsigned long djbHash(const char *str); #define STRING_INI_KEYABSOLUTEX "KeyAbsoluteX" #define STRING_INI_KEYABSOLUTEY "KeyAbsoluteY" #define STRING_INI_PADDEADZONE "PadDeadZone" +#define STRING_INI_SENSITIVITY "PadSensitivity" +#define STRING_INI_N64RANGE "N64Range" +#define STRING_INI_VIRTUALCORNERS "VirtualCorners" #define STRING_INI_MOUSESENSX "MouseSensitivityX" #define STRING_INI_MOUSESENSY "MouseSensitivityY" #define STRING_INI_RUMBLETYPE "RumbleType" @@ -171,6 +174,9 @@ unsigned long djbHash(const char *str); #define CHK_KEYABSOLUTEX 958566277UL #define CHK_KEYABSOLUTEY 958566278UL #define CHK_PADDEADZONE 2913910084UL +#define CHK_SENSITIVITY 3759052741UL +#define CHK_VIRTUALCORNERS 4174758280UL +#define CHK_N64RANGE 868748074UL #define CHK_MOUSESENSITIVITYX 1513071697UL #define CHK_MOUSESENSITIVITYY 1513071698UL #define CHK_RUMBLETYPE 3440038446UL diff --git a/Source/nragev20/Interface.cpp b/Source/nragev20/Interface.cpp index 82b2175bf..190383c61 100644 --- a/Source/nragev20/Interface.cpp +++ b/Source/nragev20/Interface.cpp @@ -67,6 +67,10 @@ INTERFACEVALUES *g_ivConfig = NULL; // This structure holds all LPDIRECTINPUTDEVICE8 g_pConfigDevice = NULL; // One device handle for current force feedback device; between messages so it needs to be persistent LPDIRECTINPUTEFFECT g_pConfigEffect = NULL; // Force feedback effect handle HWND g_hMainDialog = NULL; // Handle of base dialog +short inputX = 0; +short inputY = 0; + +ANALOGWIN AnalogW = {0}; // Main dialog control handler BOOL CALLBACK MainDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) @@ -400,7 +404,6 @@ BOOL CALLBACK ControllerTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa // Call routine to show content (recursive call) ControllerTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); - return FALSE; // Don't give it focus case WM_NOTIFY: @@ -529,6 +532,7 @@ BOOL CALLBACK ControllerTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa pcController->fXInput = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); if( hTabControl ) DestroyWindow( hTabControl ); + TabCtrl_SetCurSel(GetDlgItem(hDlg, IDC_CONTROLLERTAB), TAB_CONTROLS); // select the right tab ! if( pcController->fXInput ) hTabControl = CreateDialog(g_hResourceDLL, MAKEINTRESOURCE(IDD_XCONTROLS), hDlg, (DLGPROC)XControlsTabProc); else @@ -591,6 +595,7 @@ BOOL CALLBACK ControllerTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa MoveWindow( hTabControl, rectWindow.left + (rectTab.left - rectMain.left), rectWindow.top + (rectTab.top - rectMain.top), rectWindow.right - rectWindow.left, rectWindow.bottom - rectWindow.top, FALSE ); ShowWindow( hTabControl, SW_SHOW ); + TabCtrl_SetCurSel(GetDlgItem(hDlg, IDC_CONTROLLERTAB), TAB_CONTROLS); // select the right tab ! } // Call child dialog(s) to update their content as well @@ -619,12 +624,6 @@ BOOL CALLBACK ControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara switch(uMsg) { case WM_INITDIALOG: - // SetTicks on TrackBar - hDlgItem = GetDlgItem( hDlg, IDC_CTRRANGE ); - SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 100 )); - SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM) 10, 0 ); - SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); - // SetTicks on RapidFire Bar hDlgItem = GetDlgItem( hDlg, IDC_RAPIDFIRERATE ); SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 32 )); @@ -640,10 +639,6 @@ BOOL CALLBACK ControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara switch( LOWORD(wParam) ) { - case IDC_N64RANGE: - g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRealN64Range = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); - return TRUE; - case IDC_RAPIDFIREENABLE: g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireEnabled = (IsDlgButtonChecked( hDlg, LOWORD(wParam)) == BST_CHECKED); return TRUE; @@ -760,14 +755,6 @@ BOOL CALLBACK ControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case WM_VSCROLL: switch ( GetWindowLong( (HWND)lParam, GWL_ID ) ) { - case IDC_CTRRANGE: - TCHAR tszText[DEFAULT_BUFFER]; - - LoadString( g_hResourceDLL, IDS_C_RANGE, tszText, DEFAULT_BUFFER ); - g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); - wsprintf( szBuffer, tszText, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange ); - SendMessage( GetDlgItem( hDlg, IDT_RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); - return TRUE; case IDC_RAPIDFIRERATE: g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireRate = 33 - (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); return TRUE; @@ -784,16 +771,11 @@ BOOL CALLBACK ControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara if( wParam == 0 ) { - CheckDlgButton( hDlg, IDC_N64RANGE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRealN64Range ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_N64REALRANGE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].fRealN64Range ? BST_CHECKED : BST_UNCHECKED ); CheckDlgButton( hDlg, IDC_RAPIDFIREENABLE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireEnabled ? BST_CHECKED : BST_UNCHECKED ); CheckDlgButton( hDlg, IDC_CONFIG1, ( g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet == 0 ) ? BST_CHECKED : BST_UNCHECKED ); CheckDlgButton( hDlg, IDC_CONFIG2, ( g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet == 1 ) ? BST_CHECKED : BST_UNCHECKED ); CheckDlgButton( hDlg, IDC_CONFIG3, ( g_ivConfig->Controllers[g_ivConfig->ChosenTab].bAxisSet == 2 ) ? BST_CHECKED : BST_UNCHECKED ); - - SendMessage( GetDlgItem( hDlg, IDC_CTRRANGE ), TBM_SETPOS, TRUE, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange ); - LoadString( g_hResourceDLL, IDS_C_RANGE, szTemp, 40 ); - wsprintf( szBuffer, szTemp, g_ivConfig->Controllers[g_ivConfig->ChosenTab].bStickRange ); - SendMessage( GetDlgItem( hDlg, IDT_RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); SendMessage( GetDlgItem( hDlg, IDC_RAPIDFIRERATE ), TBM_SETPOS, TRUE, 33 - g_ivConfig->Controllers[g_ivConfig->ChosenTab].bRapidFireRate ); i = 0; @@ -857,6 +839,18 @@ BOOL CALLBACK XControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_COMMAND: switch( LOWORD( wParam )) { + case IDC_XC_INVERT_LX: + gController->stAnalogs.iInvertLX = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + case IDC_XC_INVERT_LY: + gController->stAnalogs.iInvertLY = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + case IDC_XC_INVERT_RX: + gController->stAnalogs.iInvertRX = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; + case IDC_XC_INVERT_RY: + gController->stAnalogs.iInvertRY = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; case IDC_XC_USE: StoreXInputControllerKeys( hDlg, gController ); { @@ -870,6 +864,7 @@ BOOL CALLBACK XControlsTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPar return TRUE; } return FALSE; + default: return FALSE; } @@ -884,12 +879,16 @@ BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam switch(uMsg) { + case WM_INITDIALOG: + { + + SetTimer( hDlg, 999, 33, NULL ); // TrackBars hDlgItem = GetDlgItem( hDlg, IDC_DEADZONE ); - SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 100 )); + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 0, 50 )); SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM) 10, 0 ); SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); @@ -907,11 +906,242 @@ BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam for( i = 0; i < (sizeof(sTics) / sizeof(short)); ++i ) SendMessage( hDlgItem, TBM_SETTIC, 0, sTics[i] ); } - // TrackBars End + hDlgItem = GetDlgItem( hDlg, IDC_CTRRANGE ); + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG( 10, 100 )); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM) 10, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM) 0, 1 ); + + hDlgItem = GetDlgItem( hDlg, IDC_SENSITIVITY ); + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(1, 100) ); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM)10, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM)0, 1 ); + + hDlgItem = GetDlgItem( hDlg, IDC_N64RANGE ); + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(10, 127) ); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM)10, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM)0, 1 ); + + hDlgItem = GetDlgItem( hDlg, IDC_VIRTUALCORNERS ); + SendMessage( hDlgItem, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, 45) ); + SendMessage( hDlgItem, TBM_SETTICFREQ, (WPARAM)10, 0 ); + SendMessage( hDlgItem, TBM_SETPAGESIZE, (WPARAM)0, 1 ); + // TrackBars End DevicesTabProc( hDlg, WM_USER_UPDATE, 0, 0 ); // Setting values return FALSE; // Don't give it focus + } + case WM_SIZE: + { + RECT rect; + GetClientRect(hDlg, &rect); + int width = rect.right - rect.left; + int height = rect.bottom - rect.top; + RECT rcLast; + HWND hLastCtrl = GetDlgItem(hDlg, IDC_VIRTUALCORNERS); + if (hLastCtrl && GetWindowRect(hLastCtrl, &rcLast)) + { + MapWindowPoints(NULL, hDlg, (LPPOINT)&rcLast, 2); + AnalogW.Y = rcLast.bottom + 5; + AnalogW.SIZE_W = height - rcLast.bottom - 10; + AnalogW.SIZE_H = height - rcLast.bottom - 10; + AnalogW.X = (width * 0.75) - (AnalogW.SIZE_W) / 2; + } + AnalogW.CENTER_X = AnalogW.SIZE_W / 2.0f; + AnalogW.CENTER_Y = AnalogW.SIZE_H / 2.0f; + AnalogW.RADIUS = AnalogW.SIZE_W * 0.49f; + AnalogW.TRIANGLE_HEIGHT = 3.0f; + + return FALSE; + } + + case WM_TIMER: + + if (wParam == 999) + { + + if (pcController->fXInput && pcController->fPlugged){ + XINPUT_STATE state; + ZeroMemory(&state, sizeof(XINPUT_STATE)); + DWORD result = XInputGetState(pcController->xiController.nControl, &state); + if (result == ERROR_SUCCESS) { + if (pcController->xiController.stAnalogs.iLXAxis == 0x4000){ + inputX = state.Gamepad.sThumbLX; + inputY = state.Gamepad.sThumbLY; + }else{ + inputX = state.Gamepad.sThumbRX; + inputY = state.Gamepad.sThumbRY; + } + } + + } else { + if(pcController->fPlugged) + { + LPDEVICE lpDevice = nullptr; + for (int i = 0; i < 14 + PF_AXESETS * 4; i++) + if (pcController->aButton[i].bBtnType == DT_JOYAXE) + lpDevice = pcController->aButton[i].parentDevice; + + if (lpDevice != nullptr) { + HRESULT hr = lpDevice->didHandle->Poll(); + if (FAILED(hr)) { + hr = lpDevice->didHandle->Acquire(); + } + if (SUCCEEDED(hr)) { + hr = lpDevice->didHandle->GetDeviceState(sizeof(DIJOYSTATE), &lpDevice->stateAs.joyState); + if (hr == DI_OK) { + inputX = lpDevice->stateAs.joyState.lX; + inputY = -lpDevice->stateAs.joyState.lY; + } + } + } + } + } + + RECT rectToInvalidate = {AnalogW.X, AnalogW.Y, AnalogW.X + AnalogW.SIZE_W, AnalogW.Y + AnalogW.SIZE_H}; + InvalidateRect(hDlg, &rectToInvalidate, TRUE); + + } + break; + + case WM_PAINT: + { + const float OCTAGON_RADIUS = AnalogW.RADIUS * (pcController->bStickRange / 100.0f); + const float ANGLE_THRESHOLD = pcController->bVirtualCorners / 100.0f; + + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hDlg, &ps); + HDC hdcMem = CreateCompatibleDC(hdc); + HBITMAP hbmMem = CreateCompatibleBitmap(hdc, AnalogW.SIZE_W, AnalogW.SIZE_H); + HBITMAP hbmOrigin = (HBITMAP)SelectObject(hdcMem, hbmMem); + + HPEN hOldPen = nullptr; + HBRUSH hOldBrush = nullptr; + + HBRUSH hBrushBackground = CreateSolidBrush(RGB(240, 240, 240)); + RECT rect = {0, 0, AnalogW.SIZE_W, AnalogW.SIZE_H}; + FillRect(hdcMem, &rect, hBrushBackground); + DeleteObject(hBrushBackground); + + // Gamepad Range + HPEN outhPen = CreatePen(PS_SOLID, 1, RGB(55, 55, 55)); + HBRUSH outhBrush = (HBRUSH)GetStockObject(NULL_BRUSH); + hOldPen = (HPEN)SelectObject(hdcMem, outhPen); + hOldBrush = (HBRUSH)SelectObject(hdcMem, outhBrush); + RoundRect(hdcMem, AnalogW.CENTER_X - AnalogW.RADIUS, AnalogW.CENTER_Y - AnalogW.RADIUS, AnalogW.CENTER_X + AnalogW.RADIUS, AnalogW.CENTER_Y + AnalogW.RADIUS, AnalogW.RADIUS, AnalogW.RADIUS); + SelectObject(hdcMem, hOldPen); + SelectObject(hdcMem, hOldBrush); + DeleteObject(outhPen); + + // Octagon + if (pcController->fRealN64Range) + { + HBRUSH hGrayBrush = CreateSolidBrush(RGB(215, 215, 215)); + hOldBrush = (HBRUSH)SelectObject(hdcMem, hGrayBrush); + + POINT octagon[8]; + for (int i = 0; i < 8; ++i) { + double angle = i * OCTAGON_ANGLE; + double cosA = cos(angle); + double sinA = sin(angle); + octagon[i].x = AnalogW.CENTER_X + OCTAGON_RADIUS * cosA; + octagon[i].y = AnalogW.CENTER_Y - OCTAGON_RADIUS * sinA; + } + + Polygon(hdcMem, octagon, 8); + SelectObject(hdcMem, hOldBrush); + DeleteObject(hGrayBrush); + + // Virtual Corners + HBRUSH hTriangleBrush = CreateSolidBrush(RGB(255, 100, 0)); + hOldBrush = (HBRUSH)SelectObject(hdcMem, hTriangleBrush); + for (int i = 0; i < 8; ++i) { + double angle = i * OCTAGON_ANGLE; + double cosA = cos(angle); + double sinA = sin(angle); + double cosM = cos(angle - ANGLE_THRESHOLD); + double sinM = sin(angle - ANGLE_THRESHOLD); + double cosP = cos(angle + ANGLE_THRESHOLD); + double sinP = sin(angle + ANGLE_THRESHOLD); + + POINT triangle[3] = { + {AnalogW.CENTER_X + OCTAGON_RADIUS * cosA, AnalogW.CENTER_Y - OCTAGON_RADIUS * sinA}, + {AnalogW.CENTER_X + (OCTAGON_RADIUS - AnalogW.TRIANGLE_HEIGHT) * cosM, AnalogW.CENTER_Y - (OCTAGON_RADIUS - AnalogW.TRIANGLE_HEIGHT) * sinM}, + {AnalogW.CENTER_X + (OCTAGON_RADIUS - AnalogW.TRIANGLE_HEIGHT) * cosP, AnalogW.CENTER_Y - (OCTAGON_RADIUS - AnalogW.TRIANGLE_HEIGHT) * sinP} + }; + Polygon(hdcMem, triangle, 3); + } + SelectObject(hdcMem, hOldBrush); + DeleteObject(hTriangleBrush); + } + + // DeadZone + float DEADZONE_RADIUS = pcController->bPadDeadZone * AnalogW.RADIUS / 100.0f; + HBRUSH hBrushHatched = CreateHatchBrush(HS_BDIAGONAL, RGB(50, 50, 50)); + hOldBrush = (HBRUSH)SelectObject(hdcMem, hBrushHatched); + HPEN deadZonePen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + hOldPen = (HPEN)SelectObject(hdcMem, deadZonePen); + Ellipse(hdcMem, AnalogW.CENTER_X - DEADZONE_RADIUS, AnalogW.CENTER_Y - DEADZONE_RADIUS, AnalogW.CENTER_X + DEADZONE_RADIUS, AnalogW.CENTER_Y + DEADZONE_RADIUS); + + SelectObject(hdcMem, hOldBrush); + SelectObject(hdcMem, hOldPen); + DeleteObject(hBrushHatched); + DeleteObject(deadZonePen); + + //Stick Position + float outputX = 0.0f, outputY = 0.0f; + processStickInput(pcController, inputX, inputY, outputX, outputY); + POINT position = {AnalogW.CENTER_X, AnalogW.CENTER_Y}; + POINT real_pos = {AnalogW.CENTER_X, AnalogW.CENTER_Y}; + position.x = AnalogW.CENTER_X + (outputX / (float)XC_ANALOG_MAX) * OCTAGON_RADIUS; + position.y = AnalogW.CENTER_Y - (outputY / (float)XC_ANALOG_MAX) * OCTAGON_RADIUS; + + if (!pcController->xiController.stAnalogs.iInvertLX) + real_pos.x = AnalogW.CENTER_X + (inputX / (float)XC_ANALOG_MAX) * AnalogW.RADIUS; + else + real_pos.x = AnalogW.CENTER_X + (-inputX / (float)XC_ANALOG_MAX) * AnalogW.RADIUS; + + if (!pcController->xiController.stAnalogs.iInvertLY) + real_pos.y = AnalogW.CENTER_Y - (inputY / (float)XC_ANALOG_MAX) * AnalogW.RADIUS; + else + real_pos.y = AnalogW.CENTER_Y - (-inputY / (float)XC_ANALOG_MAX) * AnalogW.RADIUS; + + // Points + HBRUSH pointBrush = CreateSolidBrush(RGB(0, 255, 0)); + hOldBrush = (HBRUSH)SelectObject(hdcMem, pointBrush); + Ellipse(hdcMem, position.x - 3, position.y - 3, position.x + 3, position.y + 3); + SelectObject(hdcMem, hOldBrush); + DeleteObject(pointBrush); + + HBRUSH pointBrush2 = CreateSolidBrush(RGB(0, 0, 0)); + hOldBrush = (HBRUSH)SelectObject(hdcMem, pointBrush2); + Ellipse(hdcMem, real_pos.x - 3, real_pos.y - 3, real_pos.x + 3, real_pos.y + 3); + SelectObject(hdcMem, hOldBrush); + DeleteObject(pointBrush2); + + BitBlt(hdc, AnalogW.X, AnalogW.Y, AnalogW.SIZE_W, AnalogW.SIZE_H, hdcMem, 0, 0, SRCCOPY); + + SelectObject(hdcMem, hbmOrigin); + DeleteObject(hbmMem); + DeleteDC(hdcMem); + EndPaint(hDlg, &ps); + return 0; + } + + case WM_ERASEBKGND: + { + HDC hdc = (HDC)wParam; + RECT rc; + GetClientRect(hDlg, &rc); + HBRUSH hbr = CreateSolidBrush(RGB(240, 240, 240)); + FillRect(hdc, &rc, hbr); + DeleteObject(hbr); + return 1; + } + + case WM_DESTROY: + KillTimer( hDlg, TIMER_BUTTON ); + return 0; case WM_COMMAND: hDlgItem = GetDlgItem( hDlg, LOWORD(wParam) ); @@ -950,6 +1180,9 @@ BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam case IDC_ACCELERATEY: pcController->fKeyAbsoluteY = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); return TRUE; + case IDC_N64REALRANGE: + pcController->fRealN64Range = ( IsDlgButtonChecked( hDlg, LOWORD(wParam) ) == BST_CHECKED ); + return TRUE; default: return FALSE; @@ -980,11 +1213,41 @@ BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam wsprintf( szBuffer, szTemp, pcController->bPadDeadZone ); SendMessage( GetDlgItem( hDlg, IDT_DEADZONE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); return TRUE; + + case IDC_SENSITIVITY: + pcController->bPadSensitivity = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_SENSITIVITY, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bPadSensitivity ); + SendMessage( GetDlgItem(hDlg, IDT_SENSITIVITY), WM_SETTEXT, 0, (LPARAM)szBuffer ); + return TRUE; + + case IDC_CTRRANGE: + pcController->bStickRange = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_C_RANGE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bStickRange ); + SendMessage( GetDlgItem( hDlg, IDT_RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + + case IDC_N64RANGE: + pcController->bN64Range = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_N64RANGE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bN64Range ); + SendMessage( GetDlgItem( hDlg, IDT_N64RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + + case IDC_VIRTUALCORNERS: + pcController->bVirtualCorners = (BYTE)SendMessage( (HWND)lParam, TBM_GETPOS, 0, 0 ); + LoadString( g_hResourceDLL, IDS_VIRTUALCORNERS, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bVirtualCorners ); + SendMessage( GetDlgItem( hDlg, IDT_VIRTUALCORNERS ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + return TRUE; + default: return FALSE; } case WM_USER_UPDATE: + if( pcController->bMouseMoveX == MM_DEAD ) CheckDlgButton( hDlg, IDC_DEADPANMOUSEX, BST_CHECKED ); else @@ -1017,6 +1280,7 @@ BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam CheckDlgButton( hDlg, IDC_ACCELERATEX, pcController->fKeyAbsoluteX ? BST_CHECKED : BST_UNCHECKED ); CheckDlgButton( hDlg, IDC_ACCELERATEY, pcController->fKeyAbsoluteY ? BST_CHECKED : BST_UNCHECKED ); + CheckDlgButton( hDlg, IDC_N64REALRANGE, pcController->fRealN64Range ? BST_CHECKED : BST_UNCHECKED ); // TrackBars SendMessage( GetDlgItem( hDlg, IDC_DEADZONE ), TBM_SETPOS, TRUE, pcController->bPadDeadZone ); @@ -1033,6 +1297,26 @@ BOOL CALLBACK DevicesTabProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam LoadString( g_hResourceDLL, IDS_D_MSY, szTemp, DEFAULT_BUFFER ); wsprintf( szBuffer, szTemp, pcController->wMouseSensitivityY ); SendMessage( GetDlgItem( hDlg, IDT_MSSENSITIVITY_Y ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + + SendMessage( GetDlgItem( hDlg, IDC_SENSITIVITY), TBM_SETPOS, TRUE, pcController->bPadSensitivity ); + LoadString( g_hResourceDLL, IDS_SENSITIVITY, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bPadSensitivity ); + SendMessage( GetDlgItem( hDlg, IDT_SENSITIVITY), WM_SETTEXT, 0, (LPARAM)szBuffer ); + + SendMessage( GetDlgItem( hDlg, IDC_CTRRANGE ), TBM_SETPOS, TRUE, pcController->bStickRange ); + LoadString( g_hResourceDLL, IDS_C_RANGE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bStickRange ); + SendMessage( GetDlgItem( hDlg, IDT_RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + + SendMessage( GetDlgItem( hDlg, IDC_N64RANGE ), TBM_SETPOS, TRUE, pcController->bN64Range ); + LoadString( g_hResourceDLL, IDS_N64RANGE, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bN64Range ); + SendMessage( GetDlgItem( hDlg, IDT_N64RANGE ), WM_SETTEXT , 0, (LPARAM)szBuffer ); + + SendMessage( GetDlgItem( hDlg, IDC_VIRTUALCORNERS ), TBM_SETPOS, TRUE, pcController->bVirtualCorners ); + LoadString( g_hResourceDLL, IDS_VIRTUALCORNERS, szTemp, DEFAULT_BUFFER ); + wsprintf( szBuffer, szTemp, pcController->bVirtualCorners ); + SendMessage( GetDlgItem( hDlg, IDT_VIRTUALCORNERS ), WM_SETTEXT , 0, (LPARAM)szBuffer ); // TrackBars End return TRUE; @@ -3331,7 +3615,7 @@ BOOL CALLBACK FoldersDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPa // This function is confusing, but not much I can do to fix it now. I'm sorry. (comment by rabid) bool GetButtonID( LPDWORD ButtonID, const BYTE bIndex, const BYTE bButtonSet ) { - // TODO: Check this + // TODO: Check this // TODO: make these constant, read from a resource or a define, or something...I don't know LPDWORD ButtonTable = NULL; int nEntries = 0; @@ -3809,7 +4093,9 @@ void SetControllerDefaults( LPCONTROLLER pcController ) pcController->bRapidFireEnabled = false; pcController->bRapidFireRate = 3; // Set default rapid fire rate here pcController->bStickRange = DEFAULT_STICKRANGE; + pcController->bN64Range = DEFAULT_N64RANGE; pcController->bPadDeadZone = DEFAULT_DEADZONE; + pcController->bPadSensitivity = DEFAULT_SENSITIVITY; pcController->bRumbleTyp = DEFAULT_RUMBLETYP; pcController->bRumbleStrength = DEFAULT_RUMBLESTRENGTH; pcController->wMouseSensitivityX = DEFAULT_MOUSESENSIVITY; diff --git a/Source/nragev20/NRagePluginV2.cpp b/Source/nragev20/NRagePluginV2.cpp index 99e214d54..d2a6cf11f 100644 --- a/Source/nragev20/NRagePluginV2.cpp +++ b/Source/nragev20/NRagePluginV2.cpp @@ -1305,3 +1305,95 @@ DWORD WINAPI DelayedShortcut(LPVOID lpParam) P_free(lpParam); return 0; } + +void OctagonProj(float& outputX, float& outputY, float CARDINAL_MAX, float ANGLE_THRESHOLD) +{ + constexpr float DIAG_RATIO = 2.448f; //CARDINAL_MAX * 0.71f / (CARDINAL_MAX - CARDINAL_MAX * 0.71f); max 71% diagonal + const float C = CARDINAL_MAX * DIAG_RATIO; + + float ax = fabs(outputX); + float ay = fabs(outputY); + float r = hypotf(ax, ay); + + if (r > EPSILON) + { + float theta = atan2f(ay, ax); + float r_max = (theta <= OCTAGON_ANGLE) + ? (C / (sinf(theta) + DIAG_RATIO * cosf(theta))) + : (C / (cosf(theta) + DIAG_RATIO * sinf(theta))); + + if (r >= r_max) + { + float new_r = r_max; + float new_ax = new_r * cosf(theta); + float new_ay = new_r * sinf(theta); + + outputX = (outputX < 0) ? -new_ax : new_ax; + outputY = (outputY < 0) ? -new_ay : new_ay; + } + + if( ANGLE_THRESHOLD > 0) + { + float angles[8] = { 0.0f, OCTAGON_ANGLE, 2 * OCTAGON_ANGLE, 3 * OCTAGON_ANGLE, 4 * OCTAGON_ANGLE, 5 * OCTAGON_ANGLE, 6 * OCTAGON_ANGLE, 7 * OCTAGON_ANGLE }; + if (r >= r_max) + { + for (int i = 0; i < 8; ++i) + { + float angle = angles[i]; + float angleLowerBound = angle - ANGLE_THRESHOLD; + float angleUpperBound = angle + ANGLE_THRESHOLD; + + // Check if we need to lock + if (theta >= angleLowerBound && theta < angleUpperBound) + { + outputX = (outputX < 0) ? -CARDINAL_MAX * cosf(angle) : CARDINAL_MAX * cosf(angle); + outputY = (outputY < 0) ? -CARDINAL_MAX * sinf(angle) : CARDINAL_MAX * sinf(angle); + break; + } + } + } + } + } +} + + +void processStickInput(CONTROLLER* pcController, short inputX, short inputY, float& outputX, float& outputY) +{ + float DEADZONE = (XC_ANALOG_MAX * (pcController->bPadDeadZone / 100.f)); + float ANGLE_THRESHOLD = pcController->bVirtualCorners / 100.f; + float stickRange = pcController->bStickRange / 100.f; + float magnitude = hypotf(static_cast(inputX), static_cast(inputY)); + float SENSITIVITY = ((1.5f - 0.1f) * (pcController->bPadSensitivity - 1) / (100 - 1)) + 0.1f; + + if (magnitude == 0.0f || magnitude <= DEADZONE) + { + outputX = 0.0f; + outputY = 0.0f; + return; + } + + float adjustedMagnitude = magnitude - DEADZONE; + float normalizedMagnitude = adjustedMagnitude / (XC_ANALOG_MAX - DEADZONE); + + if (normalizedMagnitude < stickRange) + normalizedMagnitude = normalizedMagnitude / stickRange; + else + normalizedMagnitude = 1.0f; + + normalizedMagnitude *= 1.0f + (SENSITIVITY - 1.0f) * (1.0f - normalizedMagnitude); + + //normalizedMagnitude = fmaxf(0.0f, fminf(1.0f, normalizedMagnitude * (1.0f + (SENSITIVITY - 1.0f) * (1.0f - normalizedMagnitude)))); + + outputX = (inputX / magnitude) * normalizedMagnitude * XC_ANALOG_MAX; + outputY = (inputY / magnitude) * normalizedMagnitude * XC_ANALOG_MAX; + + if (pcController->fRealN64Range) { + OctagonProj(outputX, outputY, XC_ANALOG_MAX, ANGLE_THRESHOLD); + } + + if (pcController->xiController.stAnalogs.iInvertLX) + outputX = -outputX; + if (pcController->xiController.stAnalogs.iInvertLY) + outputY = -outputY; +} + diff --git a/Source/nragev20/NRagePluginV2.h b/Source/nragev20/NRagePluginV2.h index cffc1bcda..3e9d2680f 100644 --- a/Source/nragev20/NRagePluginV2.h +++ b/Source/nragev20/NRagePluginV2.h @@ -36,8 +36,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Maximum number of modifiers #define MAX_MODIFIERS 256 -#define DEFAULT_STICKRANGE 66 +#define DEFAULT_STICKRANGE 100 +#define DEFAULT_N64RANGE 88 #define DEFAULT_DEADZONE 5 +#define DEFAULT_SENSITIVITY 50 #define DEFAULT_RUMBLETYP RUMBLE_EFF1 #define DEFAULT_RUMBLESTRENGTH 80 #define DEFAULT_MOUSESENSIVITY 100 @@ -153,13 +155,13 @@ typedef struct _CONTROLLER // An N64 controller unsigned bBackgroundInput; // Allow input while main window isn't focused? - unsigned XcheckTime; // Checks for newly connected gamepads timer + unsigned XcheckTime; // Checks for newly connected gamepads timer BYTE bRumbleTyp; // What type of rumble effect? None, constant, ramp, or direct? GUID guidFFDevice; // GUID of the device that rumble gets sent to - BYTE bStickRange; // Our "range modifier" + BYTE bStickRange; // Stick Range long wAxeBuffer[4]; // Makes pseudo-relative movement possible through keyboard or buttons and also acts as a mouse buffer @@ -167,6 +169,9 @@ typedef struct _CONTROLLER // An N64 controller WORD wMouseSensitivityY; BYTE bPadDeadZone; // Our manual dead zone, set per N64 controller BYTE bRumbleStrength; // Set per N64 controller + BYTE bPadSensitivity; // Analog Sensitivity + BYTE bN64Range; // N64 Stick Range + BYTE bVirtualCorners; // Octagon Virtual Corners unsigned short nModifiers; // Number of modifiers bool bRapidFireEnabled; @@ -391,4 +396,23 @@ void freeModifiers(CONTROLLER *pcController); void CheckShortcuts(); bool ErrorMessage(UINT uID, DWORD dwError, bool fUserChoose); +// Analog Input Management +constexpr float PI = 3.14159265358979323846; +constexpr float EPSILON = 1e-6f; +constexpr float OCTAGON_ANGLE = PI / 4.0; + +typedef struct _ANALOGWIN { + int SIZE_W; + int SIZE_H; + int X; + int Y; + int CENTER_X; + int CENTER_Y; + float RADIUS; + float TRIANGLE_HEIGHT; +} ANALOGWIN; + +void OctagonProj(float& outputX, float& outputY, float CARDINAL_MAX, float ANGLE_THRESHOLD); +void processStickInput(CONTROLLER* pcController, short inputX, short inputY, float& outputX, float& outputY); + #endif diff --git a/Source/nragev20/NRagePluginV2.rc b/Source/nragev20/NRagePluginV2.rc index 691d4d86c..655c05c74 100644 --- a/Source/nragev20/NRagePluginV2.rc +++ b/Source/nragev20/NRagePluginV2.rc @@ -31,7 +31,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN IDD_MAINCFGDIALOG, DIALOG BEGIN @@ -123,10 +123,8 @@ BEGIN BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 363 - VERTGUIDE, 16 - VERTGUIDE, 169 TOPMARGIN, 7 - BOTTOMMARGIN, 173 + BOTTOMMARGIN, 187 END IDD_MOD_MOVE, DIALOG @@ -145,9 +143,9 @@ BEGIN "IDD_MAINCFGDIALOG$(_DEBUG)", DIALOG BEGIN LEFTMARGIN, 6 - RIGHTMARGIN, 389 + RIGHTMARGIN, 390 TOPMARGIN, 7 - BOTTOMMARGIN, 344 + BOTTOMMARGIN, 312 END END #endif // APSTUDIO_INVOKED @@ -279,19 +277,16 @@ BEGIN CTEXT "PLACEHOLDER",IDT_CRIGHT,219,43,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE CTEXT "PLACEHOLDER",IDT_CDOWN,219,54,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE GROUPBOX "Analog Stick",IDC_STATIC,188,70,175,97 - CTEXT "R PLACEHOLDER",IDT_RANGE,194,81,110,8 - CONTROL "PLACEHOLDER",IDC_CTRRANGE,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,194,89,113,11 - CONTROL "Real N64 Range",IDC_N64RANGE,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_GROUP | WS_TABSTOP,312,82,44,19 - CONTROL "Config 1",IDC_CONFIG1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,194,103,42,10 - CONTROL "Config 2",IDC_CONFIG2,"Button",BS_AUTORADIOBUTTON,254,103,42,10 - PUSHBUTTON "Up",IDC_AUP,194,119,24,10,BS_NOTIFY | WS_GROUP - PUSHBUTTON "Left",IDC_ALEFT,194,130,24,10,BS_NOTIFY - PUSHBUTTON "Right",IDC_ARIGHT,194,141,24,10,BS_NOTIFY - PUSHBUTTON "Down",IDC_ADOWN,194,152,24,10,BS_NOTIFY - CTEXT "PLACEHOLDER",IDT_AUP,219,119,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE - CTEXT "PLACEHOLDER",IDT_ALEFT,219,130,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE - CTEXT "PLACEHOLDER",IDT_ARIGHT,219,141,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE - CTEXT "PLACEHOLDER",IDT_ADOWN,219,152,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + CONTROL "Config 1",IDC_CONFIG1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,232,79,40,10 + CONTROL "Config 2",IDC_CONFIG2,"Button",BS_AUTORADIOBUTTON,283,79,40,10 + PUSHBUTTON "Up",IDC_AUP,194,92,24,10,BS_NOTIFY | WS_GROUP + PUSHBUTTON "Left",IDC_ALEFT,194,103,24,10,BS_NOTIFY + PUSHBUTTON "Right",IDC_ARIGHT,194,114,24,10,BS_NOTIFY + PUSHBUTTON "Down",IDC_ADOWN,194,125,24,10,BS_NOTIFY + CTEXT "PLACEHOLDER",IDT_AUP,219,92,137,10,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ALEFT,219,103,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ARIGHT,219,114,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE + CTEXT "PLACEHOLDER",IDT_ADOWN,219,125,137,10,SS_CENTERIMAGE | NOT WS_GROUP,WS_EX_STATICEDGE END IDD_CONTROLLERPAK DIALOGEX 0, 0, 370, 180 @@ -361,7 +356,7 @@ BEGIN LTEXT "If you want to use regular DirectInput force-feedback, choose RumblePak instead.",IDC_STATIC,95,90,165,22 END -IDD_DEVICES DIALOGEX 0, 0, 370, 180 +IDD_DEVICES DIALOGEX 0, 0, 370, 230 STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD FONT 8, "MS Shell Dlg", 400, 0, 0x0 BEGIN @@ -379,9 +374,19 @@ BEGIN GROUPBOX "Keyboard",IDC_STATIC,7,96,171,27 CONTROL "Absolute X",IDC_ACCELERATEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,107,50,10 CONTROL "Absolute Y",IDC_ACCELERATEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,92,107,50,10 - GROUPBOX "GamePad",IDC_STATIC,7,124,171,38 - CTEXT "Deadzone PLACEHOLDER",IDT_DEADZONE,16,134,153,8 - CONTROL "PLACEHOLDER",IDC_DEADZONE,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,16,144,153,11 + GROUPBOX "N64 Analog",IDC_STATIC,7,127,170,52 + CTEXT "R PLACEHOLDER",IDT_N64RANGE,17,140,153,8 + CONTROL "PLACEHOLDER",IDC_N64RANGE,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,15,151,153,11 + CONTROL "Real Octa N64 Range",IDC_N64REALRANGE,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,17,160,100,19 + GROUPBOX "Gamepad Analog",IDC_STATIC,190,7,171,172 + CTEXT "Deadzone PLACEHOLDER",IDT_DEADZONE,199,17,153,8 + CONTROL "PLACEHOLDER",IDC_DEADZONE,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,199,27,153,11 + CTEXT "Sensitivity PLACEHOLDER",IDT_SENSITIVITY,199,37,153,8 + CONTROL "PLACEHOLDER",IDC_SENSITIVITY,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,199,47,153,11 + CTEXT "R PLACEHOLDER",IDT_RANGE,199,57,153,8 + CONTROL "PLACEHOLDER",IDC_CTRRANGE,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,199,67,153,11 + CTEXT "R PLACEHOLDER",IDT_VIRTUALCORNERS,199,77,153,8 + CONTROL "PLACEHOLDER",IDC_VIRTUALCORNERS,"msctls_trackbar32",TBS_AUTOTICKS | WS_GROUP | WS_TABSTOP,199,87,153,11 END IDD_PAK_TEXT DIALOGEX 0, 0, 356, 148 @@ -573,12 +578,12 @@ IDR_SHORTCUTS_DEFAULT SHORTCUT "configs/Shortcuts.sc" // TEXTINCLUDE // -1 TEXTINCLUDE +1 TEXTINCLUDE BEGIN "resource.h\0" END -2 TEXTINCLUDE +2 TEXTINCLUDE BEGIN "#include ""WinResrc.h""\r\n" "\r\n" @@ -589,7 +594,7 @@ BEGIN "\0" END -3 TEXTINCLUDE +3 TEXTINCLUDE BEGIN "\r\n" "\0" @@ -603,14 +608,14 @@ END // String Table // -STRINGTABLE +STRINGTABLE BEGIN IDS_ERR_DINOTFOUND "dinput8.dll could not be found.\nPlease reinstall the latest version of DirectX." IDS_ERR_DICREATE "Could not create DirectInput object." IDS_DLG_MPCHOOSE "Choose a MemPak or type a new name to create one." END -STRINGTABLE +STRINGTABLE BEGIN IDS_ERR_MPREAD "Couldn't read MemPak." IDS_ERR_GBROM "Can't open GB ROM file!" @@ -630,10 +635,12 @@ BEGIN IDS_ERR_PROFREAD "Couldn't read profile." END -STRINGTABLE +STRINGTABLE BEGIN IDS_C_POLLING "...Awaiting Input %i..." - IDS_C_RANGE "Range: %i%%" + IDS_C_RANGE "Stick Range: %i%%" + IDS_N64RANGE "N64 Range: %i%" + IDS_VIRTUALCORNERS "Virtual Corners: %i%%" IDS_D_MSX "Mouse Sensitivity X: %i%%" IDS_D_MSY "Mouse Sensitivity Y: %i%%" IDS_D_DEADZONE "Deadzone: %i%%" @@ -650,7 +657,12 @@ BEGIN IDS_M_MACRO "Macro" END -STRINGTABLE +STRINGTABLE +BEGIN + IDS_SENSITIVITY "Sensitivity: %i%%" +END + +STRINGTABLE BEGIN IDS_M_CONFIG "Configuration" IDS_M_ASSIGNED "Assigned to" @@ -670,7 +682,7 @@ BEGIN IDS_P_ADAPTOID_NORAW "The AdaptoidPak needs RawMode to be activated." END -STRINGTABLE +STRINGTABLE BEGIN IDS_P_NONE_RAWNORAW "No Pak inserted." IDS_P_MEM_NOCHANGE "Can't change dir while running." @@ -690,7 +702,7 @@ BEGIN IDS_DLG_SHORTCUTRESTORE "The shortcut configuration will be restored.\nAre you sure?" END -STRINGTABLE +STRINGTABLE BEGIN IDS_DLG_SHORTCUTRESTORE_TITLE "Restore default" IDS_C_GAMEPAD "Gamepad: " @@ -710,7 +722,7 @@ BEGIN IDS_DLG_ABOUT "Help us translate N-Rage Input V2 into your language!" END -STRINGTABLE +STRINGTABLE BEGIN IDS_DLG_ABOUT_TITLE "About N-Rage Input V2" IDS_ERR_NOINIT "Plugin didn't get initialized!" @@ -727,11 +739,11 @@ BEGIN IDS_ERR_MEM_NOSPEC "No MemPak specified; please configure plugin." IDS_DLG_MEM_READONLY "Mempak %s opened with read-only access.\nAfter exiting the game, the MemPak will NOT be saved." IDS_ERR_MEMOPEN "Unable to read or create MemPak file %s ; please configure plugin." - IDS_DLG_MEM_BADADDRESSCRC + IDS_DLG_MEM_BADADDRESSCRC "Bad AddressCRC detected!\nThis usually indicates a bad ROM.\n\nIgnore it and continue?" END -STRINGTABLE +STRINGTABLE BEGIN IDS_P_MEM_NOREGION "None" IDS_P_MEM_BETA "Beta" @@ -751,7 +763,7 @@ BEGIN IDS_ERR_MEMPAK_NONOTES "No free notes on MemPak (only 16 notes available per pak)." END -STRINGTABLE +STRINGTABLE BEGIN IDS_ERR_NOTEEOF "Error reading note file: unexpected end of file or read error." IDS_ERR_NOTEREAD "Couldn't read note file." @@ -785,7 +797,7 @@ LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_CHILE // #ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO +GUIDELINES DESIGNINFO BEGIN IDD_XCONTROLS, DIALOG BEGIN @@ -862,15 +874,26 @@ BEGIN COMBOBOX IDC_XC_LT,143,112,39,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CTEXT "RT",IDC_STATIC,101,130,36,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE COMBOBOX IDC_XC_RT,143,130,39,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "D-Pad and Thumbsticks configuration",IDC_STATIC,188,27,175,115 - CTEXT "Left Thumbstick",IDC_STATIC,194,65,62,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE - CTEXT "Right Thumbstick",IDC_STATIC,194,89,62,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE - CTEXT "D-Pad",IDC_STATIC,194,112,62,12,SS_CENTERIMAGE,WS_EX_CLIENTEDGE - COMBOBOX IDC_XC_LTS,262,65,94,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_XC_RTS,262,88,94,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_XC_DPAD,262,112,94,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - CTEXT "XControl",IDC_STATIC,194,45,62,8 - CTEXT "N64",IDC_STATIC,262,45,94,8 + + GROUPBOX "D-Pad and Thumbsticks configuration",IDC_STATIC,188,7,175,160 + CTEXT "XControl",IDC_STATIC,194,27,62,8 + CTEXT "N64",IDC_STATIC,262,27,94,8 + CTEXT "Left Thumbstick",IDC_STATIC,194,41,62,13,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + CONTROL "Invert X",IDC_XC_INVERT_LX,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,194,55,47,12 + CONTROL "Invert Y",IDC_XC_INVERT_LY,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,242,55,47,12 + + CTEXT "Right Thumbstick",IDC_STATIC,194,69,62,13,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + CONTROL "Invert X",IDC_XC_INVERT_RX,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,194,83,47,12 + CONTROL "Invert Y",IDC_XC_INVERT_RY,"Button",BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP,242,83,47,12 + + + CTEXT "D-Pad",IDC_STATIC,194,97,62,13,SS_CENTERIMAGE,WS_EX_CLIENTEDGE + + + COMBOBOX IDC_XC_LTS,262,41,94,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_XC_RTS,262,69,94,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_XC_DPAD,262,97,94,60,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "NOTE: LThSB and RThSB stands for Left/Right Thumbstick button respectively.",IDC_STATIC,14,155,349,18 CTEXT "XControl",IDC_STATIC,14,27,36,8 PUSHBUTTON "Save",IDC_XC_USE,306,159,50,14 diff --git a/Source/nragev20/XInputController.cpp b/Source/nragev20/XInputController.cpp index 4b66a5ab5..39d6227df 100644 --- a/Source/nragev20/XInputController.cpp +++ b/Source/nragev20/XInputController.cpp @@ -145,34 +145,18 @@ LCleanup: return bIsXinputDevice; } -void AxisDeadzone( SHORT &AxisValue, long lDeadZoneValue, float fDeadZoneRelation ) -{ - short sign = AxisValue < 0 ? -1 : 1; - float value = (float)(AxisValue < 0 ? -AxisValue : AxisValue); - - if(value < lDeadZoneValue) - value = 0; - else - { - value = (value - lDeadZoneValue) * fDeadZoneRelation; - value = value > 32767.0f ? 32767.0f : value; - } - - AxisValue = (SHORT)(value * sign); -} - void GetXInputControllerKeys( const int indexController, LPDWORD Keys ) { - - if (fnXInputGetState == NULL) + + if (fnXInputGetState == NULL) { return; } - + using namespace N64_BUTTONS; LPCONTROLLER pcController = &g_pcControllers[indexController]; - LPXCONTROLLER gController = &g_pcControllers[indexController].xiController; + LPXCONTROLLER gController = &pcController->xiController; *Keys = 0; @@ -183,44 +167,52 @@ void GetXInputControllerKeys( const int indexController, LPDWORD Keys ) XINPUT_STATE state; ULONGLONG time = GetTickCount() / 1000; - if (g_pcControllers[indexController].XcheckTime != NULL && (time - g_pcControllers[indexController].XcheckTime) < 3) + if (pcController->XcheckTime != NULL && (time - pcController->XcheckTime) < 3) return; result = fnXInputGetState(gController->nControl, &state); if (result == ERROR_DEVICE_NOT_CONNECTED) { - g_pcControllers[indexController].XcheckTime = time; + pcController->XcheckTime = time; } else { - g_pcControllers[indexController].XcheckTime = NULL; + pcController->XcheckTime = NULL; } if( result != ERROR_SUCCESS ) return; - + DWORD wButtons = state.Gamepad.wButtons; - if( pcController->bPadDeadZone > 0 ) - { - const int RANGERELATIVE = 32767; - long lDeadZoneValue = pcController->bPadDeadZone * RANGERELATIVE / 100; - float fDeadZoneRelation = (float)RANGERELATIVE / (float)( RANGERELATIVE - lDeadZoneValue ); + float LX, LY, RX, RY; + short XAx, YAx; + float N64Range = (float)pcController->bN64Range; - AxisDeadzone(state.Gamepad.sThumbLX, lDeadZoneValue, fDeadZoneRelation); - AxisDeadzone(state.Gamepad.sThumbLY, lDeadZoneValue, fDeadZoneRelation); - AxisDeadzone(state.Gamepad.sThumbRX, lDeadZoneValue, fDeadZoneRelation); - AxisDeadzone(state.Gamepad.sThumbRY, lDeadZoneValue, fDeadZoneRelation); + if (gController->stAnalogs.iLXAxis == XAxis){ + processStickInput(pcController, state.Gamepad.sThumbLX, state.Gamepad.sThumbLY, LX , LY); + LX *= N64Range / (float)XC_ANALOG_MAX; + LY *= N64Range / (float)XC_ANALOG_MAX; + RY = state.Gamepad.sThumbRY * N64_ANALOG_MAX / XC_ANALOG_MAX; + RX = state.Gamepad.sThumbRX * N64_ANALOG_MAX / XC_ANALOG_MAX; + XAx = LX; + YAx = LY; + if (pcController->xiController.stAnalogs.iInvertRX) + RX = -RX; + if (pcController->xiController.stAnalogs.iInvertRY) + RY = -RY; + }else{ + processStickInput(pcController, state.Gamepad.sThumbRX, state.Gamepad.sThumbRY, RX, RY); + RX *= N64Range / (float)XC_ANALOG_MAX; + RY *= N64Range / (float)XC_ANALOG_MAX; + LY = state.Gamepad.sThumbLY * N64_ANALOG_MAX / XC_ANALOG_MAX; + LX = state.Gamepad.sThumbLX * N64_ANALOG_MAX / XC_ANALOG_MAX; + XAx = RX; + YAx = RY; + if (pcController->xiController.stAnalogs.iInvertLX) + LX = -LX; + if (pcController->xiController.stAnalogs.iInvertLY) + LY = -LY; } - - short LY = state.Gamepad.sThumbLY * N64_ANALOG_MAX / XC_ANALOG_MAX; - short LX = state.Gamepad.sThumbLX * N64_ANALOG_MAX / XC_ANALOG_MAX; - - short RY = state.Gamepad.sThumbRY * N64_ANALOG_MAX / XC_ANALOG_MAX; - short RX = state.Gamepad.sThumbRX * N64_ANALOG_MAX / XC_ANALOG_MAX; - - short XAx = 0, XAxc = 0; - short YAx = 0, YAxc = 0; - WORD valButtons = 0; valButtons |= ( wButtons & gController->stButtons.iDRight ) ? DRight : 0; valButtons |= ( wButtons & gController->stButtons.iDLeft ) ? DLeft : 0; @@ -258,32 +250,6 @@ void GetXInputControllerKeys( const int indexController, LPDWORD Keys ) if (RY <= -BUTTON_ANALOG_VALUE) valButtons |= gController->stAnalogs.iRYAxis & (CDown | DDown) ? gController->stAnalogs.iRYAxis : 0; - if (gController->stAnalogs.iLXAxis == XAxis) - { - XAx += LX; - XAxc += LX > 0 ? 1 : 0; - } - if (gController->stAnalogs.iRXAxis == XAxis) - { - XAx += RX; - XAxc += RX > 0 ? 1 : 0; - } - if( XAxc ) - XAx /= XAxc; - - if (gController->stAnalogs.iLYAxis == YAxis) - { - YAx += LY; - YAxc += LY > 0 ? 1 : 0; - } - if (gController->stAnalogs.iRYAxis == YAxis) - { - YAx += RY; - YAxc += RY > 0 ? 1 : 0; - } - if( YAxc ) - YAx /= YAxc; - *Keys = MAKELONG(valButtons, MAKEWORD(XAx, YAx)); } @@ -307,6 +273,10 @@ void DefaultXInputControllerKeys( LPXCONTROLLER gController) gController->stAnalogs.iLXAxis = XAxis; gController->stAnalogs.iLYAxis = YAxis; gController->bConfigured = true; + gController->stAnalogs.iInvertLX = false; + gController->stAnalogs.iInvertLY = false; + gController->stAnalogs.iInvertRX = false; + gController->stAnalogs.iInvertRY = false; } void VibrateXInputController( DWORD nController, int LeftMotorVal, int RightMotorVal ) @@ -387,7 +357,6 @@ bool InitiateXInputController( LPXCONTROLLER gController, int nControl ) TCHAR * GetN64ButtonNameFromButtonCode( int Button ) { using namespace N64_BUTTONS; - static TCHAR btnName[10]; switch( Button ) @@ -509,6 +478,12 @@ bool ReadXInputControllerKeys( HWND hDlg, LPXCONTROLLER gController ) SendDlgItemMessage( hDlg, IDC_XC_LTS, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonArrayFromXAnalog( gController, XC_LTBS )); SendDlgItemMessage( hDlg, IDC_XC_RTS, CB_SELECTSTRING, -1, (LPARAM)GetN64ButtonArrayFromXAnalog( gController, XC_RTBS )); + SendDlgItemMessage(hDlg, IDC_XC_INVERT_LX, BM_SETCHECK, (gController->stAnalogs.iInvertLX ? BST_CHECKED : BST_UNCHECKED), 0); + SendDlgItemMessage(hDlg, IDC_XC_INVERT_LY, BM_SETCHECK, (gController->stAnalogs.iInvertLY ? BST_CHECKED : BST_UNCHECKED), 0); + SendDlgItemMessage(hDlg, IDC_XC_INVERT_RX, BM_SETCHECK, (gController->stAnalogs.iInvertRX ? BST_CHECKED : BST_UNCHECKED), 0); + SendDlgItemMessage(hDlg, IDC_XC_INVERT_RY, BM_SETCHECK, (gController->stAnalogs.iInvertRY ? BST_CHECKED : BST_UNCHECKED), 0); + + return true; } @@ -536,8 +511,8 @@ int GetComboBoxXInputKey( int ComboBox ) } int GetN64ButtonCode( TCHAR *btnName ) //esta wea esta muy fea, hay que buscar una mejor manera definitivamente.. -{ // ^ This translated means "This wea is very ugly, we must definitely find a better way" - // I'm assuming there must be some perceived "better way to handle this, so maybe TODO: ?" +{ // ^ This translated means "This wea is very ugly, we must definitely find a better way" + // I'm assuming there must be some perceived "better way to handle this, so maybe TODO: ?" using namespace N64_BUTTONS; int value = 0; @@ -597,6 +572,11 @@ void ResetXInputControllerKeys( LPXCONTROLLER gController ) gController->stAnalogs.iRightTrigger = 0; gController->stAnalogs.iRXAxis = 0; gController->stAnalogs.iRYAxis = 0; + + gController->stAnalogs.iInvertLX = false; + gController->stAnalogs.iInvertLY = false; + gController->stAnalogs.iInvertRX = false; + gController->stAnalogs.iInvertRY = false; } void StoreAnalogConfig( LPXCONTROLLER gController, int ComboBox, int index ) @@ -663,6 +643,10 @@ void StoreXInputControllerKeys( HWND hDlg, LPXCONTROLLER gController ) { LRESULT index = -1; DWORD value = 0; + int invertLX = gController->stAnalogs.iInvertLX; + int invertLY = gController->stAnalogs.iInvertLY; + int invertRX = gController->stAnalogs.iInvertRX; + int invertRY = gController->stAnalogs.iInvertRY; ResetXInputControllerKeys( gController ); @@ -711,6 +695,10 @@ void StoreXInputControllerKeys( HWND hDlg, LPXCONTROLLER gController ) case 14: gController->stButtons.iDRight |= value; break; } } + gController->stAnalogs.iInvertLX = invertLX; + gController->stAnalogs.iInvertLY = invertLY; + gController->stAnalogs.iInvertRX = invertRX; + gController->stAnalogs.iInvertRY = invertRY; gController->bConfigured = true; } @@ -738,7 +726,11 @@ void SaveXInputConfigToFile( FILE *file, LPXCONTROLLER gController ) fprintf( file, "LeftXAxis=%lu\n", gController->stAnalogs.iLXAxis ); fprintf( file, "LeftYAxis=%lu\n", gController->stAnalogs.iLYAxis ); fprintf( file, "RightXAxis=%lu\n", gController->stAnalogs.iRXAxis ); - fprintf( file, "RightYAxis=%lu\n\n", gController->stAnalogs.iRYAxis ); + fprintf( file, "RightYAxis=%lu\n", gController->stAnalogs.iRYAxis ); + fprintf( file, "InvertLX=%lu\n", gController->stAnalogs.iInvertLX ); + fprintf( file, "InvertLY=%lu\n", gController->stAnalogs.iInvertLY ); + fprintf( file, "InvertRX=%lu\n", gController->stAnalogs.iInvertRX ); + fprintf( file, "InvertRY=%lu\n\n", gController->stAnalogs.iInvertRY ); } void LoadXInputConfigFromFile( FILE *file, LPXCONTROLLER gController ) @@ -783,6 +775,30 @@ void LoadXInputConfigFromFile( FILE *file, LPXCONTROLLER gController ) sscanf(buffer, "DRight=%lu", &gController->stButtons.iDRight); break; } break; + case 'I': + switch( buffer[6] ) + { + case 'L': + switch( buffer[7] ) + { + case 'X': + sscanf(buffer, "InvertLX=%lu", &gController->stAnalogs.iInvertLX); + break; + case 'Y': + sscanf(buffer, "InvertLY=%lu", &gController->stAnalogs.iInvertLY); break; + } + break; + case 'R': + switch( buffer[7] ) + { + case 'X': + sscanf(buffer, "InvertRX=%lu", &gController->stAnalogs.iInvertRX); break; + case 'Y': + sscanf(buffer, "InvertRY=%lu", &gController->stAnalogs.iInvertRY); break; + } + break; + } + break; case 'L': switch( buffer[1] ) { diff --git a/Source/nragev20/XInputController.h b/Source/nragev20/XInputController.h index b3e4ea628..c808fa7a5 100644 --- a/Source/nragev20/XInputController.h +++ b/Source/nragev20/XInputController.h @@ -61,7 +61,7 @@ number, ie. first XInput controller is first N64 player, etc. #include // Defines -#define N64_ANALOG_MAX 88 +#define N64_ANALOG_MAX 127 #define XC_ANALOG_MAX 32767 #define BUTTON_ANALOG_VALUE 60 @@ -95,6 +95,7 @@ typedef struct _XCONTROLLER // XInput controller struct { int iLeftTrigger, iRightTrigger; unsigned int iRXAxis, iRYAxis, iLXAxis, iLYAxis; + unsigned int iInvertLX, iInvertLY, iInvertRX, iInvertRY; }stAnalogs; }XCONTROLLER; diff --git a/Source/nragev20/configs/Controller1.cpf b/Source/nragev20/configs/Controller1.cpf index a304af6ee..21ea6a9db 100644 --- a/Source/nragev20/configs/Controller1.cpf +++ b/Source/nragev20/configs/Controller1.cpf @@ -4,13 +4,16 @@ PakType=1 RealN64Range=1 RapidFireEnabled=0 RapidFireRate=3 -StickRange=66 +StickRange=100 +VirtualCorners=0 +N64Range=88 MouseMoveX=0 MouseMoveY=0 AxisSet=0 KeyAbsoluteX=0 KeyAbsoluteY=0 PadDeadZone=5 +PadSensitivity=50 MouseSensitivityX=100 MouseSensitivityY=100 RumbleType=1 diff --git a/Source/nragev20/resource.h b/Source/nragev20/resource.h index ddded5f69..d9f83e2d1 100644 --- a/Source/nragev20/resource.h +++ b/Source/nragev20/resource.h @@ -209,7 +209,6 @@ #define IDC_RUMBLE3 1036 #define IDC_RUMBLESTRENGTH 1037 #define IDC_MSSENSITIVITY_X 1038 -#define IDC_N64RANGE 1039 #define IDC_MSSENSITIVITY_Y 1039 #define IDC_PLUGGED 1040 #define IDC_CTRRANGE 1041 @@ -363,6 +362,20 @@ #define IDC_XC_RTS 1195 #define IDC_N64MOUSE 1196 #define IDC_BACKGROUNDINPUT 1197 +#define IDC_N64REALRANGE 1198 +#define IDC_SENSITIVITY 1199 +#define IDT_SENSITIVITY 1200 +#define IDS_SENSITIVITY 1201 +#define IDC_N64RANGE 1202 +#define IDT_N64RANGE 1203 +#define IDS_N64RANGE 1204 +#define IDC_VIRTUALCORNERS 1205 +#define IDT_VIRTUALCORNERS 1206 +#define IDS_VIRTUALCORNERS 1207 +#define IDC_XC_INVERT_LX 1208 +#define IDC_XC_INVERT_LY 1209 +#define IDC_XC_INVERT_RX 1210 +#define IDC_XC_INVERT_RY 1211 // Next default values for new objects // @@ -370,7 +383,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 149 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1198 +#define _APS_NEXT_CONTROL_VALUE 1300 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif