Lua: Don't lua_error() out of context with pending dtors
[lsnes.git] / src / library / portctrl-parse.cpp
blobe3d9c73cc4f23d11d182fddff17b885da1ea0143
1 #include "arch-detect.hpp"
2 #include "assembler.hpp"
3 #include "assembler-intrinsics-dummy.hpp"
4 #include "assembler-intrinsics-i386.hpp"
5 #include "portctrl-data.hpp"
6 #include "portctrl-parse.hpp"
7 #include "portctrl-parse-asmgen.hpp"
8 #include "json.hpp"
9 #include "string.hpp"
10 #include <algorithm>
12 namespace portctrl
14 namespace
16 std::string quote(const std::string& s)
18 std::ostringstream y;
19 y << "\"";
20 for(auto i : s)
21 if(i == '\"')
22 y << "\"";
23 else if(i == '\\')
24 y << "\\\\";
25 else
26 y << i;
27 y << "\"";
28 return y.str();
31 std::string read_str(const JSON::node& root, const JSON::pointer& ptr)
33 if(root.type_of(ptr) != JSON::string)
34 (stringfmt() << "Expected string for '" << ptr << "'").throwex();
35 return root[ptr].as_string8();
38 std::u32string read_str32(const JSON::node& root, const JSON::pointer& ptr)
40 if(root.type_of(ptr) != JSON::string)
41 (stringfmt() << "Expected string for '" << ptr << "'").throwex();
42 return root[ptr].as_string();
45 int64_t read_int(const JSON::node& root, const JSON::pointer& ptr)
47 if(root.type_of(ptr) != JSON::number)
48 (stringfmt() << "Expected number for '" << ptr << "'").throwex();
49 return root[ptr].as_int();
52 bool read_bool(const JSON::node& root, const JSON::pointer& ptr)
54 if(root.type_of(ptr) != JSON::boolean)
55 (stringfmt() << "Expected boolean for '" << ptr << "'").throwex();
56 return root[ptr].as_bool();
60 button pcb_null(const JSON::node& root, const JSON::pointer& ptr)
62 auto pshadow = ptr.field("shadow");
63 struct button ret;
64 ret.type = button::TYPE_NULL;
65 ret.name = "";
66 ret.symbol = U'\0';
67 ret.rmin = 0;
68 ret.rmax = 0;
69 ret.centers = false;
70 ret.macro = "";
71 ret.msymbol = '\0';
72 ret.shadow = (root.type_of(pshadow) != JSON::none) ? read_bool(root, pshadow) : false;
73 return ret;
76 button pcb_button(const JSON::node& root, const JSON::pointer& ptr)
78 auto pshadow = ptr.field("shadow");
79 auto pname = ptr.field("name");
80 auto psymbol = ptr.field("symbol");
81 auto pmacro = ptr.field("macro");
82 auto pmovie = ptr.field("movie");
83 struct button ret;
84 ret.type = button::TYPE_BUTTON;
85 ret.name = read_str(root, pname);
86 std::u32string symbol = (root.type_of(psymbol) != JSON::none) ? read_str32(root, psymbol) :
87 utf8::to32(ret.name);
88 if(symbol.length() != 1)
89 (stringfmt() << "Symbol at '" << ptr << "' must be 1 codepoint").throwex();
90 ret.symbol = symbol[0];
91 ret.rmin = 0;
92 ret.rmax = 0;
93 ret.centers = false;
94 ret.macro = (root.type_of(pmacro) != JSON::none) ? read_str(root, pmacro) : utf8::to8(symbol);
95 std::string movie = (root.type_of(pmovie) != JSON::none) ? read_str(root, pmovie) :
96 utf8::to8(symbol);
97 if(movie.length() != 1)
98 (stringfmt() << "Movie at '" << ptr << "' must be 1 character").throwex();
99 ret.msymbol = movie[0];
100 ret.shadow = (root.type_of(pshadow) != JSON::none) ? read_bool(root, pshadow) : false;
101 return ret;
104 button pcb_axis(const JSON::node& root, const JSON::pointer& ptr, const std::string& type)
106 auto pshadow = ptr.field("shadow");
107 auto pname = ptr.field("name");
108 auto pcenters = ptr.field("centers");
109 struct button ret;
110 if(type == "axis") ret.type = button::TYPE_AXIS;
111 if(type == "raxis") ret.type = button::TYPE_RAXIS;
112 if(type == "taxis") ret.type = button::TYPE_TAXIS;
113 if(type == "lightgun") ret.type = button::TYPE_LIGHTGUN;
114 ret.name = read_str(root, pname);
115 ret.symbol = U'\0';
116 ret.shadow = (root.type_of(pshadow) != JSON::none) ? read_bool(root, pshadow) : false;
117 ret.rmin = ret.shadow ? -32768 : read_int(root, ptr.field("min"));
118 ret.rmax = ret.shadow ? 32767 : read_int(root, ptr.field("max"));
119 ret.centers = (root.type_of(pcenters) != JSON::none) ? read_bool(root, pcenters) : false;
120 ret.macro = "";
121 ret.msymbol = '\0';
122 return ret;
125 struct button pcs_parse_button(const JSON::node& root, JSON::pointer ptr)
127 if(root.type_of_indirect(ptr) != JSON::object)
128 (stringfmt() << "Expected (indirect) object for '" << ptr << "'").throwex();
129 ptr = root.resolve_indirect(ptr);
130 const std::string& type = read_str(root, ptr.field("type"));
131 if(type == "null")
132 return pcb_null(root, ptr);
133 else if(type == "button")
134 return pcb_button(root, ptr);
135 else if(type == "axis" || type == "raxis" || type == "taxis" || type == "lightgun")
136 return pcb_axis(root, ptr, type);
137 else
138 (stringfmt() << "Unknown type '" << type << "' for '" << ptr << "'").throwex();
139 return pcb_null(root, ptr); //NOTREACHED.
142 struct controller pcs_parse_controller(const JSON::node& root, JSON::pointer ptr)
144 if(root.type_of_indirect(ptr) != JSON::object)
145 (stringfmt() << "Expected (indirect) object for '" << ptr << "'").throwex();
146 ptr = root.resolve_indirect(ptr);
147 controller ret;
148 auto pbuttons = ptr.field("buttons");
149 std::string cclass = read_str(root, ptr.field("class"));
150 std::string type = read_str(root, ptr.field("type"));
151 if(root.type_of_indirect(pbuttons) != JSON::array)
152 (stringfmt() << "Expected (indirect) array for '" << pbuttons << "'").throwex();
153 JSON::pointer _buttons = root.resolve_indirect(pbuttons);
154 const JSON::node& n_buttons = root.follow(_buttons);
155 std::vector<button> buttons;
156 for(auto i = n_buttons.begin(); i != n_buttons.end(); i++)
157 buttons.push_back(pcs_parse_button(root, _buttons.index(i.index())));
158 ret.cclass = cclass;
159 ret.type = type;
160 ret.buttons = buttons;
161 return ret;
164 struct controller_set* pcs_parse_set(const JSON::node& root, JSON::pointer ptr)
166 if(root.type_of_indirect(ptr) != JSON::object)
167 (stringfmt() << "Expected (indirect) object for '" << ptr << "'").throwex();
168 ptr = root.resolve_indirect(ptr);
169 controller_set* ret = NULL;
170 auto pcontrollers = ptr.field("controllers");
171 auto plegal = ptr.field("legal");
172 auto phname = ptr.field("hname");
173 auto psymbol = ptr.field("symbol");
174 if(root.type_of_indirect(pcontrollers) != JSON::array)
175 (stringfmt() << "Expected (indirect) array for '" << pcontrollers << "'").throwex();
176 JSON::pointer _controllers = root.resolve_indirect(pcontrollers);
177 const JSON::node& n_controllers = root.follow(_controllers);
178 std::vector<controller> controllers;
179 for(auto i = n_controllers.begin(); i != n_controllers.end(); i++)
180 controllers.push_back(pcs_parse_controller(root, _controllers.index(i.index())));
181 if(root.type_of_indirect(plegal) != JSON::array)
182 (stringfmt() << "Expected (indirect) array for '" << plegal << "'").throwex();
183 JSON::pointer _legal = root.resolve_indirect(plegal);
184 const JSON::node& n_legal = root.follow_indirect(_legal);
185 std::set<unsigned> legal;
186 for(auto i = n_legal.begin(); i != n_legal.end(); i++)
187 legal.insert(read_int(root, _legal.index(i.index())));
188 std::string iname = read_str(root, ptr.field("name"));
189 std::string hname = (root.type_of(phname) != JSON::none) ? read_str(root, phname) : iname;
190 std::string symbol = (root.type_of(psymbol) != JSON::none) ? read_str(root, psymbol) : iname;
191 ret = new controller_set;
192 ret->iname = iname;
193 ret->hname = hname;
194 ret->symbol = symbol;
195 ret->controllers = controllers;
196 ret->legal_for = legal;
197 return ret;
200 void write_button(std::ostream& s, const button& b)
202 s << "{portctrl::button::TYPE_";
203 switch(b.type) {
204 case button::TYPE_NULL: s << "NULL"; break;
205 case button::TYPE_BUTTON: s << "BUTTON"; break;
206 case button::TYPE_AXIS: s << "AXIS"; break;
207 case button::TYPE_RAXIS: s << "RAXIS"; break;
208 case button::TYPE_TAXIS: s << "TAXIS"; break;
209 case button::TYPE_LIGHTGUN: s << "LIGHTGUN"; break;
211 s << "," << (int)b.symbol << ", " << quote(b.name) << ", " << b.shadow << ", " << b.rmin << ", "
212 << b.rmax << ", " << b.centers << ", " << quote(b.macro) << ", " << (int)b.msymbol << "}";
215 void write_controller(std::ostream& s, const controller& c, unsigned idx)
217 s << "portctrl::controller port_tmp_" << idx << " = {" << quote(c.cclass) << ", " << quote(c.type)
218 << ", {\n";
219 for(auto i : c.buttons) {
220 s << "\t";
221 write_button(s, i);
222 s << ",\n";
224 s << "}};\n";
227 void write_portdata(std::ostream& s, const controller_set& cs, unsigned& idx)
229 s << "namespace portdefs {\n";
230 for(unsigned i = 0; i < cs.controllers.size(); i++)
231 write_controller(s, cs.controllers[i], idx + i);
232 s << "portctrl::controller_set port_tmp_" << (idx + cs.controllers.size()) << " = {\n";
233 s << "\t" << quote(cs.iname) << ", " << quote(cs.hname) << ", " << quote(cs.symbol) << ",{";
234 for(unsigned i = 0; i < cs.controllers.size(); i++)
235 s << "port_tmp_" << (idx + i) << ", ";
236 s << "},{";
237 for(auto i : cs.legal_for)
238 s << i << ", ";
239 s << "}\n";
240 s << "};\n";
241 s << "}\n";
242 idx += (cs.controllers.size() + 1);
245 size_t get_ssize(const controller_set& cs)
247 size_t x = 0;
248 for(auto i : cs.controllers)
249 for(auto j : i.buttons) {
250 switch(j.type) {
251 case button::TYPE_BUTTON: x++; break;
252 case button::TYPE_AXIS: x+=16; break;
253 case button::TYPE_LIGHTGUN: x+=16; break;
254 case button::TYPE_NULL: break;
255 case button::TYPE_RAXIS: x+=16; break;
256 case button::TYPE_TAXIS: x+=16; break;
259 return (x + 7) / 8;
262 size_t get_aoffset(const controller_set& cs)
264 size_t x = 0;
265 for(auto i : cs.controllers)
266 for(auto j : i.buttons) {
267 switch(j.type) {
268 case button::TYPE_BUTTON: x++; break;
269 case button::TYPE_AXIS: break;
270 case button::TYPE_LIGHTGUN: break;
271 case button::TYPE_NULL: break;
272 case button::TYPE_RAXIS: break;
273 case button::TYPE_TAXIS: break;
276 return (x + 7) / 8;
279 std::vector<type_generic::idxinfo> get_idx_instructions(const controller_set& cs)
281 std::vector<type_generic::idxinfo> ret;
282 size_t aoffset = get_aoffset(cs);
283 size_t buttonidx2 = 0;
284 size_t axisidx2 = 0;
285 for(unsigned i = 0; i < cs.controllers.size(); i++) {
286 for(unsigned j = 0; j < cs.controllers[i].buttons.size(); j++) {
287 type_generic::idxinfo ii;
288 ii.controller = i;
289 ii.index = j;
290 switch(cs.controllers[i].buttons[j].type) {
291 case button::TYPE_NULL:
292 ii.type = 0;
293 break;
294 case button::TYPE_BUTTON:
295 ii.type = 1;
296 ii.offset = buttonidx2 / 8;
297 ii.mask = 1 << (buttonidx2 & 7);
298 ii.imask = ~ii.mask;
299 buttonidx2++;
300 break;
301 case button::TYPE_AXIS:
302 case button::TYPE_RAXIS:
303 case button::TYPE_TAXIS:
304 case button::TYPE_LIGHTGUN:
305 ii.type = 2;
306 ii.offset = aoffset + 2 * axisidx2;
307 axisidx2++;
308 break;
310 ret.push_back(ii);
313 return ret;
316 std::vector<type_generic::ser_instruction> get_ser_instructions(const controller_set& cs)
318 std::vector<type_generic::ser_instruction> ret;
319 size_t aoffset = get_aoffset(cs);
320 size_t buttonidx = 0;
321 size_t axisidx = 0;
322 type_generic::ser_instruction ins;
323 for(unsigned i = 0; i < cs.controllers.size(); i++) {
324 if(i == 0 && !cs.legal_for.count(0)) {
325 ins.type = 2;
326 ret.push_back(ins);
328 if(i > 0) {
329 ins.type = 3;
330 ret.push_back(ins);
332 for(unsigned j = 0; j < cs.controllers[i].buttons.size(); j++) {
333 switch(cs.controllers[i].buttons[j].type) {
334 case button::TYPE_BUTTON:
335 ins.type = 0;
336 ins.offset = buttonidx / 8;
337 ins.mask = 1 << (buttonidx & 7);
338 ins.character = cs.controllers[i].buttons[j].msymbol;
339 ret.push_back(ins);
340 buttonidx++;
341 break;
342 default: break;
345 for(unsigned j = 0; j < cs.controllers[i].buttons.size(); j++) {
346 switch(cs.controllers[i].buttons[j].type) {
347 case button::TYPE_AXIS:
348 case button::TYPE_RAXIS:
349 case button::TYPE_TAXIS:
350 case button::TYPE_LIGHTGUN:
351 ins.type = 1;
352 ins.offset = aoffset + 2 * axisidx;
353 ret.push_back(ins);
354 axisidx++;
355 break;
356 default: break;
360 ins.type = cs.controllers.size() ? 4 : 5;
361 ret.push_back(ins);
362 return ret;
366 struct controller_set* pcs_from_json(const JSON::node& root, const std::string& ptr)
368 return pcs_parse_set(root, ptr);
371 std::string pcs_write_class(const struct controller_set& pset, unsigned& tmp_idx)
373 std::ostringstream s;
374 write_portdata(s, pset, tmp_idx);
375 unsigned pidx = tmp_idx - 1;
376 auto repr = get_ser_instructions(pset);
377 auto idxr = get_idx_instructions(pset);
378 s << "struct _" << pset.symbol << " : public portctrl::type\n";
379 s << "{\n";
380 s << "\t_" << pset.symbol << "() : type(" << quote(pset.iname) << ", " << quote(pset.hname)
381 << ", " << get_ssize(pset) << ")\n";
382 s << "\t{\n";
383 s << "\t\twrite = [](const portctrl::type* _this, unsigned char* buffer, unsigned idx, unsigned ctrl, "
384 << "short x) -> void {\n";
385 s << "\t\t\tswitch(idx) {\n";
386 int last_controller = -1;
387 for(auto i : idxr) {
388 if(i.controller != last_controller) {
389 if(last_controller >= 0) {
390 s << "\t\t\t\t}\n";
391 s << "\t\t\t\tbreak;\n";
393 s << "\t\t\tcase " << i.controller << ":\n";
394 s << "\t\t\t\tswitch(ctrl) {\n";
395 last_controller = i.controller;
397 s << "\t\t\t\tcase " << i.index << ":\n";
398 switch(i.type) {
399 case 0:
400 s << "\t\t\t\t\tbreak;\n";
401 break;
402 case 1:
403 s << "\t\t\t\t\tif(x) buffer[" << i.offset << "]|=" << (int)i.mask
404 <<"; else buffer[" << i.offset << "]&=" << (int)i.imask
405 << ";\n";
406 s << "\t\t\t\t\tbreak;\n";
407 break;
408 case 2:
409 s << "\t\t\t\t\tbuffer[" << i.offset << "]=(unsigned short)x;\n";
410 s << "\t\t\t\t\tbuffer[" << i.offset + 1 << "]=((unsigned short)x >> 8);\n";
411 s << "\t\t\t\t\tbreak;\n";
412 break;
415 if(last_controller >= 0) {
416 s << "\t\t\t\t}\n";
417 s << "\t\t\t\tbreak;\n";
419 s << "\t\t\t}\n";
420 s << "\t\t};\n";
421 s << "\t\tread = [](const portctrl::type* _this, const unsigned char* buffer, unsigned idx, "
422 << "unsigned ctrl) -> short {\n";
423 s << "\t\t\tswitch(idx) {\n";
424 last_controller = -1;
425 for(auto i : idxr) {
426 if(i.controller != last_controller) {
427 if(last_controller >= 0) {
428 s << "\t\t\t\t}\n";
429 s << "\t\t\t\treturn 0;\n";
431 s << "\t\t\tcase " << i.controller << ":\n";
432 s << "\t\t\t\tswitch(ctrl) {\n";
433 last_controller = i.controller;
435 s << "\t\t\t\tcase " << i.index << ":\n";
436 switch(i.type) {
437 case 0:
438 s << "\t\t\t\t\treturn 0;\n";
439 break;
440 case 1:
441 s << "\t\t\t\t\treturn (buffer[" << i.offset << "]&" << (int)i.mask << ") ? 1 : 0;\n";
442 break;
443 case 2:
444 s << "\t\t\t\t\treturn (short)((unsigned short)buffer[" << i.offset
445 << "] + ((unsigned short)buffer[" << i.offset + 1 << "] << 8));\n";
448 if(last_controller >= 0) {
449 s << "\t\t\t\t}\n";
450 s << "\t\t\treturn 0;\n";
452 s << "\t\t\treturn 0;\n";
453 s << "\t\t\t}\n";
454 s << "\t\t\treturn 0;\n";
455 s << "\t\t};\n";
456 s << "\t\tserialize = [](const portctrl::type* _this, const unsigned char* buffer, char* textbuf) -> "
457 << "size_t {\n";
458 s << "\t\t\tsize_t ptr = 0;\n";
459 s << "\t\t\tshort tmp;\n";
460 for(auto i : repr) {
461 switch(i.type) {
462 case 0:
463 s << "\t\t\ttextbuf[ptr++] = (buffer[" << i.offset << "] & " << (int)i.mask << ") ? (char)"
464 << (int)i.character << " : '.';\n";
465 break;
466 case 1:
467 s << "\t\t\ttmp = (short)((unsigned short)buffer[" << i.offset
468 << "] + ((unsigned short)buffer[" << (i.offset + 1) << "] << 8));\n";
469 s << "\t\t\tptr += sprintf(textbuf + ptr, \" %i\", tmp);\n";
470 break;
471 case 2:
472 s << "\t\t\ttextbuf[ptr++] = '|';\n";
473 break;
474 case 3:
475 s << "\t\t\ttextbuf[ptr++] = '|';\n";
476 break;
477 case 4:
478 s << "\t\t\treturn ptr;\n";
479 break;
480 case 5:
481 s << "\t\t\treturn 0;\n";
482 break;
485 s << "\t\t};\n";
486 s << "\t\tdeserialize = [](const portctrl::type* _this, unsigned char* buffer, const char* textbuf) -> "
487 << "size_t {\n";
488 s << "\t\t\tmemset(buffer, 0, " << get_ssize(pset) << ");\n";
489 s << "\t\t\tsize_t ptr = 0;\n";
490 s << "\t\t\tshort tmp;\n";
491 for(auto i : repr) {
492 switch(i.type) {
493 case 0:
494 s << "\t\t\tif(portctrl::read_button_value(textbuf, ptr)) buffer[" << i.offset << "]|="
495 << (int)i.mask << ";\n";
496 break;
497 case 1:
498 s << "\t\t\ttmp = portctrl::read_axis_value(textbuf, ptr);\n";
499 s << "\t\t\tbuffer[" << i.offset << "] = " << "(unsigned short)tmp;\n";
500 s << "\t\t\tbuffer[" << (i.offset + 1) << "] = " << "((unsigned short)tmp >> 8);\n";
501 break;
502 case 2:
503 break;
504 case 3:
505 s << "\t\t\tportctrl::skip_rest_of_field(textbuf, ptr, true);\n";
506 break;
507 case 4:
508 s << "\t\t\tportctrl::skip_rest_of_field(textbuf, ptr, false);\n";
509 s << "\t\t\treturn ptr;\n";
510 break;
511 case 5:
512 s << "\t\t\treturn DESERIALIZE_SPECIAL_BLANK;\n";
513 break;
516 s << "\t\t};\n";
517 s << "\t\tcontroller_info = &portdefs::port_tmp_" << pidx << ";\n";
518 s << "\t}\n";
519 s << "} " << pset.symbol << ";\n";
520 return s.str();
523 std::string pcs_write_trailer(const std::vector<controller_set*>& p)
525 std::ostringstream s;
526 s << "std::vector<portctrl::type*> _port_types{";
527 for(auto i : p)
528 s << "&" << i->symbol << ", ";
529 s << "};\n";
530 return s.str();
533 std::string pcs_write_classes(const std::vector<controller_set*>& p, unsigned& tmp_idx)
535 std::string s;
536 for(auto i : p)
537 s = s + pcs_write_class(*i, tmp_idx);
538 s = s + pcs_write_trailer(p);
539 return s;
542 std::vector<controller_set*> pcs_from_json_array(const JSON::node& root, const std::string& _ptr)
544 JSON::pointer ptr(_ptr);
545 if(root.type_of_indirect(ptr) != JSON::array)
546 (stringfmt() << "Expected (indirect) array for '" << ptr << "'").throwex();
547 ptr = root.resolve_indirect(ptr);
548 const JSON::node& n = root[ptr];
549 std::vector<controller_set*> ret;
550 try {
551 for(auto i = n.begin(); i != n.end(); i++)
552 ret.push_back(pcs_parse_set(root, ptr.index(i.index())));
553 } catch(...) {
554 for(auto i : ret)
555 delete i;
556 throw;
558 return ret;
561 void type_generic::_write(const type* _this, unsigned char* buffer, unsigned idx, unsigned ctrl, short x)
563 const type_generic* th = dynamic_cast<const type_generic*>(_this);
564 if(idx >= th->controller_info->controllers.size())
565 return;
566 if(ctrl >= th->controller_info->controllers[idx].buttons.size())
567 return;
568 auto& ii = th->indexinfo[th->indexbase[idx] + ctrl];
569 switch(ii.type) {
570 case 1:
571 if(x) buffer[ii.offset]|=ii.mask; else buffer[ii.offset]&=ii.imask;
572 break;
573 case 2:
574 buffer[ii.offset]=(unsigned short)x;
575 buffer[ii.offset+1]=((unsigned short)x >> 8);
576 break;
580 short type_generic::_read(const type* _this, const unsigned char* buffer, unsigned idx, unsigned ctrl)
582 const type_generic* th = dynamic_cast<const type_generic*>(_this);
583 if(idx >= th->controller_info->controllers.size())
584 return 0;
585 if(ctrl >= th->controller_info->controllers[idx].buttons.size())
586 return 0;
587 auto& ii = th->indexinfo[th->indexbase[idx] + ctrl];
588 switch(ii.type) {
589 case 0:
590 return 0;
591 case 1:
592 return (buffer[ii.offset]&ii.mask) ? 1 : 0;
593 case 2:
594 return (short)((unsigned short)buffer[ii.offset] + ((unsigned short)buffer[ii.offset+1] << 8));
596 return 0; //NOTREACHED
599 size_t type_generic::_serialize(const type* _this, const unsigned char* buffer, char* textbuf)
601 size_t ptr = 0;
602 short tmp;
603 ser_instruction* si;
604 const type_generic* th = dynamic_cast<const type_generic*>(_this);
605 if(__builtin_expect(!buffer, 0)) {
606 for(auto& i : th->serialize_instructions) {
607 switch(i.type) {
608 case 0: i.ejumpvector = &&ser_button; break;
609 case 1: i.ejumpvector = &&ser_axis; break;
610 case 2: i.ejumpvector = &&ser_pipe1; break;
611 case 3: i.ejumpvector = &&ser_pipe2; break;
612 case 4: i.ejumpvector = &&ser_pipe3; break;
613 case 5: i.ejumpvector = &&ser_nothing; break;
616 return 0;
618 size_t i = 0;
619 loop:
620 si = &th->serialize_instructions[i++];
621 goto *si->ejumpvector;
622 ser_button:
623 textbuf[ptr++] = (buffer[si->offset] & si->mask) ? si->character : '.';
624 goto loop;
625 ser_axis:
626 tmp = (short)((unsigned short)buffer[si->offset] + ((unsigned short)buffer[si->offset+1] << 8));
627 ptr += sprintf(textbuf + ptr, " %i", tmp);
628 goto loop;
629 ser_pipe1:
630 textbuf[ptr++] = '|';
631 goto loop;
632 ser_pipe2:
633 textbuf[ptr++] = '|';
634 goto loop;
635 ser_pipe3:
636 return ptr;
637 ser_nothing:
638 return 0;
641 size_t type_generic::_deserialize(const type* _this, unsigned char* buffer, const char* textbuf)
643 size_t ptr = 0;
644 short tmp;
645 ser_instruction* si;
646 const type_generic* th = dynamic_cast<const type_generic*>(_this);
647 if(__builtin_expect(!buffer, 0)) {
648 for(auto& i : th->serialize_instructions) {
649 switch(i.type) {
650 case 0: i.djumpvector = &&ser_button; break;
651 case 1: i.djumpvector = &&ser_axis; break;
652 case 2: i.djumpvector = &&loop; break;
653 case 3: i.djumpvector = &&ser_pipe2; break;
654 case 4: i.djumpvector = &&ser_pipe3; break;
655 case 5: i.djumpvector = &&ser_nothing; break;
658 return 0;
660 memset(buffer, 0, th->storage_size);
661 size_t i = 0;
662 loop:
663 si = &th->serialize_instructions[i++];
664 goto *si->djumpvector;
665 ser_button:
666 if(read_button_value(textbuf, ptr)) buffer[si->offset]|=si->mask;
667 goto loop;
668 ser_axis:
669 tmp = read_axis_value(textbuf, ptr);
670 buffer[si->offset] = (unsigned short)tmp;
671 buffer[si->offset+1] = ((unsigned short)tmp >> 8);
672 goto loop;
673 ser_pipe2:
674 skip_rest_of_field(textbuf, ptr, true);
675 goto loop;
676 ser_pipe3:
677 skip_rest_of_field(textbuf, ptr, false);
678 return ptr;
679 ser_nothing:
680 return DESERIALIZE_SPECIAL_BLANK;
683 type_generic::type_generic(const JSON::node& root, const std::string& ptr) throw(std::exception)
684 : type(port_iname(root, ptr), port_hname(root, ptr), port_size(root, ptr))
686 controller_info = pcs_parse_set(root, ptr);
687 write = _write;
688 read = _read;
689 serialize = _serialize;
690 deserialize = _deserialize;
691 size_t ibase = 0;
692 size_t ii = 0;
693 indexbase.resize(controller_info->controllers.size());
694 for(auto i : controller_info->controllers) {
695 indexbase[ii++] = ibase;
696 ibase += i.buttons.size();
698 serialize_instructions = get_ser_instructions(*controller_info);
699 indexinfo = get_idx_instructions(*controller_info);
700 _serialize(this, NULL, NULL);
701 _deserialize(this, NULL, NULL);
702 dyncode_block = NULL;
703 make_dynamic_blocks();
706 type_generic::~type_generic() throw()
708 delete reinterpret_cast<assembler::dynamic_code*>(dyncode_block);
711 std::string type_generic::port_iname(const JSON::node& root, const std::string& ptr)
713 auto info = pcs_parse_set(root, ptr);
714 std::string tmp = info->iname;
715 delete info;
716 return tmp;
719 std::string type_generic::port_hname(const JSON::node& root, const std::string& ptr)
721 auto info = pcs_parse_set(root, ptr);
722 std::string tmp = info->hname;
723 delete info;
724 return tmp;
727 size_t type_generic::port_size(const JSON::node& root, const std::string& ptr)
729 auto info = pcs_parse_set(root, ptr);
730 size_t tmp = get_ssize(*info);
731 delete info;
732 return tmp;
735 void type_generic::make_dynamic_blocks()
737 try {
738 assembler::label_list labels;
739 assembler::assembler a;
740 make_routines(a, labels);
742 assembler::dynamic_code* c;
743 dyncode_block = c = new assembler::dynamic_code(a.size());
744 auto m = a.flush(c->pointer());
745 if(getenv("PTG_DUMP_DYNAMIC")) {
746 const char* basename = getenv("PTG_DUMP_DYNAMIC");
747 a.dump(basename, controller_info->hname, c->pointer(), m);
749 c->commit();
750 if(m.count("read"))
751 read = (short(*)(const type*, const unsigned char*, unsigned, unsigned))m["read"];
752 if(m.count("write"))
753 write = (void(*)(const type*, unsigned char*, unsigned, unsigned, short))m["write"];
754 if(m.count("serialize"))
755 serialize = (size_t(*)(const type*, const unsigned char*, char*))m["serialize"];
756 if(m.count("deserialize"))
757 deserialize = (size_t(*)(const type*, unsigned char*, const char*))m["deserialize"];
758 } catch(std::exception& e) {
759 std::cerr << "Error assembling block: " << e.what() << std::endl;
760 delete reinterpret_cast<assembler::dynamic_code*>(dyncode_block);
761 dyncode_block = NULL;
762 } catch(...) {
763 std::cerr << "Error assembling block!" << std::endl;
764 delete reinterpret_cast<assembler::dynamic_code*>(dyncode_block);
765 dyncode_block = NULL;
769 void type_generic::make_routines(assembler::assembler& a, assembler::label_list& labels)
771 //One can freely return without doing nothing.
772 #ifndef NO_ASM_GENERATION
773 #if defined(__x86_64__) && defined(__LP64__)
774 //The check for __LP64__ is so not to try to use this on x32, as it won't work.
775 assembler_intrinsics::I386 as(a, true);
776 #define DEFINED_ASSEBLER
777 #endif
778 #if defined(__i386__)
779 assembler_intrinsics::I386 as(a, false);
780 #define DEFINED_ASSEBLER
781 #endif
783 //Backup assembler that causes this to error out.
784 #ifndef DEFINED_ASSEBLER
785 assembler_intrinsics::dummyarch as(a);
786 #endif
788 a._label(labels, "serialize");
789 codegen::emit_serialize_prologue(as, labels);
790 for(auto& i : serialize_instructions) {
791 switch(i.type) {
792 case 0: //Button.
793 codegen::emit_serialize_button(as, labels, i.offset, i.mask, i.character);
794 break;
795 case 1: //Axis
796 codegen::emit_serialize_axis(as, labels, i.offset);
797 break;
798 case 2: //Pipe character
799 case 3:
800 codegen::emit_serialize_pipe(as, labels);
801 break;
802 case 4: //End or nothing
803 case 5:
804 codegen::emit_serialize_epilogue(as, labels);
805 break;
809 a._label(labels, "deserialize");
810 assembler::label& dend = labels;
811 assembler::label* dpipe = labels;
812 codegen::emit_deserialize_prologue(as, labels);
813 codegen::emit_deserialize_clear_storage(as, labels, storage_size);
814 for(auto& i : serialize_instructions) {
815 switch(i.type) {
816 case 0: //Button.
817 codegen::emit_deserialize_button(as, labels, i.offset, i.mask, *dpipe, dend);
818 break;
819 case 1: //Axis
820 codegen::emit_deserialize_axis(as, labels, i.offset);
821 break;
822 case 2: //Pipe character 1
823 break; //Do nothing.
824 case 3: //Pipe character 2. We redefine dpipe to point to next pipe or end.
825 codegen::emit_deserialize_skip_until_pipe(as, labels, *dpipe, dend);
826 as.label(*dpipe);
827 dpipe = labels;
828 codegen::emit_deserialize_skip(as, labels);
829 break;
830 case 4: //Pipe character 3. Also note that we need to place dpipe label here.
831 codegen::emit_deserialize_skip_until_pipe(as, labels, *dpipe, dend);
832 as.label(*dpipe);
833 as.label(dend);
834 codegen::emit_deserialize_epilogue(as, labels);
835 break;
836 case 5: //Nothing.
837 codegen::emit_deserialize_special_blank(as, labels);
838 as.label(*dpipe);
839 as.label(dend);
840 codegen::emit_deserialize_epilogue(as, labels);
841 break;
845 uint32_t ilog2controls = 0;
846 for(size_t i = 0; i < controller_info->controllers.size(); i++) {
847 while((1U << ilog2controls) < controller_info->controllers[i].buttons.size())
848 ilog2controls++;
850 uint32_t mcontrols = 1 << ilog2controls;
852 a._label(labels, "read");
853 codegen::emit_read_prologue(as, labels);
854 assembler::label& rend = labels;
855 codegen::emit_read_dispatch(as, labels, controller_info->controllers.size(), ilog2controls, rend);
856 //Emit the jump table.
857 std::vector<assembler::label*> xlabels;
858 for(size_t i = 0; i < controller_info->controllers.size(); i++) {
859 size_t cnt = controller_info->controllers[i].buttons.size();
860 for(size_t j = 0; j < cnt; j++) {
861 auto& c = indexinfo[indexbase[i] + j];
862 switch(c.type) {
863 case 0:
864 codegen::emit_read_label_bad(as, labels, rend);
865 break;
866 case 1:
867 case 2:
868 xlabels.push_back(&codegen::emit_read_label(as, labels));
869 break;
872 for(size_t j = cnt; j < mcontrols; j++)
873 codegen::emit_read_label_bad(as, labels, rend);
875 //Emit Routines.
876 size_t lidx = 0;
877 for(size_t i = 0; i < controller_info->controllers.size(); i++) {
878 size_t cnt = controller_info->controllers[i].buttons.size();
879 for(size_t j = 0; j < cnt; j++) {
880 auto& c = indexinfo[indexbase[i] + j];
881 switch(c.type) {
882 case 0:
883 break;
884 case 1:
885 codegen::emit_read_button(as, labels, *xlabels[lidx++], rend, c.offset, c.mask);
886 break;
887 case 2:
888 codegen::emit_read_axis(as, labels, *xlabels[lidx++], rend, c.offset);
889 break;
893 a._label(rend);
894 codegen::emit_read_epilogue(as, labels);
896 a._label(labels, "write");
897 codegen::emit_write_prologue(as, labels);
898 assembler::label& wend = labels;
899 //Read routines here are the same as write routines.
900 codegen::emit_read_dispatch(as, labels, controller_info->controllers.size(), ilog2controls, wend);
901 xlabels.clear();
902 for(size_t i = 0; i < controller_info->controllers.size(); i++) {
903 size_t cnt = controller_info->controllers[i].buttons.size();
904 for(size_t j = 0; j < cnt; j++) {
905 auto& c = indexinfo[indexbase[i] + j];
906 switch(c.type) {
907 case 0:
908 codegen::emit_read_label_bad(as, labels, wend);
909 break;
910 case 1:
911 case 2:
912 xlabels.push_back(&codegen::emit_read_label(as, labels));
913 break;
916 for(size_t j = cnt; j < mcontrols; j++)
917 codegen::emit_read_label_bad(as, labels, wend);
919 //Emit Routines.
920 lidx = 0;
921 for(size_t i = 0; i < controller_info->controllers.size(); i++) {
922 size_t cnt = controller_info->controllers[i].buttons.size();
923 for(size_t j = 0; j < cnt; j++) {
924 auto& c = indexinfo[indexbase[i] + j];
925 switch(c.type) {
926 case 0:
927 break;
928 case 1:
929 codegen::emit_write_button(as, labels, *xlabels[lidx++], wend, c.offset, c.mask);
930 break;
931 case 2:
932 codegen::emit_write_axis(as, labels, *xlabels[lidx++], wend, c.offset);
933 break;
937 a._label(wend);
938 codegen::emit_write_epilogue(as, labels);
939 #endif