Compare commits

...

4 Commits

Author SHA1 Message Date
Jordan Woyak
a16003ae61
Merge 83ed817ad2 into 80ea68b13c 2024-11-10 21:48:54 -08:00
JMC47
80ea68b13c
Merge pull request #13183 from Tilka/sync_on_fifo_reset
ProcessorInterface: sync GPU just before PI_FIFO_RESET
2024-11-11 00:38:26 -05:00
Tillmann Karras
fbce737415 ProcessorInterface: sync GPU just before PI_FIFO_RESET
GXAbortFrame() is problematic for Dolphin because it first writes
PI_FIFO_RESET (for which we discard our internal fifo), then disables CP
reads (for which we execute pending commands in the GP fifo in emulated
memory). I don't know whether there is a race condition on hardware, but
there is one for us. Avoid this by also doing a GPU sync here.
2024-11-09 03:29:05 +00:00
Jordan Woyak
83ed817ad2 ControllerInterface/SDL: Add Battery Input. 2024-11-04 22:24:42 -06:00
2 changed files with 65 additions and 0 deletions

View File

@ -98,6 +98,10 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{
system.GetGPFifo().ResetGatherPipe();
// Assume that all bytes that made it into the GPU fifo did in fact execute
// before this MMIO write takes effect.
system.GetFifo().SyncGPUForRegisterAccess();
// Call Fifo::ResetVideoBuffer() from the video thread. Since that function
// resets various pointers used by the video thread, we can't call it directly
// from the CPU thread, so queue a task to do it instead. In single-core mode,

View File

@ -56,6 +56,38 @@ bool IsTriggerAxis(int index)
return index >= 4;
}
ControlState GetBatteryValueFromSDLPowerLevel(SDL_JoystickPowerLevel sdl_power_level)
{
// Values come from comments in SDL_joystick.h
// A proper percentage will be exposed in SDL3.
ControlState result;
switch (sdl_power_level)
{
case SDL_JOYSTICK_POWER_EMPTY:
result = 0.025;
break;
case SDL_JOYSTICK_POWER_LOW:
result = 0.125;
break;
case SDL_JOYSTICK_POWER_MEDIUM:
result = 0.45;
break;
case SDL_JOYSTICK_POWER_FULL:
result = 0.85;
break;
case SDL_JOYSTICK_POWER_WIRED:
case SDL_JOYSTICK_POWER_MAX:
result = 1.0;
break;
case SDL_JOYSTICK_POWER_UNKNOWN:
default:
result = 0.0;
break;
}
return result * ciface::BATTERY_INPUT_MAX_VALUE;
}
} // namespace
namespace ciface::SDL
@ -142,6 +174,18 @@ private:
const u8 m_direction;
};
class BatteryInput final : public Input
{
public:
explicit BatteryInput(const ControlState* battery_value) : m_battery_value(*battery_value) {}
std::string GetName() const override { return "Battery"; }
ControlState GetState() const override { return m_battery_value; }
bool IsDetectable() const override { return false; }
private:
const ControlState& m_battery_value;
};
// Rumble
template <int LowEnable, int HighEnable, int SuffixIndex>
class GenericMotor : public Output
@ -269,12 +313,18 @@ public:
std::string GetName() const override;
std::string GetSource() const override;
int GetSDLInstanceID() const;
Core::DeviceRemoval UpdateInput() override
{
m_battery_value = GetBatteryValueFromSDLPowerLevel(SDL_JoystickCurrentPowerLevel(m_joystick));
return Core::DeviceRemoval::Keep;
}
private:
SDL_GameController* const m_gamecontroller;
std::string m_name;
SDL_Joystick* const m_joystick;
SDL_Haptic* m_haptic = nullptr;
ControlState m_battery_value;
};
class InputBackend final : public ciface::InputBackend
@ -767,6 +817,17 @@ GameController::GameController(SDL_GameController* const gamecontroller,
}
}
}
// Needed to make the below power level not "UNKNOWN".
SDL_JoystickUpdate();
// Battery
if (SDL_JoystickPowerLevel const power_level = SDL_JoystickCurrentPowerLevel(m_joystick);
power_level != SDL_JOYSTICK_POWER_UNKNOWN)
{
m_battery_value = GetBatteryValueFromSDLPowerLevel(power_level);
AddInput(new BatteryInput{&m_battery_value});
}
}
GameController::~GameController()