Implicitly redirect cmdhelp includes to corresponding JSON files
[lsnes.git] / src / library / portctrl-data.cpp
blob4db2f38c68c5647f1697205efcd90fac6e4a2ce7
1 #include "binarystream.hpp"
2 #include "portctrl-data.hpp"
3 #include "threads.hpp"
4 #include "minmax.hpp"
5 #include "globalwrap.hpp"
6 #include "serialization.hpp"
7 #include "string.hpp"
8 #include "sha256.hpp"
9 #include <iostream>
10 #include <sys/time.h>
11 #include <sstream>
12 #include <list>
13 #include <deque>
14 #include <complex>
16 namespace portctrl
18 namespace
20 controller simple_controller = {"(system)", "system", {}};
21 controller_set simple_port = {"system", "system", "system", {simple_controller},{0}};
23 struct porttype_basecontrol : public type
25 porttype_basecontrol() : type("basecontrol", "basecontrol", 1)
27 write = [](const type* _this, unsigned char* buffer, unsigned idx, unsigned ctrl,
28 short x) -> void {
29 if(idx > 0 || ctrl > 0) return;
30 buffer[0] = x ? 1 : 0;
32 read = [](const type* _this, const unsigned char* buffer, unsigned idx, unsigned ctrl) ->
33 short {
34 if(idx > 0 || ctrl > 0) return 0;
35 return buffer[0] ? 1 : 0;
37 serialize = [](const type* _this, const unsigned char* buffer, char* textbuf) -> size_t {
38 textbuf[0] = buffer[0] ? 'F' : '-';
39 textbuf[1] = '\0';
40 return 1;
42 deserialize = [](const type* _this, unsigned char* buffer, const char* textbuf) ->
43 size_t {
44 size_t ptr = 0;
45 buffer[0] = 0;
46 if(read_button_value(textbuf, ptr))
47 buffer[0] = 1;
48 skip_rest_of_field(textbuf, ptr, false);
49 return ptr;
51 controller_info = &simple_port;
55 unsigned macro_random_bit()
57 static unsigned char state[32];
58 static unsigned extracted = 256;
59 if(extracted == 256) {
60 timeval tv;
61 gettimeofday(&tv, NULL);
62 unsigned char buffer[48];
63 memcpy(buffer, state, 32);
64 serialization::u64b(buffer + 32, tv.tv_sec);
65 serialization::u64b(buffer + 40, tv.tv_usec);
66 sha256::hash(state, buffer, 48);
67 extracted = 0;
69 unsigned bit = extracted++;
70 return ((state[bit / 8] >> (bit % 8)) & 1);
74 type& get_default_system_port_type()
76 static porttype_basecontrol x;
77 return x;
80 type::type(const std::string& iname, const std::string& _hname, size_t ssize) throw(std::bad_alloc)
81 : hname(_hname), storage_size(ssize), name(iname)
85 type::~type() throw()
89 bool type::is_present(unsigned controller) const throw()
91 return controller_info->controllers.size() > controller;
94 namespace
96 size_t dummy_offset = 0;
97 type* dummy_type = &get_default_system_port_type();
98 unsigned dummy_index = 0;
99 struct binding
101 std::vector<type*> types;
102 type_set* stype;
103 bool matches(const std::vector<class type*>& x)
105 if(x.size() != types.size())
106 return false;
107 for(size_t i = 0; i < x.size(); i++)
108 if(x[i] != types[i])
109 return false;
110 return true;
113 std::list<binding>& bindings()
115 static std::list<binding> x;
116 return x;
120 type_set::type_set() throw()
123 port_offsets = &dummy_offset;
124 port_types = &dummy_type;
125 port_count = 1;
126 total_size = 1;
127 _indices.resize(1);
128 _indices[0].valid = true;
129 _indices[0].port = 0;
130 _indices[0].controller = 0;
131 _indices[0].control = 0;
133 port_multiplier = 1;
134 controller_multiplier = 1;
135 indices_size = 1;
136 indices_tab = &dummy_index;
139 type_set& type_set::make(std::vector<class type*> types, struct index_map control_map)
140 throw(std::bad_alloc, std::runtime_error)
142 for(auto i : bindings())
143 if(i.matches(types))
144 return *(i.stype);
145 //Not found, create new.
146 type_set& ret = *new type_set(types, control_map);
147 binding b;
148 b.types = types;
149 b.stype = &ret;
150 bindings().push_back(b);
151 return ret;
154 type_set::type_set(std::vector<class type*> types, struct index_map control_map)
156 port_count = types.size();
157 //Verify legality of port types.
158 for(size_t i = 0; i < port_count; i++)
159 if(!types[i] || !types[i]->legal(i))
160 throw std::runtime_error("Illegal port types");
161 //Count maximum number of controller indices to determine the controller multiplier.
162 controller_multiplier = 1;
163 for(size_t i = 0; i < port_count; i++)
164 for(unsigned j = 0; j < types[i]->controller_info->controllers.size(); j++)
165 controller_multiplier = max(controller_multiplier, (size_t)types[i]->used_indices(j));
166 //Count maximum number of controllers to determine the port multiplier.
167 port_multiplier = 1;
168 for(size_t i = 0; i < port_count; i++)
169 port_multiplier = max(port_multiplier, controller_multiplier *
170 (size_t)types[i]->controller_info->controllers.size());
171 //Allocate the per-port tables.
172 port_offsets = new size_t[types.size()];
173 port_types = new class type*[types.size()];
174 //Determine the total size and offsets.
175 size_t offset = 0;
176 for(size_t i = 0; i < port_count; i++) {
177 port_offsets[i] = offset;
178 offset += types[i]->storage_size;
179 port_types[i] = types[i];
181 total_size = offset;
182 //Determine the index size and allocate it.
183 indices_size = port_multiplier * port_count;
184 indices_tab = new unsigned[indices_size];
185 for(size_t i = 0; i < indices_size; i++)
186 indices_tab[i] = 0xFFFFFFFFUL;
187 //Copy the index data (and reverse it).
188 controllers = control_map.logical_map;
189 legacy_pcids = control_map.pcid_map;
190 _indices = control_map.indices;
191 for(size_t j = 0; j < _indices.size(); j++) {
192 auto& i = _indices[j];
193 if(i.valid)
194 indices_tab[i.port * port_multiplier + i.controller * controller_multiplier + i.control] = j;
198 short read_axis_value(const char* buf, size_t& idx) throw()
200 char ch;
201 //Skip ws.
202 while(is_nonterminator(buf[idx])) {
203 char ch = buf[idx];
204 if(ch != ' ' && ch != '\t')
205 break;
206 idx++;
208 //Read the sign if any.
209 ch = buf[idx];
210 if(!is_nonterminator(ch))
211 return 0;
212 bool negative = false;
213 if(ch == '-') {
214 negative = true;
215 idx++;
217 if(ch == '+')
218 idx++;
220 //Read numeric value.
221 int numval = 0;
222 while(is_nonterminator(buf[idx]) && isdigit(static_cast<unsigned char>(ch = buf[idx]))) {
223 numval = numval * 10 + (ch - '0');
224 idx++;
226 if(negative)
227 numval = -numval;
229 return static_cast<short>(numval);
232 size_t write_axis_value(char* buf, short _v)
234 int v = _v;
235 size_t r = 0;
236 buf[r++] = ' ';
237 if(v < 0) { buf[r++] = '-'; v = -v; }
238 if(v >= 10000) buf[r++] = '0' + (v / 10000 % 10);
239 if(v >= 1000) buf[r++] = '0' + (v / 1000 % 10);
240 if(v >= 100) buf[r++] = '0' + (v / 100 % 10);
241 if(v >= 10) buf[r++] = '0' + (v / 10 % 10);
242 buf[r++] = '0' + (v % 10);
243 return r;
246 namespace
248 type_set& dummytypes()
250 static type_set x;
251 return x;
254 size_t writeu32val(char32_t* buf, int val)
256 char c[12];
257 size_t i;
258 sprintf(c, "%d", val);
259 for(i = 0; c[i]; i++)
260 buf[i] = c[i];
261 return i;
264 uint64_t find_next_sync(frame_vector& movie, uint64_t after)
266 if(after >= movie.size())
267 return after;
268 do {
269 after++;
270 } while(after < movie.size() && !movie[after].sync());
271 return after;
275 void frame::display(unsigned port, unsigned controller_n, char32_t* buf) throw()
277 if(port >= types->ports()) {
278 //Bad port.
279 *buf = '\0';
280 return;
282 uint8_t* backingmem = backing + types->port_offset(port);
283 const type& ptype = types->port_type(port);
284 if(controller_n >= ptype.controller_info->controllers.size()) {
285 //Bad controller.
286 *buf = '\0';
287 return;
289 const controller& pc = ptype.controller_info->controllers[controller_n];
290 bool need_space = false;
291 short val;
292 for(unsigned i = 0; i < pc.buttons.size(); i++) {
293 const button& pcb = pc.buttons[i];
294 if(need_space && pcb.type != button::TYPE_NULL) {
295 need_space = false;
296 *(buf++) = ' ';
298 switch(pcb.type) {
299 case button::TYPE_NULL:
300 break;
301 case button::TYPE_BUTTON:
302 *(buf++) = ptype.read(&ptype, backingmem, controller_n, i) ? pcb.symbol : U'-';
303 break;
304 case button::TYPE_AXIS:
305 case button::TYPE_RAXIS:
306 case button::TYPE_TAXIS:
307 case button::TYPE_LIGHTGUN:
308 val = ptype.read(&ptype, backingmem, controller_n, i);
309 buf += writeu32val(buf, val);
310 need_space = true;
311 break;
314 *buf = '\0';
317 counters::counters() throw(std::bad_alloc)
319 types = &dummytypes();
320 ctrs = new uint32_t[types->indices()];
321 clear();
324 counters::counters(const type_set& p) throw(std::bad_alloc)
326 types = &p;
327 ctrs = new uint32_t[types->indices()];
328 clear();
331 counters::counters(const counters& p) throw(std::bad_alloc)
333 ctrs = new uint32_t[p.types->indices()];
334 types = p.types;
335 memcpy(ctrs, p.ctrs, sizeof(uint32_t) * p.types->indices());
336 framepflag = p.framepflag;
339 counters& counters::operator=(const counters& p) throw(std::bad_alloc)
341 if(this == &p)
342 return *this;
343 uint32_t* n = new uint32_t[p.types->indices()];
344 types = p.types;
345 memcpy(n, p.ctrs, sizeof(uint32_t) * p.types->indices());
346 delete[] ctrs;
347 ctrs = n;
348 framepflag = p.framepflag;
349 return *this;
352 counters::~counters() throw()
354 delete[] ctrs;
357 void counters::clear() throw()
359 memset(ctrs, 0, sizeof(uint32_t) * types->indices());
360 framepflag = false;
363 void counters::set_all_DRDY() throw()
365 for(size_t i = 0; i < types->indices(); i++)
366 ctrs[i] |= 0x80000000UL;
369 void counters::clear_DRDY(unsigned idx) throw()
371 ctrs[idx] &= 0x7FFFFFFFUL;
374 bool counters::get_DRDY(unsigned idx) throw()
376 return ((ctrs[idx] & 0x80000000UL) != 0);
379 bool counters::has_polled() throw()
381 uint32_t res = 0;
382 for(size_t i = 0; i < types->indices() ; i++)
383 res |= ctrs[i];
384 return ((res & 0x7FFFFFFFUL) != 0);
387 uint32_t counters::get_polls(unsigned idx) throw()
389 return ctrs[idx] & 0x7FFFFFFFUL;
392 uint32_t counters::increment_polls(unsigned idx) throw()
394 uint32_t x = ctrs[idx] & 0x7FFFFFFFUL;
395 ++ctrs[idx];
396 return x;
399 uint32_t counters::max_polls() throw()
401 uint32_t max = 0;
402 for(unsigned i = 0; i < types->indices(); i++) {
403 uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL;
404 max = (max < tmp) ? tmp : max;
406 return max;
409 void counters::save_state(std::vector<uint32_t>& mem) throw(std::bad_alloc)
411 mem.resize(types->indices());
412 //Compatiblity fun.
413 for(size_t i = 0; i < types->indices(); i++)
414 mem[i] = ctrs[i];
417 void counters::load_state(const std::vector<uint32_t>& mem) throw()
419 for(size_t i = 0; i < types->indices(); i++)
420 ctrs[i] = mem[i];
423 bool counters::check(const std::vector<uint32_t>& mem) throw()
425 return (mem.size() == types->indices());
429 void counters::set_framepflag(bool value) throw()
431 framepflag = value;
434 bool counters::get_framepflag() const throw()
436 return framepflag;
439 frame::frame(const type_set& p) throw(std::runtime_error)
441 memset(memory, 0, sizeof(memory));
442 backing = memory;
443 types = &p;
444 host = NULL;
447 frame::frame(unsigned char* mem, const type_set& p, frame_vector* _host)
448 throw(std::runtime_error)
450 if(!mem)
451 throw std::runtime_error("NULL backing memory not allowed");
452 memset(memory, 0, sizeof(memory));
453 backing = mem;
454 types = &p;
455 host = _host;
458 frame::frame(const frame& obj) throw()
460 memset(memory, 0, sizeof(memory));
461 backing = memory;
462 types = obj.types;
463 memcpy(backing, obj.backing, types->size());
464 host = NULL;
467 frame& frame::operator=(const frame& obj) throw(std::runtime_error)
469 if(backing != memory && types != obj.types)
470 throw std::runtime_error("Port types do not match");
471 types = obj.types;
472 short old = sync();
473 memcpy(backing, obj.backing, types->size());
474 if(host) host->notify_sync_change(sync() - old);
475 return *this;
478 frame_vector::fchange_listener::~fchange_listener()
482 size_t frame_vector::walk_helper(size_t frame, bool sflag) throw()
484 size_t ret = sflag ? frame : 0;
485 if(frame >= frames)
486 return ret;
487 frame++;
488 ret++;
489 size_t page = frame / frames_per_page;
490 size_t offset = frame_size * (frame % frames_per_page);
491 size_t index = frame % frames_per_page;
492 if(cache_page_num != page) {
493 cache_page = &pages[page];
494 cache_page_num = page;
496 while(frame < frames) {
497 if(index == frames_per_page) {
498 page++;
499 cache_page = &pages[page];
500 cache_page_num = page;
501 index = 0;
502 offset = 0;
504 if(frame::sync(cache_page->content + offset))
505 break;
506 index++;
507 offset += frame_size;
508 frame++;
509 ret++;
511 return ret;
514 size_t frame_vector::recount_frames() throw()
516 uint64_t old_frame_count = real_frame_count;
517 size_t ret = 0;
518 if(!frames)
519 return 0;
520 cache_page_num = 0;
521 cache_page = &pages[0];
522 size_t offset = 0;
523 size_t index = 0;
524 for(size_t i = 0; i < frames; i++) {
525 if(index == frames_per_page) {
526 cache_page_num++;
527 cache_page = &pages[cache_page_num];
528 index = 0;
529 offset = 0;
531 if(frame::sync(cache_page->content + offset))
532 ret++;
533 index++;
534 offset += frame_size;
537 real_frame_count = ret;
538 call_framecount_notification(old_frame_count);
539 return ret;
542 void frame_vector::clear(const type_set& p) throw(std::runtime_error)
544 uint64_t old_frame_count = real_frame_count;
545 frame_size = p.size();
546 frames_per_page = CONTROLLER_PAGE_SIZE / frame_size;
547 frames = 0;
548 types = &p;
549 clear_cache();
550 pages.clear();
551 real_frame_count = 0;
552 call_framecount_notification(old_frame_count);
555 frame_vector::~frame_vector() throw()
557 pages.clear();
558 cache_page = NULL;
561 frame_vector::frame_vector() throw()
563 real_frame_count = 0;
564 freeze_count = 0;
565 clear(dummytypes());
568 frame_vector::frame_vector(const type_set& p) throw()
570 real_frame_count = 0;
571 freeze_count = 0;
572 clear(p);
575 void frame_vector::append(frame cframe) throw(std::bad_alloc, std::runtime_error)
577 frame check(*types);
578 if(!check.types_match(cframe))
579 throw std::runtime_error("frame_vector::append: Type mismatch");
580 if(frames % frames_per_page == 0) {
581 //Create new page.
582 pages[frames / frames_per_page];
584 //Write the entry.
585 size_t page = frames / frames_per_page;
586 size_t offset = frame_size * (frames % frames_per_page);
587 if(cache_page_num != page) {
588 cache_page_num = page;
589 cache_page = &pages[page];
591 frame(cache_page->content + offset, *types) = cframe;
592 if(cframe.sync()) real_frame_count++;
593 frames++;
596 frame_vector::frame_vector(const frame_vector& vector) throw(std::bad_alloc)
598 real_frame_count = 0;
599 freeze_count = 0;
600 clear(*vector.types);
601 *this = vector;
604 frame_vector& frame_vector::operator=(const frame_vector& v)
605 throw(std::bad_alloc)
607 if(this == &v)
608 return *this;
609 uint64_t old_frame_count = real_frame_count;
610 resize(v.frames);
611 clear_cache();
613 //Copy the fields.
614 frame_size = v.frame_size;
615 frames_per_page = v.frames_per_page;
616 types = v.types;
617 real_frame_count = v.real_frame_count;
619 //This can't fail anymore. Copy the raw page contents.
620 size_t pagecount = (frames + frames_per_page - 1) / frames_per_page;
621 for(size_t i = 0; i < pagecount; i++) {
622 page& pg = pages[i];
623 const page& pg2 = v.pages.find(i)->second;
624 pg = pg2;
626 call_framecount_notification(old_frame_count);
627 return *this;
630 void frame_vector::resize(size_t newsize) throw(std::bad_alloc)
632 clear_cache();
633 if(newsize == 0) {
634 clear();
635 } else if(newsize < frames) {
636 //Shrink movie.
637 uint64_t old_frame_count = real_frame_count;
638 for(size_t i = newsize; i < frames; i++)
639 if((*this)[i].sync()) real_frame_count--;
640 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
641 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
642 for(size_t i = pages_needed; i < current_pages; i++)
643 pages.erase(i);
644 //Now zeroize the excess memory.
645 if(newsize < pages_needed * frames_per_page) {
646 size_t offset = frame_size * (newsize % frames_per_page);
647 memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
649 frames = newsize;
650 call_framecount_notification(old_frame_count);
651 } else if(newsize > frames) {
652 //Enlarge movie.
653 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
654 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
655 //Create the needed pages.
656 for(size_t i = current_pages; i < pages_needed; i++) {
657 try {
658 pages[i];
659 } catch(...) {
660 for(size_t i = current_pages; i < pages_needed; i++)
661 if(pages.count(i))
662 pages.erase(i);
663 throw;
666 frames = newsize;
667 //This can use real_frame_count, because the real frame count won't change.
668 call_framecount_notification(real_frame_count);
672 bool frame_vector::compatible(frame_vector& with, uint64_t nframe, const uint32_t* polls)
674 //Types have to match.
675 if(get_types() != with.get_types())
676 return false;
677 const type_set& pset = with.get_types();
678 //If new movie is before first frame, anything with same project_id is compatible.
679 if(nframe == 0)
680 return true;
681 //Scan both movies until frame syncs are seen. Out of bounds reads behave as all neutral but frame
682 //sync done.
683 uint64_t syncs_seen = 0;
684 uint64_t frames_read = 0;
685 size_t old_size = size();
686 size_t new_size = with.size();
687 size_t pagenum = 0;
688 size_t ocomplete_pages = old_size / frames_per_page; //Round DOWN
689 size_t ncomplete_pages = new_size / frames_per_page; //Round DOWN
690 size_t complete_pages = min(ocomplete_pages, ncomplete_pages);
691 while(syncs_seen + frames_per_page < nframe - 1 && pagenum < complete_pages) {
692 //Fast process page. The above condition guarantees that these pages are completely used.
693 auto opagedata = pages[pagenum].content;
694 auto npagedata = with.pages[pagenum].content;
695 size_t pagedataamt = frames_per_page * frame_size;
696 if(memcmp(opagedata, npagedata, pagedataamt))
697 return false;
698 frames_read += frames_per_page;
699 pagenum++;
700 for(size_t i = 0; i < pagedataamt; i += frame_size)
701 if(opagedata[i] & 1) syncs_seen++;
703 while(syncs_seen < nframe - 1) {
704 frame oldc = blank_frame(true), newc = with.blank_frame(true);
705 if(frames_read < old_size)
706 oldc = (*this)[frames_read];
707 if(frames_read < new_size)
708 newc = with[frames_read];
709 if(oldc != newc)
710 return false; //Mismatch.
711 frames_read++;
712 if(newc.sync())
713 syncs_seen++;
715 //We increment the counter one time too many.
716 frames_read--;
717 //Current frame. We need to compare each control up to poll counter.
718 uint64_t readable_old_subframes = 0, readable_new_subframes = 0;
719 uint64_t oldlen = find_next_sync(*this, frames_read);
720 uint64_t newlen = find_next_sync(with, frames_read);
721 if(frames_read < oldlen)
722 readable_old_subframes = oldlen - frames_read;
723 if(frames_read < newlen)
724 readable_new_subframes = newlen - frames_read;
725 //Then rest of the stuff.
726 for(unsigned i = 0; i < pset.indices(); i++) {
727 uint32_t p = polls[i] & 0x7FFFFFFFUL;
728 short ov = 0, nv = 0;
729 for(uint32_t j = 0; j < p; j++) {
730 if(j < readable_old_subframes)
731 ov = (*this)[j + frames_read].axis2(i);
732 if(j < readable_new_subframes)
733 nv = with[j + frames_read].axis2(i);
734 if(ov != nv)
735 return false;
738 return true;
741 uint64_t frame_vector::binary_size() const throw()
743 return size() * get_stride();
746 void frame_vector::save_binary(binarystream::output& stream) const throw(std::runtime_error)
748 uint64_t stride = get_stride();
749 uint64_t pageframes = get_frames_per_page();
750 uint64_t vsize = size();
751 size_t pagenum = 0;
752 while(vsize > 0) {
753 uint64_t count = (vsize > pageframes) ? pageframes : vsize;
754 size_t bytes = count * stride;
755 const unsigned char* content = get_page_buffer(pagenum++);
756 stream.raw(content, bytes);
757 vsize -= count;
761 void frame_vector::load_binary(binarystream::input& stream) throw(std::bad_alloc, std::runtime_error)
763 uint64_t stride = get_stride();
764 uint64_t pageframes = get_frames_per_page();
765 uint64_t vsize = 0;
766 size_t pagenum = 0;
767 uint64_t pagesize = stride * pageframes;
768 while(stream.get_left()) {
769 resize(vsize + pageframes);
770 unsigned char* contents = get_page_buffer(pagenum++);
771 uint64_t gcount = min(pagesize, stream.get_left());
772 stream.raw(contents, gcount);
773 vsize += (gcount / stride);
775 resize(vsize);
776 recount_frames();
779 void frame_vector::swap_data(frame_vector& v) throw()
781 uint64_t toldsize = real_frame_count;
782 uint64_t voldsize = v.real_frame_count;
783 std::swap(pages, v.pages);
784 std::swap(frames_per_page, v.frames_per_page);
785 std::swap(frame_size, v.frame_size);
786 std::swap(frames, v.frames);
787 std::swap(types, v.types);
788 std::swap(cache_page_num, v.cache_page_num);
789 std::swap(cache_page, v.cache_page);
790 std::swap(real_frame_count, v.real_frame_count);
791 if(!freeze_count)
792 call_framecount_notification(toldsize);
793 if(!v.freeze_count)
794 v.call_framecount_notification(voldsize);
797 int64_t frame_vector::find_frame(uint64_t n)
799 if(!n) return -1;
800 uint64_t stride = get_stride();
801 uint64_t pageframes = get_frames_per_page();
802 uint64_t vsize = size();
803 size_t pagenum = 0;
804 while(vsize > 0) {
805 uint64_t count = (vsize > pageframes) ? pageframes : vsize;
806 const unsigned char* content = get_page_buffer(pagenum++);
807 size_t offset = 0;
808 for(unsigned i = 0; i < count; i++) {
809 if(frame::sync(content + offset)) n--;
810 if(n == 0) return (pagenum - 1) * pageframes + i;
811 offset += stride;
813 vsize -= count;
815 return -1;
818 frame::frame() throw()
820 memset(memory, 0, sizeof(memory));
821 backing = memory;
822 types = &dummytypes();
823 host = NULL;
826 unsigned controller::analog_actions() const
828 unsigned r = 0, s = 0;
829 for(unsigned i = 0; i < buttons.size(); i++) {
830 if(buttons[i].shadow)
831 continue;
832 switch(buttons[i].type) {
833 case button::TYPE_AXIS:
834 case button::TYPE_RAXIS:
835 case button::TYPE_LIGHTGUN:
836 r++;
837 break;
838 case button::TYPE_TAXIS:
839 s++;
840 break;
841 case button::TYPE_NULL:
842 case button::TYPE_BUTTON:
846 return (r + 1)/ 2 + s;
849 std::pair<unsigned, unsigned> controller::analog_action(unsigned k) const
851 unsigned x1 = std::numeric_limits<unsigned>::max();
852 unsigned x2 = std::numeric_limits<unsigned>::max();
853 unsigned r = 0;
854 bool second = false;
855 bool selecting = false;
856 for(unsigned i = 0; i < buttons.size(); i++) {
857 if(buttons[i].shadow)
858 continue;
859 switch(buttons[i].type) {
860 case button::TYPE_AXIS:
861 case button::TYPE_RAXIS:
862 case button::TYPE_LIGHTGUN:
863 if(selecting) {
864 x2 = i;
865 goto out;
867 if(r == k && !second) {
868 //This and following.
869 x1 = i;
870 selecting = true;
872 if(!second)
873 r++;
874 second = !second;
875 break;
876 case button::TYPE_TAXIS:
877 if(selecting)
878 break;
879 if(r == k) {
880 x1 = i;
881 goto out;
883 r++;
884 break;
885 case button::TYPE_NULL:
886 case button::TYPE_BUTTON:
890 out:
891 return std::make_pair(x1, x2);
894 namespace
896 std::string macro_field_as_string(const JSON::node& parent, const std::string& path)
898 const JSON::node& n = parent.follow(path);
899 if(n.type() != JSON::string)
900 (stringfmt() << "Expected string as field '" << path << "'").throwex();
901 return n.as_string8();
904 bool macro_field_as_boolean(const JSON::node& parent, const std::string& path)
906 const JSON::node& n = parent.follow(path);
907 if(n.type() != JSON::boolean)
908 (stringfmt() << "Expected boolean as field '" << path << "'").throwex();
909 return n.as_bool();
912 const JSON::node& macro_field_as_array(const JSON::node& parent, const std::string& path)
914 const JSON::node& n = parent.follow(path);
915 if(n.type() != JSON::array)
916 (stringfmt() << "Expected array as field '" << path << "'").throwex();
917 return n;
921 macro_data::macro_data(const std::string& spec, const JSON::node& desc, unsigned inum)
923 _descriptor = desc;
924 unsigned btnnum = 0;
925 std::map<std::string, unsigned> symbols;
926 if(desc.type() != JSON::array)
927 (stringfmt() << "Expected controller descriptor " << (inum + 1) << " to be an array");
928 for(auto i = desc.begin(); i != desc.end(); ++i) {
929 if(i->type() == JSON::string) {
930 symbols[i->as_string8()] = btnnum++;
931 btnmap.push_back(i.index());
932 } else if(i->type() == JSON::number) {
933 uint64_t anum = i->as_uint();
934 if(anum > aaxes.size())
935 (stringfmt() << "Descriptor axis number " << anum << " out of range in descriptor "
936 << (inum + 1)).throwex();
937 else if(anum == aaxes.size())
938 aaxes.push_back(std::make_pair(i.index(), std::numeric_limits<unsigned>::max()));
939 else
940 aaxes[anum].second = i.index();
941 } else
942 (stringfmt() << "Controller descriptor " << (inum + 1) << " contains element of unknown"
943 << "kind").throwex();
945 buttons = symbols.size();
946 orig = spec;
947 enabled = true;
948 autoterminate = false;
950 std::deque<size_t> stack;
951 bool in_sparen = false;
952 bool first = true;
953 bool btn_token = false;
954 bool btn_token_next = false;
955 size_t last_bit = 0;
956 size_t last_size = 0;
957 size_t astride = aaxes.size();
958 size_t stride = get_stride();
959 size_t idx = 0;
960 size_t len = spec.length();
961 try {
962 while(idx < len) {
963 btn_token = btn_token_next;
964 btn_token_next = false;
965 unsigned char ch = spec[idx];
966 if(autoterminate)
967 throw std::runtime_error("Asterisk must be the last thing");
968 if(ch == '(') {
969 if(in_sparen)
970 throw std::runtime_error("Parentheses in square brackets not allowed");
971 stack.push_back(data.size());
972 } else if(ch == ')') {
973 if(in_sparen)
974 throw std::runtime_error("Parentheses in square brackets not allowed");
975 if(stack.empty())
976 throw std::runtime_error("Unmatched right parenthesis");
977 size_t x = stack.back();
978 stack.pop_back();
979 last_size = (data.size() - x) / stride;
980 } else if(ch == '*') {
981 autoterminate = true;
982 } else if(ch == '?') {
983 if(!btn_token)
984 throw std::runtime_error("? needs button to apply to");
985 if(!in_sparen)
986 throw std::runtime_error("? needs to be in brackets");
987 data[data.size() - stride + last_bit] |= 2;
988 } else if(ch == '[') {
989 if(in_sparen)
990 throw std::runtime_error("Nested square brackets not allowed");
991 in_sparen = true;
992 data.resize(data.size() + stride);
993 adata.resize(adata.size() + astride);
994 last_size = 1;
995 } else if(ch == ']') {
996 if(!in_sparen)
997 throw std::runtime_error("Unmatched right square bracket");
998 in_sparen = false;
999 } else if(ch == '.') {
1000 if(!in_sparen) {
1001 data.resize(data.size() + stride);
1002 adata.resize(adata.size() + astride);
1003 last_size = 1;
1005 } else if(spec[idx] >= '0' && spec[idx] <= '9') {
1006 size_t rep = 0;
1007 unsigned i = 0;
1008 while(spec[idx + i] >= '0' && spec[idx + i] <= '9') {
1009 rep = 10 * rep + (spec[idx + i] - '0');
1010 i++;
1012 if(in_sparen) {
1013 //This has special meaning: Axis transform.
1014 //Rep is the axis pair to operate on.
1015 if(spec[idx + i] != ':')
1016 throw std::runtime_error("Expected ':' in axis transform");
1017 size_t sep = i;
1018 while(idx + i < len && spec[idx + i] != '@')
1019 i++;
1020 if(idx + i >= len)
1021 throw std::runtime_error("Expected '@' in axis transform");
1022 std::string aexpr = spec.substr(idx + sep + 1, i - sep - 1);
1023 if(rep >= astride)
1024 throw std::runtime_error("Axis transform refers to invalid axis");
1025 adata[adata.size() - astride + rep] = axis_transform(aexpr);
1026 i++;
1027 } else {
1028 if(first)
1029 throw std::runtime_error("Repeat not allowed without frame to "
1030 "repeat");
1031 size_t o = data.size();
1032 size_t ao = adata.size();
1033 data.resize(o + (rep - 1) * last_size * stride);
1034 adata.resize(ao + (rep - 1) * last_size * astride);
1035 for(unsigned i = 1; i < rep; i++) {
1036 memcpy(&data[o + (i - 1) * last_size * stride], &data[o - last_size *
1037 stride], last_size * stride);
1038 memcpy(&data[ao + (i - 1) * last_size * astride], &data[ao -
1039 last_size * astride], last_size * astride);
1041 last_size = last_size * rep;
1043 idx = idx + (i - 1);
1044 } else { //Symbol.
1045 bool found = false;
1046 for(auto k : symbols) {
1047 std::string key = k.first;
1048 size_t j;
1049 for(j = 0; idx + j < len && j < key.length(); j++)
1050 if(spec[idx + j] != key[j])
1051 break;
1052 if(j == key.length()) {
1053 idx += key.length() - 1;
1054 found = true;
1055 if(!in_sparen) {
1056 data.resize(data.size() + stride);
1057 adata.resize(adata.size() + astride);
1059 last_bit = k.second;
1060 data[data.size() - stride + k.second] |= 1;
1061 if(!in_sparen)
1062 last_size = 1;
1065 if(!found)
1066 throw std::runtime_error("Unknown character or button");
1067 btn_token_next = true;
1069 idx++;
1070 first = false;
1072 if(in_sparen)
1073 throw std::runtime_error("Unmatched left square bracket");
1074 if(!stack.empty())
1075 throw std::runtime_error("Unmatched left parenthesis");
1076 } catch(std::exception& e) {
1077 (stringfmt() << "Error parsing macro for controller " << (inum + 1) << ": " << e.what()).throwex();
1081 bool macro_data::syntax_check(const std::string& spec, const JSON::node& desc)
1083 unsigned buttons = 0;
1084 size_t astride = 0;
1085 if(desc.type() != JSON::array)
1086 return false;
1087 for(auto i = desc.begin(); i != desc.end(); ++i) {
1088 if(i->type() == JSON::string)
1089 buttons++;
1090 else if(i->type() == JSON::number) {
1091 uint64_t anum = i->as_uint();
1092 if(anum > astride)
1093 return false;
1094 else if(anum == astride)
1095 astride++;
1096 } else
1097 return false;
1099 bool autoterminate = false;
1100 size_t depth = 0;
1101 bool in_sparen = false;
1102 bool first = true;
1103 bool btn_token = false;
1104 bool btn_token_next = false;
1105 size_t idx = 0;
1106 size_t len = spec.length();
1107 while(idx < len) {
1108 btn_token = btn_token_next;
1109 btn_token_next = false;
1110 unsigned char ch = spec[idx];
1111 if(autoterminate)
1112 return false;
1113 if(ch == '(') {
1114 if(in_sparen)
1115 return false;
1116 depth++;
1117 } else if(ch == ')') {
1118 if(in_sparen)
1119 return false;
1120 if(!depth)
1121 return false;
1122 depth--;
1123 } else if(ch == '*') {
1124 autoterminate = true;
1125 } else if(ch == '?') {
1126 if(!btn_token || !in_sparen)
1127 return false;
1128 } else if(ch == '[') {
1129 if(in_sparen)
1130 return false;
1131 in_sparen = true;
1132 } else if(ch == ']') {
1133 if(!in_sparen)
1134 return false;
1135 in_sparen = false;
1136 } else if(ch == '.') {
1137 } else if(spec[idx] >= '0' && spec[idx] <= '9') {
1138 size_t rep = 0;
1139 unsigned i = 0;
1140 while(spec[idx + i] >= '0' && spec[idx + i] <= '9') {
1141 rep = 10 * rep + (spec[idx + i] - '0');
1142 i++;
1144 if(in_sparen) {
1145 //This has special meaning: Axis transform.
1146 //Rep is the axis pair to operate on.
1147 if(spec[idx + i] != ':')
1148 return false;
1149 size_t sep = i;
1150 while(idx + i < len && spec[idx + i] != '@')
1151 i++;
1152 if(idx + i >= len)
1153 return false;
1154 if(rep >= astride)
1155 return false;
1156 try {
1157 std::string aexpr = spec.substr(idx + sep + 1, i - sep - 1);
1158 axis_transform x(aexpr);
1159 } catch(...) {
1160 return false;
1162 i++;
1163 } else {
1164 if(first)
1165 return false;
1167 idx = idx + (i - 1);
1168 } else { //Symbol.
1169 bool found = false;
1170 for(auto i = desc.begin(); i != desc.end(); ++i) {
1171 if(i->type() != JSON::string)
1172 continue;
1173 std::string key = i->as_string8();
1174 size_t j;
1175 for(j = 0; idx + j < len && j < key.length(); j++)
1176 if(spec[idx + j] != key[j])
1177 break;
1178 if(j == key.length()) {
1179 idx += key.length() - 1;
1180 found = true;
1183 if(!found)
1184 return false;
1185 btn_token_next = true;
1187 idx++;
1188 first = false;
1190 if(in_sparen)
1191 return false;
1192 if(depth)
1193 return false;
1194 return true;
1197 void macro_data::write(frame& frame, unsigned port, unsigned controller_n, int64_t nframe,
1198 apply_mode amode)
1200 if(!enabled)
1201 return;
1202 if(autoterminate && (nframe < 0 || nframe >= (int64_t)get_frames()))
1203 return;
1204 if(nframe < 0)
1205 nframe += ((-nframe / get_frames()) + 3) * get_frames();
1206 nframe %= get_frames();
1207 for(size_t i = 0; i < buttons; i++) {
1208 unsigned lb = btnmap[i];
1209 unsigned st = data[nframe * get_stride() + i];
1210 if(st == 3)
1211 st = macro_random_bit();
1212 if(st == 1)
1213 switch(amode) {
1214 case AM_OVERWRITE:
1215 case AM_OR:
1216 frame.axis3(port, controller_n, lb, 1);
1217 break;
1218 case AM_XOR:
1219 frame.axis3(port, controller_n, lb, frame.axis3(port, controller_n, lb) ^ 1);
1220 break;
1222 else
1223 switch(amode) {
1224 case AM_OVERWRITE:
1225 frame.axis3(port, controller_n, lb, 0);
1226 break;
1227 case AM_OR:
1228 case AM_XOR:
1232 const controller* _ctrl = frame.porttypes().port_type(port).controller_info->get(controller_n);
1233 if(!_ctrl)
1234 return;
1235 size_t abuttons = aaxes.size();
1236 for(size_t i = 0; i < abuttons; i++) {
1237 unsigned ax = aaxes[i].first;
1238 unsigned ay = aaxes[i].second;
1239 if(ay != std::numeric_limits<unsigned>::max()) {
1240 if(ax > _ctrl->buttons.size()) continue;
1241 if(ay > _ctrl->buttons.size()) continue;
1242 auto g = adata[nframe * abuttons + i].transform(_ctrl->buttons[ax], _ctrl->buttons[ay],
1243 frame.axis3(port, controller_n, ax), frame.axis3(port, controller_n, ay));
1244 frame.axis3(port, controller_n, ax, g.first);
1245 frame.axis3(port, controller_n, ay, g.second);
1246 } else {
1247 if(ax > _ctrl->buttons.size()) continue;
1248 int16_t g = adata[nframe * abuttons + i].transform(_ctrl->buttons[ax],
1249 frame.axis3(port, controller_n, ax));
1250 frame.axis3(port, controller_n, ax, g);
1255 std::string macro_data::dump(const controller& ctrl)
1257 std::ostringstream o;
1258 for(size_t i = 0; i < get_frames(); i++) {
1259 o << "[";
1260 for(size_t j = 0; j < aaxes.size(); j++) {
1261 macro_data::axis_transform& t = adata[i * aaxes.size() + j];
1262 o << j << ":";
1263 o << t.coeffs[0] << "," << t.coeffs[1] << "," << t.coeffs[2] << ",";
1264 o << t.coeffs[3] << "," << t.coeffs[4] << "," << t.coeffs[5] << "@";
1266 for(size_t j = 0; j < buttons && j < ctrl.buttons.size(); j++) {
1267 unsigned st = data[i * get_stride() + j];
1268 if(ctrl.buttons[j].macro == "")
1269 continue;
1270 if(st == 1)
1271 o << ctrl.buttons[j].macro;
1272 if(st == 3)
1273 o << ctrl.buttons[j].macro << "?";
1275 o << "]";
1277 if(autoterminate)
1278 o << "*";
1279 return o.str();
1282 void macro::write(frame& frame, int64_t nframe)
1284 for(auto& i : macros) {
1285 unsigned port;
1286 unsigned controller;
1287 try {
1288 auto g = frame.porttypes().lcid_to_pcid(i.first);
1289 port = g.first;
1290 controller = g.second;
1291 } catch(...) {
1292 continue;
1294 i.second.write(frame, port, controller, nframe, amode);
1298 int16_t macro_data::axis_transform::transform(const button& b, int16_t v)
1300 return scale_axis(b, coeffs[0] * unscale_axis(b, v) + coeffs[4]);
1303 std::pair<int16_t, int16_t> macro_data::axis_transform::transform(const button& b1,
1304 const button& b2, int16_t v1, int16_t v2)
1306 double x, y, u, v, au, av, s;
1307 x = unscale_axis(b1, v1);
1308 y = unscale_axis(b2, v2);
1309 u = coeffs[0] * x + coeffs[1] * y + coeffs[4];
1310 v = coeffs[2] * x + coeffs[3] * y + coeffs[5];
1311 au = abs(u);
1312 av = abs(v);
1313 s = max(max(au, 1.0), max(av, 1.0));
1314 //If u and v exceed nominal range of [-1,1], those need to be projected to the edge.
1315 if(s > 1) {
1316 u /= s;
1317 v /= s;
1319 auto g = std::make_pair(scale_axis(b1, u), scale_axis(b2, v));
1320 return g;
1323 double macro_data::axis_transform::unscale_axis(const button& b, int16_t v)
1325 if(b.centers) {
1326 int32_t center = ((int32_t)b.rmin + (int32_t)b.rmax) / 2;
1327 if(v <= b.rmin)
1328 return -1;
1329 if(v < center)
1330 return -(center - (double)v) / (center - b.rmin);
1331 if(v == center)
1332 return 0;
1333 if(v < b.rmax)
1334 return ((double)v - center) / (b.rmax - center);
1335 return 1;
1336 } else {
1337 if(v <= b.rmin)
1338 return 0;
1339 if(v >= b.rmax)
1340 return 1;
1341 return ((double)v - b.rmin) / (b.rmax - b.rmin);
1345 int16_t macro_data::axis_transform::scale_axis(const button& b, double v)
1347 if(b.centers) {
1348 int32_t center = ((int32_t)b.rmin + (int32_t)b.rmax) / 2;
1349 if(v == 0)
1350 return center;
1351 if(v < 0) {
1352 double v2 = v * (center - b.rmin) + center;
1353 if(v2 < b.rmin)
1354 return b.rmin;
1355 return v2;
1357 double v2 = v * (b.rmax - center) + center;
1358 if(v2 > b.rmax)
1359 return b.rmax;
1360 return v2;
1361 } else {
1362 double v2 = v * (b.rmax - b.rmin) + b.rmin;
1363 if(v2 < b.rmin)
1364 return b.rmin;
1365 if(v2 > b.rmax)
1366 return b.rmax;
1367 return v2;
1371 namespace
1373 std::complex<double> parse_complex(const std::string& expr)
1375 regex_results r;
1376 if(r = regex("\\((.*),(.*)\\)", expr)) {
1377 //Real,Imaginary.
1378 return std::complex<double>(parse_value<double>(r[1]), parse_value<double>(r[2]));
1379 } else if(r = regex("\\((.*)<(.*)\\)", expr)) {
1380 return std::polar(parse_value<double>(r[1]), parse_value<double>(r[2]) * M_PI / 180);
1381 } else {
1382 return std::complex<double>(parse_value<double>(expr), 0.0);
1387 macro_data::axis_transform::axis_transform(const std::string& expr)
1389 regex_results r;
1390 if(r = regex("\\*(.*)\\+(.*)", expr)) {
1391 //Affine transform.
1392 std::complex<double> a = parse_complex(r[1]);
1393 std::complex<double> b = parse_complex(r[2]);
1394 coeffs[0] = a.real();
1395 coeffs[1] = -a.imag();
1396 coeffs[2] = a.imag();
1397 coeffs[3] = a.real();
1398 coeffs[4] = b.real();
1399 coeffs[5] = b.imag();
1400 } else if(r = regex("\\*(.*)", expr)) {
1401 //Linear transform.
1402 std::complex<double> a = parse_complex(r[1]);
1403 coeffs[0] = a.real();
1404 coeffs[1] = -a.imag();
1405 coeffs[2] = a.imag();
1406 coeffs[3] = a.real();
1407 coeffs[4] = 0;
1408 coeffs[5] = 0;
1409 } else if(r = regex("\\+(.*)", expr)) {
1410 //Relative
1411 std::complex<double> b = parse_complex(r[1]);
1412 coeffs[0] = 1;
1413 coeffs[1] = 0;
1414 coeffs[2] = 0;
1415 coeffs[3] = 1;
1416 coeffs[4] = b.real();
1417 coeffs[5] = b.imag();
1418 } else if(r = regex("(.*),(.*),(.*),(.*),(.*),(.*)", expr)) {
1419 //Full affine.
1420 coeffs[0] = parse_value<double>(r[1]);
1421 coeffs[1] = parse_value<double>(r[2]);
1422 coeffs[2] = parse_value<double>(r[3]);
1423 coeffs[3] = parse_value<double>(r[4]);
1424 coeffs[4] = parse_value<double>(r[5]);
1425 coeffs[5] = parse_value<double>(r[6]);
1426 } else {
1427 //Absolute.
1428 std::complex<double> b = parse_complex(expr);
1429 coeffs[0] = 0;
1430 coeffs[1] = 0;
1431 coeffs[2] = 0;
1432 coeffs[3] = 0;
1433 coeffs[4] = b.real();
1434 coeffs[5] = b.imag();
1438 JSON::node macro::serialize()
1440 JSON::node v(JSON::object);
1441 switch(amode) {
1442 case macro_data::AM_OVERWRITE: v.insert("mode", JSON::s("overwrite")); break;
1443 case macro_data::AM_OR: v.insert("mode", JSON::s("or")); break;
1444 case macro_data::AM_XOR: v.insert("mode", JSON::s("xor")); break;
1446 JSON::node& c = v.insert("data", JSON::array());
1447 for(auto& i : macros) {
1448 while(i.first > c.index_count())
1449 c.append(JSON::n());
1450 i.second.serialize(c.append(JSON::n()));
1452 return v;
1455 void macro_data::serialize(JSON::node& v)
1457 v = JSON::object();
1458 v.insert("enable", JSON::b(enabled));
1459 v.insert("expr", JSON::s(orig));
1460 v.insert("desc", _descriptor);
1463 JSON::node macro_data::make_descriptor(const controller& ctrl)
1465 JSON::node n(JSON::array);
1466 for(size_t i = 0; i < ctrl.buttons.size(); i++) {
1467 if(ctrl.buttons[i].macro != "")
1468 n.append(JSON::s(ctrl.buttons[i].macro));
1469 else
1470 n.append(JSON::n()); //Placeholder.
1472 for(size_t i = 0; i < ctrl.analog_actions(); i++) {
1473 auto g = ctrl.analog_action(i);
1474 n.index(g.first) = JSON::u(i);
1475 if(g.second != std::numeric_limits<unsigned>::max())
1476 n.index(g.second) = JSON::u(i);
1478 return n;
1481 macro::macro(const JSON::node& v)
1483 if(v.type() != JSON::object)
1484 throw std::runtime_error("Expected macro to be JSON object");
1485 std::string mode = macro_field_as_string(v, "mode");
1486 if(mode == "overwrite") amode = macro_data::AM_OVERWRITE;
1487 else if(mode == "or") amode = macro_data::AM_OR;
1488 else if(mode == "xor") amode = macro_data::AM_XOR;
1489 else (stringfmt() << "Unknown button mode '" << mode << "'").throwex();
1490 const JSON::node& c = macro_field_as_array(v, "data");
1491 for(auto i = c.begin(); i != c.end(); ++i) {
1492 if(i->type() == JSON::object)
1493 macros[i.index()] = macro_data(*i, i.index());
1494 else
1495 (stringfmt() << "Expected object as field 'data/" << i.index() << "'").throwex();
1499 macro_data::macro_data(const JSON::node& v, unsigned i)
1500 : macro_data(macro_field_as_string(v, "expr"), macro_field_as_array(v, "desc"), i)
1502 enabled = macro_field_as_boolean(v, "enable");