Merge remote-tracking branch 'remotes/origin/feature/controller-mapping'

This commit is contained in:
Thomas Jentzsch 2019-08-05 10:01:43 +02:00
commit 36cc239066
36 changed files with 1286 additions and 756 deletions

248
src/common/JoyMap.cxx Normal file
View File

@ -0,0 +1,248 @@
//============================================================================
//
// 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-2019 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 "JoyMap.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JoyMap::JoyMap(void)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::add(const Event::Type event, const JoyMapping& mapping)
{
myMap[mapping] = event;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::add(const Event::Type event, const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat, const JoyHat hdir)
{
add(event, JoyMapping(mode, button, axis, adir, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::add(const Event::Type event, const EventMode mode, const int button,
const int hat, const JoyHat hdir)
{
add(event, JoyMapping(mode, button, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::erase(const JoyMapping& mapping)
{
myMap.erase(mapping);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::erase(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir)
{
erase(JoyMapping(mode, button, axis, adir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::erase(const EventMode mode, const int button,
const int hat, const JoyHat hdir)
{
erase(JoyMapping(mode, button, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type JoyMap::get(const JoyMapping& mapping) const
{
auto find = myMap.find(mapping);
if (find != myMap.end())
return find->second;
// try without button as modifier
JoyMapping m = mapping;
m.button = JOY_CTRL_NONE;
find = myMap.find(m);
if (find != myMap.end())
return find->second;
return Event::Type::NoType;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type JoyMap::get(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir) const
{
return get(JoyMapping(mode, button, axis, adir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type JoyMap::get(const EventMode mode, const int button,
const int hat, const JoyHat hdir) const
{
return get(JoyMapping(mode, button, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool JoyMap::check(const JoyMapping & mapping) const
{
auto find = myMap.find(mapping);
return (find != myMap.end());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool JoyMap::check(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat, const JoyHat hdir) const
{
return check(JoyMapping(mode, button, axis, adir, hat, hdir));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string JoyMap::getDesc(const Event::Type event, const JoyMapping& mapping) const
{
ostringstream buf;
// button description
if (mapping.button != JOY_CTRL_NONE)
buf << "/B" << mapping.button;
// axis description
if (mapping.axis != JoyAxis::NONE)
{
buf << "/A";
switch (mapping.axis)
{
case JoyAxis::X: buf << "X"; break;
case JoyAxis::Y: buf << "Y"; break;
case JoyAxis::Z: buf << "Z"; break;
default: buf << int(mapping.axis); break;
}
if (Event::isAnalog(event))
buf << "+|-";
else if (mapping.adir == JoyDir::NEG)
buf << "-";
else
buf << "+";
}
// hat description
if (mapping.hat != JOY_CTRL_NONE)
{
buf << "/H" << mapping.hat;
switch (mapping.hdir)
{
case JoyHat::UP: buf << "/up"; break;
case JoyHat::DOWN: buf << "/down"; break;
case JoyHat::LEFT: buf << "/left"; break;
case JoyHat::RIGHT: buf << "/right"; break;
default: break;
}
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string JoyMap::getEventMappingDesc(int stick, const Event::Type event, const EventMode mode) const
{
ostringstream buf;
for (auto item : myMap)
{
if (item.second == event && item.first.mode == mode)
{
if (buf.str() != "")
buf << ", ";
buf << "J" << stick << getDesc(event, item.first);
}
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
JoyMap::JoyMappingArray JoyMap::getEventMapping(const Event::Type event, const EventMode mode) const
{
JoyMappingArray map;
for (auto item : myMap)
if (item.second == event && item.first.mode == mode)
map.push_back(item.first);
return map;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string JoyMap::saveMapping(const EventMode mode) const
{
ostringstream buf;
for (auto item : myMap)
{
if (item.first.mode == mode)
{
if (buf.str() != "")
buf << "|";
buf << item.second << ":" << item.first.button << ","
<< int(item.first.axis) << "," << int(item.first.adir) << ","
<< item.first.hat << "," << int(item.first.hdir);
}
}
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int JoyMap::loadMapping(string& list, const EventMode mode)
{
// Since istringstream swallows whitespace, we have to make the
// delimiters be spaces
std::replace(list.begin(), list.end(), '|', ' ');
std::replace(list.begin(), list.end(), ':', ' ');
std::replace(list.begin(), list.end(), ',', ' ');
istringstream buf(list);
int event, button, axis, adir, hat, hdir, i = 0;
while (buf >> event && buf >> button
&& buf >> axis && buf >> adir
&& buf >> hat && buf >> hdir && ++i)
add(Event::Type(event), EventMode(mode), button, JoyAxis(axis), JoyDir(adir), hat, JoyHat(hdir));
return i;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::eraseMode(const EventMode mode)
{
for (auto item = myMap.begin(); item != myMap.end();)
if (item->first.mode == mode) {
auto _item = item++;
erase(_item->first);
}
else item++;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void JoyMap::eraseEvent(const Event::Type event, const EventMode mode)
{
for (auto item = myMap.begin(); item != myMap.end();)
if (item->second == event && item->first.mode == mode) {
auto _item = item++;
erase(_item->first);
}
else item++;
}

147
src/common/JoyMap.hxx Normal file
View File

@ -0,0 +1,147 @@
//============================================================================
//
// 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-2019 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 CONTROLLERMAP_HXX
#define CONTROLLERMAP_HXX
#include <unordered_map>
#include "Event.hxx"
#include "EventHandlerConstants.hxx"
/**
This class handles controller mappings in Stella.
@author Thomas Jentzsch
*/
class JoyMap
{
public:
struct JoyMapping
{
EventMode mode;
int button; // button number
JoyAxis axis; // horizontal/vertical
JoyDir adir; // axis direction (neg/pos)
int hat; // hat number
JoyHat hdir; // hat direction (left/right/up/down)
JoyMapping()
: mode(EventMode(0)), button(0),
axis(JoyAxis(0)), adir(JoyDir(0)),
hat(0), hdir(JoyHat(0)) { }
JoyMapping(const JoyMapping& m)
: mode(m.mode), button(m.button),
axis(m.axis), adir(m.adir),
hat(m.hat), hdir(m.hdir) { }
explicit JoyMapping(EventMode c_mode, int c_button,
JoyAxis c_axis, JoyDir c_adir,
int c_hat, JoyHat c_hdir)
: mode(c_mode), button(c_button),
axis(c_axis), adir(c_adir),
hat(c_hat), hdir(c_hdir) { }
explicit JoyMapping(EventMode c_mode, int c_button,
JoyAxis c_axis, JoyDir c_adir)
: mode(c_mode), button(c_button),
axis(c_axis), adir(c_adir),
hat(JOY_CTRL_NONE), hdir(JoyHat::CENTER) { }
explicit JoyMapping(EventMode c_mode, int c_button,
int c_hat, JoyHat c_hdir)
: mode(c_mode), button(c_button),
axis(JoyAxis::NONE), adir(JoyDir::NONE),
hat(c_hat), hdir(c_hdir) { }
bool operator==(const JoyMapping& other) const
{
return (mode == other.mode
&& button == other.button
&& axis == other.axis
&& adir == other.adir
&& hat == other.hat
&& hdir == other.hdir
);
}
};
using JoyMappingArray = std::vector<JoyMapping>;
JoyMap();
virtual ~JoyMap() = default;
/** Add new mapping for given event */
void add(const Event::Type event, const JoyMapping& mapping);
void add(const Event::Type event, const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat = JOY_CTRL_NONE, const JoyHat hdir = JoyHat::CENTER);
void add(const Event::Type event, const EventMode mode, const int button,
const int hat, const JoyHat hdir);
/** Erase mapping */
void erase(const JoyMapping& mapping);
void erase(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir);
void erase(const EventMode mode, const int button,
const int hat, const JoyHat hdir);
/** Get event for mapping */
Event::Type get(const JoyMapping& mapping) const;
Event::Type get(const EventMode mode, const int button,
const JoyAxis axis = JoyAxis::NONE, const JoyDir adir = JoyDir::NONE) const;
Event::Type get(const EventMode mode, const int button,
const int hat, const JoyHat hdir) const;
/** Check if a mapping exists */
bool check(const JoyMapping& mapping) const;
bool check(const EventMode mode, const int button,
const JoyAxis axis, const JoyDir adir,
const int hat = JOY_CTRL_NONE, const JoyHat hdir = JoyHat::CENTER) const;
/** Get mapping description */
string getEventMappingDesc(int stick, const Event::Type event, const EventMode mode) const;
JoyMappingArray getEventMapping(const Event::Type event, const EventMode mode) const;
string saveMapping(const EventMode mode) const;
int loadMapping(string& list, const EventMode mode);
/** Erase all mappings for given mode */
void eraseMode(const EventMode mode);
/** Erase given event's mapping for given mode */
void eraseEvent(const Event::Type event, const EventMode mode);
/** clear all mappings for a modes */
// void clear() { myMap.clear(); }
size_t size() { return myMap.size(); }
private:
string getDesc(const Event::Type event, const JoyMapping& mapping) const;
struct JoyHash {
size_t operator()(const JoyMapping& m)const {
return std::hash<uInt64>()((uInt64(m.mode)) // 3 bit
^ ((uInt64(m.button)) << 2) // 2 bits
^ ((uInt64(m.axis)) << 4) // 1 bit
^ ((uInt64(m.adir)) << 5) // 1 bit
^ ((uInt64(m.hat)) << 6) // 1 bit
^ ((uInt64(m.hdir)) << 7) // 2 bits
);
}
};
std::unordered_map<JoyMapping, Event::Type, JoyHash> myMap;
};
#endif

View File

@ -161,9 +161,9 @@ string KeyMap::getEventMappingDesc(const Event::Type event, const int mode) cons
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::vector<KeyMap::Mapping> KeyMap::getEventMapping(const Event::Type event, const int mode) const KeyMap::MappingArray KeyMap::getEventMapping(const Event::Type event, const int mode) const
{ {
std::vector<KeyMap::Mapping> map; MappingArray map;
for (auto item : myMap) for (auto item : myMap)
if (item.second == event && item.first.mode == mode) if (item.second == event && item.first.mode == mode)

View File

@ -55,6 +55,7 @@ class KeyMap
); );
} }
}; };
using MappingArray = std::vector<Mapping>;
KeyMap(); KeyMap();
virtual ~KeyMap() = default; virtual ~KeyMap() = default;
@ -82,7 +83,7 @@ class KeyMap
/** Get the mapping description(s) for given event and mode */ /** Get the mapping description(s) for given event and mode */
string getEventMappingDesc(const Event::Type event, const int mode) const; string getEventMappingDesc(const Event::Type event, const int mode) const;
std::vector<Mapping> getEventMapping(const Event::Type event, const int mode) const; MappingArray getEventMapping(const Event::Type event, const int mode) const;
string saveMapping(const int mode) const; string saveMapping(const int mode) const;
int loadMapping(string& list, const int mode); int loadMapping(string& list, const int mode);

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@ using PhysicalJoystickPtr = shared_ptr<PhysicalJoystick>;
Essentially, this class is an extension of the EventHandler class, but Essentially, this class is an extension of the EventHandler class, but
handling only joystick-specific functionality. handling only joystick-specific functionality.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class PhysicalJoystickHandler class PhysicalJoystickHandler
{ {
@ -69,32 +69,38 @@ class PhysicalJoystickHandler
bool remove(const string& name); bool remove(const string& name);
void mapStelladaptors(const string& saport); void mapStelladaptors(const string& saport);
void setDefaultMapping(Event::Type type, EventMode mode); void setDefaultMapping(Event::Type type, EventMode mode);
/** define mappings for current controllers */
void defineControllerMappings(const string& controllerName, Controller::Jack port);
/** enable mappings for emulation mode */
void enableEmulationMappings();
void eraseMapping(Event::Type event, EventMode mode); void eraseMapping(Event::Type event, EventMode mode);
void saveMapping(); void saveMapping();
string getMappingDesc(Event::Type, EventMode mode) const; string getMappingDesc(Event::Type, EventMode mode) const;
/** Bind a physical joystick event to a virtual event/action. */ /** Bind a physical joystick event to a virtual event/action. */
bool addAxisMapping(Event::Type event, EventMode mode, int stick, int axis, int value); bool addJoyMapping(Event::Type event, EventMode mode, int stick,
bool addBtnMapping(Event::Type event, EventMode mode, int stick, int button); int button, JoyAxis axis, int value);
bool addHatMapping(Event::Type event, EventMode mode, int stick, int hat, JoyHat value); bool addJoyHatMapping(Event::Type event, EventMode mode, int stick,
int button, int hat, JoyHat hdir);
/** Handle a physical joystick event. */ /** Handle a physical joystick event. */
void handleAxisEvent(int stick, int axis, int value); void handleAxisEvent(int stick, int axis, int value);
void handleBtnEvent(int stick, int button, bool pressed); void handleBtnEvent(int stick, int button, bool pressed);
void handleHatEvent(int stick, int hat, int value); void handleHatEvent(int stick, int hat, int value);
Event::Type eventForAxis(int stick, int axis, int joyDir, EventMode mode) const { Event::Type eventForAxis(EventMode mode, int stick, int axis, int value, int button) const {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
return (j && joyDir != int(JoyDir::NEG)) return j->joyMap.get(mode, button, JoyAxis(axis), convertAxisValue(value));
? j->axisTable[axis][(joyDir > int(JoyDir::NEG))][mode] : Event::NoType;
} }
Event::Type eventForButton(int stick, int button, EventMode mode) const { Event::Type eventForButton(EventMode mode, int stick, int button) const {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
return j ? j->btnTable[button][mode] : Event::NoType; return j->joyMap.get(mode, button);
} }
Event::Type eventForHat(int stick, int hat, JoyHat hatDir, EventMode mode) const { Event::Type eventForHat(EventMode mode, int stick, int hat, JoyHat hatDir, int button) const {
const PhysicalJoystickPtr j = joy(stick); const PhysicalJoystickPtr j = joy(stick);
return j ? j->hatTable[hat][int(hatDir)][mode] : Event::NoType; return j->joyMap.get(mode, button, hat, hatDir);
} }
/** Returns a list of pairs consisting of joystick name and associated ID. */ /** Returns a list of pairs consisting of joystick name and associated ID. */
@ -122,17 +128,56 @@ class PhysicalJoystickHandler
} }
// Set default mapping for given joystick when no mappings already exist // Set default mapping for given joystick when no mappings already exist
void setStickDefaultMapping(int stick, Event::Type type, EventMode mode); void setStickDefaultMapping(int stick, Event::Type type, EventMode mode,
bool updateDefaults = false);
friend ostream& operator<<(ostream& os, const PhysicalJoystickHandler& jh); friend ostream& operator<<(ostream& os, const PhysicalJoystickHandler& jh);
// Static lookup tables for Stelladaptor/2600-daptor axis/button support JoyDir convertAxisValue(int value) const {
static const int NUM_JOY_BTN = 4; return value == int(JoyDir::NONE) ? JoyDir::NONE : value > 0 ? JoyDir::POS : JoyDir::NEG;
static const int NUM_KEY_BTN = 12; }
static const Event::Type SA_Axis[NUM_PORTS][NUM_JOY_AXIS]; // Structures used for action menu items
static const Event::Type SA_Button[NUM_PORTS][NUM_JOY_BTN]; struct EventMapping {
static const Event::Type SA_Key[NUM_PORTS][NUM_KEY_BTN]; Event::Type event;
int button;
JoyAxis axis = JoyAxis::NONE;
JoyDir adir = JoyDir::NONE;
int hat = JOY_CTRL_NONE;
JoyHat hdir = JoyHat::CENTER;
};
using EventMappingArray = std::vector<EventMapping>;
void setDefaultAction(const PhysicalJoystickPtr& j,
EventMapping map, Event::Type event = Event::NoType,
EventMode mode = kEmulationMode, bool updateDefaults = false);
/** returns the event's controller mode */
EventMode getEventMode(const Event::Type event, const EventMode mode) const;
/** Checks event type. */
bool isJoystickEvent(const Event::Type event) const;
bool isPaddleEvent(const Event::Type event) const;
bool isKeypadEvent(const Event::Type event) const;
bool isCommonEvent(const Event::Type event) const;
void enableCommonMappings();
void enableMappings(const Event::EventSet events, EventMode mode);
void enableMapping(const Event::Type event, EventMode mode);
private:
EventMode myLeftMode;
EventMode myRightMode;
// Controller menu and common emulation mappings
static EventMappingArray DefaultMenuMapping;
// Controller specific mappings
static EventMappingArray DefaultLeftJoystickMapping;
static EventMappingArray DefaultRightJoystickMapping;
static EventMappingArray DefaultLeftPaddlesMapping;
static EventMappingArray DefaultRightPaddlesMapping;
static EventMappingArray DefaultLeftKeypadMapping;
static EventMappingArray DefaultRightKeypadMapping;
}; };
#endif #endif

View File

@ -26,7 +26,6 @@
#include "PNGLibrary.hxx" #include "PNGLibrary.hxx"
#include "PKeyboardHandler.hxx" #include "PKeyboardHandler.hxx"
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "Debugger.hxx" #include "Debugger.hxx"
#endif #endif
@ -94,7 +93,7 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
} }
else if (eraseAll || map.event == event) else if (eraseAll || map.event == event)
{ {
myKeyMap.eraseEvent(map.event, mode); //myKeyMap.eraseEvent(map.event, mode);
myKeyMap.add(map.event, mode, map.key, map.mod); myKeyMap.add(map.event, mode, map.key, map.mod);
} }
} }
@ -107,6 +106,12 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mode, void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mode,
bool updateDefaults) bool updateDefaults)
{ {
if (!updateDefaults)
{
myKeyMap.eraseEvent(event, mode);
myKeyMap.eraseEvent(event, getEventMode(event, mode));
}
switch(mode) switch(mode)
{ {
case kEmulationMode: case kEmulationMode:
@ -186,7 +191,6 @@ void PhysicalKeyboardHandler::enableEmulationMappings()
// see below // see below
break; break;
default: default:
enableMappings(RightJoystickEvents, kJoystickMode); enableMappings(RightJoystickEvents, kJoystickMode);
break; break;
@ -226,7 +230,7 @@ void PhysicalKeyboardHandler::enableCommonMappings()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::enableMappings(const EventSet events, EventMode mode) void PhysicalKeyboardHandler::enableMappings(const Event::EventSet events, EventMode mode)
{ {
for (const auto& event : events) for (const auto& event : events)
enableMapping(event, mode); enableMapping(event, mode);
@ -236,7 +240,7 @@ void PhysicalKeyboardHandler::enableMappings(const EventSet events, EventMode mo
void PhysicalKeyboardHandler::enableMapping(const Event::Type event, EventMode mode) void PhysicalKeyboardHandler::enableMapping(const Event::Type event, EventMode mode)
{ {
// copy from controller mode into emulation mode // copy from controller mode into emulation mode
std::vector<KeyMap::Mapping> mappings = myKeyMap.getEventMapping(event, mode); KeyMap::MappingArray mappings = myKeyMap.getEventMapping(event, mode);
for (const auto& mapping : mappings) for (const auto& mapping : mappings)
myKeyMap.add(event, kEmulationMode, mapping.key, mapping.mod); myKeyMap.add(event, kEmulationMode, mapping.key, mapping.mod);
@ -387,46 +391,6 @@ void PhysicalKeyboardHandler::handleEvent(StellaKey key, StellaMod mod, bool pre
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::LeftJoystickEvents = {
Event::JoystickZeroUp, Event::JoystickZeroDown, Event::JoystickZeroLeft, Event::JoystickZeroRight,
Event::JoystickZeroFire, Event::JoystickZeroFire5, Event::JoystickZeroFire9,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::RightJoystickEvents = {
Event::JoystickOneUp, Event::JoystickOneDown, Event::JoystickOneLeft, Event::JoystickOneRight,
Event::JoystickOneFire, Event::JoystickOneFire5, Event::JoystickOneFire9
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::LeftPaddlesEvents = {
Event::PaddleZeroDecrease, Event::PaddleZeroIncrease, Event::PaddleZeroAnalog, Event::PaddleZeroFire,
Event::PaddleOneDecrease, Event::PaddleOneIncrease, Event::PaddleOneAnalog, Event::PaddleOneFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::RightPaddlesEvents = {
Event::PaddleTwoDecrease, Event::PaddleTwoIncrease, Event::PaddleTwoAnalog, Event::PaddleTwoFire,
Event::PaddleThreeDecrease, Event::PaddleThreeIncrease, Event::PaddleThreeAnalog, Event::PaddleThreeFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::LeftKeypadEvents = {
Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3,
Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6,
Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9,
Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventSet PhysicalKeyboardHandler::RightKeypadEvents = {
Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3,
Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6,
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommonMapping = { PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommonMapping = {
{Event::ConsoleSelect, KBDK_F1}, {Event::ConsoleSelect, KBDK_F1},
@ -544,6 +508,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultMenuM
{Event::UIPgDown, KBDK_PAGEDOWN}, {Event::UIPgDown, KBDK_PAGEDOWN},
{Event::UISelect, KBDK_RETURN}, {Event::UISelect, KBDK_RETURN},
{Event::UISelect, KBDK_KP_ENTER},
{Event::UICancel, KBDK_ESCAPE}, {Event::UICancel, KBDK_ESCAPE},
{Event::UINavPrev, KBDK_TAB, KBDM_SHIFT}, {Event::UINavPrev, KBDK_TAB, KBDM_SHIFT},
@ -579,11 +544,17 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoyst
{Event::JoystickZeroDown, KBDK_DOWN}, {Event::JoystickZeroDown, KBDK_DOWN},
{Event::JoystickZeroLeft, KBDK_LEFT}, {Event::JoystickZeroLeft, KBDK_LEFT},
{Event::JoystickZeroRight, KBDK_RIGHT}, {Event::JoystickZeroRight, KBDK_RIGHT},
{Event::JoystickZeroUp, KBDK_KP_8},
{Event::JoystickZeroDown, KBDK_KP_2},
{Event::JoystickZeroLeft, KBDK_KP_4},
{Event::JoystickZeroRight, KBDK_KP_6},
{Event::JoystickZeroFire, KBDK_SPACE}, {Event::JoystickZeroFire, KBDK_SPACE},
{Event::JoystickZeroFire, KBDK_LCTRL}, {Event::JoystickZeroFire, KBDK_LCTRL},
{Event::JoystickZeroFire, KBDK_KP_5},
{Event::JoystickZeroFire5, KBDK_4}, {Event::JoystickZeroFire5, KBDK_4},
{Event::JoystickZeroFire5, KBDK_KP_9},
{Event::JoystickZeroFire9, KBDK_5}, {Event::JoystickZeroFire9, KBDK_5},
{Event::JoystickZeroFire9, KBDK_KP_3},
{Event::JoystickOneUp, KBDK_Y}, {Event::JoystickOneUp, KBDK_Y},
{Event::JoystickOneDown, KBDK_H}, {Event::JoystickOneDown, KBDK_H},
{Event::JoystickOneLeft, KBDK_G}, {Event::JoystickOneLeft, KBDK_G},
@ -641,7 +612,6 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultKeypa
{Event::KeyboardOnePound, KBDK_SLASH}, {Event::KeyboardOnePound, KBDK_SLASH},
}; };
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::CompuMateMapping = { PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::CompuMateMapping = {
{Event::CompuMateShift, KBDK_LSHIFT}, {Event::CompuMateShift, KBDK_LSHIFT},

View File

@ -19,7 +19,6 @@
#define PHYSICAL_KEYBOARD_HANDLER_HXX #define PHYSICAL_KEYBOARD_HANDLER_HXX
#include <map> #include <map>
#include <set>
class OSystem; class OSystem;
class EventHandler; class EventHandler;
@ -29,8 +28,6 @@ class EventHandler;
#include "EventHandlerConstants.hxx" #include "EventHandlerConstants.hxx"
#include "KeyMap.hxx" #include "KeyMap.hxx"
using EventSet = std::set<Event::Type>;
/** /**
This class handles all physical keyboard-related operations in Stella. This class handles all physical keyboard-related operations in Stella.
@ -40,7 +37,7 @@ using EventSet = std::set<Event::Type>;
Essentially, this class is an extension of the EventHandler class, but Essentially, this class is an extension of the EventHandler class, but
handling only keyboard-specific functionality. handling only keyboard-specific functionality.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class PhysicalKeyboardHandler class PhysicalKeyboardHandler
{ {
@ -103,7 +100,7 @@ class PhysicalKeyboardHandler
void enableCommonMappings(); void enableCommonMappings();
void enableMappings(const EventSet events, EventMode mode); void enableMappings(const Event::EventSet events, EventMode mode);
void enableMapping(const Event::Type event, EventMode mode); void enableMapping(const Event::Type event, EventMode mode);
OSystem& myOSystem; OSystem& myOSystem;
@ -130,16 +127,10 @@ class PhysicalKeyboardHandler
uInt8 myAltKeyCounter; uInt8 myAltKeyCounter;
#endif #endif
// Hold controller related events // Controller menu and common emulation mappings
static EventSet LeftJoystickEvents;
static EventSet RightJoystickEvents;
static EventSet LeftPaddlesEvents;
static EventSet RightPaddlesEvents;
static EventSet LeftKeypadEvents;
static EventSet RightKeypadEvents;
static EventMappingArray DefaultMenuMapping; static EventMappingArray DefaultMenuMapping;
static EventMappingArray DefaultCommonMapping; static EventMappingArray DefaultCommonMapping;
// Controller specific mappings
static EventMappingArray DefaultJoystickMapping; static EventMappingArray DefaultJoystickMapping;
static EventMappingArray DefaultPaddleMapping; static EventMappingArray DefaultPaddleMapping;
static EventMappingArray DefaultKeypadMapping; static EventMappingArray DefaultKeypadMapping;

View File

@ -31,20 +31,16 @@ PhysicalJoystick::PhysicalJoystick()
numAxes(0), numAxes(0),
numButtons(0), numButtons(0),
numHats(0), numHats(0),
axisTable(nullptr), axisLastValue(nullptr),
btnTable(nullptr), buttonLast(nullptr)
hatTable(nullptr),
axisLastValue(nullptr)
{ {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalJoystick::~PhysicalJoystick() PhysicalJoystick::~PhysicalJoystick()
{ {
delete[] axisTable;
delete[] btnTable;
delete[] hatTable;
delete[] axisLastValue; delete[] axisLastValue;
delete[] buttonLast;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -59,109 +55,66 @@ void PhysicalJoystick::initialize(int index, const string& desc,
numAxes = axes; numAxes = axes;
numButtons = buttons; numButtons = buttons;
numHats = hats; numHats = hats;
if(numAxes)
axisTable = new Event::Type[numAxes][NUM_JOY_DIRS][kNumModes];
if(numButtons)
btnTable = new Event::Type[numButtons][kNumModes];
if(numHats)
hatTable = new Event::Type[numHats][NUM_JOY_HAT_DIRS][kNumModes];
axisLastValue = new int[numAxes]; axisLastValue = new int[numAxes];
buttonLast = new int[numButtons];
// Erase the joystick axis mapping array and last axis value // Erase the last button
for (int b = 0; b < numButtons; ++b)
buttonLast[b] = JOY_CTRL_NONE;
// Erase the last axis value
for(int a = 0; a < numAxes; ++a) for(int a = 0; a < numAxes; ++a)
{
axisLastValue[a] = 0; axisLastValue[a] = 0;
for(int m = 0; m < kNumModes; ++m)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
axisTable[a][d][m] = Event::NoType;
}
// Erase the joystick button mapping array // Erase the mappings
for(int b = 0; b < numButtons; ++b) eraseMap(kJoystickMode);
for(int m = 0; m < kNumModes; ++m) eraseMap(kPaddlesMode);
btnTable[b][m] = Event::NoType; eraseMap(kKeypadMode);
eraseMap(kMenuMode);
// Erase the joystick hat mapping array
for(int h = 0; h < numHats; ++h)
for(int m = 0; m < kNumModes; ++m)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
hatTable[h][d][m] = Event::NoType;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string PhysicalJoystick::getMap() const string PhysicalJoystick::getMap() const
{ {
// The mapping structure (for remappable devices) is defined as follows: // The mapping structure (for remappable devices) is defined as follows:
// NAME | AXIS # + values | BUTTON # + values | HAT # + values, // <NAME>'$'<MODE>['|'(<EVENT>':'<BUTTON>','<AXIS>','<VALUE>)|(<EVENT>':'<BUTTON>','<HAT>','<HATDIR>)]
// where each subsection of values is separated by ':'
if(type == JT_REGULAR)
{
ostringstream joybuf;
joybuf << name << "|" << numAxes;
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
joybuf << " " << axisTable[a][d][m];
joybuf << "|" << numButtons;
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
joybuf << " " << btnTable[b][m];
joybuf << "|" << numHats;
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
joybuf << " " << hatTable[h][d][m];
return joybuf.str(); ostringstream joybuf;
}
return EmptyString; joybuf << name;
joybuf << MODE_DELIM << int(kMenuMode) << "|" << joyMap.saveMapping(kMenuMode);
joybuf << MODE_DELIM << int(kJoystickMode) << "|" << joyMap.saveMapping(kJoystickMode);
joybuf << MODE_DELIM << int(kPaddlesMode) << "|" << joyMap.saveMapping(kPaddlesMode);
joybuf << MODE_DELIM << int(kKeypadMode) << "|" << joyMap.saveMapping(kKeypadMode);
joybuf << MODE_DELIM << int(kCommonMode) << "|" << joyMap.saveMapping(kCommonMode);
return joybuf.str();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalJoystick::setMap(const string& mapString) bool PhysicalJoystick::setMap(const string& mapString)
{ {
istringstream buf(mapString); istringstream buf(mapString);
StringList items; StringList mappings;
string item; string map;
while(getline(buf, item, '|'))
items.push_back(item);
while (getline(buf, map, MODE_DELIM))
{
// remove leading "<mode>|" string
map.erase(0, 2);
mappings.push_back(map);
}
// Error checking // Error checking
if(items.size() != 4) if(mappings.size() != 1 + 5)
return false; return false;
IntArray map; joyMap.loadMapping(mappings[1], kMenuMode);
joyMap.loadMapping(mappings[2], kJoystickMode);
// Parse axis/button/hat values joyMap.loadMapping(mappings[3], kPaddlesMode);
getValues(items[1], map); joyMap.loadMapping(mappings[4], kKeypadMode);
if(int(map.size()) == numAxes * NUM_JOY_DIRS * kNumModes) joyMap.loadMapping(mappings[5], kCommonMode);
{
// Fill the axes table with events
auto event = map.cbegin();
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
axisTable[a][d][m] = Event::Type(*event++);
}
getValues(items[2], map);
if(int(map.size()) == numButtons * kNumModes)
{
auto event = map.cbegin();
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
btnTable[b][m] = Event::Type(*event++);
}
getValues(items[3], map);
if(int(map.size()) == numHats * NUM_JOY_HAT_DIRS * kNumModes)
{
auto event = map.cbegin();
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
hatTable[h][d][m] = Event::Type(*event++);
}
return true; return true;
} }
@ -169,40 +122,13 @@ bool PhysicalJoystick::setMap(const string& mapString)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::eraseMap(EventMode mode) void PhysicalJoystick::eraseMap(EventMode mode)
{ {
// Erase axis mappings joyMap.eraseMode(mode);
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
axisTable[a][d][mode] = Event::NoType;
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
hatTable[h][d][mode] = Event::NoType;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalJoystick::eraseEvent(Event::Type event, EventMode mode) void PhysicalJoystick::eraseEvent(Event::Type event, EventMode mode)
{ {
// Erase axis mappings joyMap.eraseEvent(event, mode);
for(int a = 0; a < numAxes; ++a)
for (int d = 0; d < NUM_JOY_DIRS; ++d)
if(axisTable[a][d][mode] == event)
axisTable[a][d][mode] = Event::NoType;
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
if(btnTable[b][mode] == event)
btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
for (int d = 0; d < NUM_JOY_HAT_DIRS; ++d)
if(hatTable[h][d][mode] == event)
hatTable[h][d][mode] = Event::NoType;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -221,10 +147,8 @@ void PhysicalJoystick::getValues(const string& list, IntArray& map) const
string PhysicalJoystick::about() const string PhysicalJoystick::about() const
{ {
ostringstream buf; ostringstream buf;
buf << name; buf << " with: " << numAxes << " axes, " << numButtons << " buttons, "
if(type == JT_REGULAR) << numHats << " hats";
buf << " with: " << numAxes << " axes, " << numButtons << " buttons, "
<< numHats << " hats";
return buf.str(); return buf.str();
} }

View File

@ -20,6 +20,7 @@
#include "Event.hxx" #include "Event.hxx"
#include "EventHandlerConstants.hxx" #include "EventHandlerConstants.hxx"
#include "JoyMap.hxx"
/** /**
An abstraction of a physical (real) joystick in Stella. An abstraction of a physical (real) joystick in Stella.
@ -31,12 +32,17 @@
Specific backend class(es) will inherit from this class, and implement Specific backend class(es) will inherit from this class, and implement
functionality specific to the device. functionality specific to the device.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class PhysicalJoystick class PhysicalJoystick
{ {
friend class PhysicalJoystickHandler; friend class PhysicalJoystickHandler;
static constexpr char MODE_DELIM = '§'; // must not be '^', '|' or '#'
public: public:
PhysicalJoystick(); PhysicalJoystick();
virtual ~PhysicalJoystick(); virtual ~PhysicalJoystick();
@ -65,10 +71,12 @@ class PhysicalJoystick
int ID; int ID;
string name; string name;
int numAxes, numButtons, numHats; int numAxes, numButtons, numHats;
Event::Type (*axisTable)[NUM_JOY_DIRS][kNumModes];
Event::Type (*btnTable)[kNumModes];
Event::Type (*hatTable)[NUM_JOY_HAT_DIRS][kNumModes];
int* axisLastValue; int* axisLastValue;
int* buttonLast;
// Hashmaps of controller events
JoyMap joyMap;
private: private:
void getValues(const string& list, IntArray& map) const; void getValues(const string& list, IntArray& map) const;

View File

@ -6,6 +6,7 @@ MODULE_OBJS := \
src/common/FBSurfaceSDL2.o \ src/common/FBSurfaceSDL2.o \
src/common/FrameBufferSDL2.o \ src/common/FrameBufferSDL2.o \
src/common/FSNodeZIP.o \ src/common/FSNodeZIP.o \
src/common/JoyMap.o \
src/common/KeyMap.o \ src/common/KeyMap.o \
src/common/Logger.o \ src/common/Logger.o \
src/common/main.o \ src/common/main.o \

View File

@ -32,8 +32,8 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
myFireEvent = Event::JoystickZeroFire; myFireEvent = Event::JoystickZeroFire;
myTriggerEvent = Event::JoystickZeroFire5; myTriggerEvent = Event::JoystickZeroFire5;
myBoosterEvent = Event::JoystickZeroFire9; myBoosterEvent = Event::JoystickZeroFire9;
myXAxisValue = Event::SALeftAxis0Value; myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::SALeftAxis1Value; myYAxisValue = Event::PaddleOneAnalog;
} }
else else
{ {
@ -44,8 +44,8 @@ BoosterGrip::BoosterGrip(Jack jack, const Event& event, const System& system)
myFireEvent = Event::JoystickOneFire; myFireEvent = Event::JoystickOneFire;
myTriggerEvent = Event::JoystickOneFire5; myTriggerEvent = Event::JoystickOneFire5;
myBoosterEvent = Event::JoystickOneFire9; myBoosterEvent = Event::JoystickOneFire9;
myXAxisValue = Event::SARightAxis0Value; myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::SARightAxis1Value; myYAxisValue = Event::PaddleThreeAnalog;
} }
setPin(AnalogPin::Five, MAX_RESISTANCE); setPin(AnalogPin::Five, MAX_RESISTANCE);

View File

@ -135,6 +135,7 @@ Console::Console(OSystem& osystem, unique_ptr<Cartridge>& cart,
setControllers(md5); setControllers(md5);
// now that we know the controllers, enable the event mappings // now that we know the controllers, enable the event mappings
myOSystem.eventHandler().enableEmulationKeyMappings(); myOSystem.eventHandler().enableEmulationKeyMappings();
myOSystem.eventHandler().enableEmulationJoyMappings();
// Mute audio and clear framebuffer while autodetection runs // Mute audio and clear framebuffer while autodetection runs
myOSystem.sound().mute(1); myOSystem.sound().mute(1);
@ -804,6 +805,7 @@ 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("CM", Controller::Jack::Left);
myOSystem.eventHandler().defineJoyControllerMappings("CM", Controller::Jack::Left);
} }
else else
{ {
@ -849,6 +851,7 @@ unique_ptr<Controller> Console::getControllerPort(const string& rommd5,
unique_ptr<Controller> controller = std::move(myLeftControl); unique_ptr<Controller> controller = std::move(myLeftControl);
myOSystem.eventHandler().defineKeyControllerMappings(controllerName, port); myOSystem.eventHandler().defineKeyControllerMappings(controllerName, port);
myOSystem.eventHandler().defineJoyControllerMappings(controllerName, port);
if(controllerName == "JOYSTICK") if(controllerName == "JOYSTICK")
{ {

View File

@ -35,16 +35,16 @@ Driving::Driving(Jack jack, const Event& event, const System& system)
myCCWEvent = Event::JoystickZeroLeft; myCCWEvent = Event::JoystickZeroLeft;
myCWEvent = Event::JoystickZeroRight; myCWEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire; myFireEvent = Event::JoystickZeroFire;
myXAxisValue = Event::SALeftAxis0Value; myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::SALeftAxis1Value; myYAxisValue = Event::PaddleOneAnalog;
} }
else else
{ {
myCCWEvent = Event::JoystickOneLeft; myCCWEvent = Event::JoystickOneLeft;
myCWEvent = Event::JoystickOneRight; myCWEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire; myFireEvent = Event::JoystickOneFire;
myXAxisValue = Event::SARightAxis0Value; myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::SARightAxis1Value; myYAxisValue = Event::PaddleThreeAnalog;
} }
// Digital pins 3 and 4 are not connected // Digital pins 3 and 4 are not connected

View File

@ -19,12 +19,13 @@
#define EVENT_HXX #define EVENT_HXX
#include <mutex> #include <mutex>
#include <set>
#include "bspf.hxx" #include "bspf.hxx"
#include "StellaKeys.hxx" #include "StellaKeys.hxx"
/** /**
@author Stephen Anthony, Christian Speckner @author Stephen Anthony, Christian Speckner, Thomas Jentzsch
*/ */
class Event class Event
{ {
@ -67,9 +68,6 @@ class Event
Combo1, Combo2, Combo3, Combo4, Combo5, Combo6, Combo7, Combo8, Combo1, Combo2, Combo3, Combo4, Combo5, Combo6, Combo7, Combo8,
Combo9, Combo10, Combo11, Combo12, Combo13, Combo14, Combo15, Combo16, Combo9, Combo10, Combo11, Combo12, Combo13, Combo14, Combo15, Combo16,
SALeftAxis0Value, SALeftAxis1Value,
SARightAxis0Value, SARightAxis1Value,
MouseAxisXValue, MouseAxisYValue, MouseAxisXValue, MouseAxisYValue,
MouseButtonLeftValue, MouseButtonRightValue, MouseButtonLeftValue, MouseButtonRightValue,
@ -127,7 +125,9 @@ class Event
}; };
// Event list version, update if the id of existing event types changed // Event list version, update if the id of existing event types changed
static constexpr Int32 VERSION = 2; static constexpr Int32 VERSION = 3;
using EventSet = std::set<Event::Type>;
public: public:
/** /**
@ -200,4 +200,44 @@ class Event
Event& operator=(Event&&) = delete; Event& operator=(Event&&) = delete;
}; };
// Hold controller related events
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet LeftJoystickEvents = {
Event::JoystickZeroUp, Event::JoystickZeroDown, Event::JoystickZeroLeft, Event::JoystickZeroRight,
Event::JoystickZeroFire, Event::JoystickZeroFire5, Event::JoystickZeroFire9,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet RightJoystickEvents = {
Event::JoystickOneUp, Event::JoystickOneDown, Event::JoystickOneLeft, Event::JoystickOneRight,
Event::JoystickOneFire, Event::JoystickOneFire5, Event::JoystickOneFire9
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet LeftPaddlesEvents = {
Event::PaddleZeroDecrease, Event::PaddleZeroIncrease, Event::PaddleZeroAnalog, Event::PaddleZeroFire,
Event::PaddleOneDecrease, Event::PaddleOneIncrease, Event::PaddleOneAnalog, Event::PaddleOneFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet RightPaddlesEvents = {
Event::PaddleTwoDecrease, Event::PaddleTwoIncrease, Event::PaddleTwoAnalog, Event::PaddleTwoFire,
Event::PaddleThreeDecrease, Event::PaddleThreeIncrease, Event::PaddleThreeAnalog, Event::PaddleThreeFire,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet LeftKeypadEvents = {
Event::KeyboardZero1, Event::KeyboardZero2, Event::KeyboardZero3,
Event::KeyboardZero4, Event::KeyboardZero5, Event::KeyboardZero6,
Event::KeyboardZero7, Event::KeyboardZero8, Event::KeyboardZero9,
Event::KeyboardZeroStar, Event::KeyboardZero0, Event::KeyboardZeroPound,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static const Event::EventSet RightKeypadEvents = {
Event::KeyboardOne1, Event::KeyboardOne2, Event::KeyboardOne3,
Event::KeyboardOne4, Event::KeyboardOne5, Event::KeyboardOne6,
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound,
};
#endif #endif

View File

@ -331,10 +331,12 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleEvent(Event::Type event, bool pressed, bool repeated) void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
{ {
// Take care of special events that aren't part of the emulation core // Take care of special events that aren't part of the emulation core
// or need to be preprocessed before passing them on // or need to be preprocessed before passing them on
bool pressed = (value != 0);
switch(event) switch(event)
{ {
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -896,7 +898,7 @@ void EventHandler::handleEvent(Event::Type event, bool pressed, bool repeated)
// Otherwise, pass it to the emulation core // Otherwise, pass it to the emulation core
if (!repeated) if (!repeated)
myEvent.set(event, pressed); myEvent.set(event, value);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1124,29 +1126,13 @@ bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, StellaKey ke
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addJoyAxisMapping(Event::Type event, EventMode mode, bool EventHandler::addJoyMapping(Event::Type event, EventMode mode,
int stick, int axis, int value, int stick, int button, JoyAxis axis, int value,
bool updateMenus) bool updateMenus)
{ {
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
bool mapped = myPJoyHandler->addAxisMapping(event, mode, stick, axis, value); bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, value);
if(mapped && updateMenus) if (mapped && updateMenus)
setActionMappings(mode);
return mapped;
#else
return false;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addJoyButtonMapping(Event::Type event, EventMode mode,
int stick, int button,
bool updateMenus)
{
#ifdef JOYSTICK_SUPPORT
bool mapped = myPJoyHandler->addBtnMapping(event, mode, stick, button);
if(mapped && updateMenus)
setActionMappings(mode); setActionMappings(mode);
return mapped; return mapped;
@ -1157,12 +1143,12 @@ bool EventHandler::addJoyButtonMapping(Event::Type event, EventMode mode,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addJoyHatMapping(Event::Type event, EventMode mode, bool EventHandler::addJoyHatMapping(Event::Type event, EventMode mode,
int stick, int hat, JoyHat value, int stick, int button, int hat, JoyHat dir,
bool updateMenus) bool updateMenus)
{ {
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
bool mapped = myPJoyHandler->addHatMapping(event, mode, stick, hat, value); bool mapped = myPJoyHandler->addJoyHatMapping(event, mode, stick, button, hat, dir);
if(mapped && updateMenus) if (mapped && updateMenus)
setActionMappings(mode); setActionMappings(mode);
return mapped; return mapped;
@ -1171,6 +1157,7 @@ bool EventHandler::addJoyHatMapping(Event::Type event, EventMode mode,
#endif #endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::eraseMapping(Event::Type event, EventMode mode) void EventHandler::eraseMapping(Event::Type event, EventMode mode)
{ {

View File

@ -47,7 +47,7 @@ class PhysicalJoystick;
unchanged to the menu class, where (among other things) changing key unchanged to the menu class, where (among other things) changing key
mapping can take place. mapping can take place.
@author Stephen Anthony @author Stephen Anthony, Thomas Jentzsch
*/ */
class EventHandler class EventHandler
{ {
@ -141,7 +141,7 @@ class EventHandler
@param pressed Pressed (true) or released (false) @param pressed Pressed (true) or released (false)
@param repeated Repeated key (true) or first press/release (false) @param repeated Repeated key (true) or first press/release (false)
*/ */
void handleEvent(Event::Type type, bool pressed = true, bool repeated = false); void handleEvent(Event::Type type, Int32 value = 1, bool repeated = false);
/** /**
Handle events that must be processed each time a new console is Handle events that must be processed each time a new console is
@ -162,14 +162,14 @@ class EventHandler
Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const { Event::Type eventForKey(EventMode mode, StellaKey key, StellaMod mod) const {
return myPKeyHandler->eventForKey(mode, key, mod); return myPKeyHandler->eventForKey(mode, key, mod);
} }
Event::Type eventForJoyAxis(int stick, int axis, int value, EventMode mode) const { Event::Type eventForJoyAxis(EventMode mode, int stick, int axis, int value, int button) const {
return myPJoyHandler->eventForAxis(stick, axis, value, mode); return myPJoyHandler->eventForAxis(mode, stick, axis, value, button);
} }
Event::Type eventForJoyButton(int stick, int button, EventMode mode) const { Event::Type eventForJoyButton(EventMode mode, int stick, int button) const {
return myPJoyHandler->eventForButton(stick, button, mode); return myPJoyHandler->eventForButton(mode, stick, button);
} }
Event::Type eventForJoyHat(int stick, int hat, JoyHat value, EventMode mode) const { Event::Type eventForJoyHat(EventMode mode, int stick, int hat, JoyHat value, int button) const {
return myPJoyHandler->eventForHat(stick, hat, value, mode); return myPJoyHandler->eventForHat(mode, stick, hat, value, button);
} }
/** Get description of given event and mode. */ /** Get description of given event and mode. */
@ -208,53 +208,55 @@ class EventHandler
/** /**
Bind a physical joystick axis direction to an event/action and regenerate Bind a physical joystick axis direction to an event/action and regenerate
the mapping array(s). the mapping array(s). The axis can be combined with a button. The button
can also be mapped without an axis.
@param event The event we are remapping @param event The event we are remapping
@param mode The mode where this event is active @param mode The mode where this event is active
@param stick The joystick number @param stick The joystick number
@param button The joystick button
@param axis The joystick axis @param axis The joystick axis
@param value The value on the given axis @param value The value on the given axis
@param updateMenus Whether to update the action mappings (normally @param updateMenus Whether to update the action mappings (normally
we want to do this, unless there are a batch of we want to do this, unless there are a batch of
'adds', in which case it's delayed until the end 'adds', in which case it's delayed until the end
*/ */
bool addJoyAxisMapping(Event::Type event, EventMode mode, bool addJoyMapping(Event::Type event, EventMode mode, int stick,
int stick, int axis, int value, int button, JoyAxis axis = JoyAxis::NONE, int value = 0,
bool updateMenus = true); bool updateMenus = true);
/** /**
Bind a physical joystick button to an event/action and regenerate the Bind a physical joystick hat direction to an event/action and regenerate
mapping array(s). the mapping array(s). The hat can be combined with a button.
@param event The event we are remapping @param event The event we are remapping
@param mode The mode where this event is active @param mode The mode where this event is active
@param stick The joystick number @param stick The joystick number
@param button The joystick button @param button The joystick button
@param updateMenus Whether to update the action mappings (normally
we want to do this, unless there are a batch of
'adds', in which case it's delayed until the end
*/
bool addJoyButtonMapping(Event::Type event, EventMode mode, int stick, int button,
bool updateMenus = true);
/**
Bind a physical joystick hat direction to an event/action and regenerate
the mapping array(s).
@param event The event we are remapping
@param mode The mode where this event is active
@param stick The joystick number
@param hat The joystick hat @param hat The joystick hat
@param value The value on the given hat @param value The value on the given hat
@param updateMenus Whether to update the action mappings (normally @param updateMenus Whether to update the action mappings (normally
we want to do this, unless there are a batch of we want to do this, unless there are a batch of
'adds', in which case it's delayed until the end 'adds', in which case it's delayed until the end
*/ */
bool addJoyHatMapping(Event::Type event, EventMode mode, bool addJoyHatMapping(Event::Type event, EventMode mode, int stick,
int stick, int hat, JoyHat value, int button, int hat, JoyHat dir,
bool updateMenus = true); bool updateMenus = true);
/**
Enable controller specific keyboard event mappings.
*/
void defineJoyControllerMappings(const string& controllerName, Controller::Jack port) {
myPJoyHandler->defineControllerMappings(controllerName, port);
}
/**
Enable emulation keyboard event mappings.
*/
void enableEmulationJoyMappings() {
myPJoyHandler->enableEmulationMappings();
}
/** /**
Erase the specified mapping. Erase the specified mapping.

View File

@ -38,14 +38,20 @@ enum class MouseButton {
NONE NONE
}; };
static constexpr int JOY_CTRL_NONE = -1;
enum class JoyAxis { enum class JoyAxis {
X = 0, X = 0,
Y = 1, Y = 1,
Z = 2,
NONE = JOY_CTRL_NONE
}; };
enum class JoyDir { enum class JoyDir {
NEG = 0, NEG = -1,
POS = 1, POS = 1,
NONE = 0,
ANALOG = 2
}; };

View File

@ -30,8 +30,8 @@ Joystick::Joystick(Jack jack, const Event& event, const System& system)
myLeftEvent = Event::JoystickZeroLeft; myLeftEvent = Event::JoystickZeroLeft;
myRightEvent = Event::JoystickZeroRight; myRightEvent = Event::JoystickZeroRight;
myFireEvent = Event::JoystickZeroFire; myFireEvent = Event::JoystickZeroFire;
myXAxisValue = Event::SALeftAxis0Value; myXAxisValue = Event::PaddleZeroAnalog;
myYAxisValue = Event::SALeftAxis1Value; myYAxisValue = Event::PaddleOneAnalog;
} }
else else
{ {
@ -40,8 +40,8 @@ Joystick::Joystick(Jack jack, const Event& event, const System& system)
myLeftEvent = Event::JoystickOneLeft; myLeftEvent = Event::JoystickOneLeft;
myRightEvent = Event::JoystickOneRight; myRightEvent = Event::JoystickOneRight;
myFireEvent = Event::JoystickOneFire; myFireEvent = Event::JoystickOneFire;
myXAxisValue = Event::SARightAxis0Value; myXAxisValue = Event::PaddleTwoAnalog;
myYAxisValue = Event::SARightAxis1Value; myYAxisValue = Event::PaddleThreeAnalog;
} }
} }

View File

@ -53,8 +53,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
if(!swappaddle) // First paddle is 0, second is 1 if(!swappaddle) // First paddle is 0, second is 1
{ {
// These aren't affected by changes in axis orientation // These aren't affected by changes in axis orientation
myP0AxisValue = Event::SALeftAxis0Value; myP0AxisValue = Event::PaddleZeroAnalog;
myP1AxisValue = Event::SALeftAxis1Value; myP1AxisValue = Event::PaddleOneAnalog;
myP0FireEvent1 = Event::PaddleZeroFire; myP0FireEvent1 = Event::PaddleZeroFire;
myP0FireEvent2 = Event::JoystickZeroFire; myP0FireEvent2 = Event::JoystickZeroFire;
myP1FireEvent1 = Event::PaddleOneFire; myP1FireEvent1 = Event::PaddleOneFire;
@ -89,8 +89,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
else // First paddle is 1, second is 0 else // First paddle is 1, second is 0
{ {
// These aren't affected by changes in axis orientation // These aren't affected by changes in axis orientation
myP0AxisValue = Event::SALeftAxis1Value; myP0AxisValue = Event::PaddleOneAnalog;
myP1AxisValue = Event::SALeftAxis0Value; myP1AxisValue = Event::PaddleZeroAnalog;
myP0FireEvent1 = Event::PaddleOneFire; myP0FireEvent1 = Event::PaddleOneFire;
myP0FireEvent2 = Event::JoystickZeroFire9; myP0FireEvent2 = Event::JoystickZeroFire9;
myP1FireEvent1 = Event::PaddleZeroFire; myP1FireEvent1 = Event::PaddleZeroFire;
@ -128,8 +128,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
if(!swappaddle) // First paddle is 2, second is 3 if(!swappaddle) // First paddle is 2, second is 3
{ {
// These aren't affected by changes in axis orientation // These aren't affected by changes in axis orientation
myP0AxisValue = Event::SARightAxis0Value; myP0AxisValue = Event::PaddleTwoAnalog;
myP1AxisValue = Event::SARightAxis1Value; myP1AxisValue = Event::PaddleThreeAnalog;
myP0FireEvent1 = Event::PaddleTwoFire; myP0FireEvent1 = Event::PaddleTwoFire;
myP0FireEvent2 = Event::JoystickOneFire; myP0FireEvent2 = Event::JoystickOneFire;
myP1FireEvent1 = Event::PaddleThreeFire; myP1FireEvent1 = Event::PaddleThreeFire;
@ -164,8 +164,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
else // First paddle is 3, second is 2 else // First paddle is 3, second is 2
{ {
// These aren't affected by changes in axis orientation // These aren't affected by changes in axis orientation
myP0AxisValue = Event::SARightAxis1Value; myP0AxisValue = Event::PaddleThreeAnalog;
myP1AxisValue = Event::SARightAxis0Value; myP1AxisValue = Event::PaddleTwoAnalog;
myP0FireEvent1 = Event::PaddleThreeFire; myP0FireEvent1 = Event::PaddleThreeFire;
myP0FireEvent2 = Event::JoystickOneFire9; myP0FireEvent2 = Event::JoystickOneFire9;
myP1FireEvent1 = Event::PaddleTwoFire; myP1FireEvent1 = Event::PaddleTwoFire;

View File

@ -288,20 +288,20 @@ void ContextMenu::handleKeyDown(StellaKey key, StellaMod mod)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::handleJoyDown(int stick, int button) void ContextMenu::handleJoyDown(int stick, int button)
{ {
handleEvent(instance().eventHandler().eventForJoyButton(stick, button, kMenuMode)); handleEvent(instance().eventHandler().eventForJoyButton(kMenuMode, stick, button));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::handleJoyAxis(int stick, int axis, int value) void ContextMenu::handleJoyAxis(int stick, int axis, int value, int button)
{ {
if(value != 0) // we don't care about 'axis up' events if(value != 0) // we don't care about 'axis up' events
handleEvent(instance().eventHandler().eventForJoyAxis(stick, axis, value, kMenuMode)); handleEvent(instance().eventHandler().eventForJoyAxis(kMenuMode, stick, axis, value, button));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool ContextMenu::handleJoyHat(int stick, int hat, JoyHat value) bool ContextMenu::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
handleEvent(instance().eventHandler().eventForJoyHat(stick, hat, value, kMenuMode)); handleEvent(instance().eventHandler().eventForJoyHat(kMenuMode, stick, hat, value, button));
return true; return true;
} }

View File

@ -88,8 +88,8 @@ class ContextMenu : public Dialog, public CommandSender
void handleMouseWheel(int x, int y, int direction) override; void handleMouseWheel(int x, int y, int direction) override;
void handleKeyDown(StellaKey key, StellaMod mod) override; void handleKeyDown(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override; void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override; bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void handleEvent(Event::Type e); void handleEvent(Event::Type e);
void drawDialog() override; void drawDialog() override;

View File

@ -591,7 +591,7 @@ bool Dialog::handleMouseClicks(int x, int y, MouseButton b)
void Dialog::handleJoyDown(int stick, int button) void Dialog::handleJoyDown(int stick, int button)
{ {
Event::Type e = Event::Type e =
instance().eventHandler().eventForJoyButton(stick, button, kMenuMode); instance().eventHandler().eventForJoyButton(kMenuMode, stick, button);
// Unless a widget has claimed all responsibility for data, we assume // Unless a widget has claimed all responsibility for data, we assume
// that if an event exists for the given data, it should have priority. // that if an event exists for the given data, it should have priority.
@ -613,39 +613,39 @@ void Dialog::handleJoyUp(int stick, int button)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type Dialog::getJoyAxisEvent(int stick, int axis, int value) Event::Type Dialog::getJoyAxisEvent(int stick, int axis, int value, int button)
{ {
return instance().eventHandler().eventForJoyAxis(stick, axis, value, kMenuMode); return instance().eventHandler().eventForJoyAxis(kMenuMode, stick, axis, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::handleJoyAxis(int stick, int axis, int value) void Dialog::handleJoyAxis(int stick, int axis, int value, int button)
{ {
Event::Type e = getJoyAxisEvent(stick, axis, value); Event::Type e = getJoyAxisEvent(stick, axis, value, button);
// Unless a widget has claimed all responsibility for data, we assume // Unless a widget has claimed all responsibility for data, we assume
// that if an event exists for the given data, it should have priority. // that if an event exists for the given data, it should have priority.
if(!handleNavEvent(e) && _focusedWidget) if(!handleNavEvent(e) && _focusedWidget)
{ {
if(_focusedWidget->wantsRaw() || e == Event::NoType) if(_focusedWidget->wantsRaw() || e == Event::NoType)
_focusedWidget->handleJoyAxis(stick, axis, value); _focusedWidget->handleJoyAxis(stick, axis, value, button);
else if(value != 0) else if(value != 0)
_focusedWidget->handleEvent(e); _focusedWidget->handleEvent(e);
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Dialog::handleJoyHat(int stick, int hat, JoyHat value) bool Dialog::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
Event::Type e = Event::Type e =
instance().eventHandler().eventForJoyHat(stick, hat, value, kMenuMode); instance().eventHandler().eventForJoyHat(kMenuMode, stick, hat, value, button);
// Unless a widget has claimed all responsibility for data, we assume // Unless a widget has claimed all responsibility for data, we assume
// that if an event exists for the given data, it should have priority. // that if an event exists for the given data, it should have priority.
if(!handleNavEvent(e) && _focusedWidget) if(!handleNavEvent(e) && _focusedWidget)
{ {
if(_focusedWidget->wantsRaw() || e == Event::NoType) if(_focusedWidget->wantsRaw() || e == Event::NoType)
return _focusedWidget->handleJoyHat(stick, hat, value); return _focusedWidget->handleJoyHat(stick, hat, value, button);
else else
return _focusedWidget->handleEvent(e); return _focusedWidget->handleEvent(e);
} }

View File

@ -139,10 +139,10 @@ class Dialog : public GuiObject
virtual bool handleMouseClicks(int x, int y, MouseButton b); virtual bool handleMouseClicks(int x, int y, MouseButton b);
virtual void handleJoyDown(int stick, int button); virtual void handleJoyDown(int stick, int button);
virtual void handleJoyUp(int stick, int button); virtual void handleJoyUp(int stick, int button);
virtual void handleJoyAxis(int stick, int axis, int value); virtual void handleJoyAxis(int stick, int axis, int value, int button = JOY_CTRL_NONE);
virtual bool handleJoyHat(int stick, int hat, JoyHat value); virtual bool handleJoyHat(int stick, int hat, JoyHat value, int button = JOY_CTRL_NONE);
virtual void handleCommand(CommandSender* sender, int cmd, int data, int id) override; virtual void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
virtual Event::Type getJoyAxisEvent(int stick, int axis, int value); virtual Event::Type getJoyAxisEvent(int stick, int axis, int value, int button);
Widget* findWidget(int x, int y) const; // Find the widget at pos x,y if any Widget* findWidget(int x, int y) const; // Find the widget at pos x,y if any

View File

@ -299,7 +299,7 @@ void DialogContainer::handleJoyBtnEvent(int stick, int button, bool pressed)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value) void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value, int button)
{ {
if(myDialogStack.empty()) if(myDialogStack.empty())
return; return;
@ -307,21 +307,23 @@ void DialogContainer::handleJoyAxisEvent(int stick, int axis, int value)
// Only stop firing events if it's the current stick // Only stop firing events if it's the current stick
if(myCurrentAxisDown.stick == stick && value == 0) if(myCurrentAxisDown.stick == stick && value == 0)
{ {
cerr << "handleJoyAxisEvent 0" << endl;
myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1; myCurrentAxisDown.stick = myCurrentAxisDown.axis = -1;
} }
else if(value != 0) // never repeat the 'off' event else if(value != 0) // never repeat the 'off' event
{ {
cerr << "handleJoyAxisEvent repeat" << endl;
// Now account for repeated axis events (press and hold) // Now account for repeated axis events (press and hold)
myCurrentAxisDown.stick = stick; myCurrentAxisDown.stick = stick;
myCurrentAxisDown.axis = axis; myCurrentAxisDown.axis = axis;
myCurrentAxisDown.value = value; myCurrentAxisDown.value = value;
myAxisRepeatTime = myTime + kRepeatInitialDelay; myAxisRepeatTime = myTime + kRepeatInitialDelay;
} }
myDialogStack.top()->handleJoyAxis(stick, axis, value); myDialogStack.top()->handleJoyAxis(stick, axis, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value) void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value, int button)
{ {
if(myDialogStack.empty()) if(myDialogStack.empty())
return; return;
@ -339,7 +341,7 @@ void DialogContainer::handleJoyHatEvent(int stick, int hat, JoyHat value)
myCurrentHatDown.value = value; myCurrentHatDown.value = value;
myHatRepeatTime = myTime + kRepeatInitialDelay; myHatRepeatTime = myTime + kRepeatInitialDelay;
} }
myDialogStack.top()->handleJoyHat(stick, hat, value); myDialogStack.top()->handleJoyHat(stick, hat, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -108,7 +108,7 @@ class DialogContainer
@param axis The joystick axis @param axis The joystick axis
@param value Value associated with given axis @param value Value associated with given axis
*/ */
void handleJoyAxisEvent(int stick, int axis, int value); void handleJoyAxisEvent(int stick, int axis, int value, int button);
/** /**
Handle a joystick hat event. Handle a joystick hat event.
@ -117,7 +117,7 @@ class DialogContainer
@param hat The joystick hat @param hat The joystick hat
@param value Value associated with given hat @param value Value associated with given hat
*/ */
void handleJoyHatEvent(int stick, int hat, JoyHat value); void handleJoyHatEvent(int stick, int hat, JoyHat value, int button);
/** /**
Draw the stack of menus (full indicates to redraw all items). Draw the stack of menus (full indicates to redraw all items).

View File

@ -97,7 +97,7 @@ void EditTextWidget::drawWidget(bool hilite)
_changed && onTop && isEnabled() _changed && onTop && isEnabled()
? kDbgChangedTextColor ? kDbgChangedTextColor
: onTop && isEnabled() ? _textcolor : kColor, : onTop && isEnabled() ? _textcolor : kColor,
TextAlign::Left, -_editScrollOffset, false); TextAlign::Left, isEditable() ? -_editScrollOffset : 0, !isEditable());
// Draw the caret // Draw the caret
drawCaret(); drawCaret();

View File

@ -47,6 +47,7 @@ EventMappingWidget::EventMappingWidget(GuiObject* boss, const GUI::Font& font,
myLastAxis(0), myLastAxis(0),
myLastHat(0), myLastHat(0),
myLastValue(0), myLastValue(0),
myLastButton(JOY_CTRL_NONE),
myFirstTime(true) myFirstTime(true)
{ {
const int fontHeight = font.getFontHeight(), const int fontHeight = font.getFontHeight(),
@ -151,6 +152,7 @@ void EventMappingWidget::setDefaults()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::startRemapping() void EventMappingWidget::startRemapping()
{ {
cerr << "startRemapping" << endl;
if(myActionSelected < 0 || myRemapStatus) if(myActionSelected < 0 || myRemapStatus)
return; return;
@ -159,9 +161,10 @@ void EventMappingWidget::startRemapping()
// Reset all previous events for determining correct axis/hat values // Reset all previous events for determining correct axis/hat values
myLastStick = myLastAxis = myLastHat = myLastValue = -1; myLastStick = myLastAxis = myLastHat = myLastValue = -1;
myLastButton = JOY_CTRL_NONE;
// Reset the previously aggregated key mappings // Reset the previously aggregated key mappings
myMod = myKey = 0; myMod = myLastKey = 0;
// Disable all other widgets while in remap mode, except enable 'Cancel' // Disable all other widgets while in remap mode, except enable 'Cancel'
enableButtons(false); enableButtons(false);
@ -210,9 +213,11 @@ void EventMappingWidget::stopRemapping()
{ {
// Turn off remap mode // Turn off remap mode
myRemapStatus = false; myRemapStatus = false;
cerr << "stopRemapping " << myRemapStatus << endl;
// Reset all previous events for determining correct axis/hat values // Reset all previous events for determining correct axis/hat values
myLastStick = myLastAxis = myLastHat = myLastValue = -1; myLastStick = myLastAxis = myLastHat = myLastValue = -1;
myLastButton = JOY_CTRL_NONE;
// And re-enable all the widgets // And re-enable all the widgets
enableButtons(true); enableButtons(true);
@ -257,7 +262,7 @@ bool EventMappingWidget::handleKeyDown(StellaKey key, StellaMod mod)
// Remap keys in remap mode // Remap keys in remap mode
if (myRemapStatus && myActionSelected >= 0) if (myRemapStatus && myActionSelected >= 0)
{ {
myKey = key; myLastKey = key;
myMod |= mod; myMod |= mod;
} }
return true; return true;
@ -272,7 +277,7 @@ bool EventMappingWidget::handleKeyUp(StellaKey key, StellaMod mod)
{ {
Event::Type event = Event::Type event =
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode); instance().eventHandler().eventAtIndex(myActionSelected, myEventMode);
if (instance().eventHandler().addKeyMapping(event, myEventMode, StellaKey(myKey), StellaMod(myMod))) if (instance().eventHandler().addKeyMapping(event, myEventMode, StellaKey(myLastKey), StellaMod(myMod)))
stopRemapping(); stopRemapping();
} }
return true; return true;
@ -281,19 +286,40 @@ bool EventMappingWidget::handleKeyUp(StellaKey key, StellaMod mod)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::handleJoyDown(int stick, int button) void EventMappingWidget::handleJoyDown(int stick, int button)
{ {
cerr << "handleJoyDown" << endl;
// Remap joystick buttons in remap mode // Remap joystick buttons in remap mode
if(myRemapStatus && myActionSelected >= 0) if(myRemapStatus && myActionSelected >= 0)
{ {
Event::Type event = cerr << "remap button start " << myRemapStatus << endl;
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode); myLastStick = stick;
if(instance().eventHandler().addJoyButtonMapping(event, myEventMode, stick, button)) myLastButton = button;
stopRemapping();
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::handleJoyAxis(int stick, int axis, int value) void EventMappingWidget::handleJoyUp(int stick, int button)
{ {
cerr << "handleJoyUp" << endl;
// Remap joystick buttons in remap mode
if (myRemapStatus && myActionSelected >= 0)
{
if (myLastStick == stick && myLastButton == button)
{
EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
cerr << "remap button stop" << endl;
// This maps solo button presses only
if (eh.addJoyMapping(event, myEventMode, stick, button))
stopRemapping();
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventMappingWidget::handleJoyAxis(int stick, int axis, int value, int button)
{
cerr << "handleJoyAxis:" << axis << ", " << value << ", (" << stick << ", " << myLastStick << "), (" << axis << ", " << myLastAxis << ")" << endl;
// Remap joystick axes in remap mode // Remap joystick axes in remap mode
// There are two phases to detection: // There are two phases to detection:
// First, detect an axis 'on' event // First, detect an axis 'on' event
@ -301,8 +327,9 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value)
if(myRemapStatus && myActionSelected >= 0) if(myRemapStatus && myActionSelected >= 0)
{ {
// Detect the first axis event that represents 'on' // Detect the first axis event that represents 'on'
if(myLastStick == -1 && myLastAxis == -1 && value != 0) if((myLastStick == -1 || myLastStick == stick) && myLastAxis == -1 && value != 0)
{ {
cerr << "remap start" << endl;
myLastStick = stick; myLastStick = stick;
myLastAxis = axis; myLastAxis = axis;
myLastValue = value; myLastValue = value;
@ -311,19 +338,18 @@ void EventMappingWidget::handleJoyAxis(int stick, int axis, int value)
// stick and axis, but turns the axis 'off' // stick and axis, but turns the axis 'off'
else if(myLastStick == stick && axis == myLastAxis && value == 0) else if(myLastStick == stick && axis == myLastAxis && value == 0)
{ {
value = myLastValue; EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
Event::Type event = cerr << "remap stop" << endl;
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode); if (eh.addJoyMapping(event, myEventMode, stick, myLastButton, JoyAxis(axis), myLastValue))
if(instance().eventHandler().addJoyAxisMapping(event, myEventMode,
stick, axis, value))
stopRemapping(); stopRemapping();
} }
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value) bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
// Remap joystick hats in remap mode // Remap joystick hats in remap mode
// There are two phases to detection: // There are two phases to detection:
@ -332,7 +358,7 @@ bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value)
if(myRemapStatus && myActionSelected >= 0) if(myRemapStatus && myActionSelected >= 0)
{ {
// Detect the first hat event that represents a valid direction // Detect the first hat event that represents a valid direction
if(myLastStick == -1 && myLastHat == -1 && value != JoyHat::CENTER) if((myLastStick == -1 || myLastStick == stick) && myLastHat == -1 && value != JoyHat::CENTER)
{ {
myLastStick = stick; myLastStick = stick;
myLastHat = hat; myLastHat = hat;
@ -344,12 +370,10 @@ bool EventMappingWidget::handleJoyHat(int stick, int hat, JoyHat value)
// stick and hat, but centers the hat // stick and hat, but centers the hat
else if(myLastStick == stick && hat == myLastHat && value == JoyHat::CENTER) else if(myLastStick == stick && hat == myLastHat && value == JoyHat::CENTER)
{ {
value = JoyHat(myLastValue); EventHandler& eh = instance().eventHandler();
Event::Type event = eh.eventAtIndex(myActionSelected, myEventMode);
Event::Type event = if (eh.addJoyHatMapping(event, myEventMode, stick, myLastButton, hat, JoyHat(myLastValue)))
instance().eventHandler().eventAtIndex(myActionSelected, myEventMode);
if(instance().eventHandler().addJoyHatMapping(event, myEventMode,
stick, hat, value))
{ {
stopRemapping(); stopRemapping();
return true; return true;

View File

@ -60,8 +60,9 @@ class EventMappingWidget : public Widget, public CommandSender
bool handleKeyDown(StellaKey key, StellaMod mod) override; bool handleKeyDown(StellaKey key, StellaMod mod) override;
bool handleKeyUp(StellaKey key, StellaMod mod) override; bool handleKeyUp(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override; void handleJoyUp(int stick, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override; void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void loadConfig() override; void loadConfig() override;
void saveConfig(); void saveConfig();
@ -108,7 +109,9 @@ class EventMappingWidget : public Widget, public CommandSender
// Aggregates the modifier flags of the mapping // Aggregates the modifier flags of the mapping
int myMod; int myMod;
// Saves the last *pressed* key // Saves the last *pressed* key
int myKey; int myLastKey;
// Saves the last *pressed* button
int myLastButton;
bool myFirstTime; bool myFirstTime;

View File

@ -481,27 +481,39 @@ void InputDialog::handleJoyDown(int stick, int button)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleJoyAxis(int stick, int axis, int value) void InputDialog::handleJoyUp(int stick, int button)
{ {
// Remap joystick axis in remap mode, otherwise pass to parent dialog // Remap joystick buttons in remap mode, otherwise pass to parent dialog
if(myEmulEventMapper->remapMode()) if (myEmulEventMapper->remapMode())
myEmulEventMapper->handleJoyAxis(stick, axis, value); myEmulEventMapper->handleJoyUp(stick, button);
else if(myMenuEventMapper->remapMode()) else if (myMenuEventMapper->remapMode())
myMenuEventMapper->handleJoyAxis(stick, axis, value); myMenuEventMapper->handleJoyUp(stick, button);
else else
Dialog::handleJoyAxis(stick, axis, value); Dialog::handleJoyUp(stick, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool InputDialog::handleJoyHat(int stick, int hat, JoyHat value) void InputDialog::handleJoyAxis(int stick, int axis, int value, int button)
{
// Remap joystick axis in remap mode, otherwise pass to parent dialog
if(myEmulEventMapper->remapMode())
myEmulEventMapper->handleJoyAxis(stick, axis, value, button);
else if(myMenuEventMapper->remapMode())
myMenuEventMapper->handleJoyAxis(stick, axis, value, button);
else
Dialog::handleJoyAxis(stick, axis, value, button);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool InputDialog::handleJoyHat(int stick, int hat, JoyHat value, int button)
{ {
// Remap joystick hat in remap mode, otherwise pass to parent dialog // Remap joystick hat in remap mode, otherwise pass to parent dialog
if(myEmulEventMapper->remapMode()) if(myEmulEventMapper->remapMode())
return myEmulEventMapper->handleJoyHat(stick, hat, value); return myEmulEventMapper->handleJoyHat(stick, hat, value, button);
else if(myMenuEventMapper->remapMode()) else if(myMenuEventMapper->remapMode())
return myMenuEventMapper->handleJoyHat(stick, hat, value); return myMenuEventMapper->handleJoyHat(stick, hat, value, button);
else else
return Dialog::handleJoyHat(stick, hat, value); return Dialog::handleJoyHat(stick, hat, value, button);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -46,8 +46,9 @@ class InputDialog : public Dialog
void handleKeyDown(StellaKey key, StellaMod mod) override; void handleKeyDown(StellaKey key, StellaMod mod) override;
void handleKeyUp(StellaKey key, StellaMod mod) override; void handleKeyUp(StellaKey key, StellaMod mod) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
void handleJoyAxis(int stick, int axis, int value) override; void handleJoyUp(int stick, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value) override; void handleJoyAxis(int stick, int axis, int value, int button) override;
bool handleJoyHat(int stick, int hat, JoyHat value, int button) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void loadConfig() override; void loadConfig() override;

View File

@ -469,7 +469,7 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod)
void LauncherDialog::handleJoyDown(int stick, int button) void LauncherDialog::handleJoyDown(int stick, int button)
{ {
// open power-up options and settings for 2nd and 4th button if not mapped otherwise // open power-up options and settings for 2nd and 4th button if not mapped otherwise
Event::Type e = instance().eventHandler().eventForJoyButton(stick, button, kMenuMode); Event::Type e = instance().eventHandler().eventForJoyButton(kMenuMode, stick, button);
if (button == 1 && (e == Event::UIOK || e == Event::NoType)) if (button == 1 && (e == Event::UIOK || e == Event::NoType))
myGlobalProps->open(); myGlobalProps->open();
@ -480,9 +480,9 @@ void LauncherDialog::handleJoyDown(int stick, int button)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type LauncherDialog::getJoyAxisEvent(int stick, int axis, int value) Event::Type LauncherDialog::getJoyAxisEvent(int stick, int axis, int value, int button)
{ {
Event::Type e = instance().eventHandler().eventForJoyAxis(stick, axis, value, kMenuMode); Event::Type e = instance().eventHandler().eventForJoyAxis(kMenuMode, stick, axis, value, button);
if(myUseMinimalUI) if(myUseMinimalUI)
{ {

View File

@ -92,7 +92,7 @@ class LauncherDialog : public Dialog
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
void handleJoyDown(int stick, int button) override; void handleJoyDown(int stick, int button) override;
Event::Type getJoyAxisEvent(int stick, int axis, int value) override; Event::Type getJoyAxisEvent(int stick, int axis, int value, int button) override;
void loadConfig() override; void loadConfig() override;
void updateUI(); void updateUI();

View File

@ -79,8 +79,8 @@ class Widget : public GuiObject
virtual bool handleMouseClicks(int x, int y, MouseButton b) { return false; } virtual bool handleMouseClicks(int x, int y, MouseButton b) { return false; }
virtual void handleJoyDown(int stick, int button) { } virtual void handleJoyDown(int stick, int button) { }
virtual void handleJoyUp(int stick, int button) { } virtual void handleJoyUp(int stick, int button) { }
virtual void handleJoyAxis(int stick, int axis, int value) { } virtual void handleJoyAxis(int stick, int axis, int value, int button = JOY_CTRL_NONE) { }
virtual bool handleJoyHat(int stick, int hat, JoyHat value) { return false; } virtual bool handleJoyHat(int stick, int hat, JoyHat value, int button = JOY_CTRL_NONE) { return false; }
virtual bool handleEvent(Event::Type event) { return false; } virtual bool handleEvent(Event::Type event) { return false; }
void setDirty() override; void setDirty() override;

View File

@ -376,6 +376,7 @@
<ClCompile Include="..\common\FpsMeter.cxx" /> <ClCompile Include="..\common\FpsMeter.cxx" />
<ClCompile Include="..\common\FrameBufferSDL2.cxx" /> <ClCompile Include="..\common\FrameBufferSDL2.cxx" />
<ClCompile Include="..\common\FSNodeZIP.cxx" /> <ClCompile Include="..\common\FSNodeZIP.cxx" />
<ClCompile Include="..\common\JoyMap.cxx" />
<ClCompile Include="..\common\KeyMap.cxx" /> <ClCompile Include="..\common\KeyMap.cxx" />
<ClCompile Include="..\common\Logger.cxx" /> <ClCompile Include="..\common\Logger.cxx" />
<ClCompile Include="..\common\main.cxx" /> <ClCompile Include="..\common\main.cxx" />
@ -1072,6 +1073,7 @@
<ClInclude Include="..\common\FrameBufferSDL2.hxx" /> <ClInclude Include="..\common\FrameBufferSDL2.hxx" />
<ClInclude Include="..\common\FSNodeFactory.hxx" /> <ClInclude Include="..\common\FSNodeFactory.hxx" />
<ClInclude Include="..\common\FSNodeZIP.hxx" /> <ClInclude Include="..\common\FSNodeZIP.hxx" />
<ClInclude Include="..\common\JoyMap.hxx" />
<ClInclude Include="..\common\KeyMap.hxx" /> <ClInclude Include="..\common\KeyMap.hxx" />
<ClInclude Include="..\common\LinkedObjectPool.hxx" /> <ClInclude Include="..\common\LinkedObjectPool.hxx" />
<ClInclude Include="..\common\Logger.hxx" /> <ClInclude Include="..\common\Logger.hxx" />

View File

@ -975,6 +975,9 @@
<ClCompile Include="..\gui\R77HelpDialog.cxx"> <ClCompile Include="..\gui\R77HelpDialog.cxx">
<Filter>Source Files\gui</Filter> <Filter>Source Files\gui</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\common\JoyMap.cxx">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\common\bspf.hxx"> <ClInclude Include="..\common\bspf.hxx">
@ -1994,6 +1997,9 @@
<ClInclude Include="..\common\KeyMap.hxx"> <ClInclude Include="..\common\KeyMap.hxx">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\common\JoyMap.hxx">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="stella.ico"> <None Include="stella.ico">