From 41f501868a6eb6fa85e10748748a9ef18113e351 Mon Sep 17 00:00:00 2001 From: thrust26 Date: Sat, 25 Jul 2020 10:19:07 +0200 Subject: [PATCH] added autofire (resolves #676) --- Changes.txt | 2 + docs/graphics/eventmapping_devsports.png | Bin 7375 -> 4523 bytes docs/index.html | 6 ++ src/common/PKeyboardHandler.cxx | 3 + src/emucore/Booster.cxx | 7 +- src/emucore/Console.cxx | 28 ++++++- src/emucore/Console.hxx | 5 ++ src/emucore/Control.cxx | 11 +++ src/emucore/Control.hxx | 53 +++++++++++++ src/emucore/Driving.cxx | 18 +++-- src/emucore/Event.hxx | 1 + src/emucore/EventHandler.cxx | 12 +++ src/emucore/EventHandler.hxx | 2 +- src/emucore/Genesis.cxx | 7 +- src/emucore/Joystick.cxx | 9 ++- src/emucore/Lightgun.cxx | 10 ++- src/emucore/Paddles.cxx | 40 ++++++---- src/emucore/Paddles.hxx | 4 - src/emucore/PointingDevice.cxx | 5 +- src/emucore/Settings.cxx | 2 + src/gui/InputDialog.cxx | 95 ++++++++++++++++------- src/gui/InputDialog.hxx | 3 + 22 files changed, 247 insertions(+), 76 deletions(-) diff --git a/Changes.txt b/Changes.txt index 6d3b5b2f1..3e0571978 100644 --- a/Changes.txt +++ b/Changes.txt @@ -14,6 +14,8 @@ 6.2.1 to 6.3 (XXXX XX, 2020) + * Added autofire. + * Added new interface palette 'Dark'. (TODO: DOC) * Extended global hotkeys for debug options. diff --git a/docs/graphics/eventmapping_devsports.png b/docs/graphics/eventmapping_devsports.png index ab187595e2a69043ebf460087983ea00bc21a024..55dc205c6cfd3511ad3d0f5ae5abf9e4aab3c14d 100644 GIT binary patch literal 4523 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 diff --git a/docs/index.html b/docs/index.html index 554f2cdbd..a12d7e457 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2379,6 +2379,11 @@ faster movement. + +
-autofirerate <0 - 30>
+ Automatic trigger rate of the fire buttons in Hz (0 = disabled) + +
-joyallow4 <1|0>
Allow all 4 directions on a joystick to be pressed @@ -3302,6 +3307,7 @@ Analog paddle) Dejitter averagingStrength of paddle input averaging, suppresses mouse jitter-dejitter.base (Analog paddle) Dejitter reactionStrength of paddle reaction to fast paddle movements, suppresses mouse jitter-dejitter.diff Digital paddle sensitivitySensitivity used when emulating a paddle using a digital device-dsense + Autofire rateAutomatic trigger rate of the fire buttons in Hz-autofirerate Allow all 4 directions ...Allow all 4 joystick directions to be pressed simultaneously-joyallow4 Use modifier key combosEnable using modifier keys in keyboard actions-modcombo Swap Stelladaptor portsSwap the order of the detected Stelladaptors/2600-daptors (see Advanced Configuration - Stelladaptor/2600-daptor Support)-saport diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx index f5d39b20a..6d726f3fc 100644 --- a/src/common/PKeyboardHandler.cxx +++ b/src/common/PKeyboardHandler.cxx @@ -534,6 +534,9 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo {Event::ToggleContSnapshots, KBDK_S, MOD3}, {Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3}, #endif + + {Event::DecreaseAutoFire, KBDK_A, KBDM_SHIFT | KBDM_CTRL}, + {Event::IncreaseAutoFire, KBDK_A, KBDM_CTRL }, {Event::HandleMouseControl, KBDK_0, KBDM_CTRL}, {Event::ToggleGrabMouse, KBDK_G, KBDM_CTRL}, {Event::ToggleSAPortOrder, KBDK_1, KBDM_CTRL}, diff --git a/src/emucore/Booster.cxx b/src/emucore/Booster.cxx index fddd51c21..96d328b8a 100644 --- a/src/emucore/Booster.cxx +++ b/src/emucore/Booster.cxx @@ -59,7 +59,7 @@ void BoosterGrip::update() setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0); setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0); setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0); - setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0); + bool firePressed = myEvent.get(myFireEvent) != 0; // The CBS Booster-grip has two more buttons on it. These buttons are // connected to the inputs usually used by paddles. @@ -120,11 +120,12 @@ void BoosterGrip::update() } } // Get mouse button state - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue); if(myEvent.get(Event::MouseButtonRightValue)) setPin(AnalogPin::Nine, MIN_RESISTANCE); } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index be2907fe9..dd9146ac9 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -434,7 +434,7 @@ void Console::setFormat(uInt32 format, bool force) setTIAProperties(); initializeVideo(); // takes care of refreshing the screen - initializeAudio(); // ensure that audio synthesis is set up to match emulation speed + initializeAudio(); // ensure that audio synthesis is set up to match emulation rate myOSystem.resetFps(); // Reset FPS measurement myOSystem.frameBuffer().showMessage(message); @@ -492,7 +492,7 @@ void Console::toggleTurbo() myOSystem.settings().setValue("turbo", !enabled); - // update speed + // update rate initializeAudio(); // update VSync @@ -870,6 +870,30 @@ unique_ptr Console::getControllerPort(const Controller::Type type, return controller; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Console::changeAutoFireRate(int direction) +{ + const Int32 scanlines = std::max(tia().scanlinesLastFrame(), 240); + const bool isNTSC = scanlines <= 287; + + int rate = myOSystem.settings().getInt("autofirerate"); + + rate = BSPF::clamp(rate + direction, 0, isNTSC ? 30 : 25); + + myOSystem.settings().setValue("autofirerate", rate); + Controller::setAutoFireRate(rate); + + ostringstream val; + + if(rate) + val << rate << " Hz"; + else + { + val << "Off"; + } + myOSystem.frameBuffer().showMessage("Autofire rate", val.str(), rate, 0, isNTSC ? 30 : 25); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - float Console::getFramerate() const { diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index 1cc37fc0b..86595da9f 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -318,6 +318,11 @@ class Console : public Serializable, public ConsoleIO */ void setTIAProperties(); + /** + Change the autofire speed for all controllers + */ + void changeAutoFireRate(int direction = +1); + private: /** * Define console timing based on current display format diff --git a/src/emucore/Control.cxx b/src/emucore/Control.cxx index 0584626de..813063c04 100644 --- a/src/emucore/Control.cxx +++ b/src/emucore/Control.cxx @@ -147,3 +147,14 @@ Controller::Type Controller::getType(const string& propName) return Type::Unknown; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Controller::setAutoFireRate(int rate, bool isNTSC) +{ + rate = BSPF::clamp(rate, 0, isNTSC ? 30 : 25); + AUTO_FIRE_RATE = 32 * 1024 * rate / (isNTSC ? 60 : 50); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int Controller::AUTO_FIRE_RATE = 0; + diff --git a/src/emucore/Control.hxx b/src/emucore/Control.hxx index a670f39f6..aa7e2aed3 100644 --- a/src/emucore/Control.hxx +++ b/src/emucore/Control.hxx @@ -272,6 +272,14 @@ class Controller : public Serializable */ static Type getType(const string& propName); + /** + Sets the auto fire rate. 0 disables auto fire. + + @param speed Auto fire rate (0..30/25) in Hz + @param isNTSC NTSC or PAL frame rate + */ + static void setAutoFireRate(int rate, bool isNTSC = true); + public: /// Constant which represents maximum resistance for analog pins static constexpr Int32 MAX_RESISTANCE = 0x7FFFFFFF; @@ -310,6 +318,44 @@ class Controller : public Serializable setPin(AnalogPin::Nine, MAX_RESISTANCE); } + /** + Checks for the next auto fire event. + + @param pressed True if the fire button is current pressed + @return The result of the auto fire event check + */ + inline bool getAutoFireState(bool pressed) + { + if(AUTO_FIRE_RATE && pressed) + { + myFireDelay -= AUTO_FIRE_RATE; + if(myFireDelay <= 0) + myFireDelay += 32 * 1024; + return myFireDelay > 16 * 1024; + } + myFireDelay = 0; + return pressed; + } + + /** + Checks for the next auto fire event for paddle 1. + + @param pressed True if the fire button is current pressed + @return The result of the auto fire event check + */ + inline bool getAutoFireStateP1(bool pressed) + { + if(AUTO_FIRE_RATE && pressed) + { + myFireDelayP1 -= AUTO_FIRE_RATE; + if(myFireDelayP1 <= 0) + myFireDelayP1 += 32 * 1024; + return myFireDelayP1 > 16 * 1024; + } + myFireDelayP1 = 0; + return pressed; + } + protected: /// Specifies which jack the controller is plugged in const Jack myJack; @@ -326,6 +372,13 @@ class Controller : public Serializable /// The callback that is dispatched whenver an analog pin has changed onAnalogPinUpdateCallback myOnAnalogPinUpdateCallback{nullptr}; + /// Defines the speed of the auto fire + static int AUTO_FIRE_RATE; + + /// Delay[frames] until the next fire event + int myFireDelay{0}; + int myFireDelayP1{0}; // required for paddles only + private: /// The boolean value on each digital pin std::array myDigitalPinState{true, true, true, true, true}; diff --git a/src/emucore/Driving.cxx b/src/emucore/Driving.cxx index 83f27e336..bd08a03e0 100644 --- a/src/emucore/Driving.cxx +++ b/src/emucore/Driving.cxx @@ -50,7 +50,8 @@ Driving::Driving(Jack jack, const Event& event, const System& system) void Driving::update() { // Digital events (from keyboard or joystick hats & buttons) - setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0); + bool firePressed = myEvent.get(myFireEvent) != 0; + int d_axis = myEvent.get(myXAxisValue); if(myEvent.get(myCCWEvent) != 0 || d_axis < -16384) --myCounter; else if(myEvent.get(myCWEvent) != 0 || d_axis > 16384) ++myCounter; @@ -61,9 +62,9 @@ void Driving::update() int m_axis = myEvent.get(Event::MouseAxisXMove); if(m_axis < -2) --myCounter; else if(m_axis > 2) ++myCounter; - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); } else { @@ -74,18 +75,19 @@ void Driving::update() int m_axis = myEvent.get(Event::MouseAxisXMove); if(m_axis < -2) --myCounter; else if(m_axis > 2) ++myCounter; - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue); } if(myControlIDY > -1) { int m_axis = myEvent.get(Event::MouseAxisYMove); if(m_axis < -2) --myCounter; else if(m_axis > 2) ++myCounter; - if(myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonRightValue); } } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); // Only consider the lower-most bits (corresponding to pins 1 & 2) myGrayIndex = Int32(myCounter * SENSITIVITY / 4.0F) & 0b11; diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx index 010007c72..b9a301e7f 100644 --- a/src/emucore/Event.hxx +++ b/src/emucore/Event.hxx @@ -126,6 +126,7 @@ class Event // add new events from here to avoid that user remapped events get overwritten PreviousSettingGroup, NextSettingGroup, TogglePlayBackMode, + DecreaseAutoFire, IncreaseAutoFire, LastType }; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index 5dbd2ca2f..6e6f38b50 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -102,6 +102,7 @@ void EventHandler::initialize() Paddles::setMouseSensitivity(myOSystem.settings().getInt("msense")); PointingDevice::setSensitivity(myOSystem.settings().getInt("tsense")); Driving::setSensitivity(myOSystem.settings().getInt("dcsense")); + Controller::setAutoFireRate(myOSystem.settings().getInt("autofirerate")); #ifdef GUI_SUPPORT // Set quick select delay when typing characters in listwidgets @@ -1249,6 +1250,14 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated) return; #endif + case Event::DecreaseAutoFire: + if(pressed) myOSystem.console().changeAutoFireRate(-1); + return; + + case Event::IncreaseAutoFire: + if(pressed) myOSystem.console().changeAutoFireRate(+1); + return; + case Event::HandleMouseControl: if (pressed && !repeated) handleMouseControl(); return; @@ -2558,6 +2567,8 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { { { Event::VolumeDecrease, "Decrease volume", "" }, { Event::VolumeIncrease, "Increase volume", "" }, + { Event::DecreaseAutoFire, "Decrease auto fire speed", "" }, + { Event::IncreaseAutoFire, "Increase auto fire speed", "" }, { Event::HandleMouseControl, "Switch mouse emulation modes", "" }, { Event::ToggleGrabMouse, "Toggle grab mouse", "" }, { Event::ToggleSAPortOrder, "Swap Stelladaptor port ordering", "" }, @@ -2627,6 +2638,7 @@ const Event::EventSet EventHandler::MiscEvents = { Event::TakeSnapshot, Event::ToggleContSnapshots, Event::ToggleContSnapshotsFrame, // Event::MouseAxisXMove, Event::MouseAxisYMove, // Event::MouseButtonLeftValue, Event::MouseButtonRightValue, + Event::DecreaseAutoFire, Event::IncreaseAutoFire, Event::HandleMouseControl, Event::ToggleGrabMouse, Event::ToggleSAPortOrder, Event::PreviousMultiCartRom, Event::PreviousSettingGroup, Event::NextSettingGroup, diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx index 3f780b150..055d56d64 100644 --- a/src/emucore/EventHandler.hxx +++ b/src/emucore/EventHandler.hxx @@ -558,7 +558,7 @@ class EventHandler #else REFRESH_SIZE = 0, #endif - EMUL_ACTIONLIST_SIZE = 160 + PNG_SIZE + COMBO_SIZE + REFRESH_SIZE, + EMUL_ACTIONLIST_SIZE = 162 + PNG_SIZE + COMBO_SIZE + REFRESH_SIZE, MENU_ACTIONLIST_SIZE = 18 ; diff --git a/src/emucore/Genesis.cxx b/src/emucore/Genesis.cxx index 488f04980..0b1ef7a2f 100644 --- a/src/emucore/Genesis.cxx +++ b/src/emucore/Genesis.cxx @@ -53,7 +53,7 @@ void Genesis::update() setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0); setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0); setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0); - setPin(DigitalPin::Six, myEvent.get(myFire1Event) == 0); + bool firePressed = myEvent.get(myFire1Event) != 0; // The Genesis has one more button (C) that can be read by the 2600 // However, it seems to work opposite to the BoosterGrip controller, @@ -88,11 +88,12 @@ void Genesis::update() } } // Get mouse button state - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue); if(myEvent.get(Event::MouseButtonRightValue)) setPin(AnalogPin::Five, MAX_RESISTANCE); } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Joystick.cxx b/src/emucore/Joystick.cxx index f9ee75545..ea0d71300 100644 --- a/src/emucore/Joystick.cxx +++ b/src/emucore/Joystick.cxx @@ -52,7 +52,7 @@ void Joystick::update() setPin(DigitalPin::Two, myEvent.get(myDownEvent) == 0); setPin(DigitalPin::Three, myEvent.get(myLeftEvent) == 0); setPin(DigitalPin::Four, myEvent.get(myRightEvent) == 0); - setPin(DigitalPin::Six, myEvent.get(myFireEvent) == 0); + bool firePressed = myEvent.get(myFireEvent) != 0; // Axis events (usually generated by the Stelladaptor) int xaxis = myEvent.get(myXAxisValue); @@ -102,10 +102,11 @@ void Joystick::update() } } // Get mouse button state - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); } + setPin(DigitalPin::Six, !getAutoFireState(firePressed)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Lightgun.cxx b/src/emucore/Lightgun.cxx index 1c6c82ba7..3ae39d8e5 100644 --- a/src/emucore/Lightgun.cxx +++ b/src/emucore/Lightgun.cxx @@ -116,10 +116,12 @@ bool Lightgun::read(DigitalPin pin) void Lightgun::update() { // Digital events (from keyboard or joystick hats & buttons) - setPin(DigitalPin::One, myEvent.get(Event::JoystickZeroFire) == 0); + bool firePressed = myEvent.get(Event::JoystickZeroFire) != 0; // We allow left and right mouse buttons for fire button - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::One, false); + firePressed = firePressed + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); + + setPin(DigitalPin::One, !getAutoFireState(firePressed)); } diff --git a/src/emucore/Paddles.cxx b/src/emucore/Paddles.cxx index 31ba8875d..a7f72ce1d 100644 --- a/src/emucore/Paddles.cxx +++ b/src/emucore/Paddles.cxx @@ -186,8 +186,8 @@ void Paddles::update() setPin(DigitalPin::Four, true); // Digital events (from keyboard or joystick hats & buttons) - setPin(DigitalPin::Three, myEvent.get(myP1FireEvent) == 0); - setPin(DigitalPin::Four, myEvent.get(myP0FireEvent) == 0); + bool firePressedP0 = myEvent.get(myP0FireEvent) != 0; + bool firePressedP1 = myEvent.get(myP1FireEvent) != 0; // Paddle movement is a very difficult thing to accurately emulate, // since it originally came from an analog device that had very @@ -269,9 +269,14 @@ void Paddles::update() myCharge[myMPaddleID] = BSPF::clamp(myCharge[myMPaddleID] - (myEvent.get(myAxisMouseMotion) * MOUSE_SENSITIVITY), TRIGMIN, TRIGRANGE); - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(ourButtonPin[myMPaddleID], false); + if(myMPaddleID == 0) + firePressedP0 = firePressedP0 + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); + else + firePressedP1 = firePressedP1 + || myEvent.get(Event::MouseButtonLeftValue) + || myEvent.get(Event::MouseButtonRightValue); } else { @@ -282,18 +287,30 @@ void Paddles::update() myCharge[myMPaddleIDX] = BSPF::clamp(myCharge[myMPaddleIDX] - (myEvent.get(Event::MouseAxisXMove) * MOUSE_SENSITIVITY), TRIGMIN, TRIGRANGE); - if(myEvent.get(Event::MouseButtonLeftValue)) - setPin(ourButtonPin[myMPaddleIDX], false); + + if(myMPaddleIDX == 0) + firePressedP0 = firePressedP0 + || myEvent.get(Event::MouseButtonLeftValue); + else + firePressedP1 = firePressedP1 + || myEvent.get(Event::MouseButtonLeftValue); } if(myMPaddleIDY > -1) { myCharge[myMPaddleIDY] = BSPF::clamp(myCharge[myMPaddleIDY] - (myEvent.get(Event::MouseAxisYMove) * MOUSE_SENSITIVITY), TRIGMIN, TRIGRANGE); - if(myEvent.get(Event::MouseButtonRightValue)) - setPin(ourButtonPin[myMPaddleIDY], false); + + if(myMPaddleIDY == 0) + firePressedP0 = firePressedP0 + || myEvent.get(Event::MouseButtonRightValue); + else + firePressedP1 = firePressedP1 + || myEvent.get(Event::MouseButtonRightValue); } } + setPin(DigitalPin::Four, !getAutoFireState(firePressedP0)); + setPin(DigitalPin::Three, !getAutoFireStateP1(firePressedP1)); // Finally, consider digital input, where movement happens // until a digital event is released @@ -449,8 +466,3 @@ int Paddles::DIGITAL_DISTANCE = -1; int Paddles::MOUSE_SENSITIVITY = -1; int Paddles::DEJITTER_BASE = 0; int Paddles::DEJITTER_DIFF = 0; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const std::array Paddles::ourButtonPin = { - DigitalPin::Four, DigitalPin::Three -}; diff --git a/src/emucore/Paddles.hxx b/src/emucore/Paddles.hxx index 57acda958..bb8144b21 100644 --- a/src/emucore/Paddles.hxx +++ b/src/emucore/Paddles.hxx @@ -190,10 +190,6 @@ class Paddles : public Controller static int DEJITTER_BASE, DEJITTER_DIFF; static int MOUSE_SENSITIVITY; - // Lookup table for associating paddle buttons with controller pins - // Yes, this is hideously complex - static const std::array ourButtonPin; - private: // Following constructors and assignment operators not supported Paddles() = delete; diff --git a/src/emucore/PointingDevice.cxx b/src/emucore/PointingDevice.cxx index 4d91d010c..05cf7c031 100644 --- a/src/emucore/PointingDevice.cxx +++ b/src/emucore/PointingDevice.cxx @@ -92,9 +92,8 @@ void PointingDevice::update() setPin(DigitalPin::Six, myEvent.get(Event::JoystickZeroFire) == 0); // We allow left and right mouse buttons for fire button - if(myEvent.get(Event::MouseButtonLeftValue) || - myEvent.get(Event::MouseButtonRightValue)) - setPin(DigitalPin::Six, false); + setPin(DigitalPin::Six, !getAutoFireState( + myEvent.get(Event::MouseButtonLeftValue) || myEvent.get(Event::MouseButtonRightValue))); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 0c5073d45..0ccc7ebd5 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -100,6 +100,7 @@ Settings::Settings() setPermanent("combomap", ""); setPermanent("joydeadzone", "13"); setPermanent("joyallow4", "false"); + setPermanent("autofirerate", "0"); setPermanent("usemouse", "analog"); setPermanent("grabmouse", "true"); setPermanent("cursor", "2"); @@ -481,6 +482,7 @@ void Settings::usage() const << " -tsense <1-20> Sensitivity of mouse emulated trackball movement\n" << " -dcsense <1-20> Sensitivity of digital emulated driving controller\n" << " movement\n" + << " -autofirerate <0-30> Set fire button's autofire rate (0 means off)\n" << " -saport How to assign virtual ports to multiple\n" << " Stelladaptor/2600-daptors\n" << " -modcombo <1|0> Enable modifer key combos\n" diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx index 3cced561b..4e792348c 100644 --- a/src/gui/InputDialog.cxx +++ b/src/gui/InputDialog.cxx @@ -134,7 +134,7 @@ void InputDialog::addDevicePortTab() xpos += fontWidth * 2; // Add analog paddle sensitivity - ypos += lineHeight + VGAP; + ypos += lineHeight; myPaddleSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight, "Sensitivity", lwidth - fontWidth * 2, kPSpeedChanged, 4 * fontWidth, "%"); @@ -172,6 +172,14 @@ void InputDialog::addDevicePortTab() myDPaddleSpeed->setTickmarkIntervals(4); wid.push_back(myDPaddleSpeed); + ypos += lineHeight + VGAP * 4; + myAutoFireRate = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight, + "Autofire rate", + lwidth, kAutoFireChanged, 5 * fontWidth, "Hz"); + myAutoFireRate->setMinValue(0); myAutoFireRate->setMaxValue(30); + myAutoFireRate->setTickmarkIntervals(6); + wid.push_back(myAutoFireRate); + // Add 'allow all 4 directions' for joystick ypos += lineHeight + VGAP * 4; myAllowAll4 = new CheckboxWidget(myTab, _font, HBORDER, ypos, @@ -315,38 +323,43 @@ void InputDialog::addMouseTab() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::loadConfig() { + Settings& settings = instance().settings(); + // Left & right ports - mySAPort->setState(instance().settings().getString("saport") == "rl"); + mySAPort->setState(settings.getString("saport") == "rl"); // Use mouse as a controller myMouseControl->setSelected( - instance().settings().getString("usemouse"), "analog"); + settings.getString("usemouse"), "analog"); handleMouseControlState(); // Mouse cursor state - myCursorState->setSelected(instance().settings().getString("cursor"), "2"); + myCursorState->setSelected(settings.getString("cursor"), "2"); handleCursorState(); // Joystick deadzone - myDeadzone->setValue(instance().settings().getInt("joydeadzone")); + myDeadzone->setValue(settings.getInt("joydeadzone")); // Paddle speed (analog) - myPaddleSpeed->setValue(instance().settings().getInt("psense")); + myPaddleSpeed->setValue(settings.getInt("psense")); // Paddle dejitter (analog) - myDejitterBase->setValue(instance().settings().getInt("dejitter.base")); - myDejitterDiff->setValue(instance().settings().getInt("dejitter.diff")); + myDejitterBase->setValue(settings.getInt("dejitter.base")); + myDejitterDiff->setValue(settings.getInt("dejitter.diff")); // Paddle speed (digital and mouse) - myDPaddleSpeed->setValue(instance().settings().getInt("dsense")); - myMPaddleSpeed->setValue(instance().settings().getInt("msense")); + myDPaddleSpeed->setValue(settings.getInt("dsense")); + myMPaddleSpeed->setValue(settings.getInt("msense")); // Trackball speed - myTrackBallSpeed->setValue(instance().settings().getInt("tsense")); + myTrackBallSpeed->setValue(settings.getInt("tsense")); // Driving controller speed - myDrivingSpeed->setValue(instance().settings().getInt("dcsense")); + myDrivingSpeed->setValue(settings.getInt("dcsense")); + + // Autofire rate + myAutoFireRate->setValue(settings.getInt("autofirerate")); // AtariVox serial port - myAVoxPort->setText(instance().settings().getString("avoxport")); + myAVoxPort->setText(settings.getString("avoxport")); // EEPROM erase (only enable in emulation mode and for valid controllers) if(instance().hasConsole()) @@ -361,13 +374,13 @@ void InputDialog::loadConfig() myEraseEEPROMButton->setEnabled(false); // Allow all 4 joystick directions - myAllowAll4->setState(instance().settings().getBool("joyallow4")); + myAllowAll4->setState(settings.getBool("joyallow4")); // Grab mouse - myGrabMouse->setState(instance().settings().getBool("grabmouse")); + myGrabMouse->setState(settings.getBool("grabmouse")); // Enable/disable modifier key-combos - myModCombo->setState(instance().settings().getBool("modcombo")); + myModCombo->setState(settings.getBool("modcombo")); myTab->loadConfig(); } @@ -375,70 +388,77 @@ void InputDialog::loadConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::saveConfig() { + Settings& settings = instance().settings(); + // Left & right ports instance().eventHandler().mapStelladaptors(mySAPort->getState() ? "rl": "lr"); // Use mouse as a controller const string& usemouse = myMouseControl->getSelectedTag().toString(); - instance().settings().setValue("usemouse", usemouse); + settings.setValue("usemouse", usemouse); instance().eventHandler().setMouseControllerMode(usemouse); // Joystick deadzone int deadzone = myDeadzone->getValue(); - instance().settings().setValue("joydeadzone", deadzone); + settings.setValue("joydeadzone", deadzone); Joystick::setDeadZone(deadzone); // Paddle speed (analog) int sensitivity = myPaddleSpeed->getValue(); - instance().settings().setValue("psense", sensitivity); + settings.setValue("psense", sensitivity); Paddles::setAnalogSensitivity(sensitivity); // Paddle speed (digital and mouse) int dejitter = myDejitterBase->getValue(); - instance().settings().setValue("dejitter.base", dejitter); + settings.setValue("dejitter.base", dejitter); Paddles::setDejitterBase(dejitter); dejitter = myDejitterDiff->getValue(); - instance().settings().setValue("dejitter.diff", dejitter); + settings.setValue("dejitter.diff", dejitter); Paddles::setDejitterDiff(dejitter); sensitivity = myDPaddleSpeed->getValue(); - instance().settings().setValue("dsense", sensitivity); + settings.setValue("dsense", sensitivity); Paddles::setDigitalSensitivity(sensitivity); sensitivity = myMPaddleSpeed->getValue(); - instance().settings().setValue("msense", sensitivity); + settings.setValue("msense", sensitivity); Paddles::setMouseSensitivity(sensitivity); // Trackball speed sensitivity = myTrackBallSpeed->getValue(); - instance().settings().setValue("tsense", sensitivity); + settings.setValue("tsense", sensitivity); PointingDevice::setSensitivity(sensitivity); // Driving controller speed sensitivity = myDrivingSpeed->getValue(); - instance().settings().setValue("dcsense", sensitivity); + settings.setValue("dcsense", sensitivity); Driving::setSensitivity(sensitivity); + // Autofire rate + int rate = myAutoFireRate->getValue(); + settings.setValue("autofirerate", rate); + Controller::setAutoFireRate(rate); + // AtariVox serial port - instance().settings().setValue("avoxport", myAVoxPort->getText()); + settings.setValue("avoxport", myAVoxPort->getText()); // Allow all 4 joystick directions bool allowall4 = myAllowAll4->getState(); - instance().settings().setValue("joyallow4", allowall4); + settings.setValue("joyallow4", allowall4); instance().eventHandler().allowAllDirections(allowall4); // Grab mouse and hide cursor const string& cursor = myCursorState->getSelectedTag().toString(); - instance().settings().setValue("cursor", cursor); + settings.setValue("cursor", cursor); // only allow grab mouse if cursor is hidden in emulation int state = myCursorState->getSelected(); bool enableGrab = state != 1 && state != 3; bool grab = enableGrab ? myGrabMouse->getState() : false; - instance().settings().setValue("grabmouse", grab); + settings.setValue("grabmouse", grab); instance().frameBuffer().enableGrabMouse(grab); // Enable/disable modifier key-combos - instance().settings().setValue("modcombo", myModCombo->getState()); + settings.setValue("modcombo", myModCombo->getState()); instance().eventHandler().saveKeyMapping(); instance().eventHandler().saveJoyMapping(); @@ -477,6 +497,8 @@ void InputDialog::setDefaults() myDejitterBase->setValue(0); myDejitterDiff->setValue(0); #endif + // Autofire rate + myAutoFireRate->setValue(0); // AtariVox serial port myAVoxPort->setText(""); @@ -659,6 +681,10 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd, myTrackBallSpeed->setValueLabel(myTrackBallSpeed->getValue() * 10); break; + case kAutoFireChanged: + updateAutoFireRate(); + break; + case kDBButtonPressed: if(!myJoyDialog) { @@ -726,6 +752,15 @@ void InputDialog::updateDejitterReaction() myDejitterDiff->setValueLabel(strength ? std::to_string(strength) : "Off"); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void InputDialog::updateAutoFireRate() +{ + int rate = myAutoFireRate->getValue(); + + myAutoFireRate->setValueLabel(rate ? std::to_string(rate) : "Off"); + myAutoFireRate->setValueUnit(rate ? " Hz" : ""); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void InputDialog::handleMouseControlState() { diff --git a/src/gui/InputDialog.hxx b/src/gui/InputDialog.hxx index 48e1629a3..6893d2c43 100644 --- a/src/gui/InputDialog.hxx +++ b/src/gui/InputDialog.hxx @@ -66,6 +66,7 @@ class InputDialog : public Dialog void handleCursorState(); void updateDejitterAveraging(); void updateDejitterReaction(); + void updateAutoFireRate(); void eraseEEPROM(); private: @@ -75,6 +76,7 @@ class InputDialog : public Dialog kDejitterAvChanged = 'JAch', kDejitterReChanged = 'JRch', kDPSpeedChanged = 'PDch', + kAutoFireChanged = 'AFch', kTBSpeedChanged = 'TBch', kDCSpeedChanged = 'DCch', kDBButtonPressed = 'DBbp', @@ -99,6 +101,7 @@ class InputDialog : public Dialog SliderWidget* myDejitterBase{nullptr}; SliderWidget* myDejitterDiff{nullptr}; SliderWidget* myDPaddleSpeed{nullptr}; + SliderWidget* myAutoFireRate{nullptr}; CheckboxWidget* myAllowAll4{nullptr}; CheckboxWidget* myModCombo{nullptr};