Allow button display symbols to be Unicode characters
[lsnes.git] / src / library / controller-data.cpp
blobb534ab454c37bd4fb83450c2491719b481d525d3
1 #include "controller-data.hpp"
2 #include "threadtypes.hpp"
3 #include "minmax.hpp"
4 #include "globalwrap.hpp"
5 #include <iostream>
6 #include <list>
8 namespace
10 const char* basecontrol_chars = "F";
12 port_controller_button* null_buttons[] = {};
13 port_controller simple_controller = {"(system)", "system", 0, null_buttons};
14 port_controller* simple_controllers[] = {&simple_controller};
15 port_controller_set simple_port = {1, simple_controllers};
17 struct porttype_basecontrol : public port_type
19 porttype_basecontrol() : port_type("basecontrol", "basecontrol", 999998, 1)
21 write = [](unsigned char* buffer, unsigned idx, unsigned ctrl, short x) -> void {
22 if(idx > 0 || ctrl > 0) return;
23 buffer[0] = x ? 1 : 0;
25 read = [](const unsigned char* buffer, unsigned idx, unsigned ctrl) -> short {
26 if(idx > 0 || ctrl > 0) return 0;
27 return buffer[0] ? 1 : 0;
29 serialize = [](const unsigned char* buffer, char* textbuf) -> size_t {
30 textbuf[0] = buffer[0] ? 'F' : '-';
31 textbuf[1] = '\0';
32 return 1;
34 deserialize = [](unsigned char* buffer, const char* textbuf) -> size_t {
35 size_t ptr = 0;
36 buffer[0] = 0;
37 if(read_button_value(textbuf, ptr))
38 buffer[0] = 1;
39 skip_rest_of_field(textbuf, ptr, false);
40 return ptr;
42 legal = [](unsigned port) -> int { return (port == 0); };
43 controller_info = &simple_port;
44 used_indices = [](unsigned controller) -> unsigned { return (controller == 0) ? 1 : 0; };
49 port_type& get_default_system_port_type()
51 static porttype_basecontrol x;
52 return x;
55 port_type::port_type(const std::string& iname, const std::string& _hname, unsigned id,
56 size_t ssize) throw(std::bad_alloc)
57 : hname(_hname), storage_size(ssize), name(iname), pt_id(id)
61 port_type::~port_type() throw()
65 bool port_type::is_present(unsigned controller) const throw()
67 return controller_info->controller_count > controller;
70 namespace
72 size_t dummy_offset = 0;
73 port_type* dummy_type = &get_default_system_port_type();
74 unsigned dummy_index = 0;
75 struct binding
77 std::vector<port_type*> types;
78 port_type_set* stype;
79 bool matches(const std::vector<class port_type*>& x)
81 if(x.size() != types.size())
82 return false;
83 for(size_t i = 0; i < x.size(); i++)
84 if(x[i] != types[i])
85 return false;
86 return true;
89 std::list<binding>& bindings()
91 static std::list<binding> x;
92 return x;
96 port_type_set::port_type_set() throw()
99 port_offsets = &dummy_offset;
100 port_types = &dummy_type;
101 port_count = 1;
102 total_size = 1;
103 _indices.resize(1);
104 _indices[0].valid = true;
105 _indices[0].port = 0;
106 _indices[0].controller = 0;
107 _indices[0].control = 0;
109 port_multiplier = 1;
110 controller_multiplier = 1;
111 indices_size = 1;
112 indices_tab = &dummy_index;
115 port_type_set& port_type_set::make(std::vector<class port_type*> types, struct port_index_map control_map)
116 throw(std::bad_alloc, std::runtime_error)
118 for(auto i : bindings())
119 if(i.matches(types))
120 return *(i.stype);
121 //Not found, create new.
122 port_type_set& ret = *new port_type_set(types, control_map);
123 binding b;
124 b.types = types;
125 b.stype = &ret;
126 bindings().push_back(b);
127 return ret;
130 port_type_set::port_type_set(std::vector<class port_type*> types, struct port_index_map control_map)
132 port_count = types.size();
133 //Verify legality of port types.
134 for(size_t i = 0; i < port_count; i++)
135 if(!types[i] || !types[i]->legal(i))
136 throw std::runtime_error("Illegal port types");
137 //Count maximum number of controller indices to determine the controller multiplier.
138 controller_multiplier = 1;
139 for(size_t i = 0; i < port_count; i++)
140 for(unsigned j = 0; j < types[i]->controller_info->controller_count; j++)
141 controller_multiplier = max(controller_multiplier, (size_t)types[i]->used_indices(j));
142 //Count maximum number of controllers to determine the port multiplier.
143 port_multiplier = 1;
144 for(size_t i = 0; i < port_count; i++)
145 port_multiplier = max(port_multiplier, controller_multiplier *
146 (size_t)types[i]->controller_info->controller_count);
147 //Allocate the per-port tables.
148 port_offsets = new size_t[types.size()];
149 port_types = new class port_type*[types.size()];
150 //Determine the total size and offsets.
151 size_t offset = 0;
152 for(size_t i = 0; i < port_count; i++) {
153 port_offsets[i] = offset;
154 offset += types[i]->storage_size;
155 port_types[i] = types[i];
157 total_size = offset;
158 //Determine the index size and allocate it.
159 indices_size = port_multiplier * port_count;
160 indices_tab = new unsigned[indices_size];
161 for(size_t i = 0; i < indices_size; i++)
162 indices_tab[i] = 0xFFFFFFFFUL;
163 //Copy the index data (and reverse it).
164 controllers = control_map.logical_map;
165 legacy_pcids = control_map.pcid_map;
166 _indices = control_map.indices;
167 for(size_t j = 0; j < _indices.size(); j++) {
168 auto& i = _indices[j];
169 if(i.valid)
170 indices_tab[i.port * port_multiplier + i.controller * controller_multiplier + i.control] = j;
174 short read_axis_value(const char* buf, size_t& idx) throw()
176 char ch;
177 //Skip ws.
178 while(is_nonterminator(buf[idx])) {
179 char ch = buf[idx];
180 if(ch != ' ' && ch != '\t')
181 break;
182 idx++;
184 //Read the sign if any.
185 ch = buf[idx];
186 if(!is_nonterminator(ch))
187 return 0;
188 bool negative = false;
189 if(ch == '-') {
190 negative = true;
191 idx++;
193 if(ch == '+')
194 idx++;
196 //Read numeric value.
197 int numval = 0;
198 while(is_nonterminator(buf[idx]) && isdigit(static_cast<unsigned char>(ch = buf[idx]))) {
199 numval = numval * 10 + (ch - '0');
200 idx++;
202 if(negative)
203 numval = -numval;
205 return static_cast<short>(numval);
208 namespace
210 port_type_set& dummytypes()
212 static port_type_set x;
213 return x;
216 size_t writeu32val(char32_t* buf, int val)
218 char c[12];
219 size_t i;
220 sprintf(c, "%d", val);
221 for(i = 0; c[i]; i++)
222 buf[i] = c[i];
223 return i;
227 void controller_frame::display(unsigned port, unsigned controller, char32_t* buf) throw()
229 if(port >= types->ports()) {
230 //Bad port.
231 *buf = '\0';
232 return;
234 uint8_t* backingmem = backing + types->port_offset(port);
235 const port_type& ptype = types->port_type(port);
236 if(controller >= ptype.controller_info->controller_count) {
237 //Bad controller.
238 *buf = '\0';
239 return;
241 const port_controller* pc = ptype.controller_info->controllers[controller];
242 bool need_space = false;
243 short val;
244 for(unsigned i = 0; i < pc->button_count; i++) {
245 const port_controller_button* pcb = pc->buttons[i];
246 if(need_space && pcb->type != port_controller_button::TYPE_NULL) {
247 need_space = false;
248 *(buf++) = ' ';
250 switch(pcb->type) {
251 case port_controller_button::TYPE_NULL:
252 break;
253 case port_controller_button::TYPE_BUTTON:
254 *(buf++) = ptype.read(backingmem, controller, i) ? pcb->symbol : U'-';
255 break;
256 case port_controller_button::TYPE_AXIS:
257 case port_controller_button::TYPE_RAXIS:
258 case port_controller_button::TYPE_TAXIS:
259 val = ptype.read(backingmem, controller, i);
260 buf += writeu32val(buf, val);
261 need_space = true;
262 break;
265 *buf = '\0';
268 pollcounter_vector::pollcounter_vector() throw(std::bad_alloc)
270 types = &dummytypes();
271 ctrs = new uint32_t[types->indices()];
272 clear();
275 pollcounter_vector::pollcounter_vector(const port_type_set& p) throw(std::bad_alloc)
277 types = &p;
278 ctrs = new uint32_t[types->indices()];
279 clear();
282 pollcounter_vector::pollcounter_vector(const pollcounter_vector& p) throw(std::bad_alloc)
284 ctrs = new uint32_t[p.types->indices()];
285 types = p.types;
286 memcpy(ctrs, p.ctrs, sizeof(uint32_t) * p.types->indices());
289 pollcounter_vector& pollcounter_vector::operator=(const pollcounter_vector& p) throw(std::bad_alloc)
291 if(this == &p)
292 return *this;
293 uint32_t* n = new uint32_t[p.types->indices()];
294 types = p.types;
295 memcpy(n, p.ctrs, sizeof(uint32_t) * p.types->indices());
296 delete[] ctrs;
297 ctrs = n;
298 return *this;
301 pollcounter_vector::~pollcounter_vector() throw()
303 delete[] ctrs;
306 void pollcounter_vector::clear() throw()
308 memset(ctrs, 0, sizeof(uint32_t) * types->indices());
311 void pollcounter_vector::set_all_DRDY() throw()
313 for(size_t i = 0; i < types->indices(); i++)
314 ctrs[i] |= 0x80000000UL;
317 void pollcounter_vector::clear_DRDY(unsigned idx) throw()
319 ctrs[idx] &= 0x7FFFFFFFUL;
322 bool pollcounter_vector::get_DRDY(unsigned idx) throw()
324 return ((ctrs[idx] & 0x80000000UL) != 0);
327 bool pollcounter_vector::has_polled() throw()
329 uint32_t res = 0;
330 for(size_t i = 0; i < types->indices() ; i++)
331 res |= ctrs[i];
332 return ((res & 0x7FFFFFFFUL) != 0);
335 uint32_t pollcounter_vector::get_polls(unsigned idx) throw()
337 return ctrs[idx] & 0x7FFFFFFFUL;
340 uint32_t pollcounter_vector::increment_polls(unsigned idx) throw()
342 uint32_t x = ctrs[idx] & 0x7FFFFFFFUL;
343 ++ctrs[idx];
344 return x;
347 uint32_t pollcounter_vector::max_polls() throw()
349 uint32_t max = 0;
350 for(unsigned i = 0; i < types->indices(); i++) {
351 uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL;
352 max = (max < tmp) ? tmp : max;
354 return max;
357 void pollcounter_vector::save_state(std::vector<uint32_t>& mem) throw(std::bad_alloc)
359 mem.resize(types->indices());
360 //Compatiblity fun.
361 for(size_t i = 0; i < types->indices(); i++)
362 mem[i] = ctrs[i];
365 void pollcounter_vector::load_state(const std::vector<uint32_t>& mem) throw()
367 for(size_t i = 0; i < types->indices(); i++)
368 ctrs[i] = mem[i];
371 bool pollcounter_vector::check(const std::vector<uint32_t>& mem) throw()
373 return (mem.size() == types->indices());
377 controller_frame::controller_frame(const port_type_set& p) throw(std::runtime_error)
379 memset(memory, 0, sizeof(memory));
380 backing = memory;
381 types = &p;
384 controller_frame::controller_frame(unsigned char* mem, const port_type_set& p) throw(std::runtime_error)
386 if(!mem)
387 throw std::runtime_error("NULL backing memory not allowed");
388 memset(memory, 0, sizeof(memory));
389 backing = mem;
390 types = &p;
393 controller_frame::controller_frame(const controller_frame& obj) throw()
395 memset(memory, 0, sizeof(memory));
396 backing = memory;
397 types = obj.types;
398 memcpy(backing, obj.backing, types->size());
401 controller_frame& controller_frame::operator=(const controller_frame& obj) throw(std::runtime_error)
403 if(backing != memory && types != obj.types)
404 throw std::runtime_error("Port types do not match");
405 types = obj.types;
406 memcpy(backing, obj.backing, types->size());
407 return *this;
410 size_t controller_frame_vector::walk_helper(size_t frame, bool sflag) throw()
412 size_t ret = sflag ? frame : 0;
413 if(frame >= frames)
414 return ret;
415 frame++;
416 ret++;
417 size_t page = frame / frames_per_page;
418 size_t offset = frame_size * (frame % frames_per_page);
419 size_t index = frame % frames_per_page;
420 if(cache_page_num != page) {
421 cache_page = &pages[page];
422 cache_page_num = page;
424 while(frame < frames) {
425 if(index == frames_per_page) {
426 page++;
427 cache_page = &pages[page];
428 cache_page_num = page;
430 if(controller_frame::sync(cache_page->content + offset))
431 break;
432 index++;
433 offset += frame_size;
434 frame++;
435 ret++;
437 return ret;
440 size_t controller_frame_vector::count_frames() throw()
442 size_t ret = 0;
443 if(!frames)
444 return 0;
445 cache_page_num = 0;
446 cache_page = &pages[0];
447 size_t offset = 0;
448 size_t index = 0;
449 for(size_t i = 0; i < frames; i++) {
450 if(index == frames_per_page) {
451 cache_page_num++;
452 cache_page = &pages[cache_page_num];
453 index = 0;
454 offset = 0;
456 if(controller_frame::sync(cache_page->content + offset))
457 ret++;
458 index++;
459 offset += frame_size;
462 return ret;
465 void controller_frame_vector::clear(const port_type_set& p) throw(std::runtime_error)
467 frame_size = p.size();
468 frames_per_page = CONTROLLER_PAGE_SIZE / frame_size;
469 frames = 0;
470 types = &p;
471 clear_cache();
472 pages.clear();
475 controller_frame_vector::~controller_frame_vector() throw()
477 pages.clear();
478 cache_page = NULL;
481 controller_frame_vector::controller_frame_vector() throw()
483 clear(dummytypes());
486 controller_frame_vector::controller_frame_vector(const port_type_set& p) throw()
488 clear(p);
491 void controller_frame_vector::append(controller_frame frame) throw(std::bad_alloc, std::runtime_error)
493 controller_frame check(*types);
494 if(!check.types_match(frame))
495 throw std::runtime_error("controller_frame_vector::append: Type mismatch");
496 if(frames % frames_per_page == 0) {
497 //Create new page.
498 pages[frames / frames_per_page];
500 //Write the entry.
501 size_t page = frames / frames_per_page;
502 size_t offset = frame_size * (frames % frames_per_page);
503 if(cache_page_num != page) {
504 cache_page_num = page;
505 cache_page = &pages[page];
507 controller_frame(cache_page->content + offset, *types) = frame;
508 frames++;
511 controller_frame_vector::controller_frame_vector(const controller_frame_vector& vector) throw(std::bad_alloc)
513 clear(*vector.types);
514 *this = vector;
517 controller_frame_vector& controller_frame_vector::operator=(const controller_frame_vector& v)
518 throw(std::bad_alloc)
520 if(this == &v)
521 return *this;
522 resize(v.frames);
523 clear_cache();
525 //Copy the fields.
526 frame_size = v.frame_size;
527 frames_per_page = v.frames_per_page;
528 types = v.types;
530 //This can't fail anymore. Copy the raw page contents.
531 size_t pagecount = (frames + frames_per_page - 1) / frames_per_page;
532 for(size_t i = 0; i < pagecount; i++) {
533 page& pg = pages[i];
534 const page& pg2 = v.pages.find(i)->second;
535 pg = pg2;
538 return *this;
544 void controller_frame_vector::resize(size_t newsize) throw(std::bad_alloc)
546 clear_cache();
547 if(newsize == 0) {
548 clear();
549 } else if(newsize < frames) {
550 //Shrink movie.
551 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
552 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
553 for(size_t i = pages_needed; i < current_pages; i++)
554 pages.erase(i);
555 //Now zeroize the excess memory.
556 if(newsize < pages_needed * frames_per_page) {
557 size_t offset = frame_size * (newsize % frames_per_page);
558 memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
560 frames = newsize;
561 } else if(newsize > frames) {
562 //Enlarge movie.
563 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
564 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
565 //Create the needed pages.
566 for(size_t i = current_pages; i < pages_needed; i++) {
567 try {
568 pages[i];
569 } catch(...) {
570 for(size_t i = current_pages; i < pages_needed; i++)
571 if(pages.count(i))
572 pages.erase(i);
573 throw;
576 frames = newsize;
580 controller_frame::controller_frame() throw()
582 memset(memory, 0, sizeof(memory));
583 backing = memory;
584 types = &dummytypes();
587 unsigned port_controller::analog_actions() const
589 unsigned r = 0, s = 0;
590 for(unsigned i = 0; i < button_count; i++) {
591 if(buttons[i]->shadow)
592 continue;
593 switch(buttons[i]->type) {
594 case port_controller_button::TYPE_AXIS:
595 case port_controller_button::TYPE_RAXIS:
596 r++;
597 break;
598 case port_controller_button::TYPE_TAXIS:
599 s++;
600 break;
603 return (r + 1)/ 2 + s;
606 std::pair<unsigned, unsigned> port_controller::analog_action(unsigned k) const
608 unsigned x1 = std::numeric_limits<unsigned>::max();
609 unsigned x2 = std::numeric_limits<unsigned>::max();
610 unsigned r = 0;
611 bool second = false;
612 bool selecting = false;
613 for(unsigned i = 0; i < button_count; i++) {
614 if(buttons[i]->shadow)
615 continue;
616 switch(buttons[i]->type) {
617 case port_controller_button::TYPE_AXIS:
618 case port_controller_button::TYPE_RAXIS:
619 if(selecting) {
620 x2 = i;
621 goto out;
623 if(r == k && !second) {
624 //This and following.
625 x1 = i;
626 selecting = true;
628 if(!second)
629 r++;
630 second = !second;
631 break;
632 case port_controller_button::TYPE_TAXIS:
633 if(selecting)
634 break;
635 if(r == k) {
636 x1 = i;
637 goto out;
639 r++;
640 break;
643 out:
644 return std::make_pair(x1, x2);