diff --git a/Changes.txt b/Changes.txt index 2952f2ae0..5d8291b4f 100644 --- a/Changes.txt +++ b/Changes.txt @@ -12,6 +12,14 @@ Release History =========================================================================== +6.1 to 6.2: (??? ??, 2020) + * Paddle centering and sensitivity can be adjusted now + + * High scores: Score addresses, game variation etc. can be defined for a + game. This allows the user to save high scores for these games. For each + game and variation, the top 10 scores can be saved. + + 6.0.2 to 6.1: (March 22, 2020) * IMPORTANT NOTES: diff --git a/src/common/MouseControl.cxx b/src/common/MouseControl.cxx index 35d8941f9..ee960c6bb 100644 --- a/src/common/MouseControl.cxx +++ b/src/common/MouseControl.cxx @@ -124,7 +124,7 @@ MouseControl::MouseControl(Console& console, const string& mode) int m_range = 100; if(!(m_axis >> m_range)) m_range = 100; - Paddles::setPaddleRange(m_range); + Paddles::setDigitalPaddleRange(m_range); // If the mouse isn't used at all, we still need one item in the list if(myModeList.size() == 0) diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 5a2617409..be6f00f43 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -923,6 +923,10 @@ unique_ptr Console::getControllerPort(const Controller::Type type, swapAxis = true; else if(type == Controller::Type::PaddlesIAxDr) swapAxis = swapDir = true; + + Paddles::setAnalogCenter(myOSystem.settings().getInt("pcenter")); + Paddles::setAnalogSensitivity(myOSystem.settings().getInt("psense")); + controller = make_unique(port, myEvent, *mySystem, swapPaddles, swapAxis, swapDir); break; diff --git a/src/emucore/Paddles.cxx b/src/emucore/Paddles.cxx index d8e60365a..b4782cfb8 100644 --- a/src/emucore/Paddles.cxx +++ b/src/emucore/Paddles.cxx @@ -234,12 +234,14 @@ void Paddles::update() new_val = sa_xaxis * (1 - dejitter) + myLastAxisX * dejitter; // only use new dejittered value for larger differences - if (abs(new_val - sa_xaxis) > 10) + if(abs(new_val - sa_xaxis) > 10) sa_xaxis = new_val; - setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_xaxis)) / 65536.0))); + setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * + (BSPF::clamp(32768 - Int32(Int32(sa_xaxis) * SENSITIVITY + CENTER), 0, 65536) / 65536.0))); sa_changed = true; } + if(abs(myLastAxisY - sa_yaxis) > 10) { // dejitter, suppress small changes only @@ -250,7 +252,8 @@ void Paddles::update() if (abs(new_val - sa_yaxis) > 10) sa_yaxis = new_val; - setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * ((32767 - Int16(sa_yaxis)) / 65536.0))); + setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * + (BSPF::clamp(32768 - Int32(Int32(sa_yaxis) * SENSITIVITY + CENTER), 0, 65536) / 65536.0))); sa_changed = true; } myLastAxisX = sa_xaxis; @@ -379,6 +382,22 @@ bool Paddles::setMouseControl( return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Paddles::setAnalogCenter(int center) +{ + // TODO: convert into ~5 pixel (also in Input Dialog!) + CENTER = BSPF::clamp(center, MIN_ANALOG_CENTER, MAX_ANALOG_CENTER) * 860; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +float Paddles::setAnalogSensitivity(int sensitivity) +{ + // BASE_ANALOG_SENSE * (1.1 ^ 20) = 1.0 + SENSITIVITY = BASE_ANALOG_SENSE * std::pow(1.1, BSPF::clamp(sensitivity, 0, MAX_ANALOG_SENSE)); + + return SENSITIVITY; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Paddles::setDejitterBase(int strength) { @@ -405,13 +424,16 @@ void Paddles::setMouseSensitivity(int sensitivity) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Paddles::setPaddleRange(int range) +void Paddles::setDigitalPaddleRange(int range) { range = BSPF::clamp(range, 1, 100); TRIGRANGE = int(TRIGMAX * (range / 100.0)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int Paddles::CENTER = 0; +float Paddles::SENSITIVITY = 1.0; + int Paddles::TRIGRANGE = Paddles::TRIGMAX; int Paddles::DIGITAL_SENSITIVITY = -1; int Paddles::DIGITAL_DISTANCE = -1; diff --git a/src/emucore/Paddles.hxx b/src/emucore/Paddles.hxx index 2f64a4df2..0a8adc9c9 100644 --- a/src/emucore/Paddles.hxx +++ b/src/emucore/Paddles.hxx @@ -48,6 +48,10 @@ class Paddles : public Controller virtual ~Paddles() = default; public: + static constexpr float BASE_ANALOG_SENSE = 0.148643628f; + static constexpr int MAX_ANALOG_SENSE = 30; + static constexpr int MIN_ANALOG_CENTER = -20; + static constexpr int MAX_ANALOG_CENTER = 20; static constexpr int MAX_DIGITAL_SENSE = 20; static constexpr int MAX_MOUSE_SENSE = 20; static constexpr int MIN_DEJITTER = 0; @@ -88,6 +92,21 @@ class Paddles : public Controller bool setMouseControl(Controller::Type xtype, int xid, Controller::Type ytype, int yid) override; + /** + Sets the center for analog paddles. + + @param center Value from -20 to 20, representing the center offset/860 + */ + static void setAnalogCenter(int center); + + /** + Sets the sensitivity for analog paddles. + + @param sensitivity Value from 0 to 30, where 20 equals 1 + @return Resulting sensitivity + */ + static float setAnalogSensitivity(int sensitivity); + /** @param strength Value from 0 to 10 */ @@ -127,7 +146,7 @@ class Paddles : public Controller @param range Value from 1 to 100, representing the percentage of the range to use */ - static void setPaddleRange(int range); + static void setDigitalPaddleRange(int range); static constexpr double MAX_RESISTANCE = 1400000.0; @@ -156,6 +175,9 @@ class Paddles : public Controller int myLastAxisX{0}, myLastAxisY{0}; int myAxisDigitalZero{0}, myAxisDigitalOne{0}; + static int CENTER; + static float SENSITIVITY; + static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE; static int DEJITTER_BASE, DEJITTER_DIFF; static int MOUSE_SENSITIVITY; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index eabe55dbf..0e3de3de8 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -21,6 +21,7 @@ #include "Version.hxx" #include "Logger.hxx" #include "AudioSettings.hxx" +#include "Paddles.hxx" #ifdef DEBUGGER_SUPPORT #include "DebuggerDialog.hxx" @@ -102,6 +103,8 @@ Settings::Settings() setPermanent("dejitter.base", "0"); setPermanent("dejitter.diff", "0"); setPermanent("dsense", "10"); + setPermanent("pcenter", "0"); + setPermanent("psense", "20"); setPermanent("msense", "10"); setPermanent("tsense", "10"); setPermanent("saport", "lr"); @@ -321,6 +324,14 @@ void Settings::validate() if(i < 0 || i > 3) setValue("cursor", "2"); + i = getInt("pcenter"); + if(i < Paddles::MIN_ANALOG_CENTER || i > Paddles::MAX_ANALOG_CENTER) + setValue("pcenter", "0"); + + i = getInt("psense"); + if(i < 0|| i > Paddles::MAX_ANALOG_SENSE) + setValue("psense", "20"); + i = getInt("dsense"); if(i < 1 || i > 20) setValue("dsense", "10"); @@ -445,8 +456,10 @@ void Settings::usage() const << " properties in given mode(see manual)\n" << " -grabmouse <1|0> Locks the mouse cursor in the TIA window\n" << " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n" - << " -dejitter.base <0-10> Strength of paddle value averaging\n" - << " -dejitter.diff <0-10> Strength of paddle reaction to fast movements\n" + << " -dejitter.base <0-10> Strength of analog paddle value averaging\n" + << " -dejitter.diff <0-10> Strength of analog paddle reaction to fast movements\n" + << " -pcenter <-20-20> Center of analog paddle\n" + << " -psense <0-30> Sensitivity of analog paddle movement\n" << " -dsense <1-20> Sensitivity of digital emulated paddle movement\n" << " -msense <1-20> Sensitivity of mouse emulated paddle movement\n" << " -tsense <1-20> Sensitivity of mouse emulated trackball movement\n" @@ -486,7 +499,7 @@ void Settings::usage() const << " -launcherroms <1|0> Show only ROMs in the launcher (vs. all files)\n" << " -romviewer Show ROM info viewer at given zoom level in ROM\n" << " launcher (use 0 for off)\n" - << " -lastrom Last played ROM, automatically selected in\n" + << " -lastrom Last played ROM, automatically selected in\n" << " launcher\n" << " -romloadcount Number of ROM to load next from multicard\n" << " -uipalette addTab(" Emulation Events ", TabWidget::AUTO_WIDTH); - myEmulEventMapper = new EventMappingWidget(myTab, font, 2, 2, + tabID = myTab->addTab(" Emul. Events ", TabWidget::AUTO_WIDTH); + myEmulEventMapper = new EventMappingWidget(myTab, _font, 2, 2, myTab->getWidth(), myTab->getHeight() - 4, EventMode::kEmulationMode); @@ -66,8 +66,8 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(myEmulEventMapper->getFocusList(), myTab, tabID); // 2) Event mapper for UI actions - tabID = myTab->addTab(" UI Events ", TabWidget::AUTO_WIDTH); - myMenuEventMapper = new EventMappingWidget(myTab, font, 2, 2, + tabID = myTab->addTab(" UI Events ", TabWidget::AUTO_WIDTH); + myMenuEventMapper = new EventMappingWidget(myTab, _font, 2, 2, myTab->getWidth(), myTab->getHeight() - 4, EventMode::kMenuMode); @@ -75,7 +75,10 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, addToFocusList(myMenuEventMapper->getFocusList(), myTab, tabID); // 3) Devices & ports - addDevicePortTab(font); + addDevicePortTab(); + + // 4) Mouse + addMouseTab(); // Finalize the tabs, and activate the first tab myTab->activateTabs(); @@ -83,7 +86,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent, // Add Defaults, OK and Cancel buttons WidgetArray wid; - addDefaultsOKCancelBGroup(wid, font); + addDefaultsOKCancelBGroup(wid, _font); addBGroupToFocusList(wid); } @@ -93,135 +96,109 @@ InputDialog::~InputDialog() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void InputDialog::addDevicePortTab(const GUI::Font& font) +void InputDialog::addDevicePortTab() { - const int lineHeight = font.getLineHeight(), - fontWidth = font.getMaxCharWidth(), - fontHeight = font.getFontHeight(); - int xpos, ypos, lwidth, pwidth, tabID; + const int lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(), + fontHeight = _font.getFontHeight(); + int xpos, ypos, lwidth, tabID; WidgetArray wid; - VariantList items; const int VGAP = 4; - const int VBORDER = 9; + const int VBORDER = 8; const int HBORDER = 8; // Devices/ports - tabID = myTab->addTab(" Devices & Ports ", TabWidget::AUTO_WIDTH); + tabID = myTab->addTab("Devices & Ports", TabWidget::AUTO_WIDTH); ypos = VBORDER; - lwidth = font.getStringWidth("Digital paddle sensitivity "); // was: "Use mouse as a controller " - pwidth = font.getStringWidth("-UI, -Emulation"); - - // Use mouse as controller - items.clear(); - VarList::push_back(items, "Always", "always"); - VarList::push_back(items, "Analog devices", "analog"); - VarList::push_back(items, "Never", "never"); - myMouseControl = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items, - "Use mouse as a controller ", lwidth); - wid.push_back(myMouseControl); - - // Mouse cursor state - ypos += lineHeight + VGAP; - items.clear(); - VarList::push_back(items, "-UI, -Emulation", "0"); - VarList::push_back(items, "-UI, +Emulation", "1"); - VarList::push_back(items, "+UI, -Emulation", "2"); - VarList::push_back(items, "+UI, +Emulation", "3"); - myCursorState = new PopUpWidget(myTab, font, HBORDER, ypos, pwidth, lineHeight, items, - "Mouse cursor visibility ", lwidth, kCursorStateChanged); - wid.push_back(myCursorState); -#ifndef WINDOWED_SUPPORT - myCursorState->clearFlags(Widget::FLAG_ENABLED); -#endif - - lwidth = font.getStringWidth("Digital paddle sensitivity "); + lwidth = _font.getStringWidth("Digital paddle sensitivity "); // Add joystick deadzone setting - ypos += lineHeight + VGAP*3; - myDeadzone = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, - "Joystick deadzone size ", lwidth, kDeadzoneChanged); + myDeadzone = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Joystick deadzone size", lwidth, kDeadzoneChanged, 5 * fontWidth); myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29); myDeadzone->setTickmarkIntervals(4); xpos = HBORDER + myDeadzone->getWidth() + 5; - myDeadzoneLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 5*fontWidth, lineHeight, ""); wid.push_back(myDeadzone); + xpos = HBORDER; ypos += lineHeight + VGAP * 2; + new StaticTextWidget(myTab, _font, xpos, ypos+1, "Analog paddle:"); + + // Add paddle center + xpos += fontWidth * 2; + ypos += lineHeight + VGAP; + + myPaddleCenter = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Center", + lwidth - fontWidth * 2, kPCenterChanged, 6 * fontWidth, "px", 0, true); + myPaddleCenter->setMinValue(Paddles::MIN_ANALOG_CENTER); + myPaddleCenter->setMaxValue(Paddles::MAX_ANALOG_CENTER); + myPaddleCenter->setTickmarkIntervals(4); + wid.push_back(myPaddleCenter); + + // Add paddle sensitivity + ypos += lineHeight + VGAP; + myPaddleSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, + "Sensitivity", + lwidth - fontWidth * 2, kPSpeedChanged, 4 * fontWidth, "%"); + myPaddleSpeed->setMinValue(0); myPaddleSpeed->setMaxValue(Paddles::MAX_ANALOG_SENSE); + myPaddleSpeed->setTickmarkIntervals(3); + wid.push_back(myPaddleSpeed); + + // Add dejitter (Stelladaptor emulation for now only) ypos += lineHeight + VGAP; - myDejitterBase = new SliderWidget(myTab, font, HBORDER, ypos - 1, 6 * fontWidth, lineHeight, - "Paddle dejitter strength", lwidth, kDejitterChanged); - myDejitterBase->setMinValue(Paddles::MIN_DEJITTER); myDejitterBase->setMaxValue(Paddles::MAX_DEJITTER); + myDejitterBase = new SliderWidget(myTab, _font, xpos, ypos - 1, 6 * fontWidth, lineHeight, + "Dejitter strength", lwidth - fontWidth * 2, kDejitterChanged); + myDejitterBase->setMinValue(Paddles::MIN_DEJITTER); + myDejitterBase->setMaxValue(Paddles::MAX_DEJITTER); myDejitterBase->setTickmarkIntervals(2); - xpos = HBORDER + myDejitterBase->getWidth() + fontWidth - 4; + xpos += myDejitterBase->getWidth() + fontWidth - 4; wid.push_back(myDejitterBase); - myDejitterDiff = new SliderWidget(myTab, font, xpos, ypos - 1, 6 * fontWidth, lineHeight, + myDejitterDiff = new SliderWidget(myTab, _font, xpos, ypos - 1, 6 * fontWidth, lineHeight, "", 0, kDejitterChanged); - myDejitterDiff->setMinValue(Paddles::MIN_DEJITTER); myDejitterDiff->setMaxValue(Paddles::MAX_DEJITTER); + myDejitterDiff->setMinValue(Paddles::MIN_DEJITTER); + myDejitterDiff->setMaxValue(Paddles::MAX_DEJITTER); myDejitterDiff->setTickmarkIntervals(2); - xpos += myDejitterDiff->getWidth() + 5; + xpos += myDejitterDiff->getWidth(); wid.push_back(myDejitterDiff); - myDejitterLabel = new StaticTextWidget(myTab, font, xpos, ypos + 1, 7 * fontWidth, lineHeight, ""); + myDejitterLabel = new StaticTextWidget(myTab, _font, xpos, ypos + 1, 7 * fontWidth, lineHeight, ""); // Add paddle speed (digital emulation) - ypos += lineHeight + VGAP; - myDPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, - "Digital paddle sensitivity ", - lwidth, kDPSpeedChanged); + ypos += lineHeight + VGAP * 4; + myDPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Digital paddle sensitivity", + lwidth, kDPSpeedChanged, 4 * fontWidth, "%"); myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20); myDPaddleSpeed->setTickmarkIntervals(4); - xpos = HBORDER + myDPaddleSpeed->getWidth() + 5; - myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, ""); wid.push_back(myDPaddleSpeed); - // Add paddle speed (mouse emulation) - ypos += lineHeight + VGAP; - myMPaddleSpeed = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, - "Mouse paddle sensitivity ", - lwidth, kMPSpeedChanged); - myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20); - myMPaddleSpeed->setTickmarkIntervals(4); - xpos = HBORDER + myMPaddleSpeed->getWidth() + 5; - myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, ""); - wid.push_back(myMPaddleSpeed); - // Add trackball speed - ypos += lineHeight + VGAP; - myTrackBallSpeed = new SliderWidget(myTab, font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, - "Trackball sensitivity ", - lwidth, kTBSpeedChanged); + ypos += lineHeight + VGAP * 2; + myTrackBallSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Trackball sensitivity", + lwidth, kTBSpeedChanged, 4 * fontWidth, "%"); myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20); myTrackBallSpeed->setTickmarkIntervals(4); - xpos = HBORDER + myTrackBallSpeed->getWidth() + 5; - myTrackBallLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, ""); wid.push_back(myTrackBallSpeed); // Add 'allow all 4 directions' for joystick - ypos += lineHeight + VGAP*3; - myAllowAll4 = new CheckboxWidget(myTab, font, HBORDER, ypos, + ypos += lineHeight + VGAP * 4; + myAllowAll4 = new CheckboxWidget(myTab, _font, HBORDER, ypos, "Allow all 4 directions on joystick"); wid.push_back(myAllowAll4); - // Grab mouse (in windowed mode) - ypos += lineHeight + VGAP; - myGrabMouse = new CheckboxWidget(myTab, font, HBORDER, ypos, - "Grab mouse in emulation mode"); - wid.push_back(myGrabMouse); -#ifndef WINDOWED_SUPPORT - myGrabMouse->clearFlags(Widget::FLAG_ENABLED); -#endif - // Enable/disable modifier key-combos ypos += lineHeight + VGAP; - myModCombo = new CheckboxWidget(myTab, font, HBORDER, ypos, - "Use modifier key combos"); + myModCombo = new CheckboxWidget(myTab, _font, HBORDER, ypos, + "Use modifier key combos"); wid.push_back(myModCombo); ypos += lineHeight + VGAP; // Stelladaptor mappings - mySAPort = new CheckboxWidget(myTab, font, HBORDER, ypos, + mySAPort = new CheckboxWidget(myTab, _font, HBORDER, ypos, "Swap Stelladaptor ports"); wid.push_back(mySAPort); @@ -229,37 +206,101 @@ void InputDialog::addDevicePortTab(const GUI::Font& font) // Add EEPROM erase (part 1/2) ypos += VGAP*4; - fwidth = font.getStringWidth("AtariVox/SaveKey"); - lwidth = font.getStringWidth("AtariVox/SaveKey"); - new StaticTextWidget(myTab, font, _w - HBORDER - 4 - (fwidth + lwidth) / 2, ypos, + fwidth = _font.getStringWidth("AtariVox/SaveKey"); + lwidth = _font.getStringWidth("AtariVox/SaveKey"); + new StaticTextWidget(myTab, _font, _w - HBORDER - 4 - (fwidth + lwidth) / 2, ypos, "AtariVox/SaveKey"); // Show joystick database ypos += lineHeight; - myJoyDlgButton = new ButtonWidget(myTab, font, HBORDER, ypos, 20, + myJoyDlgButton = new ButtonWidget(myTab, _font, HBORDER, ypos, 20, "Joystick Database" + ELLIPSIS, kDBButtonPressed); wid.push_back(myJoyDlgButton); // Add EEPROM erase (part 1/2) - myEraseEEPROMButton = new ButtonWidget(myTab, font, _w - HBORDER - 4 - fwidth, ypos, + myEraseEEPROMButton = new ButtonWidget(myTab, _font, _w - HBORDER - 4 - fwidth, ypos, fwidth, lineHeight+4, "Erase EEPROM", kEEButtonPressed); wid.push_back(myEraseEEPROMButton); // Add AtariVox serial port - ypos += lineHeight + VGAP*2; - lwidth = font.getStringWidth("AVox serial port "); + ypos += lineHeight + VGAP * 2; + lwidth = _font.getStringWidth("AVox serial port "); fwidth = _w - HBORDER * 2 - 4 - lwidth; - new StaticTextWidget(myTab, font, HBORDER, ypos + 2, "AVox serial port "); - myAVoxPort = new EditTextWidget(myTab, font, HBORDER + lwidth, ypos, + new StaticTextWidget(myTab, _font, HBORDER, ypos + 2, "AVox serial port "); + myAVoxPort = new EditTextWidget(myTab, _font, HBORDER + lwidth, ypos, fwidth, fontHeight); - wid.push_back(myAVoxPort); // Add items for virtual device ports addToFocusList(wid, myTab, tabID); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::addMouseTab() +{ + const int lineHeight = _font.getLineHeight(), + fontWidth = _font.getMaxCharWidth(), + fontHeight = _font.getFontHeight(); + int ypos, lwidth, pwidth, tabID; + WidgetArray wid; + VariantList items; + const int VGAP = 4; + const int VBORDER = 8; + const int HBORDER = 8; + + // Mouse + tabID = myTab->addTab(" Mouse ", TabWidget::AUTO_WIDTH); + + ypos = VBORDER; + lwidth = _font.getStringWidth("Use mouse as a controller "); + pwidth = _font.getStringWidth("-UI, -Emulation"); + + // Use mouse as controller + VarList::push_back(items, "Always", "always"); + VarList::push_back(items, "Analog devices", "analog"); + VarList::push_back(items, "Never", "never"); + myMouseControl = new PopUpWidget(myTab, _font, HBORDER, ypos, pwidth, lineHeight, items, + "Use mouse as a controller ", lwidth, kMouseCtrlChanged); + wid.push_back(myMouseControl); + + // Add paddle speed (mouse emulation) + ypos += lineHeight + VGAP; + myMPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Mouse paddle sensitivity ", + lwidth, kMPSpeedChanged, 4 * fontWidth, "%"); + myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20); + myMPaddleSpeed->setTickmarkIntervals(4); + wid.push_back(myMPaddleSpeed); + + + // Mouse cursor state + ypos += lineHeight + VGAP * 4; + items.clear(); + VarList::push_back(items, "-UI, -Emulation", "0"); + VarList::push_back(items, "-UI, +Emulation", "1"); + VarList::push_back(items, "+UI, -Emulation", "2"); + VarList::push_back(items, "+UI, +Emulation", "3"); + myCursorState = new PopUpWidget(myTab, _font, HBORDER, ypos, pwidth, lineHeight, items, + "Mouse cursor visibility ", lwidth, kCursorStateChanged); + wid.push_back(myCursorState); +#ifndef WINDOWED_SUPPORT + myCursorState->clearFlags(Widget::FLAG_ENABLED); +#endif + + // Grab mouse (in windowed mode) + ypos += lineHeight + VGAP; + myGrabMouse = new CheckboxWidget(myTab, _font, HBORDER, ypos, + "Grab mouse in emulation mode"); + wid.push_back(myGrabMouse); +#ifndef WINDOWED_SUPPORT + myGrabMouse->clearFlags(Widget::FLAG_ENABLED); +#endif + + // Add items for mouse + addToFocusList(wid, myTab, tabID); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::loadConfig() { @@ -269,6 +310,7 @@ void InputDialog::loadConfig() // Use mouse as a controller myMouseControl->setSelected( instance().settings().getString("usemouse"), "analog"); + handleMouseControlState(); // Mouse cursor state myCursorState->setSelected(instance().settings().getString("cursor"), "2"); @@ -276,20 +318,20 @@ void InputDialog::loadConfig() // Joystick deadzone myDeadzone->setValue(instance().settings().getInt("joydeadzone")); - myDeadzoneLabel->setValue(Joystick::deadzone()); + + // Paddle center & speed (analog) + myPaddleCenter->setValue(instance().settings().getInt("pcenter")); + myPaddleSpeed->setValue(instance().settings().getInt("psense")); // Paddle speed (digital and mouse) myDejitterBase->setValue(instance().settings().getInt("dejitter.base")); myDejitterDiff->setValue(instance().settings().getInt("dejitter.diff")); updateDejitter(); myDPaddleSpeed->setValue(instance().settings().getInt("dsense")); - myDPaddleLabel->setLabel(instance().settings().getString("dsense")); myMPaddleSpeed->setValue(instance().settings().getInt("msense")); - myMPaddleLabel->setLabel(instance().settings().getString("msense")); // Trackball speed myTrackBallSpeed->setValue(instance().settings().getInt("tsense")); - myTrackBallLabel->setLabel(instance().settings().getString("tsense")); // AtariVox serial port myAVoxPort->setText(instance().settings().getString("avoxport")); @@ -334,6 +376,16 @@ void InputDialog::saveConfig() instance().settings().setValue("joydeadzone", deadzone); Joystick::setDeadZone(deadzone); + // Paddle center (analog) + int center = myPaddleCenter->getValue(); + instance().settings().setValue("pcenter", center); + Paddles::setAnalogCenter(center); + + // Paddle speed (analog) + int sensitivity = myPaddleSpeed->getValue(); + instance().settings().setValue("psense", sensitivity); + Paddles::setAnalogSensitivity(sensitivity); + // Paddle speed (digital and mouse) int dejitter = myDejitterBase->getValue(); instance().settings().setValue("dejitter.base", dejitter); @@ -342,7 +394,7 @@ void InputDialog::saveConfig() instance().settings().setValue("dejitter.diff", dejitter); Paddles::setDejitterDiff(dejitter); - int sensitivity = myDPaddleSpeed->getValue(); + sensitivity = myDPaddleSpeed->getValue(); instance().settings().setValue("dsense", sensitivity); Paddles::setDigitalSensitivity(sensitivity); @@ -394,26 +446,19 @@ void InputDialog::setDefaults() myMenuEventMapper->setDefaults(); break; - case 2: // Virtual devices - { + case 2: // Devices & Ports // Left & right ports mySAPort->setState(false); - // Use mouse as a controller - myMouseControl->setSelected("analog"); - - // Mouse cursor state - myCursorState->setSelected("2"); - // Joystick deadzone myDeadzone->setValue(0); - myDeadzoneLabel->setValue(3200); - // Paddle speed (digital and mouse) + // Paddle center & speed (analog) + myPaddleCenter->setValue(0); + myPaddleSpeed->setValue(20); + + // Paddle speed (digital) myDPaddleSpeed->setValue(10); - myDPaddleLabel->setLabel("10"); - myMPaddleSpeed->setValue(10); - myMPaddleLabel->setLabel("10"); #if defined(RETRON77) myDejitterBase->setValue(2); myDejitterDiff->setValue(6); @@ -423,7 +468,6 @@ void InputDialog::setDefaults() #endif updateDejitter(); myTrackBallSpeed->setValue(10); - myTrackBallLabel->setLabel("10"); // AtariVox serial port myAVoxPort->setText(""); @@ -431,16 +475,27 @@ void InputDialog::setDefaults() // Allow all 4 joystick directions myAllowAll4->setState(false); - // Grab mouse - myGrabMouse->setState(true); - // Enable/disable modifier key-combos myModCombo->setState(true); - handleCursorState(); - break; - } + + case 3: // Mouse + // Use mouse as a controller + myMouseControl->setSelected("analog"); + + // Mouse cursor state + myCursorState->setSelected("2"); + + // Grab mouse + myGrabMouse->setState(true); + + // Paddle speed (mouse) + myMPaddleSpeed->setValue(10); + + handleMouseControlState(); + handleCursorState(); + break; default: break; @@ -566,28 +621,28 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, setDefaults(); break; - case kCursorStateChanged: - handleCursorState(); - break; - case kDeadzoneChanged: - myDeadzoneLabel->setValue(3200 + 1000*myDeadzone->getValue()); + myDeadzone->setValueLabel(3200 + 1000 * myDeadzone->getValue()); break; - case kDPSpeedChanged: - myDPaddleLabel->setValue(myDPaddleSpeed->getValue()); + case kPCenterChanged: + myPaddleCenter->setValueLabel(myPaddleCenter->getValue() * 5); break; - case kMPSpeedChanged: - myMPaddleLabel->setValue(myMPaddleSpeed->getValue()); + case kPSpeedChanged: + myPaddleSpeed->setValueLabel(Paddles::setAnalogSensitivity(myPaddleSpeed->getValue()) * 100.0 + 0.5); break; case kDejitterChanged: updateDejitter(); break; + case kDPSpeedChanged: + myDPaddleSpeed->setValueLabel(myDPaddleSpeed->getValue() * 10); + break; + case kTBSpeedChanged: - myTrackBallLabel->setValue(myTrackBallSpeed->getValue()); + myTrackBallSpeed->setValueLabel(myTrackBallSpeed->getValue() * 10); break; case kDBButtonPressed: @@ -623,20 +678,23 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, eraseEEPROM(); break; + case kMouseCtrlChanged: + handleMouseControlState(); + break; + + case kCursorStateChanged: + handleCursorState(); + break; + + case kMPSpeedChanged: + myMPaddleSpeed->setValueLabel(myMPaddleSpeed->getValue() * 10); + break; + default: Dialog::handleCommand(sender, cmd, data, 0); } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void InputDialog::handleCursorState() -{ - int state = myCursorState->getSelected(); - bool enableGrab = state != 1 && state != 3; - - myGrabMouse->setEnabled(enableGrab); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::updateDejitter() { @@ -659,3 +717,17 @@ void InputDialog::updateDejitter() myDejitterLabel->setLabel(label.str()); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::handleMouseControlState() +{ + myMPaddleSpeed->setEnabled(myMouseControl->getSelected() != 2); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::handleCursorState() +{ + int state = myCursorState->getSelected(); + bool enableGrab = state != 1 && state != 3; + + myGrabMouse->setEnabled(enableGrab); +} diff --git a/src/gui/InputDialog.hxx b/src/gui/InputDialog.hxx index 45fb8ed35..b86155fca 100644 --- a/src/gui/InputDialog.hxx +++ b/src/gui/InputDialog.hxx @@ -59,23 +59,29 @@ class InputDialog : public Dialog void saveConfig() override; void setDefaults() override; - void addDevicePortTab(const GUI::Font& font); + void addDevicePortTab(); + void addMouseTab(); + + void handleMouseControlState(); void handleCursorState(); void updateDejitter(); void eraseEEPROM(); private: enum { - kCursorStateChanged = 'CSch', kDeadzoneChanged = 'DZch', + kPCenterChanged = 'Pcch', + kPSpeedChanged = 'Ppch', kDejitterChanged = 'Pjch', kDPSpeedChanged = 'PDch', - kMPSpeedChanged = 'PMch', kTBSpeedChanged = 'TBch', kDBButtonPressed = 'DBbp', kEEButtonPressed = 'EEbp', - kConfirmEEEraseCmd = 'EEcf' + kConfirmEEEraseCmd = 'EEcf', + kMouseCtrlChanged = 'MCch', + kCursorStateChanged = 'CSch', + kMPSpeedChanged = 'PMch', }; TabWidget* myTab{nullptr}; @@ -90,16 +96,14 @@ class InputDialog : public Dialog EditTextWidget* myAVoxPort{nullptr}; SliderWidget* myDeadzone{nullptr}; - StaticTextWidget* myDeadzoneLabel{nullptr}; + SliderWidget* myPaddleCenter{nullptr}; + SliderWidget* myPaddleSpeed{nullptr}; SliderWidget* myDejitterBase{nullptr}; SliderWidget* myDejitterDiff{nullptr}; SliderWidget* myDPaddleSpeed{nullptr}; SliderWidget* myMPaddleSpeed{nullptr}; SliderWidget* myTrackBallSpeed{nullptr}; StaticTextWidget* myDejitterLabel{nullptr}; - StaticTextWidget* myDPaddleLabel{nullptr}; - StaticTextWidget* myMPaddleLabel{nullptr}; - StaticTextWidget* myTrackBallLabel{nullptr}; CheckboxWidget* myAllowAll4{nullptr}; CheckboxWidget* myGrabMouse{nullptr}; CheckboxWidget* myModCombo{nullptr};