2 #include "controllerdata.hpp"
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
;
12 for(unsigned i
= 0; i
< MAX_SYSTEM_CONTROLS
; i
++)
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
) {
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
)
34 for(unsigned j
= 0; j
< components
; j
++) {
35 std::string tmp
= line
;
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
)
91 if(controls
[2] || controls
[3]) {
92 std::ostringstream out
;
93 out
<< x
<< " " << controls
[2] << " " << controls
[3];
99 std::string
cencode::none(unsigned port
, const short* controls
) throw(std::bad_alloc
)
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
)])
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
];
125 std::string
cencode::mouse(unsigned port
, const short* controls
) throw(std::bad_alloc
)
127 std::ostringstream 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)];
135 std::string
cencode::superscope(unsigned port
, const short* controls
) throw(std::bad_alloc
)
137 std::ostringstream 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)];
147 std::string
cencode::justifier(unsigned port
, const short* controls
) throw(std::bad_alloc
)
149 std::ostringstream 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)];
157 std::string
cencode::justifiers(unsigned port
, const short* controls
) throw(std::bad_alloc
)
159 std::ostringstream 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)];
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)];
171 controls_t
controls_t::operator^(controls_t other
) throw()
174 for(size_t i
= 0; i
< TOTAL_CONTROLS
; i
++)
175 x
.controls
[i
] = controls
[i
] ^ ((i
< MAX_SYSTEM_CONTROLS
) ? 0 : other
.controls
[i
]);
179 controls_t::controls_t(bool sync
) throw()
181 memset(controls
, 0, sizeof(controls
));
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
)
223 x
= cencode::system(controls
);
224 for(unsigned i
= 0; i
< encoders
.size(); i
++)
225 x
= x
+ encoders
[i
](i
, controls
);
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
])
238 controlfield::controlfield(std::vector
<control_subfield
> _subfields
) throw(std::bad_alloc
)
240 subfields
= _subfields
;
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
++)
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
)
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;
272 for(unsigned i
= 0; i
< subfields
.size(); i
++)
274 if(subfields
[i
].type
== control_subfield::AXIS
) {
276 //Skip whitespace before subfield.
277 while(pos
< str
.length() && (str
[pos
] == ' ' || str
[pos
] == '\t'))
279 if(pos
< str
.length())
280 value
= (short)atoi(str
.c_str() + pos
);
281 values
[subfields
[i
].index
] = value
;
287 std::vector
<struct control_subfield
> gamepad() throw(std::bad_alloc
)
289 static std::vector
<struct control_subfield
> g
;
290 static bool init
= false;
292 for(unsigned i
= 0; i
< 12; i
++)
293 g
.push_back(control_subfield(i
, control_subfield::BUTTON
));
299 std::vector
<struct control_subfield
> mousejustifier() throw(std::bad_alloc
)
301 static std::vector
<struct control_subfield
> g
;
302 static bool init
= false;
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
));
313 std::vector
<struct control_subfield
> superscope() throw(std::bad_alloc
)
315 static std::vector
<struct control_subfield
> g
;
316 static bool init
= false;
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
));
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;
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
));
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()
374 const port_type
& port_type::lookup(const std::string
& name
, bool port2
) throw(std::bad_alloc
,
377 for(unsigned i
= 0; i
<= PT_LAST_CTYPE
; i
++) {
378 if(name
!= port_types
[i
].name
)
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 }