diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index 325378cee..87fe983c6 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -98,6 +98,7 @@ void EventHandler::initialize() setActionMappings(kMenuMode); Joystick::setDeadZone(myOSystem.settings().getInt("joydeadzone")); + Paddles::setDejitter(myOSystem.settings().getInt("dejitter")); Paddles::setDigitalSensitivity(myOSystem.settings().getInt("dsense")); Paddles::setMouseSensitivity(myOSystem.settings().getInt("msense")); PointingDevice::setSensitivity(myOSystem.settings().getInt("tsense")); diff --git a/src/emucore/Paddles.cxx b/src/emucore/Paddles.cxx index daecb7343..e8e1ddc34 100644 --- a/src/emucore/Paddles.cxx +++ b/src/emucore/Paddles.cxx @@ -262,23 +262,41 @@ void Paddles::update() bool sa_changed = false; int sa_xaxis = myEvent.get(myP0AxisValue); int sa_yaxis = myEvent.get(myP1AxisValue); - const double factor1 = 0.2; // TODO: configurable - const double factor2 = 1.0 / 256; + + const double fac1[MAX_DEJITTER - MIN_DEJITTER + 1] = { + // higher values mean more dejitter strength + 0, // off + 0.5, 0.6, 0.7, 0.8, 0.9, + 0.5, 0.6, 0.7, 0.8, 0.9, + 0.5, 0.6, 0.7, 0.8, 0.9, + 0.5, 0.6, 0.7, 0.8, 0.9 + }; + const double fac2[MAX_DEJITTER - MIN_DEJITTER + 1] = { + // lower values mean more dejitter strength + 1, // off + 1.0 / 32 , 1.0 / 32 , 1.0 / 32 , 1.0 / 32 , 1.0 / 32 , + 1.0 / 64 , 1.0 / 64 , 1.0 / 64 , 1.0 / 64 , 1.0 / 64 , + 1.0 / 128, 1.0 / 128, 1.0 / 128, 1.0 / 128, 1.0 / 128, + 1.0 / 256, 1.0 / 256, 1.0 / 256, 1.0 / 256, 1.0 / 256, + + }; + const double factor1 = fac1[DEJITTER]; + const double factor2 = fac2[DEJITTER]; if(abs(myLastAxisX - sa_xaxis) > 10) { - // anti jitter - double dFactor = std::pow(factor1, 1 / (abs(sa_xaxis - myLastAxisX) * factor2)); - sa_xaxis = sa_xaxis * dFactor + myLastAxisX * (1 - dFactor); + // anti jitter, suppress small changes only + double dejitter = std::pow(factor1, abs(sa_xaxis - myLastAxisX) * factor2); + sa_xaxis = sa_xaxis * (1 - dejitter) + myLastAxisX * dejitter; setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_xaxis)) / 65536.0))); sa_changed = true; } if(abs(myLastAxisY - sa_yaxis) > 10) { - // anti jitter - double dFactor = std::pow(factor1, 1 / (abs(sa_yaxis - myLastAxisY) * factor2)); - sa_yaxis = sa_yaxis * dFactor + myLastAxisY * (1 - dFactor); + // anti jitter, suppress small changes only + double dejitter = std::pow(factor1, abs(sa_yaxis - myLastAxisY) * factor2); + sa_yaxis = sa_yaxis * (1 - dejitter) + myLastAxisY * dejitter; setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_yaxis)) / 65536.0))); sa_changed = true; @@ -409,6 +427,12 @@ bool Paddles::setMouseControl( return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Paddles::setDejitter(int strength) +{ + DEJITTER = BSPF::clamp(strength, MIN_DEJITTER, MAX_DEJITTER); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Paddles::setDigitalSensitivity(int sensitivity) { @@ -434,6 +458,7 @@ int Paddles::TRIGRANGE = Paddles::TRIGMAX; int Paddles::DIGITAL_SENSITIVITY = -1; int Paddles::DIGITAL_DISTANCE = -1; int Paddles::MOUSE_SENSITIVITY = -1; +int Paddles::DEJITTER = 0; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const Controller::DigitalPin Paddles::ourButtonPin[2] = { diff --git a/src/emucore/Paddles.hxx b/src/emucore/Paddles.hxx index e17c92e93..e5f95c139 100644 --- a/src/emucore/Paddles.hxx +++ b/src/emucore/Paddles.hxx @@ -48,6 +48,12 @@ class Paddles : public Controller virtual ~Paddles() = default; public: + + static constexpr int MAX_DIGITAL_SENSE = 20; + static constexpr int MAX_MOUSE_SENSE = 20; + static constexpr int MIN_DEJITTER = 0; + static constexpr int MAX_DEJITTER = 20; + /** Update the entire digital and analog pin state according to the events currently set. @@ -83,6 +89,11 @@ class Paddles : public Controller bool setMouseControl(Controller::Type xtype, int xid, Controller::Type ytype, int yid) override; + /** + @param strength Value from 0 to 20 + */ + static void setDejitter(int strength); + /** Sets the sensitivity for digital emulation of paddle movement. This is only used for *digital* events (ie, buttons or keys, @@ -141,9 +152,8 @@ class Paddles : public Controller static constexpr int TRIGMAX = 4096; static int TRIGRANGE; // This one is variable for the upper range - static constexpr int MAX_DIGITAL_SENSE = 20; - static constexpr int MAX_MOUSE_SENSE = 20; static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE; + static int DEJITTER; static int MOUSE_SENSITIVITY; // Lookup table for associating paddle buttons with controller pins diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 6bddc4598..557e4052f 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -87,6 +87,7 @@ Settings::Settings() setPermanent("usemouse", "analog"); setPermanent("grabmouse", "true"); setPermanent("cursor", "2"); + setPermanent("dejitter", "0"); setPermanent("dsense", "10"); setPermanent("msense", "10"); setPermanent("tsense", "10"); diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index ce5b036d2..5d230b9ed 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -51,7 +51,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, StringList actions; // Set real dimensions - setSize(50 * fontWidth + 10, 16 * (lineHeight + 4) + 16 + _th, max_w, max_h); + setSize(50 * fontWidth + 10, 17 * (lineHeight + 4) + 16 + _th, max_w, max_h); // The tab widget xpos = 2; ypos = vBorder + _th; @@ -151,6 +151,17 @@ void InputDialog::addDevicePortTab(const GUI::Font& font) myDeadzoneLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 5*fontWidth, lineHeight, ""); wid.push_back(myDeadzone); + // Add dejitter (Stelladaptor emulation for now only) + ypos += lineHeight + VGAP; + myDejitter = new SliderWidget(myTab, font, HBORDER, ypos, + "Paddle dejitter strength", + lwidth, kDejitterChanged); + myDejitter->setMinValue(Paddles::MIN_DEJITTER); myDejitter->setMaxValue(Paddles::MAX_DEJITTER); + myDejitter->setTickmarkInterval(4); + xpos = HBORDER + myDejitter->getWidth() + 5; + myDejitterLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, 24, lineHeight, ""); + wid.push_back(myDejitter); + // Add paddle speed (digital emulation) ypos += lineHeight + VGAP; myDPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos, @@ -264,6 +275,8 @@ void InputDialog::loadConfig() myDeadzoneLabel->setValue(Joystick::deadzone()); // Paddle speed (digital and mouse) + myDejitter->setValue(instance().settings().getInt("dejitter")); + myDejitterLabel->setLabel(instance().settings().getString("dejitter")); myDPaddleSpeed->setValue(instance().settings().getInt("dsense")); myDPaddleLabel->setLabel(instance().settings().getString("dsense")); myMPaddleSpeed->setValue(instance().settings().getInt("msense")); @@ -317,9 +330,14 @@ void InputDialog::saveConfig() Joystick::setDeadZone(deadzone); // Paddle speed (digital and mouse) + int dejitter = myDejitter->getValue(); + instance().settings().setValue("dejitter", dejitter); + Paddles::setDejitter(dejitter); + int sensitivity = myDPaddleSpeed->getValue(); instance().settings().setValue("dsense", sensitivity); Paddles::setDigitalSensitivity(sensitivity); + sensitivity = myMPaddleSpeed->getValue(); instance().settings().setValue("msense", sensitivity); Paddles::setMouseSensitivity(sensitivity); @@ -384,6 +402,8 @@ void InputDialog::setDefaults() myDPaddleLabel->setLabel("10"); myMPaddleSpeed->setValue(10); myMPaddleLabel->setLabel("10"); + myDejitter->setValue(0); + myDejitterLabel->setLabel("0"); myTrackBallSpeed->setValue(10); myTrackBallLabel->setLabel("10"); @@ -508,6 +528,10 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, myMPaddleLabel->setValue(myMPaddleSpeed->getValue()); break; + case kDejitterChanged: + myDejitterLabel->setValue(myDejitter->getValue()); + break; + case kTBSpeedChanged: myTrackBallLabel->setValue(myTrackBallSpeed->getValue()); break; diff --git a/src/gui/InputDialog.hxx b/src/gui/InputDialog.hxx index 2f3444be8..ba69da450 100644 --- a/src/gui/InputDialog.hxx +++ b/src/gui/InputDialog.hxx @@ -60,6 +60,7 @@ class InputDialog : public Dialog private: enum { kDeadzoneChanged = 'DZch', + kDejitterChanged = 'Pjch', kDPSpeedChanged = 'PDch', kMPSpeedChanged = 'PMch', kTBSpeedChanged = 'TBch', @@ -81,9 +82,11 @@ class InputDialog : public Dialog SliderWidget* myDeadzone; StaticTextWidget* myDeadzoneLabel; + SliderWidget* myDejitter; SliderWidget* myDPaddleSpeed; SliderWidget* myMPaddleSpeed; SliderWidget* myTrackBallSpeed; + StaticTextWidget* myDejitterLabel; StaticTextWidget* myDPaddleLabel; StaticTextWidget* myMPaddleLabel; StaticTextWidget* myTrackBallLabel;