[SAVEVERSION+] Fix vibration motors backwards and too low power delivery to small motor

Also fix inconsequential but (technically) incorrect return values for vibration mapping command
This commit is contained in:
RedPanda4552 2023-07-27 21:55:30 -04:00 committed by refractionpcsx2
parent c3446a16cc
commit 824147fd7d
3 changed files with 27 additions and 5 deletions

View File

@ -150,9 +150,12 @@ u8 PadDualshock2::Poll(u8 commandByte)
return (buttons >> 8) & 0xff;
case 4:
this->vibrationMotors[1] = commandByte;
// Order is reversed here - SetPadVibrationIntensity takes large motor first, then small. PS2 orders small motor first, large motor second.
InputManager::SetPadVibrationIntensity(this->unifiedSlot,
std::min(static_cast<float>(this->vibrationMotors[0]) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f),
std::min(static_cast<float>(this->vibrationMotors[1]) * GetVibrationScale(1) * (1.0f / 255.0f), 1.0f)
std::min(static_cast<float>(this->vibrationMotors[1]) * GetVibrationScale(1) * (1.0f / 255.0f), 1.0f),
// Small motor on the PS2 is either on full power or zero power, it has no variable speed. If the game supplies any value here at all,
// the pad in turn supplies full power to the motor, or no power at all if zero.
std::min(static_cast<float>((this->vibrationMotors[0] ? 0xff : 0)) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f)
);
// PS1 mode: If the controller is still in digital mode, it is time to stop acknowledging.
@ -378,14 +381,27 @@ u8 PadDualshock2::Constant3(u8 commandByte)
}
}
// Set which byte of the poll command will correspond to a motor's power level.
// In all known cases, games never rearrange the motors. We've hard coded pad polls
// to always use the first vibration byte as small motor, and the second as big motor.
// There is no reason to rearrange these. Games never rearrange these. If someone does
// try to rearrange these, they should suffer.
//
// The return values for cases 3 and 4 are just to notify the pad module of what the mapping was, prior to this command.
u8 PadDualshock2::VibrationMap(u8 commandByte)
{
u8 ret = 0xff;
switch (commandBytesReceived)
{
case 3:
return 0x00;
ret = this->smallMotorLastConfig;
this->smallMotorLastConfig = commandByte;
return ret;
case 4:
return 0x01;
ret = this->largeMotorLastConfig;
this->largeMotorLastConfig = commandByte;
return ret;
case 8:
g_Sio0.SetAcknowledge(false);
return 0xff;
@ -787,6 +803,8 @@ bool PadDualshock2::Freeze(StateWrapper& sw)
sw.Do(&vibrationScale);
sw.Do(&pressureModifier);
sw.Do(&buttonDeadzone);
sw.Do(&smallMotorLastConfig);
sw.Do(&largeMotorLastConfig);
return !sw.HasError();
}

View File

@ -96,6 +96,10 @@ private:
// a way to simulate pressure sensitive controls.
float pressureModifier;
float buttonDeadzone;
// Used to store the last vibration mapping request the PS2 made for the small motor.
u8 smallMotorLastConfig = 0xff;
// Used to store the last vibration mapping request the PS2 made for the large motor.
u8 largeMotorLastConfig = 0xff;
u8 Mystery(u8 commandByte);
u8 ButtonQuery(u8 commandByte);

View File

@ -37,7 +37,7 @@ enum class FreezeAction
// [SAVEVERSION+]
// This informs the auto updater that the users savestates will be invalidated.
static const u32 g_SaveVersion = (0x9A3B << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A3C << 16) | 0x0000;
// the freezing data between submodules and core