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 ab187595e..55dc205c6 100644
Binary files a/docs/graphics/eventmapping_devsports.png and b/docs/graphics/eventmapping_devsports.png differ
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 averaging | Strength of paddle input averaging, suppresses mouse jitter | -dejitter.base |
(Analog paddle) Dejitter reaction | Strength of paddle reaction to fast paddle movements, suppresses mouse jitter | -dejitter.diff |
Digital paddle sensitivity | Sensitivity used when emulating a paddle using a digital device | -dsense |
+ Autofire rate | Automatic 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 combos | Enable using modifier keys in keyboard actions | -modcombo |
Swap Stelladaptor ports | Swap 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};