added multiple controller support (joystick, driving, SaveKey, AtariVox)

This commit is contained in:
Thomas Jentzsch 2020-09-03 15:14:55 +02:00
parent 36aa23824a
commit 21bc244d97
10 changed files with 351 additions and 53 deletions

View File

@ -37,7 +37,7 @@
are no longer corrupted/cut off. This includes properly supporting the are no longer corrupted/cut off. This includes properly supporting the
2600-daptor II, which is flashable to an AVox-USB converter. 2600-daptor II, which is flashable to an AVox-USB converter.
* Added QuadTari controller support for josticks (TODO: doc, settings etc.) * Added QuadTari controller support for several controllers (TODO: docs)
* Added option to select the audio device. * Added option to select the audio device.

View File

@ -268,24 +268,15 @@
Atari 2600 FPGA project, including cycle-exact audio, analog interference Atari 2600 FPGA project, including cycle-exact audio, analog interference
from mixing of audio channels, as well as stereo sound support; dynamic from mixing of audio channels, as well as stereo sound support; dynamic
sound resampling is also included</li> sound resampling is also included</li>
<li>Emulates the Atari 2600 Joystick Controllers using your computer's keyboard, <li>Emulates the Atari 2600 Joystick, Paddle, Driving, CBS BoosterGrip, Sega Genesis, QuadTari controllers using your computer's keyboard,
joysticks or mouse</li> joysticks or mouse</li>
<li>Emulates the Atari 2600 Keyboard Controllers using your computer's keyboard</li> <li>Emulates CX22/CX80 style Trackballs, Amiga/Atari Mouse, Mindlink controller and the Light Gun using your
<li>Emulates the Atari 2600 Paddle Controllers using your computer's mouse, keyboard
or joysticks</li>
<li>Emulates the Atari 2600 Driving Controllers using your computer's keyboard,
joysticks or mouse</li>
<li>Emulates the CBS BoosterGrip Controller using your computer's keyboard,
joysticks or mouse</li>
<li>Emulates the Sega Genesis Controller using your computer's keyboard,
joysticks or mouse</li>
<li>Emulates CX22/CX80 style trackballs and Amiga/Atari Mouse using your
computer's mouse</li> computer's mouse</li>
<li>Emulates the Atari 2600 Keyboard controllers using your computer's keyboard</li>
<li>Emulates <a href="http://en.wikipedia.org/wiki/CompuMate">Spectravideo CompuMate</a> system using your computer's keyboard, <li>Emulates <a href="http://en.wikipedia.org/wiki/CompuMate">Spectravideo CompuMate</a> system using your computer's keyboard,
including mapping of CompuMate 'Backspace', 'Space' and 'Enter' functionality to including mapping of CompuMate 'Backspace', 'Space' and 'Enter' functionality to
to the actual keys on your keyboard</li> to the actual keys on your keyboard</li>
<li>Emulates the Mindlink Controller and the Light Gun using your computer's mouse</li> <li>Supports autodetection for most common controller types</li>
<li>Supports autodetection for most common controller types</li>
<li>Support for real Atari 2600 controllers using the <li>Support for real Atari 2600 controllers using the
<a href="http://www.grandideastudio.com/portfolio/stelladaptor-2600">Stelladaptor</a> and <a href="http://www.grandideastudio.com/portfolio/stelladaptor-2600">Stelladaptor</a> and
<a href="http://2600-daptor.com">2600-daptor/2600-daptor II</a></li> <a href="http://2600-daptor.com">2600-daptor/2600-daptor II</a></li>

View File

@ -699,6 +699,11 @@ bool ControllerDetector::isProbablyLightGun(const ByteBuffer& image, size_t size
bool ControllerDetector::isProbablyQuadTari(const ByteBuffer& image, size_t size, bool ControllerDetector::isProbablyQuadTari(const ByteBuffer& image, size_t size,
Controller::Jack port) Controller::Jack port)
{ {
uInt8 signatureBoth[] = { 0x1B, 0x1F, 0x0B, 0x0E, 0x1E, 0x0B, 0x1C, 0x13 }; // "QUADTARI"
if(searchForBytes(image, size, signatureBoth, 8))
return true;
if(port == Controller::Jack::Left) if(port == Controller::Jack::Left)
{ {
uInt8 signature[] = { 'Q', 'U', 'A', 'D', 'L' }; uInt8 signature[] = { 'Q', 'U', 'A', 'D', 'L' };
@ -711,8 +716,5 @@ bool ControllerDetector::isProbablyQuadTari(const ByteBuffer& image, size_t size
return searchForBytes(image, size, signature, 5); return searchForBytes(image, size, signature, 5);
} }
return false;
uInt8 signature[] = { 0x1B, 0x1F, 0x0B, 0x0E, 0x1E, 0x0B, 0x1C, 0x13 };
return searchForBytes(image, size, signature, 8);
} }

View File

@ -65,17 +65,18 @@ QuadTari::QuadTari(Jack jack, OSystem& osystem, const System& system, const Prop
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Controller> QuadTari::addController(const Controller::Type type, bool second) unique_ptr<Controller> QuadTari::addController(const Controller::Type type, bool second)
{ {
FilesystemNode nvramfile = myOSystem.nvramDir();
Controller::onMessageCallback callback = [&os = myOSystem](const string& msg) {
bool devSettings = os.settings().getBool("dev.settings");
if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
os.frameBuffer().showMessage(msg);
};
switch(type) switch(type)
{ {
case Controller::Type::AtariVox: case Controller::Type::AtariVox:
{ {
FilesystemNode nvramfile = myOSystem.nvramDir();
nvramfile /= "atarivox_eeprom.dat"; nvramfile /= "atarivox_eeprom.dat";
Controller::onMessageCallback callback = [&os = myOSystem](const string& msg) {
bool devSettings = os.settings().getBool("dev.settings");
if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
os.frameBuffer().showMessage(msg);
};
return make_unique<AtariVox>(myJack, myEvent, mySystem, return make_unique<AtariVox>(myJack, myEvent, mySystem,
myOSystem.settings().getString("avoxport"), myOSystem.settings().getString("avoxport"),
nvramfile, callback); // no alternative mapping here nvramfile, callback); // no alternative mapping here
@ -85,13 +86,7 @@ unique_ptr<Controller> QuadTari::addController(const Controller::Type type, bool
case Controller::Type::SaveKey: case Controller::Type::SaveKey:
{ {
FilesystemNode nvramfile = myOSystem.nvramDir();
nvramfile /= "savekey_eeprom.dat"; nvramfile /= "savekey_eeprom.dat";
Controller::onMessageCallback callback = [&os = myOSystem](const string& msg) {
bool devSettings = os.settings().getBool("dev.settings");
if(os.settings().getBool(devSettings ? "dev.eepromaccess" : "plr.eepromaccess"))
os.frameBuffer().showMessage(msg);
};
return make_unique<SaveKey>(myJack, myEvent, mySystem, return make_unique<SaveKey>(myJack, myEvent, mySystem,
nvramfile, callback); // no alternative mapping here nvramfile, callback); // no alternative mapping here
} }

View File

@ -31,6 +31,7 @@
#include "PopUpWidget.hxx" #include "PopUpWidget.hxx"
#include "Props.hxx" #include "Props.hxx"
#include "PropsSet.hxx" #include "PropsSet.hxx"
#include "QuadTariDialog.hxx"
#include "TabWidget.hxx" #include "TabWidget.hxx"
#include "TIAConstants.hxx" #include "TIAConstants.hxx"
#include "Widget.hxx" #include "Widget.hxx"
@ -236,10 +237,6 @@ GameInfoDialog::GameInfoDialog(
myLeftPortLabel->getTop()-1, myLeftPortLabel->getTop()-1,
pwidth, lineHeight, ctrls, "", 0, kLeftCChanged); pwidth, lineHeight, ctrls, "", 0, kLeftCChanged);
wid.push_back(myLeftPort); wid.push_back(myLeftPort);
myLeftQuadTari = new ButtonWidget(myTab, font, myLeftPort->getRight() + fontWidth * 2, myLeftPort->getTop() - 2,
"QuadTari" + ELLIPSIS, kLeftQTPressed);
wid.push_back(myLeftQuadTari);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
myLeftPortDetected = new StaticTextWidget(myTab, ifont, myLeftPort->getLeft(), ypos, myLeftPortDetected = new StaticTextWidget(myTab, ifont, myLeftPort->getLeft(), ypos,
@ -252,17 +249,17 @@ GameInfoDialog::GameInfoDialog(
pwidth, lineHeight, ctrls, "", 0, kRightCChanged); pwidth, lineHeight, ctrls, "", 0, kRightCChanged);
wid.push_back(myRightPort); wid.push_back(myRightPort);
myRightQuadTari = new ButtonWidget(myTab, font, myRightPort->getRight() + fontWidth * 2, myRightPort->getTop() - 2, myQuadTariButton = new ButtonWidget(myTab, font, myRightPort->getRight() + fontWidth * 4, myRightPort->getTop() - 2,
"QuadTari" + ELLIPSIS, kRightQTPressed); "QuadTari" + ELLIPSIS, kQuadTariPressed);
wid.push_back(myRightQuadTari); wid.push_back(myQuadTariButton);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
myRightPortDetected = new StaticTextWidget(myTab, ifont, myRightPort->getLeft(), ypos, myRightPortDetected = new StaticTextWidget(myTab, ifont, myRightPort->getLeft(), ypos,
"Sega Genesis detected"); "Sega Genesis detected");
ypos += ifont.getLineHeight() + VGAP + 4; ypos += ifont.getLineHeight() + VGAP + 4;
mySwapPorts = new CheckboxWidget(myTab, font, xpos + fontWidth * 2, mySwapPorts = new CheckboxWidget(myTab, font, myLeftPort->getRight() + fontWidth * 4,
myLeftPortDetected->getTop()-1, "Swap ports"); myLeftPort->getTop() + 1, "Swap ports");
wid.push_back(mySwapPorts); wid.push_back(mySwapPorts);
// EEPROM erase button for left/right controller // EEPROM erase button for left/right controller
@ -601,8 +598,22 @@ void GameInfoDialog::saveProperties()
myGameProperties.set(PropType::Console_RightDiff, myRightDiffGroup->getSelected() ? "B" : "A"); myGameProperties.set(PropType::Console_RightDiff, myRightDiffGroup->getSelected() ? "B" : "A");
// Controller properties // Controller properties
myGameProperties.set(PropType::Controller_Left, myLeftPort->getSelectedTag().toString()); string controller = myLeftPort->getSelectedTag().toString();
myGameProperties.set(PropType::Controller_Right, myRightPort->getSelectedTag().toString()); myGameProperties.set(PropType::Controller_Left, controller);
if(controller != "AUTO" && controller != "QUADTARI")
{
myGameProperties.set(PropType::Controller_Left1, "");
myGameProperties.set(PropType::Controller_Left2, "");
}
controller = myRightPort->getSelectedTag().toString();
myGameProperties.set(PropType::Controller_Right, controller);
if(controller != "AUTO" && controller != "QUADTARI")
{
myGameProperties.set(PropType::Controller_Right1, "");
myGameProperties.set(PropType::Controller_Right2, "");
}
myGameProperties.set(PropType::Console_SwapPorts, (mySwapPorts->isEnabled() && mySwapPorts->getState()) ? "YES" : "NO"); myGameProperties.set(PropType::Console_SwapPorts, (mySwapPorts->isEnabled() && mySwapPorts->getState()) ? "YES" : "NO");
myGameProperties.set(PropType::Controller_SwapPaddles, mySwapPaddles->getState() ? "YES" : "NO"); myGameProperties.set(PropType::Controller_SwapPaddles, mySwapPaddles->getState() ? "YES" : "NO");
@ -715,8 +726,12 @@ void GameInfoDialog::updateControllerStates()
if(type == Controller::Type::Unknown) if(type == Controller::Type::Unknown)
{ {
if(instance().hasConsole()) if(instance().hasConsole())
{
label = (!swapPorts ? instance().console().leftController().name() label = (!swapPorts ? instance().console().leftController().name()
: instance().console().rightController().name()) + " detected"; : instance().console().rightController().name() + " detected");
if(BSPF::startsWithIgnoreCase(label, "QUADTARI"))
label = "QuadTari detected"; // remove plugged-in controller names
}
else if(autoDetect) else if(autoDetect)
label = ControllerDetector::detectName(image, size, type, label = ControllerDetector::detectName(image, size, type,
!swapPorts ? Controller::Jack::Left : Controller::Jack::Right, !swapPorts ? Controller::Jack::Left : Controller::Jack::Right,
@ -730,8 +745,12 @@ void GameInfoDialog::updateControllerStates()
if(type == Controller::Type::Unknown) if(type == Controller::Type::Unknown)
{ {
if(instance().hasConsole()) if(instance().hasConsole())
{
label = (!swapPorts ? instance().console().rightController().name() label = (!swapPorts ? instance().console().rightController().name()
: instance().console().leftController().name()) + " detected"; : instance().console().leftController().name()) + " detected";
if(BSPF::startsWithIgnoreCase(label, "QUADTARI"))
label = "QuadTari detected"; // remove plugged-in controller names
}
else if(autoDetect) else if(autoDetect)
label = ControllerDetector::detectName(image, size, type, label = ControllerDetector::detectName(image, size, type,
!swapPorts ? Controller::Jack::Right : Controller::Jack::Left, !swapPorts ? Controller::Jack::Right : Controller::Jack::Left,
@ -770,8 +789,10 @@ void GameInfoDialog::updateControllerStates()
myRightPortLabel->setEnabled(enableSelectControl); myRightPortLabel->setEnabled(enableSelectControl);
myLeftPort->setEnabled(enableSelectControl); myLeftPort->setEnabled(enableSelectControl);
myRightPort->setEnabled(enableSelectControl); myRightPort->setEnabled(enableSelectControl);
myLeftQuadTari->setEnabled(BSPF::startsWithIgnoreCase(contrLeft, "QUADTARI")); myQuadTariButton->setEnabled(BSPF::startsWithIgnoreCase(contrLeft, "QUADTARI") ||
myRightQuadTari->setEnabled(BSPF::startsWithIgnoreCase(contrRight, "QUADTARI")); BSPF::startsWithIgnoreCase(contrRight, "QUADTARI") ||
BSPF::startsWithIgnoreCase(myLeftPortDetected->getLabel(), "QUADTARI") ||
BSPF::startsWithIgnoreCase(myRightPortDetected->getLabel(), "QUADTARI"));
mySwapPorts->setEnabled(enableSelectControl); mySwapPorts->setEnabled(enableSelectControl);
mySwapPaddles->setEnabled(enablePaddles); mySwapPaddles->setEnabled(enablePaddles);
@ -843,7 +864,7 @@ void GameInfoDialog::saveCurrentPropertiesToDisk()
void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
int data, int id) int data, int id)
{ {
switch (cmd) switch(cmd)
{ {
case GuiObject::kOKCmd: case GuiObject::kOKCmd:
saveConfig(); saveConfig();
@ -871,12 +892,22 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
updateControllerStates(); updateControllerStates();
break; break;
case kLeftQTPressed: case kQuadTariPressed:
break; {
bool enableLeft =
BSPF::startsWithIgnoreCase(myLeftPort->getSelectedTag().toString(), "QUADTARI") ||
BSPF::startsWithIgnoreCase(myLeftPortDetected->getLabel(), "QUADTARI");
bool enableRight =
BSPF::startsWithIgnoreCase(myRightPort->getSelectedTag().toString(), "QUADTARI") ||
BSPF::startsWithIgnoreCase(myRightPortDetected->getLabel(), "QUADTARI");
case kRightQTPressed: if(!myQuadTariDialog)
myQuadTariDialog = make_unique<QuadTariDialog>
(this, _font, _font.getMaxCharWidth() * 37, _font.getFontHeight() * 8,
myGameProperties);
myQuadTariDialog->show(enableLeft, enableRight);
break; break;
}
case kEEButtonPressed: case kEEButtonPressed:
eraseEEPROM(); eraseEEPROM();
break; break;

View File

@ -26,6 +26,7 @@ class StaticTextWidget;
class RadioButtonGroup; class RadioButtonGroup;
class TabWidget; class TabWidget;
class SliderWidget; class SliderWidget;
class QuadTariDialog;
#include "Dialog.hxx" #include "Dialog.hxx"
#include "Command.hxx" #include "Command.hxx"
@ -87,8 +88,7 @@ class GameInfoDialog : public Dialog, public CommandSender
StaticTextWidget* myLeftPortDetected{nullptr}; StaticTextWidget* myLeftPortDetected{nullptr};
PopUpWidget* myRightPort{nullptr}; PopUpWidget* myRightPort{nullptr};
StaticTextWidget* myRightPortDetected{nullptr}; StaticTextWidget* myRightPortDetected{nullptr};
ButtonWidget* myLeftQuadTari{nullptr}; ButtonWidget* myQuadTariButton{nullptr};
ButtonWidget* myRightQuadTari{nullptr};
CheckboxWidget* mySwapPorts{nullptr}; CheckboxWidget* mySwapPorts{nullptr};
CheckboxWidget* mySwapPaddles{nullptr}; CheckboxWidget* mySwapPaddles{nullptr};
StaticTextWidget* myEraseEEPROMLabel{nullptr}; StaticTextWidget* myEraseEEPROMLabel{nullptr};
@ -102,6 +102,9 @@ class GameInfoDialog : public Dialog, public CommandSender
PopUpWidget* myMouseY{nullptr}; PopUpWidget* myMouseY{nullptr};
SliderWidget* myMouseRange{nullptr}; SliderWidget* myMouseRange{nullptr};
// Allow assigning the four QuadTari controllers
unique_ptr<QuadTariDialog> myQuadTariDialog;
// Cartridge properties // Cartridge properties
EditTextWidget* myName{nullptr}; EditTextWidget* myName{nullptr};
EditTextWidget* myMD5{nullptr}; EditTextWidget* myMD5{nullptr};
@ -116,8 +119,7 @@ class GameInfoDialog : public Dialog, public CommandSender
kPPBlendChanged = 'PBch', kPPBlendChanged = 'PBch',
kLeftCChanged = 'LCch', kLeftCChanged = 'LCch',
kRightCChanged = 'RCch', kRightCChanged = 'RCch',
kLeftQTPressed = 'LQTp', kQuadTariPressed = 'QTpr',
kRightQTPressed = 'RQTp',
kMCtrlChanged = 'MCch', kMCtrlChanged = 'MCch',
kEEButtonPressed = 'EEgb', kEEButtonPressed = 'EEgb',
kPXCenterChanged = 'Pxch', kPXCenterChanged = 'Pxch',

200
src/gui/QuadTariDialog.cxx Normal file
View File

@ -0,0 +1,200 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "OSystem.hxx"
#include "EventHandler.hxx"
#include "Widget.hxx"
#include "PopUpWidget.hxx"
#include "Font.hxx"
#include "Variant.hxx"
#include "Props.hxx"
#include "PropsSet.hxx"
#include "QuadTariDialog.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
QuadTariDialog::QuadTariDialog(GuiObject* boss, const GUI::Font& font, int max_w, int max_h,
Properties& properties)
: Dialog(boss->instance(), boss->parent(), font, "QuadTari controllers", 0, 0, max_w, max_h),
myGameProperties(properties)
{
const int lineHeight = font.getLineHeight(),
fontHeight = font.getFontHeight(),
fontWidth = font.getMaxCharWidth(),
buttonHeight = font.getLineHeight() * 1.25;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
const int VGAP = fontHeight / 4;
int xpos, ypos;
WidgetArray wid;
VariantList ctrls;
xpos = HBORDER; ypos = VBORDER + _th;
ctrls.clear();
//VarList::push_back(ctrls, "Auto-detect", "AUTO");
VarList::push_back(ctrls, "Joystick", "JOYSTICK");
//VarList::push_back(ctrls, "Paddles", "PADDLES");
//VarList::push_back(ctrls, "Paddles_IAxis", "PADDLES_IAXIS");
//VarList::push_back(ctrls, "Paddles_IAxDr", "PADDLES_IAXDR");
//VarList::push_back(ctrls, "BoosterGrip", "BOOSTERGRIP");
VarList::push_back(ctrls, "Driving", "DRIVING");
//VarList::push_back(ctrls, "Keyboard", "KEYBOARD");
//VarList::push_back(ctrls, "AmigaMouse", "AMIGAMOUSE");
//VarList::push_back(ctrls, "AtariMouse", "ATARIMOUSE");
//VarList::push_back(ctrls, "Trakball", "TRAKBALL");
VarList::push_back(ctrls, "AtariVox", "ATARIVOX");
VarList::push_back(ctrls, "SaveKey", "SAVEKEY");
//VarList::push_back(ctrls, "Sega Genesis", "GENESIS");
//VarList::push_back(ctrls, "KidVid", "KIDVID");
//VarList::push_back(ctrls, "Lightgun", "LIGHTGUN");
//VarList::push_back(ctrls, "MindLink", "MINDLINK");
//VarList::push_back(ctrls, "QuadTari", "QUADTARI");
int pwidth = font.getStringWidth("Joystick12"); // looks better overall
myLeftPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Left port");
ypos += lineHeight + VGAP * 2;
myLeft1Port = new PopUpWidget(this, font, xpos, ypos,
pwidth, lineHeight, ctrls, "P1 ");
wid.push_back(myLeft1Port);
ypos += lineHeight + VGAP * 2;
myLeft2Port = new PopUpWidget(this, font, xpos, ypos,
pwidth, lineHeight, ctrls, "P2 ");
wid.push_back(myLeft2Port);
xpos = _w - HBORDER - myLeft1Port->getWidth(); // aligned right
ypos = myLeftPortLabel->getTop() - 1;
myRightPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Right port");
ypos += lineHeight + VGAP * 2;
myRight1Port = new PopUpWidget(this, font, xpos, ypos,
pwidth, lineHeight, ctrls, "P3 ");
wid.push_back(myRight1Port);
ypos += lineHeight + VGAP * 2;
myRight2Port = new PopUpWidget(this, font, xpos, ypos,
pwidth, lineHeight, ctrls, "P4 ");
wid.push_back(myRight2Port);
addDefaultsOKCancelBGroup(wid, _font);
addBGroupToFocusList(wid);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void QuadTariDialog::show(bool enableLeft, bool enableRight)
{
myLeftPortLabel->setEnabled(enableLeft);
myLeft1Port->setEnabled(enableLeft);
myLeft2Port->setEnabled(enableLeft);
myRightPortLabel->setEnabled(enableRight);
myRight1Port->setEnabled(enableRight);
myRight2Port->setEnabled(enableRight);
open();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void QuadTariDialog::loadControllerProperties(const Properties& props)
{
string controller;
if(myLeftPortLabel->isEnabled())
{
controller = props.get(PropType::Controller_Left1);
myLeft1Port->setSelected(controller, "Joystick");
controller = props.get(PropType::Controller_Left2);
myLeft2Port->setSelected(controller, "Joystick");
}
if(myRightPortLabel->isEnabled())
{
controller = props.get(PropType::Controller_Right1);
myRight1Port->setSelected(controller, "Joystick");
controller = props.get(PropType::Controller_Right2);
myRight2Port->setSelected(controller, "Joystick");
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void QuadTariDialog::loadConfig()
{
loadControllerProperties(myGameProperties);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void QuadTariDialog::saveConfig()
{
if(myLeftPortLabel->isEnabled())
{
string controller = myLeft1Port->getSelectedTag().toString();
myGameProperties.set(PropType::Controller_Left1, controller);
controller = myLeft2Port->getSelectedTag().toString();
myGameProperties.set(PropType::Controller_Left2, controller);
}
else
{
myGameProperties.set(PropType::Controller_Left1, "");
myGameProperties.set(PropType::Controller_Left2, "");
}
if(myRightPortLabel->isEnabled())
{
string controller = myRight1Port->getSelectedTag().toString();
myGameProperties.set(PropType::Controller_Right1, controller);
controller = myRight2Port->getSelectedTag().toString();
myGameProperties.set(PropType::Controller_Right2, controller);
}
else
{
myGameProperties.set(PropType::Controller_Right1, "");
myGameProperties.set(PropType::Controller_Right2, "");
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void QuadTariDialog::setDefaults()
{
// Load the default properties
const string& md5 = myGameProperties.get(PropType::Cart_MD5);
Properties defaultProperties;
instance().propSet().getMD5(md5, defaultProperties, true);
loadControllerProperties(defaultProperties);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void QuadTariDialog::handleCommand(CommandSender* sender, int cmd, int data, int id)
{
switch(cmd)
{
case GuiObject::kOKCmd:
saveConfig();
close();
break;
case GuiObject::kDefaultsCmd:
setDefaults();
break;
default:
Dialog::handleCommand(sender, cmd, data, id);
break;
}
}

View File

@ -0,0 +1,69 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef JOYSTICK_DIALOG_HXX
#define JOYSTICK_DIALOG_HXX
class CommandSender;
class PopUpWidget;
#include "Dialog.hxx"
/**
* Allow assigning controllers to the four QuadTari ports.
*/
class QuadTariDialog: public Dialog
{
public:
QuadTariDialog(GuiObject* boss, const GUI::Font& font, int max_w, int max_h,
Properties& properties);
~QuadTariDialog() override = default;
/** Place the dialog onscreen */
void show(bool enableLeft, bool enableRight);
private:
void loadConfig() override;
void saveConfig() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void setDefaults() override;
void loadControllerProperties(const Properties& props);
private:
StaticTextWidget* myLeftPortLabel{nullptr};
PopUpWidget* myLeft1Port{nullptr};
PopUpWidget* myLeft2Port{nullptr};
StaticTextWidget* myRightPortLabel{nullptr};
PopUpWidget* myRight1Port{nullptr};
PopUpWidget* myRight2Port{nullptr};
// Game properties for currently loaded ROM
Properties& myGameProperties;
private:
// Following constructors and assignment operators not supported
QuadTariDialog() = delete;
QuadTariDialog(const QuadTariDialog&) = delete;
QuadTariDialog(QuadTariDialog&&) = delete;
QuadTariDialog& operator=(const QuadTariDialog&) = delete;
QuadTariDialog& operator=(QuadTariDialog&&) = delete;
};
#endif

View File

@ -773,6 +773,7 @@
<ClCompile Include="..\gui\MessageDialog.cxx" /> <ClCompile Include="..\gui\MessageDialog.cxx" />
<ClCompile Include="..\gui\MessageMenu.cxx" /> <ClCompile Include="..\gui\MessageMenu.cxx" />
<ClCompile Include="..\gui\MinUICommandDialog.cxx" /> <ClCompile Include="..\gui\MinUICommandDialog.cxx" />
<ClCompile Include="..\gui\QuadTariDialog.cxx" />
<ClCompile Include="..\gui\R77HelpDialog.cxx" /> <ClCompile Include="..\gui\R77HelpDialog.cxx" />
<ClCompile Include="..\gui\RadioButtonWidget.cxx" /> <ClCompile Include="..\gui\RadioButtonWidget.cxx" />
<ClCompile Include="..\gui\SnapshotDialog.cxx" /> <ClCompile Include="..\gui\SnapshotDialog.cxx" />
@ -1815,6 +1816,7 @@
<ClInclude Include="..\gui\MessageDialog.hxx" /> <ClInclude Include="..\gui\MessageDialog.hxx" />
<ClInclude Include="..\gui\MessageMenu.hxx" /> <ClInclude Include="..\gui\MessageMenu.hxx" />
<ClInclude Include="..\gui\MinUICommandDialog.hxx" /> <ClInclude Include="..\gui\MinUICommandDialog.hxx" />
<ClInclude Include="..\gui\QuadTariDialog.hxx" />
<ClInclude Include="..\gui\R77HelpDialog.hxx" /> <ClInclude Include="..\gui\R77HelpDialog.hxx" />
<ClInclude Include="..\gui\RadioButtonWidget.hxx" /> <ClInclude Include="..\gui\RadioButtonWidget.hxx" />
<ClInclude Include="..\gui\SnapshotDialog.hxx" /> <ClInclude Include="..\gui\SnapshotDialog.hxx" />

View File

@ -1023,6 +1023,9 @@
<ClCompile Include="..\debugger\gui\QuadTariWidget.cxx"> <ClCompile Include="..\debugger\gui\QuadTariWidget.cxx">
<Filter>Source Files\debugger</Filter> <Filter>Source Files\debugger</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\gui\QuadTariDialog.cxx">
<Filter>Source Files\gui</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\common\bspf.hxx"> <ClInclude Include="..\common\bspf.hxx">
@ -2102,6 +2105,9 @@
<ClInclude Include="..\debugger\gui\QuadTariWidget.hxx"> <ClInclude Include="..\debugger\gui\QuadTariWidget.hxx">
<Filter>Header Files\debugger</Filter> <Filter>Header Files\debugger</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\gui\QuadTariDialog.hxx">
<Filter>Header Files\gui</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="stella.ico"> <None Include="stella.ico">