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"
16 std::string
quote(const std::string
& s
)
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");
64 ret
.type
= button::TYPE_NULL
;
72 ret
.shadow
= (root
.type_of(pshadow
) != JSON::none
) ? read_bool(root
, pshadow
) : false;
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");
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
) :
88 if(symbol
.length() != 1)
89 (stringfmt() << "Symbol at '" << ptr
<< "' must be 1 codepoint").throwex();
90 ret
.symbol
= symbol
[0];
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
) :
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;
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");
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
);
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;
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"));
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
);
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
);
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())));
160 ret
.buttons
= buttons
;
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
;
194 ret
->symbol
= symbol
;
195 ret
->controllers
= controllers
;
196 ret
->legal_for
= legal
;
200 void write_button(std::ostream
& s
, const button
& b
)
202 s
<< "{portctrl::button::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
)
219 for(auto i
: c
.buttons
) {
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
) << ", ";
237 for(auto i
: cs
.legal_for
)
242 idx
+= (cs
.controllers
.size() + 1);
245 size_t get_ssize(const controller_set
& cs
)
248 for(auto i
: cs
.controllers
)
249 for(auto j
: i
.buttons
) {
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;
262 size_t get_aoffset(const controller_set
& cs
)
265 for(auto i
: cs
.controllers
)
266 for(auto j
: i
.buttons
) {
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;
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;
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
;
290 switch(cs
.controllers
[i
].buttons
[j
].type
) {
291 case button::TYPE_NULL
:
294 case button::TYPE_BUTTON
:
296 ii
.offset
= buttonidx2
/ 8;
297 ii
.mask
= 1 << (buttonidx2
& 7);
301 case button::TYPE_AXIS
:
302 case button::TYPE_RAXIS
:
303 case button::TYPE_TAXIS
:
304 case button::TYPE_LIGHTGUN
:
306 ii
.offset
= aoffset
+ 2 * axisidx2
;
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;
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)) {
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
:
336 ins
.offset
= buttonidx
/ 8;
337 ins
.mask
= 1 << (buttonidx
& 7);
338 ins
.character
= cs
.controllers
[i
].buttons
[j
].msymbol
;
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
:
352 ins
.offset
= aoffset
+ 2 * axisidx
;
360 ins
.type
= cs
.controllers
.size() ? 4 : 5;
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";
380 s
<< "\t_" << pset
.symbol
<< "() : type(" << quote(pset
.iname
) << ", " << quote(pset
.hname
)
381 << ", " << get_ssize(pset
) << ")\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;
388 if(i
.controller
!= last_controller
) {
389 if(last_controller
>= 0) {
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";
400 s
<< "\t\t\t\t\tbreak;\n";
403 s
<< "\t\t\t\t\tif(x) buffer[" << i
.offset
<< "]|=" << (int)i
.mask
404 <<"; else buffer[" << i
.offset
<< "]&=" << (int)i
.imask
406 s
<< "\t\t\t\t\tbreak;\n";
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";
415 if(last_controller
>= 0) {
417 s
<< "\t\t\t\tbreak;\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;
426 if(i
.controller
!= last_controller
) {
427 if(last_controller
>= 0) {
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";
438 s
<< "\t\t\t\t\treturn 0;\n";
441 s
<< "\t\t\t\t\treturn (buffer[" << i
.offset
<< "]&" << (int)i
.mask
<< ") ? 1 : 0;\n";
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) {
450 s
<< "\t\t\treturn 0;\n";
452 s
<< "\t\t\treturn 0;\n";
454 s
<< "\t\t\treturn 0;\n";
456 s
<< "\t\tserialize = [](const portctrl::type* _this, const unsigned char* buffer, char* textbuf) -> "
458 s
<< "\t\t\tsize_t ptr = 0;\n";
459 s
<< "\t\t\tshort tmp;\n";
463 s
<< "\t\t\ttextbuf[ptr++] = (buffer[" << i
.offset
<< "] & " << (int)i
.mask
<< ") ? (char)"
464 << (int)i
.character
<< " : '.';\n";
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";
472 s
<< "\t\t\ttextbuf[ptr++] = '|';\n";
475 s
<< "\t\t\ttextbuf[ptr++] = '|';\n";
478 s
<< "\t\t\treturn ptr;\n";
481 s
<< "\t\t\treturn 0;\n";
486 s
<< "\t\tdeserialize = [](const portctrl::type* _this, unsigned char* buffer, const char* textbuf) -> "
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";
494 s
<< "\t\t\tif(portctrl::read_button_value(textbuf, ptr)) buffer[" << i
.offset
<< "]|="
495 << (int)i
.mask
<< ";\n";
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";
505 s
<< "\t\t\tportctrl::skip_rest_of_field(textbuf, ptr, true);\n";
508 s
<< "\t\t\tportctrl::skip_rest_of_field(textbuf, ptr, false);\n";
509 s
<< "\t\t\treturn ptr;\n";
512 s
<< "\t\t\treturn DESERIALIZE_SPECIAL_BLANK;\n";
517 s
<< "\t\tcontroller_info = &portdefs::port_tmp_" << pidx
<< ";\n";
519 s
<< "} " << pset
.symbol
<< ";\n";
523 std::string
pcs_write_trailer(const std::vector
<controller_set
*>& p
)
525 std::ostringstream s
;
526 s
<< "std::vector<portctrl::type*> _port_types{";
528 s
<< "&" << i
->symbol
<< ", ";
533 std::string
pcs_write_classes(const std::vector
<controller_set
*>& p
, unsigned& tmp_idx
)
537 s
= s
+ pcs_write_class(*i
, tmp_idx
);
538 s
= s
+ pcs_write_trailer(p
);
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
;
551 for(auto i
= n
.begin(); i
!= n
.end(); i
++)
552 ret
.push_back(pcs_parse_set(root
, ptr
.index(i
.index())));
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())
566 if(ctrl
>= th
->controller_info
->controllers
[idx
].buttons
.size())
568 auto& ii
= th
->indexinfo
[th
->indexbase
[idx
] + ctrl
];
571 if(x
) buffer
[ii
.offset
]|=ii
.mask
; else buffer
[ii
.offset
]&=ii
.imask
;
574 buffer
[ii
.offset
]=(unsigned short)x
;
575 buffer
[ii
.offset
+1]=((unsigned short)x
>> 8);
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())
585 if(ctrl
>= th
->controller_info
->controllers
[idx
].buttons
.size())
587 auto& ii
= th
->indexinfo
[th
->indexbase
[idx
] + ctrl
];
592 return (buffer
[ii
.offset
]&ii
.mask
) ? 1 : 0;
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
)
604 const type_generic
* th
= dynamic_cast<const type_generic
*>(_this
);
605 if(__builtin_expect(!buffer
, 0)) {
606 for(auto& i
: th
->serialize_instructions
) {
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;
620 si
= &th
->serialize_instructions
[i
++];
621 goto *si
->ejumpvector
;
623 textbuf
[ptr
++] = (buffer
[si
->offset
] & si
->mask
) ? si
->character
: '.';
626 tmp
= (short)((unsigned short)buffer
[si
->offset
] + ((unsigned short)buffer
[si
->offset
+1] << 8));
627 ptr
+= sprintf(textbuf
+ ptr
, " %i", tmp
);
630 textbuf
[ptr
++] = '|';
633 textbuf
[ptr
++] = '|';
641 size_t type_generic::_deserialize(const type
* _this
, unsigned char* buffer
, const char* textbuf
)
646 const type_generic
* th
= dynamic_cast<const type_generic
*>(_this
);
647 if(__builtin_expect(!buffer
, 0)) {
648 for(auto& i
: th
->serialize_instructions
) {
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;
660 memset(buffer
, 0, th
->storage_size
);
663 si
= &th
->serialize_instructions
[i
++];
664 goto *si
->djumpvector
;
666 if(read_button_value(textbuf
, ptr
)) buffer
[si
->offset
]|=si
->mask
;
669 tmp
= read_axis_value(textbuf
, ptr
);
670 buffer
[si
->offset
] = (unsigned short)tmp
;
671 buffer
[si
->offset
+1] = ((unsigned short)tmp
>> 8);
674 skip_rest_of_field(textbuf
, ptr
, true);
677 skip_rest_of_field(textbuf
, ptr
, false);
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
);
689 serialize
= _serialize
;
690 deserialize
= _deserialize
;
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
;
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
;
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
);
735 void type_generic::make_dynamic_blocks()
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
);
751 read
= (short(*)(const type
*, const unsigned char*, unsigned, unsigned))m
["read"];
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
;
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
778 #if defined(__i386__)
779 assembler_intrinsics::I386
as(a
, false);
780 #define DEFINED_ASSEBLER
783 //Backup assembler that causes this to error out.
784 #ifndef DEFINED_ASSEBLER
785 assembler_intrinsics::dummyarch
as(a
);
788 a
._label(labels
, "serialize");
789 codegen::emit_serialize_prologue(as
, labels
);
790 for(auto& i
: serialize_instructions
) {
793 codegen::emit_serialize_button(as
, labels
, i
.offset
, i
.mask
, i
.character
);
796 codegen::emit_serialize_axis(as
, labels
, i
.offset
);
798 case 2: //Pipe character
800 codegen::emit_serialize_pipe(as
, labels
);
802 case 4: //End or nothing
804 codegen::emit_serialize_epilogue(as
, labels
);
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
) {
817 codegen::emit_deserialize_button(as
, labels
, i
.offset
, i
.mask
, *dpipe
, dend
);
820 codegen::emit_deserialize_axis(as
, labels
, i
.offset
);
822 case 2: //Pipe character 1
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
);
828 codegen::emit_deserialize_skip(as
, labels
);
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
);
834 codegen::emit_deserialize_epilogue(as
, labels
);
837 codegen::emit_deserialize_special_blank(as
, labels
);
840 codegen::emit_deserialize_epilogue(as
, labels
);
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())
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
];
864 codegen::emit_read_label_bad(as
, labels
, rend
);
868 xlabels
.push_back(&codegen::emit_read_label(as
, labels
));
872 for(size_t j
= cnt
; j
< mcontrols
; j
++)
873 codegen::emit_read_label_bad(as
, labels
, rend
);
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
];
885 codegen::emit_read_button(as
, labels
, *xlabels
[lidx
++], rend
, c
.offset
, c
.mask
);
888 codegen::emit_read_axis(as
, labels
, *xlabels
[lidx
++], rend
, c
.offset
);
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
);
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
];
908 codegen::emit_read_label_bad(as
, labels
, wend
);
912 xlabels
.push_back(&codegen::emit_read_label(as
, labels
));
916 for(size_t j
= cnt
; j
< mcontrols
; j
++)
917 codegen::emit_read_label_bad(as
, labels
, wend
);
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
];
929 codegen::emit_write_button(as
, labels
, *xlabels
[lidx
++], wend
, c
.offset
, c
.mask
);
932 codegen::emit_write_axis(as
, labels
, *xlabels
[lidx
++], wend
, c
.offset
);
938 codegen::emit_write_epilogue(as
, labels
);