stella/src/common/PhysicalJoystick.cxx

174 lines
4.5 KiB
C++

//============================================================================
//
// 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 <map>
#include "OSystem.hxx"
#include "Settings.hxx"
#include "Vec.hxx"
#include "bspf.hxx"
#include "PhysicalJoystick.hxx"
#include "jsonDefinitions.hxx"
#include "Logger.hxx"
using json = nlohmann::json;
namespace {
string jsonName(EventMode eventMode) {
return json(eventMode).get<string>();
}
EventMode eventModeFromJsonName(const string& name) {
EventMode result;
from_json(json(name), result);
return result;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::initialize(int index, const string& desc,
int axes, int buttons, int hats, int /*balls*/)
{
ID = index;
name = desc;
numAxes = axes;
numButtons = buttons;
numHats = hats;
axisLastValue.resize(numAxes, 0);
buttonLast.resize(numButtons, JOY_CTRL_NONE);
// Erase the mappings
eraseMap(EventMode::kMenuMode);
eraseMap(EventMode::kJoystickMode);
eraseMap(EventMode::kPaddlesMode);
eraseMap(EventMode::kKeypadMode);
eraseMap(EventMode::kCommonMode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
json PhysicalJoystick::getMap() const
{
json mapping = json::object();
mapping["name"] = name;
for (auto& mode: {
EventMode::kMenuMode, EventMode::kJoystickMode, EventMode::kPaddlesMode, EventMode::kKeypadMode, EventMode::kCommonMode
})
mapping[jsonName(mode)] = joyMap.saveMapping(mode);
return mapping;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalJoystick::setMap(const json& map)
{
int i = 0;
for (auto& entry: map.items()) {
if (entry.key() == "name") continue;
try {
joyMap.loadMapping(entry.value(), eventModeFromJsonName(entry.key()));
} catch (const json::exception&) {
Logger::error("ignoring invalid json mapping for " + entry.key());
}
i++;
}
if(i != 5)
{
Logger::error("invalid controller mappings found for " +
((map.contains("name") && map.at("name").is_string()) ? ("stick " + map["name"].get<string>()) : "unknown stick")
);
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
json PhysicalJoystick::convertLegacyMapping(const string& mapping, const string& name)
{
istringstream buf(mapping);
json convertedMapping = json::object();
string map;
// Skip joystick name
getline(buf, map, MODE_DELIM);
while (getline(buf, map, MODE_DELIM))
{
int mode;
// Get event mode
std::replace(map.begin(), map.end(), '|', ' ');
istringstream modeBuf(map);
modeBuf >> mode;
// Remove leading "<mode>|" string
map.erase(0, 2);
json mappingForMode = JoyMap::convertLegacyMapping(map);
convertedMapping[jsonName(EventMode(mode))] = mappingForMode;
}
convertedMapping["name"] = name;
return convertedMapping;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::eraseMap(EventMode mode)
{
joyMap.eraseMode(mode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::eraseEvent(Event::Type event, EventMode mode)
{
joyMap.eraseEvent(event, mode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::getValues(const string& list, IntArray& map) const
{
map.clear();
istringstream buf(list);
int value;
buf >> value; // we don't need to know the # of items at this point
while(buf >> value)
map.push_back(value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string PhysicalJoystick::about() const
{
ostringstream buf;
buf << "'" << name << "' with: " << numAxes << " axes, " << numButtons << " buttons, "
<< numHats << " hats";
return buf.str();
}