mirror of
https://github.com/libretro/parallel-gx1.git
synced 2026-11-07 04:26:01 -10:00
In dual core the CPU thread called into the frontend while the frontend's own loop was running: every button and axis read went to input_cb from SI polling, each field's audio went to the batch callback, and rumble went to the rumble interface. retro_run now reads every input of the libretro devices once, right after poll_cb, and emulation reads those values. Rumble the emulation asks for is kept until the end of retro_run, which hands it over together with the audio the frame produced.
168 lines
6.1 KiB
C++
168 lines
6.1 KiB
C++
#pragma once
|
|
|
|
#include <libretro.h>
|
|
#include "Common/WindowSystemInfo.h"
|
|
|
|
// only 4 support sensors, but the array may be upto 8 if connected GC controllers
|
|
#define NUM_CONTROLLERS_FOR_SENSORS 8
|
|
|
|
struct WiimoteUpdateFlags
|
|
{
|
|
bool irMode = false;
|
|
bool irOffset = false; // center
|
|
bool irYaw = false; // width
|
|
bool irPitch = false; // height
|
|
bool irDeadzone = false;
|
|
bool irModifier = false;
|
|
bool swingModifier = false;
|
|
bool swingAngle = false;
|
|
bool sideways = false; // hotkey
|
|
bool upright = false; // hotkey
|
|
bool rumble = false;
|
|
bool gcMicBtn = false;
|
|
bool irPassthrough = false;
|
|
|
|
bool any() const {
|
|
return irMode || irOffset || irYaw || irPitch ||
|
|
irDeadzone || irModifier || swingModifier ||
|
|
swingAngle || sideways || rumble || gcMicBtn || irPassthrough;
|
|
}
|
|
};
|
|
|
|
void refresh_all_wiimote_flags(unsigned port, unsigned device);
|
|
void poll_microphone();
|
|
void UpdateInputDescriptors();
|
|
|
|
namespace Libretro
|
|
{
|
|
namespace Input
|
|
{
|
|
constexpr std::string_view source = "Libretro";
|
|
extern double g_accel_pos[NUM_CONTROLLERS_FOR_SENSORS][3];
|
|
extern double g_accel_neg[NUM_CONTROLLERS_FOR_SENSORS][3];
|
|
extern double g_gyro_pos[NUM_CONTROLLERS_FOR_SENSORS][3];
|
|
extern double g_gyro_neg[NUM_CONTROLLERS_FOR_SENSORS][3];
|
|
// Where the VR controller points, as one-sided -1..1 pairs: right, left, down, up.
|
|
extern double g_point[NUM_CONTROLLERS_FOR_SENSORS][4];
|
|
|
|
static retro_sensor_interface sensor_interface = {0};
|
|
|
|
void Init(const WindowSystemInfo& wsi);
|
|
void InitStage2();
|
|
void InitSensors();
|
|
// VR: player 1's Wiimote takes its motion and pointing from the right VR controller.
|
|
bool UsesVRMotion(unsigned port);
|
|
// Accelerometer in m/s^2 and gyroscope in rad/s about the remote's axes (+X left, +Y back,
|
|
// +Z up), and where it points (-1..1, +X right, +Y up).
|
|
void SetVRMotion(unsigned port, const float accel[3], const float gyro[3], const float point[2]);
|
|
void UpdateAccelerometer(unsigned port);
|
|
void UpdateGyro(unsigned port);
|
|
void Update();
|
|
// From retro_run after the frame: rumble the emulation asked for goes to the frontend.
|
|
void FlushOutputs();
|
|
void Shutdown();
|
|
void ResetControllers(const WiimoteUpdateFlags& f);
|
|
void BluetoothPassthroughBind();
|
|
void UpdateWiimoteMappings(const WiimoteUpdateFlags& f, unsigned port, unsigned device);
|
|
void UpdateGCMappings(const WiimoteUpdateFlags& f, unsigned port, unsigned device);
|
|
} // namespace Input
|
|
} // namespace Libretro
|
|
|
|
class SensorDevice : public ciface::Core::Device
|
|
{
|
|
public:
|
|
explicit SensorDevice(unsigned port) : m_port(port) {}
|
|
|
|
std::string GetName() const override { return "Sensor"; }
|
|
std::string GetSource() const override { return std::string(Libretro::Input::source); }
|
|
unsigned int GetPort() const { return m_port; }
|
|
ciface::Core::DeviceRemoval UpdateInput() override { return ciface::Core::DeviceRemoval::Keep; }
|
|
|
|
private:
|
|
class ScalarInput : public ciface::Core::Device::Input
|
|
{
|
|
public:
|
|
ScalarInput(const char* name, const double* slot) : m_name(name), m_slot(slot) {}
|
|
std::string GetName() const override { return m_name; }
|
|
ControlState GetState() const override { return *m_slot; }
|
|
private:
|
|
const char* m_name;
|
|
const double* m_slot;
|
|
};
|
|
|
|
public:
|
|
/// Each axis is a PAIR of one-sided inputs: ControlExpression clamps a control
|
|
/// to >= 0, so a lone signed input loses half its travel. The IMU groups
|
|
/// subtract one direction from the other, rebuilding the signed value.
|
|
void RegisterAll()
|
|
{
|
|
AddInput(new ScalarInput("GyroX+", &Libretro::Input::g_gyro_pos[m_port][0]));
|
|
AddInput(new ScalarInput("GyroX-", &Libretro::Input::g_gyro_neg[m_port][0]));
|
|
AddInput(new ScalarInput("GyroY+", &Libretro::Input::g_gyro_pos[m_port][1]));
|
|
AddInput(new ScalarInput("GyroY-", &Libretro::Input::g_gyro_neg[m_port][1]));
|
|
AddInput(new ScalarInput("GyroZ+", &Libretro::Input::g_gyro_pos[m_port][2]));
|
|
AddInput(new ScalarInput("GyroZ-", &Libretro::Input::g_gyro_neg[m_port][2]));
|
|
AddInput(new ScalarInput("AccelX+", &Libretro::Input::g_accel_pos[m_port][0]));
|
|
AddInput(new ScalarInput("AccelX-", &Libretro::Input::g_accel_neg[m_port][0]));
|
|
AddInput(new ScalarInput("AccelY+", &Libretro::Input::g_accel_pos[m_port][1]));
|
|
AddInput(new ScalarInput("AccelY-", &Libretro::Input::g_accel_neg[m_port][1]));
|
|
AddInput(new ScalarInput("AccelZ+", &Libretro::Input::g_accel_pos[m_port][2]));
|
|
AddInput(new ScalarInput("AccelZ-", &Libretro::Input::g_accel_neg[m_port][2]));
|
|
AddInput(new ScalarInput("PointRight", &Libretro::Input::g_point[m_port][0]));
|
|
AddInput(new ScalarInput("PointLeft", &Libretro::Input::g_point[m_port][1]));
|
|
AddInput(new ScalarInput("PointDown", &Libretro::Input::g_point[m_port][2]));
|
|
AddInput(new ScalarInput("PointUp", &Libretro::Input::g_point[m_port][3]));
|
|
}
|
|
|
|
private:
|
|
unsigned m_port;
|
|
};
|
|
|
|
class GyroDevice : public ciface::Core::Device
|
|
{
|
|
private:
|
|
class GyroAxis : public ciface::Core::Device::Input
|
|
{
|
|
public:
|
|
enum Axis { PITCH, ROLL, YAW };
|
|
|
|
GyroAxis(unsigned port, Axis axis, const char* name)
|
|
: m_port(port), m_axis(axis), m_name(name) {}
|
|
|
|
std::string GetName() const override { return m_name; }
|
|
|
|
ControlState GetState() const override
|
|
{
|
|
if (!Libretro::Input::sensor_interface.get_sensor_input)
|
|
return 0.0;
|
|
|
|
switch (m_axis)
|
|
{
|
|
case PITCH:
|
|
return Libretro::Input::sensor_interface.get_sensor_input(m_port, RETRO_SENSOR_GYROSCOPE_Y);
|
|
case ROLL:
|
|
return Libretro::Input::sensor_interface.get_sensor_input(m_port, RETRO_SENSOR_GYROSCOPE_X);
|
|
case YAW:
|
|
return Libretro::Input::sensor_interface.get_sensor_input(m_port, RETRO_SENSOR_GYROSCOPE_Z);
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
private:
|
|
const unsigned m_port;
|
|
const Axis m_axis;
|
|
const char* m_name;
|
|
};
|
|
|
|
public:
|
|
GyroDevice(unsigned port)
|
|
{
|
|
AddInput(new GyroAxis(port, GyroAxis::PITCH, "Pitch"));
|
|
AddInput(new GyroAxis(port, GyroAxis::ROLL, "Roll"));
|
|
AddInput(new GyroAxis(port, GyroAxis::YAW, "Yaw"));
|
|
}
|
|
|
|
std::string GetName() const override { return "Gyroscope"; }
|
|
std::string GetSource() const override { return std::string(Libretro::Input::source); }
|
|
};
|