replace magic controller strings with enums

automatic detected controller update in GameInfoDialog & StellaSettingsDialog
This commit is contained in:
Thomas Jentzsch 2019-08-16 11:05:55 +02:00
parent d531d8e686
commit 48836e849e
15 changed files with 364 additions and 311 deletions

View File

@ -321,33 +321,37 @@ void PhysicalJoystickHandler::setDefaultMapping(Event::Type event, EventMode mod
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystickHandler::defineControllerMappings(const string& controllerName, Controller::Jack port) void PhysicalJoystickHandler::defineControllerMappings(const Controller::Type type, Controller::Jack port)
{ {
// determine controller events to use // determine controller events to use
if ((controllerName == "KEYBOARD") || (controllerName == "KEYPAD")) switch(type)
{ {
if (port == Controller::Jack::Left) case Controller::Type::Keyboard:
myLeftMode = EventMode::kKeypadMode; if(port == Controller::Jack::Left)
else myLeftMode = EventMode::kKeypadMode;
myRightMode = EventMode::kKeypadMode; else
} myRightMode = EventMode::kKeypadMode;
else if (BSPF::startsWithIgnoreCase(controllerName, "PADDLES")) break;
{
if (port == Controller::Jack::Left) case Controller::Type::Paddles:
myLeftMode = EventMode::kPaddlesMode; case Controller::Type::PaddlesIAxDr:
else case Controller::Type::PaddlesIAxis:
myRightMode = EventMode::kPaddlesMode; if(port == Controller::Jack::Left)
} myLeftMode = EventMode::kPaddlesMode;
else if (controllerName == "CM") else
{ myRightMode = EventMode::kPaddlesMode;
myLeftMode = myRightMode = EventMode::kCompuMateMode; break;
}
else case Controller::Type::CompuMate:
{ myLeftMode = myRightMode = EventMode::kCompuMateMode;
if (port == Controller::Jack::Left) break;
myLeftMode = EventMode::kJoystickMode;
else default:
myRightMode = EventMode::kJoystickMode; // let's use joystick then
if(port == Controller::Jack::Left)
myLeftMode = EventMode::kJoystickMode;
else
myRightMode = EventMode::kJoystickMode;
} }
} }

View File

@ -71,7 +71,7 @@ class PhysicalJoystickHandler
void setDefaultMapping(Event::Type type, EventMode mode); void setDefaultMapping(Event::Type type, EventMode mode);
/** define mappings for current controllers */ /** define mappings for current controllers */
void defineControllerMappings(const string& controllerName, Controller::Jack port); void defineControllerMappings(const Controller::Type type, Controller::Jack port);
/** enable mappings for emulation mode */ /** enable mappings for emulation mode */
void enableEmulationMappings(); void enableEmulationMappings();

View File

@ -139,33 +139,37 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::defineControllerMappings(const string& controllerName, Controller::Jack port) void PhysicalKeyboardHandler::defineControllerMappings(const Controller::Type type, Controller::Jack port)
{ {
// determine controller events to use // determine controller events to use
if ((controllerName == "KEYBOARD") || (controllerName == "KEYPAD")) switch(type)
{ {
if (port == Controller::Jack::Left) case Controller::Type::Keyboard:
myLeftMode = EventMode::kKeypadMode; if(port == Controller::Jack::Left)
else myLeftMode = EventMode::kKeypadMode;
myRightMode = EventMode::kKeypadMode; else
} myRightMode = EventMode::kKeypadMode;
else if (BSPF::startsWithIgnoreCase(controllerName, "PADDLES")) break;
{
if (port == Controller::Jack::Left) case Controller::Type::Paddles:
myLeftMode = EventMode::kPaddlesMode; case Controller::Type::PaddlesIAxDr:
else case Controller::Type::PaddlesIAxis:
myRightMode = EventMode::kPaddlesMode; if(port == Controller::Jack::Left)
} myLeftMode = EventMode::kPaddlesMode;
else if (controllerName == "CM") else
{ myRightMode = EventMode::kPaddlesMode;
myLeftMode = myRightMode = EventMode::kCompuMateMode; break;
}
else case Controller::Type::CompuMate:
{ myLeftMode = myRightMode = EventMode::kCompuMateMode;
if (port == Controller::Jack::Left) break;
myLeftMode = EventMode::kJoystickMode;
else default:
myRightMode = EventMode::kJoystickMode; // let's use joystick then
if(port == Controller::Jack::Left)
myLeftMode = EventMode::kJoystickMode;
else
myRightMode = EventMode::kJoystickMode;
} }
} }

View File

@ -48,7 +48,7 @@ class PhysicalKeyboardHandler
void setDefaultMapping(Event::Type type, EventMode mode, bool updateDefaults = false); void setDefaultMapping(Event::Type type, EventMode mode, bool updateDefaults = false);
/** define mappings for current controllers */ /** define mappings for current controllers */
void defineControllerMappings(const string& controllerName, Controller::Jack port); void defineControllerMappings(const Controller::Type type, Controller::Jack port);
/** enable mappings for emulation mode */ /** enable mappings for emulation mode */
void enableEmulationMappings(); void enableEmulationMappings();

View File

@ -801,14 +801,14 @@ void Console::setControllers(const string& romMd5)
myLeftControl = std::move(myCMHandler->leftController()); myLeftControl = std::move(myCMHandler->leftController());
myRightControl = std::move(myCMHandler->rightController()); myRightControl = std::move(myCMHandler->rightController());
myOSystem.eventHandler().defineKeyControllerMappings("CM", Controller::Jack::Left); myOSystem.eventHandler().defineKeyControllerMappings(Controller::Type::CompuMate, Controller::Jack::Left);
myOSystem.eventHandler().defineJoyControllerMappings("CM", Controller::Jack::Left); myOSystem.eventHandler().defineJoyControllerMappings(Controller::Type::CompuMate, Controller::Jack::Left);
} }
else else
{ {
// Setup the controllers based on properties // Setup the controllers based on properties
string left = myProperties.get(PropType::Controller_Left); Controller::Type leftType = Controller::getType(myProperties.get(PropType::Controller_Left));
string right = myProperties.get(PropType::Controller_Right); Controller::Type rightType = Controller::getType(myProperties.get(PropType::Controller_Right));
uInt32 size = 0; uInt32 size = 0;
const uInt8* image = myCart->getImage(size); const uInt8* image = myCart->getImage(size);
const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES"; const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES";
@ -816,14 +816,14 @@ void Console::setControllers(const string& romMd5)
// Try to detect controllers // Try to detect controllers
if(image != nullptr || size != 0) if(image != nullptr || size != 0)
{ {
left = ControllerDetector::detectType(image, size, left, leftType = ControllerDetector::detectType(image, size, leftType,
!swappedPorts ? Controller::Jack::Left : Controller::Jack::Right, myOSystem.settings()); !swappedPorts ? Controller::Jack::Left : Controller::Jack::Right, myOSystem.settings());
right = ControllerDetector::detectType(image, size, right, rightType = ControllerDetector::detectType(image, size, rightType,
!swappedPorts ? Controller::Jack::Right : Controller::Jack::Left, myOSystem.settings()); !swappedPorts ? Controller::Jack::Right : Controller::Jack::Left, myOSystem.settings());
} }
unique_ptr<Controller> leftC = getControllerPort(left, Controller::Jack::Left, romMd5), unique_ptr<Controller> leftC = getControllerPort(leftType, Controller::Jack::Left, romMd5),
rightC = getControllerPort(right, Controller::Jack::Right, romMd5); rightC = getControllerPort(rightType, Controller::Jack::Right, romMd5);
// Swap the ports if necessary // Swap the ports if necessary
if(!swappedPorts) if(!swappedPorts)
@ -848,90 +848,95 @@ void Console::setControllers(const string& romMd5)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unique_ptr<Controller> Console::getControllerPort(const string& controllerName, unique_ptr<Controller> Console::getControllerPort(const Controller::Type type,
Controller::Jack port, const string& romMd5) const Controller::Jack port, const string& romMd5)
{ {
unique_ptr<Controller> controller; unique_ptr<Controller> controller;
myOSystem.eventHandler().defineKeyControllerMappings(controllerName, port); myOSystem.eventHandler().defineKeyControllerMappings(type, port);
myOSystem.eventHandler().defineJoyControllerMappings(controllerName, port); myOSystem.eventHandler().defineJoyControllerMappings(type, port);
if(controllerName == "JOYSTICK") switch(type)
{ {
// always create because it may have been changed by user dialog case Controller::Type::BoosterGrip:
controller = make_unique<Joystick>(port, myEvent, *mySystem); controller = make_unique<BoosterGrip>(port, myEvent, *mySystem);
break;
case Controller::Type::Driving:
controller = make_unique<Driving>(port, myEvent, *mySystem);
break;
case Controller::Type::Keyboard:
controller = make_unique<Keyboard>(port, myEvent, *mySystem);
break;
case Controller::Type::Paddles:
case Controller::Type::PaddlesIAxis:
case Controller::Type::PaddlesIAxDr:
{
// Also check if we should swap the paddles plugged into a jack
bool swapPaddles = myProperties.get(PropType::Controller_SwapPaddles) == "YES";
bool swapAxis = false, swapDir = false;
if(type == Controller::Type::PaddlesIAxis)
swapAxis = true;
else if(type == Controller::Type::PaddlesIAxDr)
swapAxis = swapDir = true;
controller = make_unique<Paddles>(port, myEvent, *mySystem,
swapPaddles, swapAxis, swapDir);
break;
}
case Controller::Type::AmigaMouse:
controller = make_unique<AmigaMouse>(port, myEvent, *mySystem);
break;
case Controller::Type::AtariMouse:
controller = make_unique<AtariMouse>(port, myEvent, *mySystem);
break;
case Controller::Type::TrakBall:
controller = make_unique<TrakBall>(port, myEvent, *mySystem);
break;
case Controller::Type::AtariVox:
{
const string& nvramfile = myOSystem.nvramDir() + "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);
};
controller = make_unique<AtariVox>(port, myEvent, *mySystem,
myOSystem.settings().getString("avoxport"), nvramfile, callback);
break;
}
case Controller::Type::SaveKey:
{
const string& nvramfile = myOSystem.nvramDir() + "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);
};
controller = make_unique<SaveKey>(port, myEvent, *mySystem, nvramfile, callback);
break;
}
case Controller::Type::Genesis:
controller = make_unique<Genesis>(port, myEvent, *mySystem);
break;
case Controller::Type::KidVid:
controller = make_unique<KidVid>(port, myEvent, *mySystem, romMd5);
break;
case Controller::Type::MindLink:
controller = make_unique<MindLink>(port, myEvent, *mySystem);
break;
default:
// What else can we do?
// always create because it may have been changed by user dialog
controller = make_unique<Joystick>(port, myEvent, *mySystem);
} }
else if(controllerName == "BOOSTERGRIP")
{
controller = make_unique<BoosterGrip>(port, myEvent, *mySystem);
}
else if(controllerName == "DRIVING")
{
controller = make_unique<Driving>(port, myEvent, *mySystem);
}
else if((controllerName == "KEYBOARD") || (controllerName == "KEYPAD"))
{
controller = make_unique<Keyboard>(port, myEvent, *mySystem);
}
else if(BSPF::startsWithIgnoreCase(controllerName, "PADDLES"))
{
// Also check if we should swap the paddles plugged into a jack
bool swapPaddles = myProperties.get(PropType::Controller_SwapPaddles) == "YES";
bool swapAxis = false, swapDir = false;
if(controllerName == "PADDLES_IAXIS")
swapAxis = true;
else if(controllerName == "PADDLES_IAXDR")
swapAxis = swapDir = true;
controller = make_unique<Paddles>(port, myEvent, *mySystem,
swapPaddles, swapAxis, swapDir);
}
else if(controllerName == "AMIGAMOUSE")
{
controller = make_unique<AmigaMouse>(port, myEvent, *mySystem);
}
else if(controllerName == "ATARIMOUSE")
{
controller = make_unique<AtariMouse>(port, myEvent, *mySystem);
}
else if(controllerName == "TRAKBALL")
{
controller = make_unique<TrakBall>(port, myEvent, *mySystem);
}
else if(controllerName == "ATARIVOX")
{
const string& nvramfile = myOSystem.nvramDir() + "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);
};
controller = make_unique<AtariVox>(port, myEvent, *mySystem,
myOSystem.settings().getString("avoxport"), nvramfile, callback);
}
else if(controllerName == "SAVEKEY")
{
const string& nvramfile = myOSystem.nvramDir() + "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);
};
controller = make_unique<SaveKey>(port, myEvent, *mySystem, nvramfile, callback);
}
else if(controllerName == "GENESIS")
{
controller = make_unique<Genesis>(port, myEvent, *mySystem);
}
else if(controllerName == "KIDVID")
{
controller = make_unique<KidVid>(port, myEvent, *mySystem, romMd5);
}
else if(controllerName == "MINDLINK")
{
controller = make_unique<MindLink>(port, myEvent, *mySystem);
}
else // What else can we do?
controller = make_unique<Joystick>(port, myEvent, *mySystem);
return controller; return controller;
} }

View File

@ -339,8 +339,8 @@ class Console : public Serializable, public ConsoleIO
/** /**
Selects the left or right controller depending on ROM properties Selects the left or right controller depending on ROM properties
*/ */
unique_ptr<Controller> getControllerPort(const string& controllerName, unique_ptr<Controller> getControllerPort(const Controller::Type type,
Controller::Jack port, const string& romMd5); const Controller::Jack port, const string& romMd5);
/** /**
Loads a user-defined palette file (from OSystem::paletteFile), filling the Loads a user-defined palette file (from OSystem::paletteFile), filling the

View File

@ -103,3 +103,48 @@ bool Controller::load(Serializer& in)
} }
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Controller::getName(const Type type)
{
string NAMES[int(Controller::Type::LastType)] =
{
"Unknown",
"AmigaMouse", "AtariMouse", "AtariVox", "BoosterGrip", "CompuMate",
"Driving", "Sega Genesis", "Joystick", "Keyboard", "KidVid", "MindLink",
"Paddles", "Paddles_IAxis", "Paddles_IAxDr", "SaveKey", "TrakBall"
};
return NAMES[int(type)];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Controller::getPropName(const Type type)
{
string PROP_NAMES[int(Controller::Type::LastType)] =
{
"AUTO",
"AMIGAMOUSE", "ATARIMOUSE", "ATARIVOX", "BOOSTERGRIP", "COMPUMATE",
"DRIVING", "GENESIS", "JOYSTICK", "KEYBOARD", "KIDVID", "MINDLINK",
"PADDLES", "PADDLES_IAXIS", "PADDLES_IAXDR", "SAVEKEY", "TRAKBALL"
};
return PROP_NAMES[int(type)];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::Type Controller::getType(const string& propName)
{
for(int i = 0; i < static_cast<int>(Type::LastType); ++i)
{
if(BSPF::equalsIgnoreCase(propName, getPropName(Type(i))))
{
return Type(i);
}
}
// special case
if(BSPF::equalsIgnoreCase(propName, "KEYPAD"))
return Type::Keyboard;
return Type::Unknown;
}

View File

@ -90,9 +90,11 @@ class Controller : public Serializable
*/ */
enum class Type enum class Type
{ {
Unknown,
AmigaMouse, AtariMouse, AtariVox, BoosterGrip, CompuMate, AmigaMouse, AtariMouse, AtariVox, BoosterGrip, CompuMate,
Driving, Genesis, Joystick, Keyboard, KidVid, MindLink, Driving, Genesis, Joystick, Keyboard, KidVid, MindLink,
Paddles, SaveKey, TrakBall Paddles, PaddlesIAxis, PaddlesIAxDr, SaveKey, TrakBall,
LastType
}; };
/** /**
@ -254,6 +256,21 @@ class Controller : public Serializable
myOnAnalogPinUpdateCallback = callback; myOnAnalogPinUpdateCallback = callback;
} }
/**
Returns the display name of the given controller type
*/
static string getName(const Type type);
/**
Returns the property name of the given controller type
*/
static string getPropName(const Type type);
/**
Returns the controller type of the given property name
*/
static Type getType(const string& propName);
public: public:
/// Constant which represents maximum resistance for analog pins /// Constant which represents maximum resistance for analog pins
static constexpr Int32 MAX_RESISTANCE = 0x7FFFFFFF; static constexpr Int32 MAX_RESISTANCE = 0x7FFFFFFF;

View File

@ -17,26 +17,27 @@
//============================================================================ //============================================================================
#include "Settings.hxx" #include "Settings.hxx"
#include "Logger.hxx"
#include "ControllerDetector.hxx" #include "ControllerDetector.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string ControllerDetector::detectType(const uInt8* image, uInt32 size, Controller::Type ControllerDetector::detectType(const uInt8* image, uInt32 size,
const string& controller, const Controller::Jack port, const Controller::Type type, const Controller::Jack port,
const Settings& settings) const Settings& settings)
{ {
string type(controller); if(type == Controller::Type::Unknown || settings.getBool("rominfo"))
if(type == "AUTO" || settings.getBool("rominfo"))
{ {
string detectedType = autodetectPort(image, size, port, settings); Controller::Type detectedType = autodetectPort(image, size, port, settings);
if(type != "AUTO" && type != detectedType) if(type != Controller::Type::Unknown && type != detectedType)
{ {
cerr << "Controller auto-detection not consistent: " cerr << "Controller auto-detection not consistent: "
<< type << ", " << detectedType << endl; << Controller::getName(type) << ", " << Controller::getName(detectedType) << endl;
} }
type = detectedType; Logger::debug(Controller::getName(detectedType) + " detected for " +
(port == Controller::Jack::Left ? "left" : "right") + " port");
return detectedType;
} }
return type; return type;
@ -44,38 +45,39 @@ string ControllerDetector::detectType(const uInt8* image, uInt32 size,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string ControllerDetector::detectName(const uInt8* image, uInt32 size, string ControllerDetector::detectName(const uInt8* image, uInt32 size,
const string& controller, const Controller::Jack port, const Controller::Type controller, const Controller::Jack port,
const Settings& settings) const Settings& settings)
{ {
return getControllerName(detectType(image, size, controller, port, settings)); return Controller::getName(detectType(image, size, controller, port, settings));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string ControllerDetector::autodetectPort(const uInt8* image, uInt32 size, Controller::Type ControllerDetector::autodetectPort(const uInt8* image, uInt32 size,
Controller::Jack port, const Settings& settings) Controller::Jack port, const Settings& settings)
{ {
// default type joystick // default type joystick
string type = "JOYSTICK"; // TODO: remove magic strings Controller::Type type = Controller::Type::Joystick;
if(isProbablySaveKey(image, size, port)) if(isProbablySaveKey(image, size, port))
type = "SAVEKEY"; type = Controller::Type::SaveKey;
else if(usesJoystickButton(image, size, port)) else if(usesJoystickButton(image, size, port))
{ {
if(isProbablyTrakBall(image, size)) if(isProbablyTrakBall(image, size))
type = "TRAKBALL"; type = Controller::Type::TrakBall;
else if(isProbablyAtariMouse(image, size)) else if(isProbablyAtariMouse(image, size))
type = "ATARIMOUSE"; type = Controller::Type::AmigaMouse;
else if(isProbablyAmigaMouse(image, size)) else if(isProbablyAmigaMouse(image, size))
type = "AMIGAMOUSE"; type = Controller::Type::AmigaMouse;
else if(usesKeyboard(image, size, port)) else if(usesKeyboard(image, size, port))
type = "KEYBOARD"; type = Controller::Type::Keyboard;
else if(usesGenesisButton(image, size, port)) else if(usesGenesisButton(image, size, port))
type = "GENESIS";
type = Controller::Type::Genesis;
} }
else else
{ {
if(usesPaddle(image, size, port, settings)) if(usesPaddle(image, size, port, settings))
type = "PADDLES"; type = Controller::Type::Paddles;
} }
// TODO: BOOSTERGRIP, DRIVING, MINDLINK, ATARIVOX, KIDVID // TODO: BOOSTERGRIP, DRIVING, MINDLINK, ATARIVOX, KIDVID
// not detectable: PADDLES_IAXIS, PADDLES_IAXDR // not detectable: PADDLES_IAXIS, PADDLES_IAXDR
@ -638,44 +640,3 @@ bool ControllerDetector::isProbablySaveKey(const uInt8* image, uInt32 size, Cont
return false; return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string ControllerDetector::getControllerName(const string& controller)
{
// auto detected:
if(BSPF::equalsIgnoreCase(controller, "JOYSTICK"))
return "Joystick";
if(BSPF::equalsIgnoreCase(controller, "SAVEKEY"))
return "SaveKey";
if(BSPF::equalsIgnoreCase(controller, "TRAKBALL"))
return "TrakBall";
if(BSPF::equalsIgnoreCase(controller, "ATARIMOUSE"))
return "AtariMouse";
if(BSPF::equalsIgnoreCase(controller, "AMIGAMOUSE"))
return "AmigaMouse";
if(BSPF::equalsIgnoreCase(controller, "KEYBOARD"))
return "Keyboard";
if(BSPF::equalsIgnoreCase(controller, "GENESIS"))
return "Sega Genesis";
if(BSPF::equalsIgnoreCase(controller, "PADDLES"))
return "Paddles";
// not auto detected:
if(BSPF::equalsIgnoreCase(controller, "BOOSTERGRIP"))
return "BoosterGrip";
if(BSPF::equalsIgnoreCase(controller, "DRIVING"))
return "Driving";
if(BSPF::equalsIgnoreCase(controller, "MINDLINK"))
return "MindLink";
if(BSPF::equalsIgnoreCase(controller, "ATARIVOX"))
return "AtariVox";
if(BSPF::equalsIgnoreCase(controller, "PADDLES_IAXIS"))
return "Paddles IAxis";
if(BSPF::equalsIgnoreCase(controller, "PADDLES_IAXDR"))
return "Paddles IAxDr";
if(BSPF::equalsIgnoreCase(controller, "COMPUMATE"))
return "CompuMate";
if(BSPF::equalsIgnoreCase(controller, "KIDVID"))
return "KidVid";
return controller;
}

View File

@ -15,7 +15,6 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================ //============================================================================
#ifndef CONTROLLER_DETECTOR_HXX #ifndef CONTROLLER_DETECTOR_HXX
#define CONTROLLER_DETECTOR_HXX #define CONTROLLER_DETECTOR_HXX
@ -40,9 +39,9 @@ class ControllerDetector
@param settings A reference to the various settings (read-only) @param settings A reference to the various settings (read-only)
@return The detected controller type @return The detected controller type
*/ */
static string detectType(const uInt8* image, uInt32 size, static Controller::Type detectType(const uInt8* image, uInt32 size,
const string& controller, const Controller::Jack port, const Controller::Type controller, const Controller::Jack port,
const Settings& settings); const Settings& settings);
/** /**
Detects the controller type at the given port if no controller is provided Detects the controller type at the given port if no controller is provided
@ -50,25 +49,16 @@ class ControllerDetector
@param image A pointer to the ROM image @param image A pointer to the ROM image
@param size The size of the ROM image @param size The size of the ROM image
@param controller The provided controller type of the ROM image @param type The provided controller type of the ROM image
@param port The port to be checked @param port The port to be checked
@param settings A reference to the various settings (read-only) @param settings A reference to the various settings (read-only)
@return The (detected) controller name @return The (detected) controller name
*/ */
static string detectName(const uInt8* image, uInt32 size, static string detectName(const uInt8* image, uInt32 size,
const string& controller, const Controller::Jack port, const Controller::Type type, const Controller::Jack port,
const Settings& settings); const Settings& settings);
/**
Returns a nicer formatted name for the given controller.
@param controller The provided controller type of the ROM image
@return The controller name
*/
static const string getControllerName(const string& controller);
private: private:
/** /**
Detects the controller type at the given port. Detects the controller type at the given port.
@ -80,8 +70,8 @@ class ControllerDetector
@return The detected controller type @return The detected controller type
*/ */
static string autodetectPort(const uInt8* image, uInt32 size, Controller::Jack port, static Controller::Type autodetectPort(const uInt8* image, uInt32 size, Controller::Jack port,
const Settings& settings); const Settings& settings);
/** /**
Search the image for the specified byte signature. Search the image for the specified byte signature.

View File

@ -194,8 +194,8 @@ class EventHandler
/** /**
Enable controller specific keyboard event mappings. Enable controller specific keyboard event mappings.
*/ */
void defineKeyControllerMappings(const string& controllerName, Controller::Jack port) { void defineKeyControllerMappings(const Controller::Type type, Controller::Jack port) {
myPKeyHandler->defineControllerMappings(controllerName, port); myPKeyHandler->defineControllerMappings(type, port);
} }
/** /**
@ -245,8 +245,8 @@ class EventHandler
/** /**
Enable controller specific keyboard event mappings. Enable controller specific keyboard event mappings.
*/ */
void defineJoyControllerMappings(const string& controllerName, Controller::Jack port) { void defineJoyControllerMappings(const Controller::Type type, Controller::Jack port) {
myPJoyHandler->defineControllerMappings(controllerName, port); myPJoyHandler->defineControllerMappings(type, port);
} }
/** /**

View File

@ -462,50 +462,10 @@ void GameInfoDialog::loadConsoleProperties(const Properties& props)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::loadControllerProperties(const Properties& props) void GameInfoDialog::loadControllerProperties(const Properties& props)
{ {
bool swapPorts = props.get(PropType::Console_SwapPorts) == "YES";
bool autoDetect = false;
ByteBuffer image;
string md5 = props.get(PropType::Cart_MD5);
uInt32 size = 0;
// try to load the image for auto detection
if(!instance().hasConsole())
{
const FilesystemNode& node = FilesystemNode(instance().launcher().selectedRom());
autoDetect = node.exists() && !node.isDirectory() && (image = instance().openROM(node, md5, size)) != nullptr;
}
string label = "";
string controller = props.get(PropType::Controller_Left); string controller = props.get(PropType::Controller_Left);
myLeftPort->setSelected(controller, "AUTO"); myLeftPort->setSelected(controller, "AUTO");
if(myLeftPort->getSelectedTag().toString() == "AUTO")
{
if(instance().hasConsole())
label = (!swapPorts ? instance().console().leftController().name()
: instance().console().rightController().name()) + " detected";
else if(autoDetect)
label = ControllerDetector::detectName(image.get(), size, controller,
!swapPorts ? Controller::Jack::Left : Controller::Jack::Right,
instance().settings()) + " detected";
}
myLeftPortDetected->setLabel(label);
label = "";
controller = props.get(PropType::Controller_Right); controller = props.get(PropType::Controller_Right);
myRightPort->setSelected(controller, "AUTO"); myRightPort->setSelected(controller, "AUTO");
if(myRightPort->getSelectedTag().toString() == "AUTO")
{
if(instance().hasConsole())
label = (!swapPorts ? instance().console().rightController().name()
: instance().console().leftController().name()) + " detected";
else if(autoDetect)
label = ControllerDetector::detectName(image.get(), size, controller,
!swapPorts ? Controller::Jack::Right : Controller::Jack::Left,
instance().settings()) + " detected";
}
myRightPortDetected->setLabel(label);
mySwapPorts->setState(props.get(PropType::Console_SwapPorts) == "YES"); mySwapPorts->setState(props.get(PropType::Console_SwapPorts) == "YES");
mySwapPaddles->setState(props.get(PropType::Controller_SwapPaddles) == "YES"); mySwapPaddles->setState(props.get(PropType::Controller_SwapPaddles) == "YES");
@ -650,6 +610,49 @@ void GameInfoDialog::setDefaults()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void GameInfoDialog::updateControllerStates() void GameInfoDialog::updateControllerStates()
{ {
bool swapPorts = mySwapPorts->getState();
bool autoDetect = false;
ByteBuffer image;
string md5 = myGameProperties.get(PropType::Cart_MD5);
uInt32 size = 0;
// try to load the image for auto detection
if(!instance().hasConsole())
{
const FilesystemNode& node = FilesystemNode(instance().launcher().selectedRom());
autoDetect = node.exists() && !node.isDirectory() && (image = instance().openROM(node, md5, size)) != nullptr;
}
string label = "";
Controller::Type type = Controller::getType(myLeftPort->getSelectedTag().toString());
if(type == Controller::Type::Unknown)
{
if(instance().hasConsole())
label = (!swapPorts ? instance().console().leftController().name()
: instance().console().rightController().name()) + " detected";
else if(autoDetect)
label = ControllerDetector::detectName(image.get(), size, type,
!swapPorts ? Controller::Jack::Left : Controller::Jack::Right,
instance().settings()) + " detected";
}
myLeftPortDetected->setLabel(label);
label = "";
type = Controller::getType(myRightPort->getSelectedTag().toString());
if(type == Controller::Type::Unknown)
{
if(instance().hasConsole())
label = (!swapPorts ? instance().console().rightController().name()
: instance().console().leftController().name()) + " detected";
else if(autoDetect)
label = ControllerDetector::detectName(image.get(), size, type,
!swapPorts ? Controller::Jack::Right : Controller::Jack::Left,
instance().settings()) + " detected";
}
myRightPortDetected->setLabel(label);
const string& contrLeft = myLeftPort->getSelectedTag().toString(); const string& contrLeft = myLeftPort->getSelectedTag().toString();
const string& contrRight = myRightPort->getSelectedTag().toString(); const string& contrRight = myRightPort->getSelectedTag().toString();
bool enableEEEraseButton = false; bool enableEEEraseButton = false;
@ -667,9 +670,6 @@ void GameInfoDialog::updateControllerStates()
const Controller& lport = instance().console().leftController(); const Controller& lport = instance().console().leftController();
const Controller& rport = instance().console().rightController(); const Controller& rport = instance().console().rightController();
enableSwapPaddles |= BSPF::equalsIgnoreCase(instance().console().leftController().name(), "Paddles");
enableSwapPaddles |= BSPF::equalsIgnoreCase(instance().console().rightController().name(), "Paddles");
// we only enable the button if we have a valid previous and new controller. // we only enable the button if we have a valid previous and new controller.
bool enableBtnForLeft = bool enableBtnForLeft =
(contrLeft == "AUTO" || contrLeft == "SAVEKEY" || contrLeft == "ATARIVOX") && (contrLeft == "AUTO" || contrLeft == "SAVEKEY" || contrLeft == "ATARIVOX") &&
@ -728,7 +728,7 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
break; break;
case TabWidget::kTabChangedCmd: case TabWidget::kTabChangedCmd:
if(data == 2) // 'Controller' tab selected if(data == 2) // 'Controllers' tab selected
updateControllerStates(); updateControllerStates();
// The underlying dialog still needs access to this command // The underlying dialog still needs access to this command

View File

@ -136,6 +136,8 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node)
// Load the image for controller auto detection // Load the image for controller auto detection
string left = myProperties.get(PropType::Controller_Left); string left = myProperties.get(PropType::Controller_Left);
string right = myProperties.get(PropType::Controller_Right); string right = myProperties.get(PropType::Controller_Right);
Controller::Type leftType = Controller::getType(left);
Controller::Type rightType = Controller::getType(right);
try try
{ {
ByteBuffer image; ByteBuffer image;
@ -145,10 +147,10 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node)
if(node.exists() && !node.isDirectory() && if(node.exists() && !node.isDirectory() &&
(image = instance().openROM(node, md5, size)) != nullptr) (image = instance().openROM(node, md5, size)) != nullptr)
{ {
left = ControllerDetector::detectName(image.get(), size, left, left = ControllerDetector::detectName(image.get(), size, leftType,
!swappedPorts ? Controller::Jack::Left : Controller::Jack::Right, !swappedPorts ? Controller::Jack::Left : Controller::Jack::Right,
instance().settings()); instance().settings());
right = ControllerDetector::detectName(image.get(), size, right, right = ControllerDetector::detectName(image.get(), size, rightType,
!swappedPorts ? Controller::Jack::Right : Controller::Jack::Left, !swappedPorts ? Controller::Jack::Right : Controller::Jack::Left,
instance().settings()); instance().settings());
} }

View File

@ -187,7 +187,7 @@ void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos
int pwidth = font.getStringWidth("Sega Genesis"); int pwidth = font.getStringWidth("Sega Genesis");
myLeftPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Left port "); myLeftPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Left port ");
myLeftPort = new PopUpWidget(this, font, myLeftPortLabel->getRight(), myLeftPort = new PopUpWidget(this, font, myLeftPortLabel->getRight(),
myLeftPortLabel->getTop() - 1, pwidth, lineHeight, ctrls, ""); myLeftPortLabel->getTop() - 1, pwidth, lineHeight, ctrls, "", 0, kLeftCChanged);
wid.push_back(myLeftPort); wid.push_back(myLeftPort);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
@ -197,7 +197,7 @@ void StellaSettingsDialog::addGameOptions(WidgetArray& wid, int& xpos, int& ypos
myRightPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Right port "); myRightPortLabel = new StaticTextWidget(this, font, xpos, ypos + 1, "Right port ");
myRightPort = new PopUpWidget(this, font, myRightPortLabel->getRight(), myRightPort = new PopUpWidget(this, font, myRightPortLabel->getRight(),
myRightPortLabel->getTop() - 1, pwidth, lineHeight, ctrls, ""); myRightPortLabel->getTop() - 1, pwidth, lineHeight, ctrls, "", 0, kRightCChanged);
wid.push_back(myRightPort); wid.push_back(myRightPort);
ypos += lineHeight + VGAP; ypos += lineHeight + VGAP;
myRightPortDetected = new StaticTextWidget(this, ifont, myRightPort->getLeft(), ypos, myRightPortDetected = new StaticTextWidget(this, ifont, myRightPort->getLeft(), ypos,
@ -371,6 +371,11 @@ void StellaSettingsDialog::handleCommand(CommandSender* sender, int cmd,
handleOverscanChange(); handleOverscanChange();
break; break;
case kLeftCChanged:
case kRightCChanged:
updateControllerStates();
break;
default: default:
Dialog::handleCommand(sender, cmd, data, 0); Dialog::handleCommand(sender, cmd, data, 0);
break; break;
@ -441,49 +446,12 @@ void StellaSettingsDialog::loadControllerProperties(const Properties& props)
if (enable) if (enable)
{ {
bool autoDetect = false;
ByteBuffer image;
string md5 = props.get(PropType::Cart_MD5);
uInt32 size = 0;
const FilesystemNode& node = FilesystemNode(instance().launcher().selectedRom());
// try to load the image for auto detection
if (!instance().hasConsole() &&
node.exists() && !node.isDirectory() && (image = instance().openROM(node, md5, size)) != nullptr)
autoDetect = true;
string label = "";
string controller = props.get(PropType::Controller_Left); string controller = props.get(PropType::Controller_Left);
bool swapPorts = props.get(PropType::Console_SwapPorts) == "YES";
myLeftPort->setSelected(controller, "AUTO"); myLeftPort->setSelected(controller, "AUTO");
if (myLeftPort->getSelectedTag().toString() == "AUTO")
{
if (instance().hasConsole())
label = (!swapPorts ? instance().console().leftController().name()
: instance().console().rightController().name()) + " detected";
else if (autoDetect)
label = ControllerDetector::detectName(image.get(), size, controller,
!swapPorts ? Controller::Jack::Left : Controller::Jack::Right,
instance().settings()) + " detected";
}
myLeftPortDetected->setLabel(label);
label = "";
controller = props.get(PropType::Controller_Right); controller = props.get(PropType::Controller_Right);
myRightPort->setSelected(controller, "AUTO"); myRightPort->setSelected(controller, "AUTO");
if (myRightPort->getSelectedTag().toString() == "AUTO")
{ updateControllerStates();
if (instance().hasConsole())
label = (!swapPorts ? instance().console().rightController().name()
: instance().console().leftController().name()) + " detected";
else if (autoDetect)
label = ControllerDetector::detectName(image.get(), size, controller,
!swapPorts ? Controller::Jack::Right : Controller::Jack::Left,
instance().settings()) + " detected";
}
myRightPortDetected->setLabel(label);
} }
else else
{ {
@ -529,3 +497,56 @@ void StellaSettingsDialog::openHelp()
#endif #endif
myHelpDialog->open(); myHelpDialog->open();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StellaSettingsDialog::updateControllerStates()
{
bool autoDetect = false;
ByteBuffer image;
string md5 = myGameProperties.get(PropType::Cart_MD5);
uInt32 size = 0;
// try to load the image for auto detection
if(!instance().hasConsole())
{
const FilesystemNode& node = FilesystemNode(instance().launcher().selectedRom());
autoDetect = node.exists() && !node.isDirectory() && (image = instance().openROM(node, md5, size)) != nullptr;
}
string label = "";
Controller::Type type = Controller::getType(myLeftPort->getSelectedTag().toString());
if(type == Controller::Type::Unknown)
{
if(instance().hasConsole())
label = (instance().console().leftController().name()) + " detected";
else if(autoDetect)
label = ControllerDetector::detectName(image.get(), size, type,
Controller::Jack::Left,
instance().settings()) + " detected";
}
myLeftPortDetected->setLabel(label);
label = "";
type = Controller::getType(myRightPort->getSelectedTag().toString());
if(type == Controller::Type::Unknown)
{
if(instance().hasConsole())
label = (instance().console().rightController().name()) + " detected";
else if(autoDetect)
label = ControllerDetector::detectName(image.get(), size, type,
Controller::Jack::Right,
instance().settings()) + " detected";
}
myRightPortDetected->setLabel(label);
// Compumate bankswitching scheme doesn't allow to select controllers
bool enableSelectControl = myGameProperties.get(PropType::Cart_Type) != "CM";
myLeftPortLabel->setEnabled(enableSelectControl);
myRightPortLabel->setEnabled(enableSelectControl);
myLeftPort->setEnabled(enableSelectControl);
myRightPort->setEnabled(enableSelectControl);
}

View File

@ -66,6 +66,8 @@ class StellaSettingsDialog : public Dialog
void openHelp(); void openHelp();
void updateControllerStates();
private: private:
// UI theme // UI theme
PopUpWidget* myThemePopup; PopUpWidget* myThemePopup;
@ -109,7 +111,9 @@ class StellaSettingsDialog : public Dialog
kHelp = 'SShl', kHelp = 'SShl',
kScanlinesChanged = 'SSsc', kScanlinesChanged = 'SSsc',
kPhosphorChanged = 'SSph', kPhosphorChanged = 'SSph',
kOverscanChanged = 'SSov' kOverscanChanged = 'SSov',
kLeftCChanged = 'LCch',
kRightCChanged = 'RCch',
}; };
// Game properties for currently loaded ROM // Game properties for currently loaded ROM