added autofire (resolves #676)

This commit is contained in:
thrust26 2020-07-25 10:19:07 +02:00
parent 78419f10d6
commit 41f501868a
22 changed files with 247 additions and 76 deletions

View File

@ -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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -2379,6 +2379,11 @@
faster movement.</td>
</tr>
<tr>
<td><pre>-autofirerate &lt;0 - 30&gt;</pre></td>
<td>Automatic trigger rate of the fire buttons in Hz (0 = disabled)</td>
</tr>
<tr>
<td><pre>-joyallow4 &lt;1|0&gt;</pre></td>
<td>Allow all 4 directions on a joystick to be pressed
@ -3302,6 +3307,7 @@
<tr><td>Analog paddle) Dejitter averaging</td><td>Strength of paddle input averaging, suppresses mouse jitter</td><td>-dejitter.base</td></tr>
<tr><td>(Analog paddle) Dejitter reaction</td><td>Strength of paddle reaction to fast paddle movements, suppresses mouse jitter</td><td>-dejitter.diff</td></tr>
<tr><td>Digital paddle sensitivity</td><td>Sensitivity used when emulating a paddle using a digital device</td><td>-dsense</td></tr>
<tr><td>Autofire rate</td><td>Automatic trigger rate of the fire buttons in Hz</td><td>-autofirerate</td></tr>
<tr><td>Allow all 4 directions ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
<tr><td>Use modifier key combos</td><td>Enable using modifier keys in keyboard actions</td><td>-modcombo</td></tr>
<tr><td>Swap Stelladaptor ports</td><td>Swap the order of the detected Stelladaptors/2600-daptors (see <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor/2600-daptor Support</a></b>)</td><td>-saport</td></tr>

View File

@ -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},

View File

@ -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));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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<Controller> Console::getControllerPort(const Controller::Type type,
return controller;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::changeAutoFireRate(int direction)
{
const Int32 scanlines = std::max<Int32>(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
{

View File

@ -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

View File

@ -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;

View File

@ -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<bool, 5> myDigitalPinState{true, true, true, true, true};

View File

@ -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;

View File

@ -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
};

View File

@ -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,

View File

@ -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
;

View File

@ -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));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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));
}

View File

@ -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<Controller::DigitalPin, 2> Paddles::ourButtonPin = {
DigitalPin::Four, DigitalPin::Three
};

View File

@ -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<Controller::DigitalPin, 2> ourButtonPin;
private:
// Following constructors and assignment operators not supported
Paddles() = delete;

View File

@ -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)));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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 <lr|rl> How to assign virtual ports to multiple\n"
<< " Stelladaptor/2600-daptors\n"
<< " -modcombo <1|0> Enable modifer key combos\n"

View File

@ -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()
{

View File

@ -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};