Rework how memory tracking works
[lsnes.git] / src / library / portctrl-data.cpp
blob726b58e0713200ca7d4584a7eb6f24026d19eb8f
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 const char* movie_page_id = "Input tracks";
19 namespace
21 controller simple_controller = {"(system)", "system", {}};
22 controller_set simple_port = {"system", "system", "system", {simple_controller},{0}};
24 struct porttype_basecontrol : public type
26 porttype_basecontrol() : type("basecontrol", "basecontrol", 1)
28 write = [](const type* _this, unsigned char* buffer, unsigned idx, unsigned ctrl,
29 short x) -> void {
30 if(idx > 0 || ctrl > 0) return;
31 buffer[0] = x ? 1 : 0;
33 read = [](const type* _this, const unsigned char* buffer, unsigned idx, unsigned ctrl) ->
34 short {
35 if(idx > 0 || ctrl > 0) return 0;
36 return buffer[0] ? 1 : 0;
38 serialize = [](const type* _this, const unsigned char* buffer, char* textbuf) -> size_t {
39 textbuf[0] = buffer[0] ? 'F' : '-';
40 textbuf[1] = '\0';
41 return 1;
43 deserialize = [](const type* _this, unsigned char* buffer, const char* textbuf) ->
44 size_t {
45 size_t ptr = 0;
46 buffer[0] = 0;
47 if(read_button_value(textbuf, ptr))
48 buffer[0] = 1;
49 skip_rest_of_field(textbuf, ptr, false);
50 return ptr;
52 controller_info = &simple_port;
56 unsigned macro_random_bit()
58 static unsigned char state[32];
59 static unsigned extracted = 256;
60 if(extracted == 256) {
61 timeval tv;
62 gettimeofday(&tv, NULL);
63 unsigned char buffer[48];
64 memcpy(buffer, state, 32);
65 serialization::u64b(buffer + 32, tv.tv_sec);
66 serialization::u64b(buffer + 40, tv.tv_usec);
67 sha256::hash(state, buffer, 48);
68 extracted = 0;
70 unsigned bit = extracted++;
71 return ((state[bit / 8] >> (bit % 8)) & 1);
75 type& get_default_system_port_type()
77 static porttype_basecontrol x;
78 return x;
81 type::type(const std::string& iname, const std::string& _hname, size_t ssize) throw(std::bad_alloc)
82 : hname(_hname), storage_size(ssize), name(iname)
86 type::~type() throw()
90 bool type::is_present(unsigned controller) const throw()
92 return controller_info->controllers.size() > controller;
95 namespace
97 size_t dummy_offset = 0;
98 type* dummy_type = &get_default_system_port_type();
99 unsigned dummy_index = 0;
100 struct binding
102 std::vector<type*> types;
103 type_set* stype;
104 bool matches(const std::vector<class type*>& x)
106 if(x.size() != types.size())
107 return false;
108 for(size_t i = 0; i < x.size(); i++)
109 if(x[i] != types[i])
110 return false;
111 return true;
114 std::list<binding>& bindings()
116 static std::list<binding> x;
117 return x;
121 type_set::type_set() throw()
124 port_offsets = &dummy_offset;
125 port_types = &dummy_type;
126 port_count = 1;
127 total_size = 1;
128 _indices.resize(1);
129 _indices[0].valid = true;
130 _indices[0].port = 0;
131 _indices[0].controller = 0;
132 _indices[0].control = 0;
134 port_multiplier = 1;
135 controller_multiplier = 1;
136 indices_size = 1;
137 indices_tab = &dummy_index;
140 type_set& type_set::make(std::vector<class type*> types, struct index_map control_map)
141 throw(std::bad_alloc, std::runtime_error)
143 for(auto i : bindings())
144 if(i.matches(types))
145 return *(i.stype);
146 //Not found, create new.
147 type_set& ret = *new type_set(types, control_map);
148 binding b;
149 b.types = types;
150 b.stype = &ret;
151 bindings().push_back(b);
152 return ret;
155 type_set::type_set(std::vector<class type*> types, struct index_map control_map)
157 port_count = types.size();
158 //Verify legality of port types.
159 for(size_t i = 0; i < port_count; i++)
160 if(!types[i] || !types[i]->legal(i))
161 throw std::runtime_error("Illegal port types");
162 //Count maximum number of controller indices to determine the controller multiplier.
163 controller_multiplier = 1;
164 for(size_t i = 0; i < port_count; i++)
165 for(unsigned j = 0; j < types[i]->controller_info->controllers.size(); j++)
166 controller_multiplier = max(controller_multiplier, (size_t)types[i]->used_indices(j));
167 //Count maximum number of controllers to determine the port multiplier.
168 port_multiplier = 1;
169 for(size_t i = 0; i < port_count; i++)
170 port_multiplier = max(port_multiplier, controller_multiplier *
171 (size_t)types[i]->controller_info->controllers.size());
172 //Allocate the per-port tables.
173 port_offsets = new size_t[types.size()];
174 port_types = new class type*[types.size()];
175 //Determine the total size and offsets.
176 size_t offset = 0;
177 for(size_t i = 0; i < port_count; i++) {
178 port_offsets[i] = offset;
179 offset += types[i]->storage_size;
180 port_types[i] = types[i];
182 total_size = offset;
183 //Determine the index size and allocate it.
184 indices_size = port_multiplier * port_count;
185 indices_tab = new unsigned[indices_size];
186 for(size_t i = 0; i < indices_size; i++)
187 indices_tab[i] = 0xFFFFFFFFUL;
188 //Copy the index data (and reverse it).
189 controllers = control_map.logical_map;
190 legacy_pcids = control_map.pcid_map;
191 _indices = control_map.indices;
192 for(size_t j = 0; j < _indices.size(); j++) {
193 auto& i = _indices[j];
194 if(i.valid)
195 indices_tab[i.port * port_multiplier + i.controller * controller_multiplier + i.control] = j;
199 short read_axis_value(const char* buf, size_t& idx) throw()
201 char ch;
202 //Skip ws.
203 while(is_nonterminator(buf[idx])) {
204 char ch = buf[idx];
205 if(ch != ' ' && ch != '\t')
206 break;
207 idx++;
209 //Read the sign if any.
210 ch = buf[idx];
211 if(!is_nonterminator(ch))
212 return 0;
213 bool negative = false;
214 if(ch == '-') {
215 negative = true;
216 idx++;
218 if(ch == '+')
219 idx++;
221 //Read numeric value.
222 int numval = 0;
223 while(is_nonterminator(buf[idx]) && isdigit(static_cast<unsigned char>(ch = buf[idx]))) {
224 numval = numval * 10 + (ch - '0');
225 idx++;
227 if(negative)
228 numval = -numval;
230 return static_cast<short>(numval);
233 size_t write_axis_value(char* buf, short _v)
235 int v = _v;
236 size_t r = 0;
237 buf[r++] = ' ';
238 if(v < 0) { buf[r++] = '-'; v = -v; }
239 if(v >= 10000) buf[r++] = '0' + (v / 10000 % 10);
240 if(v >= 1000) buf[r++] = '0' + (v / 1000 % 10);
241 if(v >= 100) buf[r++] = '0' + (v / 100 % 10);
242 if(v >= 10) buf[r++] = '0' + (v / 10 % 10);
243 buf[r++] = '0' + (v % 10);
244 return r;
247 namespace
249 type_set& dummytypes()
251 static type_set x;
252 return x;
255 size_t writeu32val(char32_t* buf, int val)
257 char c[12];
258 size_t i;
259 sprintf(c, "%d", val);
260 for(i = 0; c[i]; i++)
261 buf[i] = c[i];
262 return i;
265 uint64_t find_next_sync(frame_vector& movie, uint64_t after)
267 if(after >= movie.size())
268 return after;
269 do {
270 after++;
271 } while(after < movie.size() && !movie[after].sync());
272 return after;
276 void frame::display(unsigned port, unsigned controller_n, char32_t* buf) throw()
278 if(port >= types->ports()) {
279 //Bad port.
280 *buf = '\0';
281 return;
283 uint8_t* backingmem = backing + types->port_offset(port);
284 const type& ptype = types->port_type(port);
285 if(controller_n >= ptype.controller_info->controllers.size()) {
286 //Bad controller.
287 *buf = '\0';
288 return;
290 const controller& pc = ptype.controller_info->controllers[controller_n];
291 bool need_space = false;
292 short val;
293 for(unsigned i = 0; i < pc.buttons.size(); i++) {
294 const button& pcb = pc.buttons[i];
295 if(need_space && pcb.type != button::TYPE_NULL) {
296 need_space = false;
297 *(buf++) = ' ';
299 switch(pcb.type) {
300 case button::TYPE_NULL:
301 break;
302 case button::TYPE_BUTTON:
303 *(buf++) = ptype.read(&ptype, backingmem, controller_n, i) ? pcb.symbol : U'-';
304 break;
305 case button::TYPE_AXIS:
306 case button::TYPE_RAXIS:
307 case button::TYPE_TAXIS:
308 case button::TYPE_LIGHTGUN:
309 val = ptype.read(&ptype, backingmem, controller_n, i);
310 buf += writeu32val(buf, val);
311 need_space = true;
312 break;
315 *buf = '\0';
318 counters::counters() throw(std::bad_alloc)
320 types = &dummytypes();
321 ctrs = new uint32_t[types->indices()];
322 clear();
325 counters::counters(const type_set& p) throw(std::bad_alloc)
327 types = &p;
328 ctrs = new uint32_t[types->indices()];
329 clear();
332 counters::counters(const counters& p) throw(std::bad_alloc)
334 ctrs = new uint32_t[p.types->indices()];
335 types = p.types;
336 memcpy(ctrs, p.ctrs, sizeof(uint32_t) * p.types->indices());
337 framepflag = p.framepflag;
340 counters& counters::operator=(const counters& p) throw(std::bad_alloc)
342 if(this == &p)
343 return *this;
344 uint32_t* n = new uint32_t[p.types->indices()];
345 types = p.types;
346 memcpy(n, p.ctrs, sizeof(uint32_t) * p.types->indices());
347 delete[] ctrs;
348 ctrs = n;
349 framepflag = p.framepflag;
350 return *this;
353 counters::~counters() throw()
355 delete[] ctrs;
358 void counters::clear() throw()
360 memset(ctrs, 0, sizeof(uint32_t) * types->indices());
361 framepflag = false;
364 void counters::set_all_DRDY() throw()
366 for(size_t i = 0; i < types->indices(); i++)
367 ctrs[i] |= 0x80000000UL;
370 void counters::clear_DRDY(unsigned idx) throw()
372 ctrs[idx] &= 0x7FFFFFFFUL;
375 bool counters::get_DRDY(unsigned idx) throw()
377 return ((ctrs[idx] & 0x80000000UL) != 0);
380 bool counters::has_polled() throw()
382 uint32_t res = 0;
383 for(size_t i = 0; i < types->indices() ; i++)
384 res |= ctrs[i];
385 return ((res & 0x7FFFFFFFUL) != 0);
388 uint32_t counters::get_polls(unsigned idx) throw()
390 return ctrs[idx] & 0x7FFFFFFFUL;
393 uint32_t counters::increment_polls(unsigned idx) throw()
395 uint32_t x = ctrs[idx] & 0x7FFFFFFFUL;
396 ++ctrs[idx];
397 return x;
400 uint32_t counters::max_polls() throw()
402 uint32_t max = 0;
403 for(unsigned i = 0; i < types->indices(); i++) {
404 uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL;
405 max = (max < tmp) ? tmp : max;
407 return max;
410 void counters::save_state(std::vector<uint32_t>& mem) throw(std::bad_alloc)
412 mem.resize(types->indices());
413 //Compatiblity fun.
414 for(size_t i = 0; i < types->indices(); i++)
415 mem[i] = ctrs[i];
418 void counters::load_state(const std::vector<uint32_t>& mem) throw()
420 for(size_t i = 0; i < types->indices(); i++)
421 ctrs[i] = mem[i];
424 bool counters::check(const std::vector<uint32_t>& mem) throw()
426 return (mem.size() == types->indices());
430 void counters::set_framepflag(bool value) throw()
432 framepflag = value;
435 bool counters::get_framepflag() const throw()
437 return framepflag;
440 frame::frame(const type_set& p) throw(std::runtime_error)
442 memset(memory, 0, sizeof(memory));
443 backing = memory;
444 types = &p;
445 host = NULL;
448 frame::frame(unsigned char* mem, const type_set& p, frame_vector* _host)
449 throw(std::runtime_error)
451 if(!mem)
452 throw std::runtime_error("NULL backing memory not allowed");
453 memset(memory, 0, sizeof(memory));
454 backing = mem;
455 types = &p;
456 host = _host;
459 frame::frame(const frame& obj) throw()
461 memset(memory, 0, sizeof(memory));
462 backing = memory;
463 types = obj.types;
464 memcpy(backing, obj.backing, types->size());
465 host = NULL;
468 frame& frame::operator=(const frame& obj) throw(std::runtime_error)
470 if(backing != memory && types != obj.types)
471 throw std::runtime_error("Port types do not match");
472 types = obj.types;
473 short old = sync();
474 memcpy(backing, obj.backing, types->size());
475 if(host) host->notify_sync_change(sync() - old);
476 return *this;
479 frame_vector::fchange_listener::~fchange_listener()
483 size_t frame_vector::walk_helper(size_t frame, bool sflag) throw()
485 size_t ret = sflag ? frame : 0;
486 if(frame >= frames)
487 return ret;
488 frame++;
489 ret++;
490 size_t page = frame / frames_per_page;
491 size_t offset = frame_size * (frame % frames_per_page);
492 size_t index = frame % frames_per_page;
493 if(cache_page_num != page) {
494 cache_page = &pages[page];
495 cache_page_num = page;
497 while(frame < frames) {
498 if(index == frames_per_page) {
499 page++;
500 cache_page = &pages[page];
501 cache_page_num = page;
502 index = 0;
503 offset = 0;
505 if(frame::sync(cache_page->content + offset))
506 break;
507 index++;
508 offset += frame_size;
509 frame++;
510 ret++;
512 return ret;
515 size_t frame_vector::recount_frames() throw()
517 uint64_t old_frame_count = real_frame_count;
518 size_t ret = 0;
519 if(!frames)
520 return 0;
521 cache_page_num = 0;
522 cache_page = &pages[0];
523 size_t offset = 0;
524 size_t index = 0;
525 for(size_t i = 0; i < frames; i++) {
526 if(index == frames_per_page) {
527 cache_page_num++;
528 cache_page = &pages[cache_page_num];
529 index = 0;
530 offset = 0;
532 if(frame::sync(cache_page->content + offset))
533 ret++;
534 index++;
535 offset += frame_size;
538 real_frame_count = ret;
539 call_framecount_notification(old_frame_count);
540 return ret;
543 void frame_vector::clear(const type_set& p) throw(std::runtime_error)
545 uint64_t old_frame_count = real_frame_count;
546 frame_size = p.size();
547 frames_per_page = CONTROLLER_PAGE_SIZE / frame_size;
548 frames = 0;
549 types = &p;
550 clear_cache();
551 pages.clear();
552 real_frame_count = 0;
553 call_framecount_notification(old_frame_count);
556 frame_vector::~frame_vector() throw()
558 pages.clear();
559 cache_page = NULL;
562 frame_vector::frame_vector() throw()
563 : tracker(memtracker::singleton(), movie_page_id, sizeof(*this))
565 real_frame_count = 0;
566 freeze_count = 0;
567 clear(dummytypes());
570 frame_vector::frame_vector(const type_set& p) throw()
571 : tracker(memtracker::singleton(), movie_page_id, sizeof(*this))
573 real_frame_count = 0;
574 freeze_count = 0;
575 clear(p);
578 void frame_vector::append(frame cframe) throw(std::bad_alloc, std::runtime_error)
580 frame check(*types);
581 if(!check.types_match(cframe))
582 throw std::runtime_error("frame_vector::append: Type mismatch");
583 if(frames % frames_per_page == 0) {
584 //Create new page.
585 pages[frames / frames_per_page];
587 //Write the entry.
588 size_t page = frames / frames_per_page;
589 size_t offset = frame_size * (frames % frames_per_page);
590 if(cache_page_num != page) {
591 cache_page_num = page;
592 cache_page = &pages[page];
594 frame(cache_page->content + offset, *types) = cframe;
595 if(cframe.sync()) real_frame_count++;
596 frames++;
599 frame_vector::frame_vector(const frame_vector& vector) throw(std::bad_alloc)
600 : tracker(memtracker::singleton(), movie_page_id, sizeof(*this))
602 real_frame_count = 0;
603 freeze_count = 0;
604 clear(*vector.types);
605 *this = vector;
608 frame_vector& frame_vector::operator=(const frame_vector& v)
609 throw(std::bad_alloc)
611 if(this == &v)
612 return *this;
613 uint64_t old_frame_count = real_frame_count;
614 resize(v.frames);
615 clear_cache();
617 //Copy the fields.
618 frame_size = v.frame_size;
619 frames_per_page = v.frames_per_page;
620 types = v.types;
621 real_frame_count = v.real_frame_count;
623 //This can't fail anymore. Copy the raw page contents.
624 size_t pagecount = (frames + frames_per_page - 1) / frames_per_page;
625 for(size_t i = 0; i < pagecount; i++) {
626 page& pg = pages[i];
627 const page& pg2 = v.pages.find(i)->second;
628 pg = pg2;
630 call_framecount_notification(old_frame_count);
631 return *this;
634 void frame_vector::resize(size_t newsize) throw(std::bad_alloc)
636 clear_cache();
637 if(newsize == 0) {
638 clear();
639 } else if(newsize < frames) {
640 //Shrink movie.
641 uint64_t old_frame_count = real_frame_count;
642 for(size_t i = newsize; i < frames; i++)
643 if((*this)[i].sync()) real_frame_count--;
644 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
645 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
646 for(size_t i = pages_needed; i < current_pages; i++)
647 pages.erase(i);
648 //Now zeroize the excess memory.
649 if(newsize < pages_needed * frames_per_page) {
650 size_t offset = frame_size * (newsize % frames_per_page);
651 memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
653 frames = newsize;
654 call_framecount_notification(old_frame_count);
655 } else if(newsize > frames) {
656 //Enlarge movie.
657 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
658 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
659 //Create the needed pages.
660 for(size_t i = current_pages; i < pages_needed; i++) {
661 try {
662 pages[i];
663 } catch(...) {
664 for(size_t i = current_pages; i < pages_needed; i++)
665 if(pages.count(i))
666 pages.erase(i);
667 throw;
670 frames = newsize;
671 //This can use real_frame_count, because the real frame count won't change.
672 call_framecount_notification(real_frame_count);
676 bool frame_vector::compatible(frame_vector& with, uint64_t nframe, const uint32_t* polls)
678 //Types have to match.
679 if(get_types() != with.get_types())
680 return false;
681 const type_set& pset = with.get_types();
682 //If new movie is before first frame, anything with same project_id is compatible.
683 if(nframe == 0)
684 return true;
685 //Scan both movies until frame syncs are seen. Out of bounds reads behave as all neutral but frame
686 //sync done.
687 uint64_t syncs_seen = 0;
688 uint64_t frames_read = 0;
689 size_t old_size = size();
690 size_t new_size = with.size();
691 size_t pagenum = 0;
692 size_t ocomplete_pages = old_size / frames_per_page; //Round DOWN
693 size_t ncomplete_pages = new_size / frames_per_page; //Round DOWN
694 size_t complete_pages = min(ocomplete_pages, ncomplete_pages);
695 while(syncs_seen + frames_per_page < nframe - 1 && pagenum < complete_pages) {
696 //Fast process page. The above condition guarantees that these pages are completely used.
697 auto opagedata = pages[pagenum].content;
698 auto npagedata = with.pages[pagenum].content;
699 size_t pagedataamt = frames_per_page * frame_size;
700 if(memcmp(opagedata, npagedata, pagedataamt))
701 return false;
702 frames_read += frames_per_page;
703 pagenum++;
704 for(size_t i = 0; i < pagedataamt; i += frame_size)
705 if(opagedata[i] & 1) syncs_seen++;
707 while(syncs_seen < nframe - 1) {
708 frame oldc = blank_frame(true), newc = with.blank_frame(true);
709 if(frames_read < old_size)
710 oldc = (*this)[frames_read];
711 if(frames_read < new_size)
712 newc = with[frames_read];
713 if(oldc != newc)
714 return false; //Mismatch.
715 frames_read++;
716 if(newc.sync())
717 syncs_seen++;
719 //We increment the counter one time too many.
720 frames_read--;
721 //Current frame. We need to compare each control up to poll counter.
722 uint64_t readable_old_subframes = 0, readable_new_subframes = 0;
723 uint64_t oldlen = find_next_sync(*this, frames_read);
724 uint64_t newlen = find_next_sync(with, frames_read);
725 if(frames_read < oldlen)
726 readable_old_subframes = oldlen - frames_read;
727 if(frames_read < newlen)
728 readable_new_subframes = newlen - frames_read;
729 //Then rest of the stuff.
730 for(unsigned i = 0; i < pset.indices(); i++) {
731 uint32_t p = polls[i] & 0x7FFFFFFFUL;
732 short ov = 0, nv = 0;
733 for(uint32_t j = 0; j < p; j++) {
734 if(j < readable_old_subframes)
735 ov = (*this)[j + frames_read].axis2(i);
736 if(j < readable_new_subframes)
737 nv = with[j + frames_read].axis2(i);
738 if(ov != nv)
739 return false;
742 return true;
745 uint64_t frame_vector::binary_size() const throw()
747 return size() * get_stride();
750 void frame_vector::save_binary(binarystream::output& stream) const throw(std::runtime_error)
752 uint64_t stride = get_stride();
753 uint64_t pageframes = get_frames_per_page();
754 uint64_t vsize = size();
755 size_t pagenum = 0;
756 while(vsize > 0) {
757 uint64_t count = (vsize > pageframes) ? pageframes : vsize;
758 size_t bytes = count * stride;
759 const unsigned char* content = get_page_buffer(pagenum++);
760 stream.raw(content, bytes);
761 vsize -= count;
765 void frame_vector::load_binary(binarystream::input& stream) throw(std::bad_alloc, std::runtime_error)
767 uint64_t stride = get_stride();
768 uint64_t pageframes = get_frames_per_page();
769 uint64_t vsize = 0;
770 size_t pagenum = 0;
771 uint64_t pagesize = stride * pageframes;
772 while(stream.get_left()) {
773 resize(vsize + pageframes);
774 unsigned char* contents = get_page_buffer(pagenum++);
775 uint64_t gcount = min(pagesize, stream.get_left());
776 stream.raw(contents, gcount);
777 vsize += (gcount / stride);
779 resize(vsize);
780 recount_frames();
783 void frame_vector::swap_data(frame_vector& v) throw()
785 uint64_t toldsize = real_frame_count;
786 uint64_t voldsize = v.real_frame_count;
787 std::swap(pages, v.pages);
788 std::swap(frames_per_page, v.frames_per_page);
789 std::swap(frame_size, v.frame_size);
790 std::swap(frames, v.frames);
791 std::swap(types, v.types);
792 std::swap(cache_page_num, v.cache_page_num);
793 std::swap(cache_page, v.cache_page);
794 std::swap(real_frame_count, v.real_frame_count);
795 if(!freeze_count)
796 call_framecount_notification(toldsize);
797 if(!v.freeze_count)
798 v.call_framecount_notification(voldsize);
801 int64_t frame_vector::find_frame(uint64_t n)
803 if(!n) return -1;
804 uint64_t stride = get_stride();
805 uint64_t pageframes = get_frames_per_page();
806 uint64_t vsize = size();
807 size_t pagenum = 0;
808 while(vsize > 0) {
809 uint64_t count = (vsize > pageframes) ? pageframes : vsize;
810 const unsigned char* content = get_page_buffer(pagenum++);
811 size_t offset = 0;
812 for(unsigned i = 0; i < count; i++) {
813 if(frame::sync(content + offset)) n--;
814 if(n == 0) return (pagenum - 1) * pageframes + i;
815 offset += stride;
817 vsize -= count;
819 return -1;
822 frame::frame() throw()
824 memset(memory, 0, sizeof(memory));
825 backing = memory;
826 types = &dummytypes();
827 host = NULL;
830 unsigned controller::analog_actions() const
832 unsigned r = 0, s = 0;
833 for(unsigned i = 0; i < buttons.size(); i++) {
834 if(buttons[i].shadow)
835 continue;
836 switch(buttons[i].type) {
837 case button::TYPE_AXIS:
838 case button::TYPE_RAXIS:
839 case button::TYPE_LIGHTGUN:
840 r++;
841 break;
842 case button::TYPE_TAXIS:
843 s++;
844 break;
845 case button::TYPE_NULL:
846 case button::TYPE_BUTTON:
850 return (r + 1)/ 2 + s;
853 std::pair<unsigned, unsigned> controller::analog_action(unsigned k) const
855 unsigned x1 = std::numeric_limits<unsigned>::max();
856 unsigned x2 = std::numeric_limits<unsigned>::max();
857 unsigned r = 0;
858 bool second = false;
859 bool selecting = false;
860 for(unsigned i = 0; i < buttons.size(); i++) {
861 if(buttons[i].shadow)
862 continue;
863 switch(buttons[i].type) {
864 case button::TYPE_AXIS:
865 case button::TYPE_RAXIS:
866 case button::TYPE_LIGHTGUN:
867 if(selecting) {
868 x2 = i;
869 goto out;
871 if(r == k && !second) {
872 //This and following.
873 x1 = i;
874 selecting = true;
876 if(!second)
877 r++;
878 second = !second;
879 break;
880 case button::TYPE_TAXIS:
881 if(selecting)
882 break;
883 if(r == k) {
884 x1 = i;
885 goto out;
887 r++;
888 break;
889 case button::TYPE_NULL:
890 case button::TYPE_BUTTON:
894 out:
895 return std::make_pair(x1, x2);
898 namespace
900 std::string macro_field_as_string(const JSON::node& parent, const std::string& path)
902 const JSON::node& n = parent.follow(path);
903 if(n.type() != JSON::string)
904 (stringfmt() << "Expected string as field '" << path << "'").throwex();
905 return n.as_string8();
908 bool macro_field_as_boolean(const JSON::node& parent, const std::string& path)
910 const JSON::node& n = parent.follow(path);
911 if(n.type() != JSON::boolean)
912 (stringfmt() << "Expected boolean as field '" << path << "'").throwex();
913 return n.as_bool();
916 const JSON::node& macro_field_as_array(const JSON::node& parent, const std::string& path)
918 const JSON::node& n = parent.follow(path);
919 if(n.type() != JSON::array)
920 (stringfmt() << "Expected array as field '" << path << "'").throwex();
921 return n;
925 macro_data::macro_data(const std::string& spec, const JSON::node& desc, unsigned inum)
927 _descriptor = desc;
928 unsigned btnnum = 0;
929 std::map<std::string, unsigned> symbols;
930 if(desc.type() != JSON::array)
931 (stringfmt() << "Expected controller descriptor " << (inum + 1) << " to be an array");
932 for(auto i = desc.begin(); i != desc.end(); ++i) {
933 if(i->type() == JSON::string) {
934 symbols[i->as_string8()] = btnnum++;
935 btnmap.push_back(i.index());
936 } else if(i->type() == JSON::number) {
937 uint64_t anum = i->as_uint();
938 if(anum > aaxes.size())
939 (stringfmt() << "Descriptor axis number " << anum << " out of range in descriptor "
940 << (inum + 1)).throwex();
941 else if(anum == aaxes.size())
942 aaxes.push_back(std::make_pair(i.index(), std::numeric_limits<unsigned>::max()));
943 else
944 aaxes[anum].second = i.index();
945 } else
946 (stringfmt() << "Controller descriptor " << (inum + 1) << " contains element of unknown"
947 << "kind").throwex();
949 buttons = symbols.size();
950 orig = spec;
951 enabled = true;
952 autoterminate = false;
954 std::deque<size_t> stack;
955 bool in_sparen = false;
956 bool first = true;
957 bool btn_token = false;
958 bool btn_token_next = false;
959 size_t last_bit = 0;
960 size_t last_size = 0;
961 size_t astride = aaxes.size();
962 size_t stride = get_stride();
963 size_t idx = 0;
964 size_t len = spec.length();
965 try {
966 while(idx < len) {
967 btn_token = btn_token_next;
968 btn_token_next = false;
969 unsigned char ch = spec[idx];
970 if(autoterminate)
971 throw std::runtime_error("Asterisk must be the last thing");
972 if(ch == '(') {
973 if(in_sparen)
974 throw std::runtime_error("Parentheses in square brackets not allowed");
975 stack.push_back(data.size());
976 } else if(ch == ')') {
977 if(in_sparen)
978 throw std::runtime_error("Parentheses in square brackets not allowed");
979 if(stack.empty())
980 throw std::runtime_error("Unmatched right parenthesis");
981 size_t x = stack.back();
982 stack.pop_back();
983 last_size = (data.size() - x) / stride;
984 } else if(ch == '*') {
985 autoterminate = true;
986 } else if(ch == '?') {
987 if(!btn_token)
988 throw std::runtime_error("? needs button to apply to");
989 if(!in_sparen)
990 throw std::runtime_error("? needs to be in brackets");
991 data[data.size() - stride + last_bit] |= 2;
992 } else if(ch == '[') {
993 if(in_sparen)
994 throw std::runtime_error("Nested square brackets not allowed");
995 in_sparen = true;
996 data.resize(data.size() + stride);
997 adata.resize(adata.size() + astride);
998 last_size = 1;
999 } else if(ch == ']') {
1000 if(!in_sparen)
1001 throw std::runtime_error("Unmatched right square bracket");
1002 in_sparen = false;
1003 } else if(ch == '.') {
1004 if(!in_sparen) {
1005 data.resize(data.size() + stride);
1006 adata.resize(adata.size() + astride);
1007 last_size = 1;
1009 } else if(spec[idx] >= '0' && spec[idx] <= '9') {
1010 size_t rep = 0;
1011 unsigned i = 0;
1012 while(spec[idx + i] >= '0' && spec[idx + i] <= '9') {
1013 rep = 10 * rep + (spec[idx + i] - '0');
1014 i++;
1016 if(in_sparen) {
1017 //This has special meaning: Axis transform.
1018 //Rep is the axis pair to operate on.
1019 if(spec[idx + i] != ':')
1020 throw std::runtime_error("Expected ':' in axis transform");
1021 size_t sep = i;
1022 while(idx + i < len && spec[idx + i] != '@')
1023 i++;
1024 if(idx + i >= len)
1025 throw std::runtime_error("Expected '@' in axis transform");
1026 std::string aexpr = spec.substr(idx + sep + 1, i - sep - 1);
1027 if(rep >= astride)
1028 throw std::runtime_error("Axis transform refers to invalid axis");
1029 adata[adata.size() - astride + rep] = axis_transform(aexpr);
1030 i++;
1031 } else {
1032 if(first)
1033 throw std::runtime_error("Repeat not allowed without frame to "
1034 "repeat");
1035 size_t o = data.size();
1036 size_t ao = adata.size();
1037 data.resize(o + (rep - 1) * last_size * stride);
1038 adata.resize(ao + (rep - 1) * last_size * astride);
1039 for(unsigned i = 1; i < rep; i++) {
1040 memcpy(&data[o + (i - 1) * last_size * stride], &data[o - last_size *
1041 stride], last_size * stride);
1042 memcpy(&data[ao + (i - 1) * last_size * astride], &data[ao -
1043 last_size * astride], last_size * astride);
1045 last_size = last_size * rep;
1047 idx = idx + (i - 1);
1048 } else { //Symbol.
1049 bool found = false;
1050 for(auto k : symbols) {
1051 std::string key = k.first;
1052 size_t j;
1053 for(j = 0; idx + j < len && j < key.length(); j++)
1054 if(spec[idx + j] != key[j])
1055 break;
1056 if(j == key.length()) {
1057 idx += key.length() - 1;
1058 found = true;
1059 if(!in_sparen) {
1060 data.resize(data.size() + stride);
1061 adata.resize(adata.size() + astride);
1063 last_bit = k.second;
1064 data[data.size() - stride + k.second] |= 1;
1065 if(!in_sparen)
1066 last_size = 1;
1069 if(!found)
1070 throw std::runtime_error("Unknown character or button");
1071 btn_token_next = true;
1073 idx++;
1074 first = false;
1076 if(in_sparen)
1077 throw std::runtime_error("Unmatched left square bracket");
1078 if(!stack.empty())
1079 throw std::runtime_error("Unmatched left parenthesis");
1080 } catch(std::exception& e) {
1081 (stringfmt() << "Error parsing macro for controller " << (inum + 1) << ": " << e.what()).throwex();
1085 bool macro_data::syntax_check(const std::string& spec, const JSON::node& desc)
1087 unsigned buttons = 0;
1088 size_t astride = 0;
1089 if(desc.type() != JSON::array)
1090 return false;
1091 for(auto i = desc.begin(); i != desc.end(); ++i) {
1092 if(i->type() == JSON::string)
1093 buttons++;
1094 else if(i->type() == JSON::number) {
1095 uint64_t anum = i->as_uint();
1096 if(anum > astride)
1097 return false;
1098 else if(anum == astride)
1099 astride++;
1100 } else
1101 return false;
1103 bool autoterminate = false;
1104 size_t depth = 0;
1105 bool in_sparen = false;
1106 bool first = true;
1107 bool btn_token = false;
1108 bool btn_token_next = false;
1109 size_t idx = 0;
1110 size_t len = spec.length();
1111 while(idx < len) {
1112 btn_token = btn_token_next;
1113 btn_token_next = false;
1114 unsigned char ch = spec[idx];
1115 if(autoterminate)
1116 return false;
1117 if(ch == '(') {
1118 if(in_sparen)
1119 return false;
1120 depth++;
1121 } else if(ch == ')') {
1122 if(in_sparen)
1123 return false;
1124 if(!depth)
1125 return false;
1126 depth--;
1127 } else if(ch == '*') {
1128 autoterminate = true;
1129 } else if(ch == '?') {
1130 if(!btn_token || !in_sparen)
1131 return false;
1132 } else if(ch == '[') {
1133 if(in_sparen)
1134 return false;
1135 in_sparen = true;
1136 } else if(ch == ']') {
1137 if(!in_sparen)
1138 return false;
1139 in_sparen = false;
1140 } else if(ch == '.') {
1141 } else if(spec[idx] >= '0' && spec[idx] <= '9') {
1142 size_t rep = 0;
1143 unsigned i = 0;
1144 while(spec[idx + i] >= '0' && spec[idx + i] <= '9') {
1145 rep = 10 * rep + (spec[idx + i] - '0');
1146 i++;
1148 if(in_sparen) {
1149 //This has special meaning: Axis transform.
1150 //Rep is the axis pair to operate on.
1151 if(spec[idx + i] != ':')
1152 return false;
1153 size_t sep = i;
1154 while(idx + i < len && spec[idx + i] != '@')
1155 i++;
1156 if(idx + i >= len)
1157 return false;
1158 if(rep >= astride)
1159 return false;
1160 try {
1161 std::string aexpr = spec.substr(idx + sep + 1, i - sep - 1);
1162 axis_transform x(aexpr);
1163 } catch(...) {
1164 return false;
1166 i++;
1167 } else {
1168 if(first)
1169 return false;
1171 idx = idx + (i - 1);
1172 } else { //Symbol.
1173 bool found = false;
1174 for(auto i = desc.begin(); i != desc.end(); ++i) {
1175 if(i->type() != JSON::string)
1176 continue;
1177 std::string key = i->as_string8();
1178 size_t j;
1179 for(j = 0; idx + j < len && j < key.length(); j++)
1180 if(spec[idx + j] != key[j])
1181 break;
1182 if(j == key.length()) {
1183 idx += key.length() - 1;
1184 found = true;
1187 if(!found)
1188 return false;
1189 btn_token_next = true;
1191 idx++;
1192 first = false;
1194 if(in_sparen)
1195 return false;
1196 if(depth)
1197 return false;
1198 return true;
1201 void macro_data::write(frame& frame, unsigned port, unsigned controller_n, int64_t nframe,
1202 apply_mode amode)
1204 if(!enabled)
1205 return;
1206 if(autoterminate && (nframe < 0 || nframe >= (int64_t)get_frames()))
1207 return;
1208 if(nframe < 0)
1209 nframe += ((-nframe / get_frames()) + 3) * get_frames();
1210 nframe %= get_frames();
1211 for(size_t i = 0; i < buttons; i++) {
1212 unsigned lb = btnmap[i];
1213 unsigned st = data[nframe * get_stride() + i];
1214 if(st == 3)
1215 st = macro_random_bit();
1216 if(st == 1)
1217 switch(amode) {
1218 case AM_OVERWRITE:
1219 case AM_OR:
1220 frame.axis3(port, controller_n, lb, 1);
1221 break;
1222 case AM_XOR:
1223 frame.axis3(port, controller_n, lb, frame.axis3(port, controller_n, lb) ^ 1);
1224 break;
1226 else
1227 switch(amode) {
1228 case AM_OVERWRITE:
1229 frame.axis3(port, controller_n, lb, 0);
1230 break;
1231 case AM_OR:
1232 case AM_XOR:
1236 const controller* _ctrl = frame.porttypes().port_type(port).controller_info->get(controller_n);
1237 if(!_ctrl)
1238 return;
1239 size_t abuttons = aaxes.size();
1240 for(size_t i = 0; i < abuttons; i++) {
1241 unsigned ax = aaxes[i].first;
1242 unsigned ay = aaxes[i].second;
1243 if(ay != std::numeric_limits<unsigned>::max()) {
1244 if(ax > _ctrl->buttons.size()) continue;
1245 if(ay > _ctrl->buttons.size()) continue;
1246 auto g = adata[nframe * abuttons + i].transform(_ctrl->buttons[ax], _ctrl->buttons[ay],
1247 frame.axis3(port, controller_n, ax), frame.axis3(port, controller_n, ay));
1248 frame.axis3(port, controller_n, ax, g.first);
1249 frame.axis3(port, controller_n, ay, g.second);
1250 } else {
1251 if(ax > _ctrl->buttons.size()) continue;
1252 int16_t g = adata[nframe * abuttons + i].transform(_ctrl->buttons[ax],
1253 frame.axis3(port, controller_n, ax));
1254 frame.axis3(port, controller_n, ax, g);
1259 std::string macro_data::dump(const controller& ctrl)
1261 std::ostringstream o;
1262 for(size_t i = 0; i < get_frames(); i++) {
1263 o << "[";
1264 for(size_t j = 0; j < aaxes.size(); j++) {
1265 macro_data::axis_transform& t = adata[i * aaxes.size() + j];
1266 o << j << ":";
1267 o << t.coeffs[0] << "," << t.coeffs[1] << "," << t.coeffs[2] << ",";
1268 o << t.coeffs[3] << "," << t.coeffs[4] << "," << t.coeffs[5] << "@";
1270 for(size_t j = 0; j < buttons && j < ctrl.buttons.size(); j++) {
1271 unsigned st = data[i * get_stride() + j];
1272 if(ctrl.buttons[j].macro == "")
1273 continue;
1274 if(st == 1)
1275 o << ctrl.buttons[j].macro;
1276 if(st == 3)
1277 o << ctrl.buttons[j].macro << "?";
1279 o << "]";
1281 if(autoterminate)
1282 o << "*";
1283 return o.str();
1286 void macro::write(frame& frame, int64_t nframe)
1288 for(auto& i : macros) {
1289 unsigned port;
1290 unsigned controller;
1291 try {
1292 auto g = frame.porttypes().lcid_to_pcid(i.first);
1293 port = g.first;
1294 controller = g.second;
1295 } catch(...) {
1296 continue;
1298 i.second.write(frame, port, controller, nframe, amode);
1302 int16_t macro_data::axis_transform::transform(const button& b, int16_t v)
1304 return scale_axis(b, coeffs[0] * unscale_axis(b, v) + coeffs[4]);
1307 std::pair<int16_t, int16_t> macro_data::axis_transform::transform(const button& b1,
1308 const button& b2, int16_t v1, int16_t v2)
1310 double x, y, u, v, au, av, s;
1311 x = unscale_axis(b1, v1);
1312 y = unscale_axis(b2, v2);
1313 u = coeffs[0] * x + coeffs[1] * y + coeffs[4];
1314 v = coeffs[2] * x + coeffs[3] * y + coeffs[5];
1315 au = abs(u);
1316 av = abs(v);
1317 s = max(max(au, 1.0), max(av, 1.0));
1318 //If u and v exceed nominal range of [-1,1], those need to be projected to the edge.
1319 if(s > 1) {
1320 u /= s;
1321 v /= s;
1323 auto g = std::make_pair(scale_axis(b1, u), scale_axis(b2, v));
1324 return g;
1327 double macro_data::axis_transform::unscale_axis(const button& b, int16_t v)
1329 if(b.centers) {
1330 int32_t center = ((int32_t)b.rmin + (int32_t)b.rmax) / 2;
1331 if(v <= b.rmin)
1332 return -1;
1333 if(v < center)
1334 return -(center - (double)v) / (center - b.rmin);
1335 if(v == center)
1336 return 0;
1337 if(v < b.rmax)
1338 return ((double)v - center) / (b.rmax - center);
1339 return 1;
1340 } else {
1341 if(v <= b.rmin)
1342 return 0;
1343 if(v >= b.rmax)
1344 return 1;
1345 return ((double)v - b.rmin) / (b.rmax - b.rmin);
1349 int16_t macro_data::axis_transform::scale_axis(const button& b, double v)
1351 if(b.centers) {
1352 int32_t center = ((int32_t)b.rmin + (int32_t)b.rmax) / 2;
1353 if(v == 0)
1354 return center;
1355 if(v < 0) {
1356 double v2 = v * (center - b.rmin) + center;
1357 if(v2 < b.rmin)
1358 return b.rmin;
1359 return v2;
1361 double v2 = v * (b.rmax - center) + center;
1362 if(v2 > b.rmax)
1363 return b.rmax;
1364 return v2;
1365 } else {
1366 double v2 = v * (b.rmax - b.rmin) + b.rmin;
1367 if(v2 < b.rmin)
1368 return b.rmin;
1369 if(v2 > b.rmax)
1370 return b.rmax;
1371 return v2;
1375 namespace
1377 std::complex<double> parse_complex(const std::string& expr)
1379 regex_results r;
1380 if(r = regex("\\((.*),(.*)\\)", expr)) {
1381 //Real,Imaginary.
1382 return std::complex<double>(parse_value<double>(r[1]), parse_value<double>(r[2]));
1383 } else if(r = regex("\\((.*)<(.*)\\)", expr)) {
1384 return std::polar(parse_value<double>(r[1]), parse_value<double>(r[2]) * M_PI / 180);
1385 } else {
1386 return std::complex<double>(parse_value<double>(expr), 0.0);
1391 macro_data::axis_transform::axis_transform(const std::string& expr)
1393 regex_results r;
1394 if(r = regex("\\*(.*)\\+(.*)", expr)) {
1395 //Affine transform.
1396 std::complex<double> a = parse_complex(r[1]);
1397 std::complex<double> b = parse_complex(r[2]);
1398 coeffs[0] = a.real();
1399 coeffs[1] = -a.imag();
1400 coeffs[2] = a.imag();
1401 coeffs[3] = a.real();
1402 coeffs[4] = b.real();
1403 coeffs[5] = b.imag();
1404 } else if(r = regex("\\*(.*)", expr)) {
1405 //Linear transform.
1406 std::complex<double> a = parse_complex(r[1]);
1407 coeffs[0] = a.real();
1408 coeffs[1] = -a.imag();
1409 coeffs[2] = a.imag();
1410 coeffs[3] = a.real();
1411 coeffs[4] = 0;
1412 coeffs[5] = 0;
1413 } else if(r = regex("\\+(.*)", expr)) {
1414 //Relative
1415 std::complex<double> b = parse_complex(r[1]);
1416 coeffs[0] = 1;
1417 coeffs[1] = 0;
1418 coeffs[2] = 0;
1419 coeffs[3] = 1;
1420 coeffs[4] = b.real();
1421 coeffs[5] = b.imag();
1422 } else if(r = regex("(.*),(.*),(.*),(.*),(.*),(.*)", expr)) {
1423 //Full affine.
1424 coeffs[0] = parse_value<double>(r[1]);
1425 coeffs[1] = parse_value<double>(r[2]);
1426 coeffs[2] = parse_value<double>(r[3]);
1427 coeffs[3] = parse_value<double>(r[4]);
1428 coeffs[4] = parse_value<double>(r[5]);
1429 coeffs[5] = parse_value<double>(r[6]);
1430 } else {
1431 //Absolute.
1432 std::complex<double> b = parse_complex(expr);
1433 coeffs[0] = 0;
1434 coeffs[1] = 0;
1435 coeffs[2] = 0;
1436 coeffs[3] = 0;
1437 coeffs[4] = b.real();
1438 coeffs[5] = b.imag();
1442 JSON::node macro::serialize()
1444 JSON::node v(JSON::object);
1445 switch(amode) {
1446 case macro_data::AM_OVERWRITE: v.insert("mode", JSON::s("overwrite")); break;
1447 case macro_data::AM_OR: v.insert("mode", JSON::s("or")); break;
1448 case macro_data::AM_XOR: v.insert("mode", JSON::s("xor")); break;
1450 JSON::node& c = v.insert("data", JSON::array());
1451 for(auto& i : macros) {
1452 while(i.first > c.index_count())
1453 c.append(JSON::n());
1454 i.second.serialize(c.append(JSON::n()));
1456 return v;
1459 void macro_data::serialize(JSON::node& v)
1461 v = JSON::object();
1462 v.insert("enable", JSON::b(enabled));
1463 v.insert("expr", JSON::s(orig));
1464 v.insert("desc", _descriptor);
1467 JSON::node macro_data::make_descriptor(const controller& ctrl)
1469 JSON::node n(JSON::array);
1470 for(size_t i = 0; i < ctrl.buttons.size(); i++) {
1471 if(ctrl.buttons[i].macro != "")
1472 n.append(JSON::s(ctrl.buttons[i].macro));
1473 else
1474 n.append(JSON::n()); //Placeholder.
1476 for(size_t i = 0; i < ctrl.analog_actions(); i++) {
1477 auto g = ctrl.analog_action(i);
1478 n.index(g.first) = JSON::u(i);
1479 if(g.second != std::numeric_limits<unsigned>::max())
1480 n.index(g.second) = JSON::u(i);
1482 return n;
1485 macro::macro(const JSON::node& v)
1487 if(v.type() != JSON::object)
1488 throw std::runtime_error("Expected macro to be JSON object");
1489 std::string mode = macro_field_as_string(v, "mode");
1490 if(mode == "overwrite") amode = macro_data::AM_OVERWRITE;
1491 else if(mode == "or") amode = macro_data::AM_OR;
1492 else if(mode == "xor") amode = macro_data::AM_XOR;
1493 else (stringfmt() << "Unknown button mode '" << mode << "'").throwex();
1494 const JSON::node& c = macro_field_as_array(v, "data");
1495 for(auto i = c.begin(); i != c.end(); ++i) {
1496 if(i->type() == JSON::object)
1497 macros[i.index()] = macro_data(*i, i.index());
1498 else
1499 (stringfmt() << "Expected object as field 'data/" << i.index() << "'").throwex();
1503 macro_data::macro_data(const JSON::node& v, unsigned i)
1504 : macro_data(macro_field_as_string(v, "expr"), macro_field_as_array(v, "desc"), i)
1506 enabled = macro_field_as_boolean(v, "enable");