1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#ifndef CONTROLLERMAP_HXX
19#define CONTROLLERMAP_HXX
20
21#include <unordered_map>
22#include "Event.hxx"
23#include "EventHandlerConstants.hxx"
24
25/**
26 This class handles controller mappings in Stella.
27
28 @author Thomas Jentzsch
29*/
30class JoyMap
31{
32 public:
33
34 struct JoyMapping
35 {
36 EventMode mode;
37 int button; // button number
38 JoyAxis axis; // horizontal/vertical
39 JoyDir adir; // axis direction (neg/pos)
40 int hat; // hat number
41 JoyHatDir hdir; // hat direction (left/right/up/down)
42
43 JoyMapping()
44 : mode(EventMode(0)), button(0),
45 axis(JoyAxis(0)), adir(JoyDir(0)),
46 hat(0), hdir(JoyHatDir(0)) { }
47 JoyMapping(const JoyMapping& m)
48 : mode(m.mode), button(m.button),
49 axis(m.axis), adir(m.adir),
50 hat(m.hat), hdir(m.hdir) { }
51 explicit JoyMapping(EventMode c_mode, int c_button,
52 JoyAxis c_axis, JoyDir c_adir,
53 int c_hat, JoyHatDir c_hdir)
54 : mode(c_mode), button(c_button),
55 axis(c_axis), adir(c_adir),
56 hat(c_hat), hdir(c_hdir) { }
57 explicit JoyMapping(EventMode c_mode, int c_button,
58 JoyAxis c_axis, JoyDir c_adir)
59 : mode(c_mode), button(c_button),
60 axis(c_axis), adir(c_adir),
61 hat(JOY_CTRL_NONE), hdir(JoyHatDir::CENTER) { }
62 explicit JoyMapping(EventMode c_mode, int c_button,
63 int c_hat, JoyHatDir c_hdir)
64 : mode(c_mode), button(c_button),
65 axis(JoyAxis::NONE), adir(JoyDir::NONE),
66 hat(c_hat), hdir(c_hdir) { }
67
68 bool operator==(const JoyMapping& other) const
69 {
70 return (mode == other.mode
71 && button == other.button
72 && axis == other.axis
73 && adir == other.adir
74 && hat == other.hat
75 && hdir == other.hdir
76 );
77 }
78 };
79 using JoyMappingArray = std::vector<JoyMapping>;
80
81 JoyMap();
82 virtual ~JoyMap() = default;
83
84 /** Add new mapping for given event */
85 void add(const Event::Type event, const JoyMapping& mapping);
86 void add(const Event::Type event, const EventMode mode, const int button,
87 const JoyAxis axis, const JoyDir adir,
88 const int hat = JOY_CTRL_NONE, const JoyHatDir hdir = JoyHatDir::CENTER);
89 void add(const Event::Type event, const EventMode mode, const int button,
90 const int hat, const JoyHatDir hdir);
91
92 /** Erase mapping */
93 void erase(const JoyMapping& mapping);
94 void erase(const EventMode mode, const int button,
95 const JoyAxis axis, const JoyDir adir);
96 void erase(const EventMode mode, const int button,
97 const int hat, const JoyHatDir hdir);
98
99 /** Get event for mapping */
100 Event::Type get(const JoyMapping& mapping) const;
101 Event::Type get(const EventMode mode, const int button,
102 const JoyAxis axis = JoyAxis::NONE, const JoyDir adir = JoyDir::NONE) const;
103 Event::Type get(const EventMode mode, const int button,
104 const int hat, const JoyHatDir hdir) const;
105
106 /** Check if a mapping exists */
107 bool check(const JoyMapping& mapping) const;
108 bool check(const EventMode mode, const int button,
109 const JoyAxis axis, const JoyDir adir,
110 const int hat = JOY_CTRL_NONE, const JoyHatDir hdir = JoyHatDir::CENTER) const;
111
112 /** Get mapping description */
113 string getEventMappingDesc(int stick, const Event::Type event, const EventMode mode) const;
114
115 JoyMappingArray getEventMapping(const Event::Type event, const EventMode mode) const;
116
117 string saveMapping(const EventMode mode) const;
118 int loadMapping(string& list, const EventMode mode);
119
120 /** Erase all mappings for given mode */
121 void eraseMode(const EventMode mode);
122 /** Erase given event's mapping for given mode */
123 void eraseEvent(const Event::Type event, const EventMode mode);
124 /** clear all mappings for a modes */
125 // void clear() { myMap.clear(); }
126 size_t size() { return myMap.size(); }
127
128 private:
129 string getDesc(const Event::Type event, const JoyMapping& mapping) const;
130
131 struct JoyHash {
132 size_t operator()(const JoyMapping& m)const {
133 return std::hash<uInt64>()((uInt64(m.mode)) // 3 bits
134 + ((uInt64(m.button)) * 7) // 3 bits
135 + (((uInt64(m.axis)) << 0) // 2 bits
136 | ((uInt64(m.adir)) << 2) // 2 bits
137 | ((uInt64(m.hat )) << 4) // 1 bit
138 | ((uInt64(m.hdir)) << 5) // 2 bits
139 ) * 61
140 );
141 }
142 };
143
144 std::unordered_map<JoyMapping, Event::Type, JoyHash> myMap;
145};
146
147#endif
148