Fix all warnings -Wall spews
[lsnes.git] / controllerdata.cpp
blobed0654de4e9966b62c5c652d66e83e01351d048d
1 #include "lsnes.hpp"
2 #include "controllerdata.hpp"
3 #include <sstream>
4 #include <iostream>
5 #include <cstring>
7 void cdecode::system(fieldsplitter& line, short* controls, unsigned version) throw(std::bad_alloc, std::runtime_error)
9 static controlfield_system p(version);
10 std::string tmp = line;
11 p.set_field(tmp);
12 for(unsigned i = 0; i < MAX_SYSTEM_CONTROLS; i++)
13 controls[i] = p[i];
16 namespace
18 inline unsigned ccindex(unsigned port, unsigned controller, unsigned control) throw(std::logic_error)
20 if(port >= MAX_PORTS || controller >= MAX_CONTROLLERS_PER_PORT || control >= CONTROLLER_CONTROLS) {
21 std::ostringstream x;
22 x << "ccindex: Invalid (port, controller, control) tuple (" << port << "," << controller
23 << "," << control << ")";
24 throw std::logic_error(x.str());
26 return MAX_SYSTEM_CONTROLS + port * CONTROLLER_CONTROLS * MAX_CONTROLLERS_PER_PORT +
27 CONTROLLER_CONTROLS * controller + control;
30 template<unsigned components, class cfield>
31 void decode(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
33 static cfield p;
34 for(unsigned j = 0; j < components; j++) {
35 std::string tmp = line;
36 p.set_field(tmp);
37 for(unsigned i = 0; i < p.indices(); i++)
38 controls[MAX_SYSTEM_CONTROLS + port * CONTROLLER_CONTROLS * MAX_CONTROLLERS_PER_PORT +
39 CONTROLLER_CONTROLS * j + i] = p[i];
44 unsigned ccindex2(unsigned port, unsigned controller, unsigned control) throw(std::logic_error)
46 return ccindex(port, controller, control);
50 void cdecode::none(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
52 decode<0, controlfield_gamepad>(port, line, controls);
55 void cdecode::gamepad(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
57 decode<1, controlfield_gamepad>(port, line, controls);
59 void cdecode::multitap(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
61 decode<4, controlfield_gamepad>(port, line, controls);
64 void cdecode::mouse(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
66 decode<1, controlfield_mousejustifier>(port, line, controls);
69 void cdecode::superscope(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
71 decode<1, controlfield_superscope>(port, line, controls);
74 void cdecode::justifier(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
76 decode<1, controlfield_mousejustifier>(port, line, controls);
79 void cdecode::justifiers(unsigned port, fieldsplitter& line, short* controls) throw(std::bad_alloc, std::runtime_error)
81 decode<2, controlfield_mousejustifier>(port, line, controls);
84 std::string cencode::system(const short* controls) throw(std::bad_alloc)
86 std::string x = "..";
87 if(controls[0])
88 x[0] = 'F';
89 if(controls[1])
90 x[1] = 'R';
91 if(controls[2] || controls[3]) {
92 std::ostringstream out;
93 out << x << " " << controls[2] << " " << controls[3];
94 x = out.str();
96 return x;
99 std::string cencode::none(unsigned port, const short* controls) throw(std::bad_alloc)
101 return "";
104 std::string cencode::gamepad(unsigned port, const short* controls) throw(std::bad_alloc)
106 const char chars[] = "BYsSudlrAXLR";
107 std::string x = "|............";
108 for(unsigned i = 0; i < 12; i++)
109 if(controls[ccindex(port, 0, i)])
110 x[i + 1] = chars[i];
111 return x;
114 std::string cencode::multitap(unsigned port, const short* controls) throw(std::bad_alloc)
116 const char chars[] = "BYsSudlrAXLR";
117 std::string x = "|............|............|............|............";
118 for(unsigned j = 0; j < 4; j++)
119 for(unsigned i = 0; i < 12; i++)
120 if(controls[ccindex(port, j, i)])
121 x[13 * j + i + 1] = chars[i];
122 return x;
125 std::string cencode::mouse(unsigned port, const short* controls) throw(std::bad_alloc)
127 std::ostringstream s;
128 s << "|";
129 s << (controls[ccindex(port, 0, 2)] ? 'L' : '.');
130 s << (controls[ccindex(port, 0, 3)] ? 'R' : '.');
131 s << " " << controls[ccindex(port, 0, 0)] << " " << controls[ccindex(port, 0, 1)];
132 return s.str();
135 std::string cencode::superscope(unsigned port, const short* controls) throw(std::bad_alloc)
137 std::ostringstream s;
138 s << "|";
139 s << (controls[ccindex(port, 0, 2)] ? 'T' : '.');
140 s << (controls[ccindex(port, 0, 3)] ? 'C' : '.');
141 s << (controls[ccindex(port, 0, 4)] ? 'U' : '.');
142 s << (controls[ccindex(port, 0, 5)] ? 'P' : '.');
143 s << " " << controls[ccindex(port, 0, 0)] << " " << controls[ccindex(port, 0, 1)];
144 return s.str();
147 std::string cencode::justifier(unsigned port, const short* controls) throw(std::bad_alloc)
149 std::ostringstream s;
150 s << "|";
151 s << (controls[ccindex(port, 0, 2)] ? 'T' : '.');
152 s << (controls[ccindex(port, 0, 3)] ? 'S' : '.');
153 s << " " << controls[ccindex(port, 0, 0)] << " " << controls[ccindex(port, 0, 1)];
154 return s.str();
157 std::string cencode::justifiers(unsigned port, const short* controls) throw(std::bad_alloc)
159 std::ostringstream s;
160 s << "|";
161 s << (controls[ccindex(port, 0, 2)] ? 'T' : '.');
162 s << (controls[ccindex(port, 0, 3)] ? 'S' : '.');
163 s << " " << controls[ccindex(port, 0, 0)] << " " << controls[ccindex(port, 0, 1)];
164 s << "|";
165 s << (controls[ccindex(port, 1, 2)] ? 'T' : '.');
166 s << (controls[ccindex(port, 1, 3)] ? 'S' : '.');
167 s << " " << controls[ccindex(port, 1, 0)] << " " << controls[ccindex(port, 1, 1)];
168 return s.str();
171 controls_t controls_t::operator^(controls_t other) throw()
173 controls_t x;
174 for(size_t i = 0; i < TOTAL_CONTROLS; i++)
175 x.controls[i] = controls[i] ^ ((i < MAX_SYSTEM_CONTROLS) ? 0 : other.controls[i]);
176 return x;
179 controls_t::controls_t(bool sync) throw()
181 memset(controls, 0, sizeof(controls));
182 if(sync)
183 controls[CONTROL_FRAME_SYNC] = 1;
186 const short& controls_t::operator()(unsigned port, unsigned controller, unsigned control) const throw(std::logic_error)
188 return controls[ccindex(port, controller, control)];
191 const short& controls_t::operator()(unsigned control) const throw(std::logic_error)
193 if(control >= TOTAL_CONTROLS)
194 throw std::logic_error("controls_t::operator(): Invalid control index");
195 return controls[control];
198 short& controls_t::operator()(unsigned port, unsigned controller, unsigned control) throw(std::logic_error)
200 return controls[ccindex(port, controller, control)];
203 short& controls_t::operator()(unsigned control) throw(std::logic_error)
205 if(control >= TOTAL_CONTROLS)
206 throw std::logic_error("controls_t::operator(): Invalid control index");
207 return controls[control];
210 controls_t::controls_t(const std::string& line, const std::vector<cdecode::fn_t>& decoders, unsigned version)
211 throw(std::bad_alloc, std::runtime_error)
213 memset(controls, 0, sizeof(controls));
214 fieldsplitter _line(line);
215 cdecode::system(_line, controls, version);
216 for(unsigned i = 0; i < decoders.size(); i++)
217 decoders[i](i, _line, controls);
220 std::string controls_t::tostring(const std::vector<cencode::fn_t>& encoders) const throw(std::bad_alloc)
222 std::string x;
223 x = cencode::system(controls);
224 for(unsigned i = 0; i < encoders.size(); i++)
225 x = x + encoders[i](i, controls);
226 return x;
229 bool controls_t::operator==(const controls_t& c) const throw()
231 for(size_t i = 0; i < TOTAL_CONTROLS; i++)
232 if(controls[i] != c.controls[i])
233 return false;
234 return true;
238 controlfield::controlfield(std::vector<control_subfield> _subfields) throw(std::bad_alloc)
240 subfields = _subfields;
241 size_t needed = 0;
242 for(size_t i = 0; i < subfields.size(); i++)
243 if(needed <= subfields[i].index)
244 needed = subfields[i].index + 1;
245 values.resize(needed);
246 for(size_t i = 0; i < needed; i++)
247 values[i] = 0;
250 short controlfield::operator[](unsigned index) throw(std::logic_error)
252 if(index >= values.size())
253 throw std::logic_error("controlfield::operator[]: Bad subfield index");
254 return values[index];
257 unsigned controlfield::indices() throw()
259 return values.size();
262 void controlfield::set_field(const std::string& str) throw(std::bad_alloc)
264 size_t pos = 0;
265 for(unsigned i = 0; i < subfields.size(); i++)
266 //Buttons always come first.
267 if(subfields[i].type == control_subfield::BUTTON) {
268 values[subfields[i].index] = (pos < str.length() && str[pos] != '.' && str[pos] != ' ' &&
269 str[pos] != '\t') ? 1 : 0;
270 pos++;
272 for(unsigned i = 0; i < subfields.size(); i++)
273 //Then the axis.
274 if(subfields[i].type == control_subfield::AXIS) {
275 short value = 0;
276 //Skip whitespace before subfield.
277 while(pos < str.length() && (str[pos] == ' ' || str[pos] == '\t'))
278 pos++;
279 if(pos < str.length())
280 value = (short)atoi(str.c_str() + pos);
281 values[subfields[i].index] = value;
285 namespace
287 std::vector<struct control_subfield> gamepad() throw(std::bad_alloc)
289 static std::vector<struct control_subfield> g;
290 static bool init = false;
291 if(!init) {
292 for(unsigned i = 0; i < 12; i++)
293 g.push_back(control_subfield(i, control_subfield::BUTTON));
294 init = true;
296 return g;
299 std::vector<struct control_subfield> mousejustifier() throw(std::bad_alloc)
301 static std::vector<struct control_subfield> g;
302 static bool init = false;
303 if(!init) {
304 g.push_back(control_subfield(0, control_subfield::AXIS));
305 g.push_back(control_subfield(1, control_subfield::AXIS));
306 g.push_back(control_subfield(2, control_subfield::BUTTON));
307 g.push_back(control_subfield(3, control_subfield::BUTTON));
308 init = true;
310 return g;
313 std::vector<struct control_subfield> superscope() throw(std::bad_alloc)
315 static std::vector<struct control_subfield> g;
316 static bool init = false;
317 if(!init) {
318 g.push_back(control_subfield(0, control_subfield::AXIS));
319 g.push_back(control_subfield(1, control_subfield::AXIS));
320 g.push_back(control_subfield(2, control_subfield::BUTTON));
321 g.push_back(control_subfield(3, control_subfield::BUTTON));
322 g.push_back(control_subfield(4, control_subfield::BUTTON));
323 g.push_back(control_subfield(5, control_subfield::BUTTON));
324 init = true;
326 return g;
329 std::vector<struct control_subfield> csystem(unsigned version) throw(std::bad_alloc, std::runtime_error)
331 static std::vector<struct control_subfield> g0;
332 static bool init0 = false;
333 if(version == 0) {
334 if(!init0) {
335 g0.push_back(control_subfield(0, control_subfield::BUTTON));
336 g0.push_back(control_subfield(1, control_subfield::BUTTON));
337 g0.push_back(control_subfield(2, control_subfield::AXIS));
338 g0.push_back(control_subfield(3, control_subfield::AXIS));
339 init0 = true;
341 return g0;
342 } else
343 throw std::runtime_error("csystem: Unknown record version");
347 controlfield_system::controlfield_system(unsigned version) throw(std::bad_alloc, std::runtime_error)
348 : controlfield(csystem(version))
352 controlfield_gamepad::controlfield_gamepad() throw(std::bad_alloc)
353 : controlfield(gamepad())
357 controlfield_mousejustifier::controlfield_mousejustifier() throw(std::bad_alloc)
358 : controlfield(mousejustifier())
362 controlfield_superscope::controlfield_superscope() throw(std::bad_alloc)
363 : controlfield(superscope())
368 control_subfield::control_subfield(unsigned _index, enum control_subfield::control_subfield_type _type) throw()
370 index = _index;
371 type = _type;
374 const port_type& port_type::lookup(const std::string& name, bool port2) throw(std::bad_alloc,
375 std::runtime_error)
377 for(unsigned i = 0; i <= PT_LAST_CTYPE; i++) {
378 if(name != port_types[i].name)
379 continue;
380 if(!port2 && !port_types[i].valid_port1)
381 throw std::runtime_error("Can't connect " + name + " to port #1");
382 return port_types[i];
384 throw std::runtime_error("Unknown port type '" + name + "'");
387 port_type port_types[] = {
388 { "none", cdecode::none, cencode::none, PT_NONE, 0, DT_NONE, true },
389 { "gamepad", cdecode::gamepad, cencode::gamepad, PT_GAMEPAD, 1, DT_GAMEPAD, true },
390 { "multitap", cdecode::multitap, cencode::multitap, PT_MULTITAP, 4, DT_GAMEPAD, true },
391 { "mouse", cdecode::mouse, cencode::mouse, PT_MOUSE, 1, DT_MOUSE, true },
392 { "superscope", cdecode::superscope, cencode::superscope, PT_SUPERSCOPE, 1, DT_SUPERSCOPE, false },
393 { "justifier", cdecode::justifier, cencode::justifier, PT_JUSTIFIER, 1, DT_JUSTIFIER, false },
394 { "justifiers", cdecode::justifiers, cencode::justifiers, PT_JUSTIFIERS, 2, DT_JUSTIFIER, false }