2 #include "controllerdata.hpp"
11 inline unsigned ccindex(unsigned port
, unsigned controller
, unsigned control
) throw(std::logic_error
)
13 if(port
>= MAX_PORTS
|| controller
>= MAX_CONTROLLERS_PER_PORT
|| control
>= CONTROLLER_CONTROLS
) {
15 x
<< "ccindex: Invalid (port, controller, control) tuple (" << port
<< "," << controller
16 << "," << control
<< ")";
17 throw std::logic_error(x
.str());
19 return MAX_SYSTEM_CONTROLS
+ port
* CONTROLLER_CONTROLS
* MAX_CONTROLLERS_PER_PORT
+
20 CONTROLLER_CONTROLS
* controller
+ control
;
23 bool parse_button_ctrl(const std::string
& str
, size_t& pos
) throw()
25 if(pos
>= str
.length())
40 short parse_number_ctrl(const std::string
& str
, size_t& pos
) throw()
44 while(pos
< str
.length()) {
46 if(ch
!= ' ' && ch
!= '\t')
50 //Read the sign if any.
51 if(pos
>= str
.length() || (ch
= str
[pos
]) == '|')
53 bool negative
= false;
63 while(pos
< str
.length() && isdigit(static_cast<unsigned char>(ch
= str
[pos
]))) {
64 numval
= numval
* 10 + (ch
- '0');
70 return static_cast<short>(numval
);
73 void parse_end_of_field(const std::string
& str
, size_t& pos
) throw()
75 while(pos
< str
.length() && str
[pos
] != '|')
80 size_t cdecode::system(const std::string
& line
, size_t pos
, short* controls
, unsigned version
) throw(std::bad_alloc
,
83 controls
[0] = parse_button_ctrl(line
, pos
); //Frame sync.
84 controls
[1] = parse_button_ctrl(line
, pos
); //Reset.
85 controls
[2] = parse_number_ctrl(line
, pos
); //Reset cycles hi.
86 controls
[3] = parse_number_ctrl(line
, pos
); //Reset cycles lo.
87 parse_end_of_field(line
, pos
);
91 size_t cdecode::none(unsigned port
, const std::string
& line
, size_t pos
, short* controls
) throw(std::bad_alloc
,
97 size_t cdecode::gamepad(unsigned port
, const std::string
& line
, size_t pos
, short* controls
) throw(std::bad_alloc
,
100 for(unsigned i
= 0; i
< 12; i
++)
101 controls
[ccindex(port
, 0, i
)] = parse_button_ctrl(line
, pos
);
102 parse_end_of_field(line
, pos
);
106 size_t cdecode::multitap(unsigned port
, const std::string
& line
, size_t pos
, short* controls
) throw(std::bad_alloc
,
109 for(unsigned j
= 0; j
< 4; j
++) {
110 for(unsigned i
= 0; i
< 12; i
++)
111 controls
[ccindex(port
, j
, i
)] = parse_button_ctrl(line
, pos
);
112 parse_end_of_field(line
, pos
);
118 size_t cdecode::mouse(unsigned port
, const std::string
& line
, size_t pos
, short* controls
) throw(std::bad_alloc
,
121 controls
[ccindex(port
, 0, 2)] = parse_button_ctrl(line
, pos
);
122 controls
[ccindex(port
, 0, 3)] = parse_button_ctrl(line
, pos
);
123 controls
[ccindex(port
, 0, 0)] = parse_number_ctrl(line
, pos
);
124 controls
[ccindex(port
, 0, 1)] = parse_number_ctrl(line
, pos
);
125 parse_end_of_field(line
, pos
);
129 size_t cdecode::superscope(unsigned port
, const std::string
& line
, size_t pos
, short* controls
) throw(std::bad_alloc
,
132 controls
[ccindex(port
, 0, 2)] = parse_button_ctrl(line
, pos
);
133 controls
[ccindex(port
, 0, 3)] = parse_button_ctrl(line
, pos
);
134 controls
[ccindex(port
, 0, 4)] = parse_button_ctrl(line
, pos
);
135 controls
[ccindex(port
, 0, 5)] = parse_button_ctrl(line
, pos
);
136 controls
[ccindex(port
, 0, 0)] = parse_number_ctrl(line
, pos
);
137 controls
[ccindex(port
, 0, 1)] = parse_number_ctrl(line
, pos
);
138 parse_end_of_field(line
, pos
);
142 size_t cdecode::justifier(unsigned port
, const std::string
& line
, size_t pos
, short* controls
) throw(std::bad_alloc
,
145 controls
[ccindex(port
, 0, 2)] = parse_button_ctrl(line
, pos
);
146 controls
[ccindex(port
, 0, 3)] = parse_button_ctrl(line
, pos
);
147 controls
[ccindex(port
, 0, 0)] = parse_number_ctrl(line
, pos
);
148 controls
[ccindex(port
, 0, 1)] = parse_number_ctrl(line
, pos
);
149 parse_end_of_field(line
, pos
);
153 size_t cdecode::justifiers(unsigned port
, const std::string
& line
, size_t pos
, short* controls
) throw(std::bad_alloc
,
156 for(unsigned i
= 0; i
< 2; i
++) {
157 controls
[ccindex(port
, i
, 2)] = parse_button_ctrl(line
, pos
);
158 controls
[ccindex(port
, i
, 3)] = parse_button_ctrl(line
, pos
);
159 controls
[ccindex(port
, i
, 0)] = parse_number_ctrl(line
, pos
);
160 controls
[ccindex(port
, i
, 1)] = parse_number_ctrl(line
, pos
);
161 parse_end_of_field(line
, pos
);
167 size_t cencode::system(char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
169 buffer
[bufferpos
++] = controls
[0] ? 'F' : '.';
170 buffer
[bufferpos
++] = controls
[1] ? 'R' : '.';
171 if(controls
[2] || controls
[3]) {
172 bufferpos
+= sprintf(buffer
+ bufferpos
, " %i %i", static_cast<int>(controls
[2]),
173 static_cast<int>(controls
[3]));
178 size_t cencode::none(unsigned port
, char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
180 return ENCODE_SPECIAL_NO_OUTPUT
;
183 size_t cencode::gamepad(unsigned port
, char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
185 static const char* characters
= "BYsSudlrAXLR";
186 for(unsigned i
= 0; i
< 12; i
++)
187 buffer
[bufferpos
++] = controls
[ccindex(port
, 0, i
)] ? characters
[i
] : '.';
191 size_t cencode::multitap(unsigned port
, char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
193 static const char* characters
= "BYsSudlrAXLR";
194 for(unsigned j
= 0; j
< 4; j
++) {
195 for(unsigned i
= 0; i
< 12; i
++)
196 buffer
[bufferpos
++] = controls
[ccindex(port
, j
, i
)] ? characters
[i
] : '.';
197 buffer
[bufferpos
++] = '|';
199 bufferpos
--; //Eat the last '|', it shouldn't be there.
203 size_t cencode::mouse(unsigned port
, char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
205 bufferpos
+= sprintf(buffer
+ bufferpos
, "%c%c %i %i", controls
[ccindex(port
, 0, 2)] ? 'L' : '.',
206 controls
[ccindex(port
, 0, 3)] ? 'R' : '.', static_cast<int>(controls
[ccindex(port
, 0, 0)]),
207 static_cast<int>(controls
[ccindex(port
, 0, 1)]));
211 size_t cencode::superscope(unsigned port
, char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
213 bufferpos
+= sprintf(buffer
+ bufferpos
, "%c%c%c%c %i %i", controls
[ccindex(port
, 0, 2)] ? 'T' : '.',
214 controls
[ccindex(port
, 0, 3)] ? 'C' : '.', controls
[ccindex(port
, 0, 4)] ? 'U' : '.',
215 controls
[ccindex(port
, 0, 5)] ? 'P' : '.', static_cast<int>(controls
[ccindex(port
, 0, 0)]),
216 static_cast<int>(controls
[ccindex(port
, 0, 1)]));
220 size_t cencode::justifier(unsigned port
, char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
222 bufferpos
+= sprintf(buffer
+ bufferpos
, "%c%c %i %i", controls
[ccindex(port
, 0, 2)] ? 'T' : '.',
223 controls
[ccindex(port
, 0, 3)] ? 'S' : '.', static_cast<int>(controls
[ccindex(port
, 0, 0)]),
224 static_cast<int>(controls
[ccindex(port
, 0, 1)]));
228 size_t cencode::justifiers(unsigned port
, char* buffer
, size_t bufferpos
, const short* controls
) throw(std::bad_alloc
)
230 bufferpos
+= sprintf(buffer
+ bufferpos
, "%c%c %i %i", controls
[ccindex(port
, 0, 2)] ? 'T' : '.',
231 controls
[ccindex(port
, 0, 3)] ? 'S' : '.', static_cast<int>(controls
[ccindex(port
, 0, 0)]),
232 static_cast<int>(controls
[ccindex(port
, 0, 1)]));
233 buffer
[bufferpos
++] = '|';
234 bufferpos
+= sprintf(buffer
+ bufferpos
, "%c%c %i %i", controls
[ccindex(port
, 0, 2)] ? 'T' : '.',
235 controls
[ccindex(port
, 0, 3)] ? 'S' : '.', static_cast<int>(controls
[ccindex(port
, 0, 0)]),
236 static_cast<int>(controls
[ccindex(port
, 0, 1)]));
241 unsigned ccindex2(unsigned port
, unsigned controller
, unsigned control
) throw(std::logic_error
)
243 return ccindex(port
, controller
, control
);
247 controls_t
controls_t::operator^(controls_t other
) throw()
250 for(size_t i
= 0; i
< TOTAL_CONTROLS
; i
++)
251 x
.controls
[i
] = controls
[i
] ^ ((i
< MAX_SYSTEM_CONTROLS
) ? 0 : other
.controls
[i
]);
255 controls_t::controls_t(bool sync
) throw()
257 memset(controls
, 0, sizeof(controls
));
259 controls
[CONTROL_FRAME_SYNC
] = 1;
262 const short& controls_t::operator()(unsigned port
, unsigned controller
, unsigned control
) const throw(std::logic_error
)
264 return controls
[ccindex(port
, controller
, control
)];
267 const short& controls_t::operator()(unsigned control
) const throw(std::logic_error
)
269 if(control
>= TOTAL_CONTROLS
)
270 throw std::logic_error("controls_t::operator(): Invalid control index");
271 return controls
[control
];
274 short& controls_t::operator()(unsigned port
, unsigned controller
, unsigned control
) throw(std::logic_error
)
276 return controls
[ccindex(port
, controller
, control
)];
279 short& controls_t::operator()(unsigned control
) throw(std::logic_error
)
281 if(control
>= TOTAL_CONTROLS
)
282 throw std::logic_error("controls_t::operator(): Invalid control index");
283 return controls
[control
];
286 controls_t::controls_t(const std::string
& line
, const std::vector
<cdecode::fn_t
>& decoders
, unsigned version
)
287 throw(std::bad_alloc
, std::runtime_error
)
289 memset(controls
, 0, sizeof(controls
));
291 position
= cdecode::system(line
, position
, controls
, version
);
292 for(unsigned i
= 0; i
< decoders
.size(); i
++) {
293 if(position
< line
.length() && line
[position
] == '|')
295 position
= decoders
[i
](i
, line
, position
, controls
);
299 std::string
controls_t::tostring(const std::vector
<cencode::fn_t
>& encoders
) const throw(std::bad_alloc
)
302 size_t linelen
= 0, tmp
;
303 tmp
= cencode::system(buffer
, linelen
, controls
);
304 for(unsigned i
= 0; i
< encoders
.size(); i
++) {
305 if(tmp
!= ENCODE_SPECIAL_NO_OUTPUT
)
306 buffer
[(linelen
= tmp
)++] = '|';
307 tmp
= encoders
[i
](i
, buffer
, linelen
, controls
);
309 if(tmp
!= ENCODE_SPECIAL_NO_OUTPUT
)
311 return std::string(buffer
, buffer
+ linelen
);
314 bool controls_t::operator==(const controls_t
& c
) const throw()
316 for(size_t i
= 0; i
< TOTAL_CONTROLS
; i
++)
317 if(controls
[i
] != c
.controls
[i
])
323 const port_type
& port_type::lookup(const std::string
& name
, bool port2
) throw(std::bad_alloc
,
326 for(unsigned i
= 0; i
<= PT_LAST_CTYPE
; i
++) {
327 if(name
!= port_types
[i
].name
)
329 if(!port2
&& !port_types
[i
].valid_port1
)
330 throw std::runtime_error("Can't connect " + name
+ " to port #1");
331 return port_types
[i
];
333 throw std::runtime_error("Unknown port type '" + name
+ "'");
336 port_type port_types
[] = {
337 { "none", cdecode::none
, cencode::none
, PT_NONE
, 0, DT_NONE
, true },
338 { "gamepad", cdecode::gamepad
, cencode::gamepad
, PT_GAMEPAD
, 1, DT_GAMEPAD
, true },
339 { "multitap", cdecode::multitap
, cencode::multitap
, PT_MULTITAP
, 4, DT_GAMEPAD
, true },
340 { "mouse", cdecode::mouse
, cencode::mouse
, PT_MOUSE
, 1, DT_MOUSE
, true },
341 { "superscope", cdecode::superscope
, cencode::superscope
, PT_SUPERSCOPE
, 1, DT_SUPERSCOPE
, false },
342 { "justifier", cdecode::justifier
, cencode::justifier
, PT_JUSTIFIER
, 1, DT_JUSTIFIER
, false },
343 { "justifiers", cdecode::justifiers
, cencode::justifiers
, PT_JUSTIFIERS
, 2, DT_JUSTIFIER
, false }