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#include <map>
19
20#include "OSystem.hxx"
21#include "Settings.hxx"
22#include "Vec.hxx"
23#include "bspf.hxx"
24#include "PhysicalJoystick.hxx"
25
26// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27PhysicalJoystick::PhysicalJoystick()
28 : type(JT_NONE),
29 ID(-1),
30 name("None"),
31 numAxes(0),
32 numButtons(0),
33 numHats(0),
34 axisLastValue(nullptr),
35 buttonLast(nullptr)
36{
37}
38
39// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
40PhysicalJoystick::~PhysicalJoystick()
41{
42 delete[] axisLastValue;
43 delete[] buttonLast;
44}
45
46// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
47void PhysicalJoystick::initialize(int index, const string& desc,
48 int axes, int buttons, int hats, int /*balls*/)
49{
50 ID = index;
51 name = desc;
52
53 // Dynamically create the various mapping arrays for this joystick,
54 // based on its specific attributes
55 numAxes = axes;
56 numButtons = buttons;
57 numHats = hats;
58 axisLastValue = new int[numAxes];
59 buttonLast = new int[numButtons];
60
61 // Erase the last button
62 for (int b = 0; b < numButtons; ++b)
63 buttonLast[b] = JOY_CTRL_NONE;
64
65 // Erase the last axis value
66 for(int a = 0; a < numAxes; ++a)
67 axisLastValue[a] = 0;
68
69 // Erase the mappings
70 eraseMap(EventMode::kMenuMode);
71 eraseMap(EventMode::kJoystickMode);
72 eraseMap(EventMode::kPaddlesMode);
73 eraseMap(EventMode::kKeypadMode);
74 eraseMap(EventMode::kCommonMode);
75}
76
77// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
78string PhysicalJoystick::getMap() const
79{
80 // The mapping structure (for remappable devices) is defined as follows:
81 // <NAME>'>'<MODE>['|'(<EVENT>':'<BUTTON>','<AXIS>','<VALUE>)|(<EVENT>':'<BUTTON>','<HAT>','<HATDIR>)]
82
83 ostringstream joybuf;
84
85 joybuf << name;
86 joybuf << MODE_DELIM << int(EventMode::kMenuMode) << "|" << joyMap.saveMapping(EventMode::kMenuMode);
87 joybuf << MODE_DELIM << int(EventMode::kJoystickMode) << "|" << joyMap.saveMapping(EventMode::kJoystickMode);
88 joybuf << MODE_DELIM << int(EventMode::kPaddlesMode) << "|" << joyMap.saveMapping(EventMode::kPaddlesMode);
89 joybuf << MODE_DELIM << int(EventMode::kKeypadMode) << "|" << joyMap.saveMapping(EventMode::kKeypadMode);
90 joybuf << MODE_DELIM << int(EventMode::kCommonMode) << "|" << joyMap.saveMapping(EventMode::kCommonMode);
91
92 return joybuf.str();
93}
94
95// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96bool PhysicalJoystick::setMap(const string& mapString)
97{
98 istringstream buf(mapString);
99 string map;
100 int i = 0;
101
102 // Skip joystick name
103 getline(buf, map, MODE_DELIM);
104
105 while (getline(buf, map, MODE_DELIM))
106 {
107 int mode;
108
109 // Get event mode
110 std::replace(map.begin(), map.end(), '|', ' ');
111 istringstream modeBuf(map);
112 modeBuf >> mode;
113
114 // Remove leading "<mode>|" string
115 map.erase(0, 2);
116
117 joyMap.loadMapping(map, EventMode(mode));
118 i++;
119 }
120 // Brief error checking
121 if(i != 5)
122 {
123 cerr << "ERROR: Invalid controller mappings found" << endl;
124 return false;
125 }
126
127 return true;
128}
129
130// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
131void PhysicalJoystick::eraseMap(EventMode mode)
132{
133 joyMap.eraseMode(mode);
134}
135
136// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
137void PhysicalJoystick::eraseEvent(Event::Type event, EventMode mode)
138{
139 joyMap.eraseEvent(event, mode);
140}
141
142// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
143void PhysicalJoystick::getValues(const string& list, IntArray& map) const
144{
145 map.clear();
146 istringstream buf(list);
147
148 int value;
149 buf >> value; // we don't need to know the # of items at this point
150 while(buf >> value)
151 map.push_back(value);
152}
153
154// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
155string PhysicalJoystick::about() const
156{
157 ostringstream buf;
158 buf << "'" << name << "' with: " << numAxes << " axes, " << numButtons << " buttons, "
159 << numHats << " hats";
160
161 return buf.str();
162}
163