Skip to content

Commit

Permalink
Support for secondary GearUp/Down controls
Browse files Browse the repository at this point in the history
  • Loading branch information
mika-n committed Jan 31, 2021
1 parent bb1ef9e commit aec124f
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 7 deletions.
5 changes: 4 additions & 1 deletion ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The original RBR game and RBRTM and RBR_RX plugins have various problems and lim
- RBR_RX replay files cannot be replayed afterwards. You can replay those only once right after the stage is finished and before you go back to RBR main menu. After this you cannot replay RBRRX/BTB recordings.
- RBR has a bug how it handles inverted pedals (input.ini) at startup or after alt-tabbing to a desktop. For example throttle goes to 100% until a driver presses the inverted pedal at least once.
- RBR has limited support for xbox360/xboxOne gamepad triggers. RBR handles triggers as combined Accelerate-Brake control, so it is impossible to control throttle and brake independently (not good in a rally car).
- RBR supports only one set of GearUp/GearDown controls at the same time (not possible to map both sequantial gear stick and steering wheel paddles as gear up/down controls at the same time).

Good news! **NGPCarMenu plugin solves these issues** by doing following enhancements in RBR:
- Shows the actual NGP car specs (HP, gears, transmission), car preview images and 3D car model details in **RBR/RBRTM/RBRRX** menu screens.
Expand All @@ -24,6 +25,7 @@ Good news! **NGPCarMenu plugin solves these issues** by doing following enhancem
- "Rename profile" feature renames the driver profile while preserving profile settings (ie. you no longer have to call yourself as MULLIGATAWNY. Now you can rename the driver via NGPCarMenu plugin and still keep all maps and cars unlocked).
- Inverted pedals behave correctly right away without going through the hassle of pressing all pedals at least once while waiting for a countdown.
- Xbox360/XboxOne triggers are splitted and work independently as a separate Throttle and Brake in RBR controls (How to use this fix? Set triggers as combined AccelerateBrake control as usual, but then set Throttle and Brake controls to any keyboard key and choose a gamepad ID in SplitCombinedThrottleBrake in-game menu, NGPCarMenu plugin menu).
- When steering wheel or gamepad is used for steering (=an analog Steering control in RBR is set) then NGPCarMenu adds support for a secondary gear up/down controls.
- RallyStatsDB feature to store a detailed history of all rallies in one place (RBR original stages, RBRTM stages, RSF stages, BTB stages).
- In-game menu to hide or show steering wheel/windscreen/wipers in the cockpit camera view (internal cam).
- In-game menu to enable or disable camera shaking in the cockpit camera view.
Expand Down Expand Up @@ -76,6 +78,7 @@ rbr\Plugins\NGPCarMenu.ini options (see the NGPCarMenu.ini.sample file for more
| RBRTM_RecentResultsPosition | The location of "Recent results" data on RBRTM main menu. RBRTM_RecentResultsPosition=0 hides the information. |
| RBRRX_RecentResultsPosition | The location of "Recent results" data on RBRRX stages menu. RBRRB_RecentResultsPosition=0 hides the information. |
| InvertedPedalsStartupFix | 0 or 1. If enabled (default) then NGPCarMenu fixes the notorious "inverted pedals" RBR bug when the car is at starting line (ie. throttle goes to 100% until a driver presses the inverted pedal at least once). |
| SecondaryGearUpDownControls | 0 (disabled) or 1 (enabled, default). If enabled and an analog Steering control is set then RBR control screen supports both primary and secondary gear up/down control keys (for example, you can map both sequantial gear stick and steering wheel paddles as gear buttons at the same time). |
| SplitCombinedThrottleBrakeAxis | The game controller ID used when a combined triggers are splitted as two different analog axis in RBR controls. 0 (disabled), 1-4 gamepad ID. |
| SplitThrottleAxis | LT = Left trigger, RT = Right trigger. The same for SplitBrakeAxis option also. If combined trigger is splitted then defines which trigger is throttle or brake. |
| DeadzoneXXXX | Optional deadzone for DeadzoneSteering/Throttle/Brake/Clutch/Handbrake controls. Useful for those gamepad drivers where the left or right stick in the gamepad is no longer stable or don't return to absolute center position. |
Expand Down Expand Up @@ -199,5 +202,5 @@ The customized "Select Car" menu works also with RBR_RX plugin and NGPCarMenu sh

This plugin has been tested by NGPCarMenu author with these magnificent RBR plugins/tools and the plugin works great with these other plugins. In fact, this plugin should be compatible with any plugin because the plugin doesn't change how the RBR game handles racing and the actual car models.

NGPCarMenu. Copyright (c) 2020 by MIKA-N. All rights reserved. See LicenseText.txt file for more information (don't worry, this is published free of charge but use at your own risk).
NGPCarMenu. Copyright (c) 2020-2021 by MIKA-N. All rights reserved. See LicenseText.txt file for more information (don't worry, this is published free of charge but use at your own risk).
https://github.com/mika-n/NGPCarMenu
80 changes: 78 additions & 2 deletions src/NGPCarMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ tRBRDirectXEndScene Func_OrigRBRDirectXEndScene = nullptr;
tRBRReplay Func_OrigRBRReplay = nullptr; // Re-routed RBR replay class method
tRBRSaveReplay Func_OrigRBRSaveReplay = nullptr; //

tRBRControllerAxisData Func_OrigRBRControllerAxisData = nullptr;// Controller axis data, the custom method is used to fix inverted pedal RBR bug
tRBRControllerAxisData Func_OrigRBRControllerAxisData = nullptr; // Controller axis data, the custom method is used to fix inverted pedal RBR bug
tRBRControllerAxisDigitalData Func_OrigRBRControllerAxisDigitalData = nullptr; // Controller axis data (digital btns)

tRBRCallForHelp Func_OrigRBRCallForHelp = nullptr; // CallForHelp handler

Expand All @@ -71,6 +72,10 @@ wchar_t g_wszCustomLoadReplayStatusText[256] = L"\0"; // Custom LoadReplay text
wchar_t* g_pOrigRallySchoolMenuText = nullptr; // The original (localized) "Rally School" menu text (could be that the menu is replacemend with custom menu name)
wchar_t g_wszRallySchoolMenuReplacementText[128] = L"Rally School"; // Custom rallySchool menu text

wchar_t* g_pOrigControlLeftText = nullptr; // Original ptr to controller "Left" and "Right" text
wchar_t* g_pOrigControlRightText = nullptr;


#if USE_DEBUG == 1
CD3DFont* g_pFontDebug = nullptr;
#endif
Expand All @@ -97,7 +102,8 @@ WCHAR* g_pOrigCarSpecTitleHorsepower = nullptr;
std::vector<std::string>* g_pRBRRXTrackNameListAlreadyInitialized = nullptr; // List of RBRRX track folder names with a missing track.ini splashscreen option and already scanned for default JPG/PNG preview image during this RBR process life time


int g_iInvertedPedalsStartupFixFlag = 0; // Bit1=Throttle (0x01), Bit2=Brake (0x02), Bit3=Clutch (0x04), Bit4=Handbrake (0x08). Fix the inverted pedal bug in RBR when the game is started or alt-tabbed to desktop
int g_iInvertedPedalsStartupFixFlag = 0; // Bit1=Throttle (0x01), Bit2=Brake (0x02), Bit3=Clutch (0x04), Bit4=Handbrake (0x08). Fix the inverted pedal bug in RBR when the game is started or alt-tabbed to desktop
int g_iAlternativeGearUpDownSupport = 1; // 0=Disable support for alternative gear up/down controls, 1=Enable the alternative gear up/down btn support (left/right digital controls used as alternative gear btns)

int g_iXInputSplitThrottleBrakeAxis = -1; // -1=disabled, 0>=Split xinput controller# left and right analog triggers (by default RBR sees xbox xinput triggers as one axis)
int g_iXInputThrottle = 1; // 1=Right trigger
Expand Down Expand Up @@ -941,6 +947,7 @@ CNGPCarMenu::CNGPCarMenu(IRBRGame* pGame)
gtcRBRReplay = nullptr;
gtcRBRSaveReplay = nullptr;
gtcRBRControllerAxisData = nullptr;
gtcRBRControllerAxisDigitalData = nullptr;
gtcRBRCallForHelp = nullptr;

//RefreshSettingsFromPluginINIFile();
Expand All @@ -965,6 +972,7 @@ CNGPCarMenu::~CNGPCarMenu(void)
SAFE_DELETE(gtcRBRReplay);
SAFE_DELETE(gtcRBRSaveReplay);
SAFE_DELETE(gtcRBRControllerAxisData);
SAFE_DELETE(gtcRBRControllerAxisDigitalData);
SAFE_DELETE(gtcRBRCallForHelp);

#if USE_DEBUG == 1
Expand Down Expand Up @@ -1575,6 +1583,8 @@ void CNGPCarMenu::RefreshSettingsFromPluginINIFile(bool fistTimeRefresh)
}
}

// Map left/right digital btns as alternative secondary gear up/down if the analog Steering control is set
g_iAlternativeGearUpDownSupport = pluginINIFile.GetValueEx(L"Default", L"", L"SecondaryGearUpDownControls", 1);

// Split combined throttle and brake axis as separate throttle and brake (ie set CombinedThrottleBrake axis in RBR to analog trigger and set separate brake and throttle to some unused keyboard keys)
g_iXInputSplitThrottleBrakeAxis = pluginINIFile.GetValueEx(L"Default", L"", L"SplitCombinedThrottleBrakeAxis", 0);
Expand Down Expand Up @@ -4540,9 +4550,21 @@ const char* CNGPCarMenu::GetName(void)
Func_OrigRBRControllerAxisData = (tRBRControllerAxisData)gtcRBRControllerAxisData->GetTrampoline();
}


if (g_iAlternativeGearUpDownSupport == 1)
{
LogPrint("Secondary gear up/down control support enabled (works when analog Steering control is set)");

gtcRBRControllerAxisDigitalData = new DetourXS((LPVOID)0x4C25D0, ::CustomRBRControllerAxisDigitalData, TRUE);
Func_OrigRBRControllerAxisDigitalData = (tRBRControllerAxisDigitalData)gtcRBRControllerAxisDigitalData->GetTrampoline();
}


// Custom callForHelp handler (raceDB counts the num of times callForHelp was called during a race)
gtcRBRCallForHelp = new DetourXS((LPVOID)0x56E6D0, ::CustomRBRCallForHelp, TRUE);
Func_OrigRBRCallForHelp = (tRBRCallForHelp)gtcRBRCallForHelp->GetTrampoline();


// Override the gray RBRRX "loading track debug msg screen" with a real map preview img. Do this only one time when this plugin was initialized for the first time
if (m_iMenuRBRRXOption && m_bShowCustomLoadTrackScreenRBRRX)
RBRRX_OverrideLoadTrackScreen();
Expand Down Expand Up @@ -5432,6 +5454,23 @@ inline void CNGPCarMenu::CustomRBRDirectXBeginScene()
((PRBRPluginMenuItemObj2)g_pRBRMenuSystem->menuObj[RBRMENUIDX_MAIN]->pItemObj[3])->wszMenuTitleName = g_wszRallySchoolMenuReplacementText;
}

if (g_iAlternativeGearUpDownSupport == 1)
{
if (g_pRBRGameConfig->controllerBaseObj->controllerObj->controllerAxis[0].controllerAxisData != nullptr)
{
if (g_pOrigControlLeftText == nullptr) g_pOrigControlLeftText = g_pRBRGameConfig->controllerBaseObj->controllerObj->controllerAxis[1].wszAxisName;
if (g_pOrigControlRightText == nullptr) g_pOrigControlRightText = g_pRBRGameConfig->controllerBaseObj->controllerObj->controllerAxis[2].wszAxisName;

if (g_pOrigControlLeftText != nullptr) g_pRBRGameConfig->controllerBaseObj->controllerObj->controllerAxis[1].wszAxisName = L"Gear Up (Secondary)";
if (g_pOrigControlRightText != nullptr) g_pRBRGameConfig->controllerBaseObj->controllerObj->controllerAxis[2].wszAxisName = L"Gear Down (Secondary)";
}
else
{
if (g_pOrigControlLeftText != nullptr) g_pRBRGameConfig->controllerBaseObj->controllerObj->controllerAxis[1].wszAxisName = g_pOrigControlLeftText;
if (g_pOrigControlRightText != nullptr) g_pRBRGameConfig->controllerBaseObj->controllerObj->controllerAxis[2].wszAxisName = g_pOrigControlRightText;
}
}

if (m_bRenameDriverNameActive)
{
// If the current menu or the focused profile menu line has changed then user has either accepted or canceled the profile saving (renaming)
Expand Down Expand Up @@ -7015,6 +7054,43 @@ float __fastcall CustomRBRControllerAxisData(void* objPointer, DWORD /*ignoreEDX
}


//----------------------------------------------------------------------------------------------------------------------------
// Controller handler for digital btns (axisID 07=GearUp, 08=GearDown)
//
int __fastcall CustomRBRControllerAxisDigitalData(void* objPointer, DWORD /*ignoreEDX*/, __int32 axisID)
{
// Check if alternative GearUp/GearDown keys are set and re-map those as "real" gear
// btn events if analog steering is set (0), left/right digital controls are set (1 and 2), its value is non-zero and the real gear up/down control is set (7 and 8)
if (g_iAlternativeGearUpDownSupport == 1 && ((PRBRControllerAxis)objPointer)[0].controllerAxisData != nullptr)
{
switch (axisID)
{
case 7:
// GearUp
if (((PRBRControllerAxis)objPointer)[1].controllerAxisData != nullptr
&& ((PRBRControllerAxis)objPointer)[1].controllerAxisData->axisRawValue > 0
&& ((PRBRControllerAxis)objPointer)[7].controllerAxisData != nullptr)
{
((PRBRControllerAxis)objPointer)[7].controllerAxisData->axisValue = ((PRBRControllerAxis)objPointer)[1].controllerAxisData->axisValue;
}
break;

case 8:
// GearDown
if (((PRBRControllerAxis)objPointer)[2].controllerAxisData != nullptr
&& ((PRBRControllerAxis)objPointer)[2].controllerAxisData->axisRawValue > 0
&& ((PRBRControllerAxis)objPointer)[8].controllerAxisData != nullptr)
{
((PRBRControllerAxis)objPointer)[8].controllerAxisData->axisValue = ((PRBRControllerAxis)objPointer)[2].controllerAxisData->axisValue;
}
break;
}
}

return Func_OrigRBRControllerAxisDigitalData(objPointer, axisID);
}


//----------------------------------------------------------------------------------------------------------------------------
// RBR CallForHelp
//
Expand Down
2 changes: 2 additions & 0 deletions src/NGPCarMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ extern int __fastcall CustomRBRReplay(void* objPointer, DWORD dummyEDX, cons
extern int __fastcall CustomRBRSaveReplay(void* objPointer, DWORD dummyEDX, const char* szReplayFileName, __int32 mapID, __int32 carID, __int32 unknown1);

extern float __fastcall CustomRBRControllerAxisData(void* objPointer, DWORD dummyEDX, __int32 axisID);
extern int __fastcall CustomRBRControllerAxisDigitalData(void* objPointer, DWORD dummyEDX, __int32 axisID);

extern void __fastcall CustomRBRCallForHelp(void* objPointer, DWORD dummyEDX);

Expand Down Expand Up @@ -671,6 +672,7 @@ class CNGPCarMenu : public IPlugin
DetourXS* gtcRBRReplay;
DetourXS* gtcRBRSaveReplay;
DetourXS* gtcRBRControllerAxisData;
DetourXS* gtcRBRControllerAxisDigitalData;
DetourXS* gtcRBRCallForHelp;

static BOOL CALLBACK MonitorEnumCallback(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData);
Expand Down
5 changes: 5 additions & 0 deletions src/NGPCarMenu.ini
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
;
; InvertedPedalsStartupFix = 0 (disabled) or 1 (enabled, default). When this option is set to value 1 then NGPCarMenu fixes the notorious "inverted pedals" RBR bug at starting line (ie. throttle/brake/clutch/handbrake goes to 100% until a driver presses the inverted pedal at least once).
;
; SecondaryGearUpDownControls = 0 (disabled) or 1 (enabled, default). If enabled and an analog Steering control is set then RBR control screen supports both primary and secondary gear up/down control keys (for example, you can map both sequantial gear stick and steering wheel paddles as gear buttons at the same time).
;
; SplitCombinedThrottleBrakeAxis = 0 (disabled), 1-4 controller ID used to read left and right trigger and splitting the combined AccelerateAndBrake RBR axis.
; This option is useful for Xbox360/XboxOne gamepad drivers because RBR sees left and right trigger as combined. By enabling this option, NGPCarMenu plugin fixes this RBR limitation and allows to use separate Throttle and Brake controls in RBR.
; SplitThrottleAxis = RT (right trigger, default)
Expand Down Expand Up @@ -199,6 +201,9 @@ RallySchoolMenuReplacement=Disabled
;
InvertedPedalsStartupFix = 1

; Support secondary gear up/down controls (0=Disabled 1=Enabled, default). Note! This requires that an analog Steering control is set instead of only digital left/right controls in RBR control setup screen.
SecondaryGearUpDownControls = 1

;
; Xbox gamepad trigger buttons (left=LT, right=RT) must be set as the "combined AccelerateBrake" control in RBR controller setup screen.
; This is why it is not possible to control the throttle and brake independently with xbox gamepad triggers in RBR (limitation of RBR controller implementation).
Expand Down
8 changes: 4 additions & 4 deletions src/NGPCarMenu.rc
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,17,1
PRODUCTVERSION 1,0,17,1
FILEVERSION 1,0,17,2
PRODUCTVERSION 1,0,17,2
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "MIKA-N"
VALUE "FileDescription", "NGPCarMenu - Customized ""Select Car"" and ""Select Stage"" game menus with RBRTM and RBR_RX integration for Richard Burns Rally (RBR) 1.02 SSE. https://github.com/mika-n/NGPCarMenu"
VALUE "FileVersion", "1.0.17.1"
VALUE "FileVersion", "1.0.17.2"
VALUE "InternalName", "NGPCarMe.dll"
VALUE "LegalCopyright", "Copyright (C) 2020 by mika-n. All rights reserved. See LicenseText.txt for more information. This tool is distributed free of charge. Use at your own risk. https://github.com/mika-n/NGPCarMenu"
VALUE "OriginalFilename", "NGPCarMenu.dll"
VALUE "ProductName", "NGPCarMenu"
VALUE "ProductVersion", "1.0.17.1"
VALUE "ProductVersion", "1.0.17.2"
END
END
BLOCK "VarFileInfo"
Expand Down
1 change: 1 addition & 0 deletions src/RBRAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ typedef int(__thiscall* tRBRSaveReplay)(void* objPointer, const char* szReplayFi

// Overloaded dinput controller axis (digital button/steering analog axis) handler method
typedef float(__thiscall* tRBRControllerAxisData)(void* objPointer, __int32 axisID);
typedef int(__thiscall* tRBRControllerAxisDigitalData)(void* objPointer, __int32 axisID);

// Overloaded CallForHelp handler
typedef void(__thiscall* tRBRCallForHelp)(void* objPointer);
Expand Down

0 comments on commit aec124f

Please sign in to comment.