Extern references in library/controller-data.hpp are no-no
[lsnes.git] / src / library / controller-data.cpp
blobfc01c49245eb8b530220ac6be5e890ce892d2a31
1 #include "library/controller-data.hpp"
2 #include "library/workthread.hpp"
3 #include "library/minmax.hpp"
4 #include "library/globalwrap.hpp"
5 #include <iostream>
6 #include <list>
8 namespace
10 void set_core_controller_illegal(unsigned port) throw()
12 std::cerr << "Attempt to set core port type to INVALID port type" << std::endl;
13 exit(1);
16 int button_id_illegal(unsigned controller, unsigned lbid)
18 return -1;
21 struct port_index_map invalid_construct_map(std::vector<port_type*> types)
23 struct port_index_map i;
24 i.indices.resize(1);
25 i.indices[0].valid = true;
26 i.indices[0].port = 0;
27 i.indices[0].controller = 0;
28 i.indices[0].control = 0;
29 return i;
32 inline size_t invalid_serialize(const unsigned char* buffer, char* textbuf) throw()
34 return 0;
37 inline void invalid_display(const unsigned char* buffer, unsigned idx, char* buf)
39 *buf = 0;
42 inline void basecontrol_display(const unsigned char* buffer, unsigned idx, char* buf)
44 if(idx)
45 *buf = 0;
46 else {
47 buf[0] = (buffer[0] & 1) ? 'F' : '-';
48 buf[1] = 0;
52 inline const char* invalid_controller_name(unsigned c)
54 return c ? NULL : "(system)";
57 struct port_type_group invalid_group;
58 struct porttype_invalid : public port_type
60 porttype_invalid() : port_type(invalid_group, "invalid-port-type", "invalid-port-type", 999999, 0)
62 write = generic_port_write<0, 0, 0>;
63 read = generic_port_read<0, 0, 0>;
64 display = invalid_display;
65 serialize = invalid_serialize;
66 deserialize = generic_port_deserialize<0, 0, 0>;
67 legal = generic_port_legal<0xFFFFFFFFU>;
68 deviceflags = generic_port_deviceflags<0, 0>;
69 used_indices = generic_used_indices<0, 0>;
70 controller_name = invalid_controller_name;
71 button_id = button_id_illegal;
72 construct_map = invalid_construct_map;
73 controllers = 0;
74 set_core_controller = set_core_controller_illegal;
78 inline size_t basecontrol_serialize(const unsigned char* buffer, char* textbuf) throw()
80 textbuf[0] = (buffer[0] & 1) ? 'F' : '.';
81 return 1;
84 struct porttype_basecontrol : public port_type
86 porttype_basecontrol() : port_type(invalid_group, "basecontrol", "basecontrol", 999998, 0)
88 write = generic_port_write<1, 0, 1>;
89 read = generic_port_read<1, 0, 1>;
90 display = basecontrol_display;
91 serialize = basecontrol_serialize;
92 deserialize = generic_port_deserialize<1, 0, 1>;
93 legal = generic_port_legal<0>;
94 deviceflags = generic_port_deviceflags<0, 0>;
95 button_id = button_id_illegal;
96 construct_map = invalid_construct_map;
97 used_indices = generic_used_indices<1, 1>;
98 controller_name = invalid_controller_name;
99 controllers = 1;
100 set_core_controller = set_core_controller_illegal;
102 static port_type& get()
104 static porttype_basecontrol x;
105 return x;
109 struct pending_registration
111 port_type_group* group;
112 std::string name;
113 port_type* toreg;
116 globalwrap<mutex_class> reg_mutex;
117 globalwrap<std::set<port_type_group*>> ready_groups;
118 globalwrap<std::list<pending_registration>> pending_registrations;
120 void run_pending_registrations()
122 umutex_class m(reg_mutex());
123 auto i = pending_registrations().begin();
124 while(i != pending_registrations().end()) {
125 auto entry = i++;
126 if(ready_groups().count(entry->group)) {
127 entry->group->register_type(entry->name, *entry->toreg);
128 pending_registrations().erase(entry);
133 void add_registration(port_type_group& group, const std::string& name, port_type& type)
136 umutex_class m(reg_mutex());
137 pending_registration p;
138 p.group = &group;
139 p.name = name;
140 p.toreg = &type;
141 pending_registrations().push_back(p);
143 run_pending_registrations();
146 void delete_registration(port_type_group& group, const std::string& name)
149 umutex_class m(reg_mutex());
150 if(ready_groups().count(&group))
151 group.unregister_type(name);
152 else {
153 auto i = pending_registrations().begin();
154 while(i != pending_registrations().end()) {
155 auto entry = i++;
156 if(entry->group == &group && entry->name == name)
157 pending_registrations().erase(entry);
164 port_type_group::port_type_group() throw(std::bad_alloc)
167 umutex_class m(reg_mutex());
168 ready_groups().insert(this);
170 run_pending_registrations();
173 port_type_group::~port_type_group() throw()
176 umutex_class m(reg_mutex());
177 ready_groups().erase(this);
181 port_type& port_type_group::get_type(const std::string& name) const throw(std::runtime_error)
183 if(types.count(name))
184 return *(types.find(name)->second);
185 else
186 throw std::runtime_error("Unknown port type");
189 port_type& port_type_group::get_default_type(unsigned port) const throw(std::runtime_error)
191 if(defaults.count(port))
192 return *(defaults.find(port)->second);
193 else
194 throw std::runtime_error("No default for this port");
197 std::set<port_type*> port_type_group::get_types() const throw(std::bad_alloc)
199 std::set<port_type*> p;
200 for(auto i : types)
201 p.insert(i.second);
202 return p;
205 void port_type_group::set_default(unsigned port, port_type& ptype)
207 defaults[port] = &ptype;
210 void port_type_group::register_type(const std::string& type, port_type& port)
212 types[type] = &port;
215 void port_type_group::unregister_type(const std::string& type)
217 types.erase(type);
220 port_type::port_type(port_type_group& group, const std::string& iname, const std::string& _hname, unsigned id,
221 size_t ssize) throw(std::bad_alloc)
222 : ingroup(group), name(iname), hname(_hname), pt_id(id), storage_size(ssize)
224 add_registration(ingroup, name, *this);
227 port_type::~port_type() throw()
229 delete_registration(ingroup, name);
232 bool port_type::is_present(unsigned controller) const throw()
234 return (deviceflags(controller) & 1) != 0;
237 bool port_type::is_analog(unsigned controller) const throw()
239 return (deviceflags(controller) & 6) != 0;
242 bool port_type::is_mouse(unsigned controller) const throw()
244 return (deviceflags(controller) & 4) != 0;
247 namespace
249 size_t dummy_offset = 0;
250 port_type* dummy_type = &porttype_basecontrol::get();
251 unsigned dummy_index = 0;
252 struct binding
254 std::vector<port_type*> types;
255 port_type_set* stype;
256 bool matches(const std::vector<class port_type*>& x)
258 if(x.size() != types.size())
259 return false;
260 for(size_t i = 0; i < x.size(); i++)
261 if(x[i] != types[i])
262 return false;
263 return true;
266 std::list<binding>& bindings()
268 static std::list<binding> x;
269 return x;
273 port_type_set::port_type_set() throw()
276 port_offsets = &dummy_offset;
277 port_types = &dummy_type;
278 port_count = 1;
279 total_size = 1;
280 _indices.resize(1);
281 _indices[0].valid = true;
282 _indices[0].port = 0;
283 _indices[0].controller = 0;
284 _indices[0].control = 0;
285 _indices[0].marks_nonlag = false;
287 port_multiplier = 1;
288 controller_multiplier = 1;
289 indices_size = 1;
290 indices_tab = &dummy_index;
293 port_type_set& port_type_set::make(std::vector<class port_type*> types) throw(std::bad_alloc, std::runtime_error)
295 for(auto i : bindings())
296 if(i.matches(types))
297 return *(i.stype);
298 //Not found, create new.
299 port_type_set& ret = *new port_type_set(types);
300 binding b;
301 b.types = types;
302 b.stype = &ret;
303 bindings().push_back(b);
304 return ret;
307 port_type_set::port_type_set(std::vector<class port_type*> types)
309 port_count = types.size();
310 //Verify legality of port types.
311 for(size_t i = 0; i < port_count; i++)
312 if(!types[i] || (i > 0 && !types[i]->legal(i - 1)))
313 throw std::runtime_error("Illegal port types");
314 //Count maximum number of controller indices to determine the controller multiplier.
315 controller_multiplier = 1;
316 for(size_t i = 0; i < port_count; i++)
317 for(unsigned j = 0; j < types[i]->controllers; j++)
318 controller_multiplier = max(controller_multiplier, (size_t)types[i]->used_indices(j));
319 //Count maximum number of controllers to determine the port multiplier.
320 port_multiplier = 1;
321 for(size_t i = 0; i < port_count; i++)
322 port_multiplier = max(port_multiplier, controller_multiplier * (size_t)types[i]->controllers);
323 //Query core about maps.
324 struct port_index_map control_map = types[0]->construct_map(types);
325 //Allocate the per-port tables.
326 port_offsets = new size_t[types.size()];
327 port_types = new class port_type*[types.size()];
328 //Determine the total size and offsets.
329 size_t offset = 0;
330 for(size_t i = 0; i < port_count; i++) {
331 port_offsets[i] = offset;
332 offset += types[i]->storage_size;
333 port_types[i] = types[i];
335 total_size = offset;
336 //Determine the index size and allocate it.
337 indices_size = port_multiplier * port_count;
338 indices_tab = new unsigned[indices_size];
339 for(size_t i = 0; i < indices_size; i++)
340 indices_tab[i] = 0xFFFFFFFFUL;
341 //Copy the index data (and reverse it).
342 controllers = control_map.logical_map;
343 legacy_pcids = control_map.pcid_map;
344 _indices = control_map.indices;
345 for(size_t j = 0; j < _indices.size(); j++) {
346 auto& i = _indices[j];
347 if(i.valid)
348 indices_tab[i.port * port_multiplier + i.controller * controller_multiplier + i.control] = j;
352 short read_axis_value(const char* buf, size_t& idx) throw()
354 char ch;
355 //Skip ws.
356 while(is_nonterminator(buf[idx])) {
357 char ch = buf[idx];
358 if(ch != ' ' && ch != '\t')
359 break;
360 idx++;
362 //Read the sign if any.
363 ch = buf[idx];
364 if(!is_nonterminator(ch))
365 return 0;
366 bool negative = false;
367 if(ch == '-') {
368 negative = true;
369 idx++;
371 if(ch == '+')
372 idx++;
374 //Read numeric value.
375 int numval = 0;
376 while(is_nonterminator(buf[idx]) && isdigit(static_cast<unsigned char>(ch = buf[idx]))) {
377 numval = numval * 10 + (ch - '0');
378 idx++;
380 if(negative)
381 numval = -numval;
383 return static_cast<short>(numval);
386 port_type& get_dummy_port_type() throw(std::bad_alloc)
388 static porttype_invalid inv;
389 return inv;
392 namespace
394 port_type_set& dummytypes()
396 static port_type_set x;
397 return x;
401 pollcounter_vector::pollcounter_vector() throw(std::bad_alloc)
403 types = &dummytypes();
404 ctrs = new uint32_t[types->indices()];
405 clear();
408 pollcounter_vector::pollcounter_vector(const port_type_set& p) throw(std::bad_alloc)
410 types = &p;
411 ctrs = new uint32_t[types->indices()];
412 clear();
415 pollcounter_vector::pollcounter_vector(const pollcounter_vector& p) throw(std::bad_alloc)
417 ctrs = new uint32_t[p.types->indices()];
418 types = p.types;
419 memcpy(ctrs, p.ctrs, sizeof(uint32_t) * p.types->indices());
422 pollcounter_vector& pollcounter_vector::operator=(const pollcounter_vector& p) throw(std::bad_alloc)
424 if(this == &p)
425 return *this;
426 uint32_t* n = new uint32_t[p.types->indices()];
427 types = p.types;
428 memcpy(n, p.ctrs, sizeof(uint32_t) * p.types->indices());
429 delete[] ctrs;
430 ctrs = n;
431 return *this;
434 pollcounter_vector::~pollcounter_vector() throw()
436 delete[] ctrs;
439 void pollcounter_vector::clear() throw()
441 memset(ctrs, 0, sizeof(uint32_t) * types->indices());
444 void pollcounter_vector::set_all_DRDY() throw()
446 for(size_t i = 0; i < types->indices(); i++)
447 ctrs[i] |= 0x80000000UL;
450 void pollcounter_vector::clear_DRDY(unsigned idx) throw()
452 ctrs[idx] &= 0x7FFFFFFFUL;
455 bool pollcounter_vector::get_DRDY(unsigned idx) throw()
457 return ((ctrs[idx] & 0x80000000UL) != 0);
460 bool pollcounter_vector::has_polled() throw()
462 uint32_t res = 0;
463 for(size_t i = 0; i < types->indices() ; i++)
464 res |= ctrs[i];
465 return ((res & 0x7FFFFFFFUL) != 0);
468 uint32_t pollcounter_vector::get_polls(unsigned idx) throw()
470 return ctrs[idx] & 0x7FFFFFFFUL;
473 uint32_t pollcounter_vector::increment_polls(unsigned idx) throw()
475 uint32_t x = ctrs[idx] & 0x7FFFFFFFUL;
476 ++ctrs[idx];
477 return x;
480 uint32_t pollcounter_vector::max_polls() throw()
482 uint32_t max = 0;
483 for(unsigned i = 0; i < types->indices(); i++) {
484 uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL;
485 max = (max < tmp) ? tmp : max;
487 return max;
490 void pollcounter_vector::save_state(std::vector<uint32_t>& mem) throw(std::bad_alloc)
492 mem.resize(types->indices());
493 //Compatiblity fun.
494 for(size_t i = 0; i < types->indices(); i++)
495 mem[i] = ctrs[i];
498 void pollcounter_vector::load_state(const std::vector<uint32_t>& mem) throw()
500 for(size_t i = 0; i < types->indices(); i++)
501 ctrs[i] = mem[i];
504 bool pollcounter_vector::check(const std::vector<uint32_t>& mem) throw()
506 return (mem.size() == types->indices());
510 controller_frame::controller_frame(const port_type_set& p) throw(std::runtime_error)
512 memset(memory, 0, sizeof(memory));
513 backing = memory;
514 types = &p;
517 controller_frame::controller_frame(unsigned char* mem, const port_type_set& p) throw(std::runtime_error)
519 if(!mem)
520 throw std::runtime_error("NULL backing memory not allowed");
521 memset(memory, 0, sizeof(memory));
522 backing = mem;
523 types = &p;
526 controller_frame::controller_frame(const controller_frame& obj) throw()
528 memset(memory, 0, sizeof(memory));
529 backing = memory;
530 types = obj.types;
531 memcpy(backing, obj.backing, types->size());
534 controller_frame& controller_frame::operator=(const controller_frame& obj) throw(std::runtime_error)
536 if(backing != memory && types != obj.types)
537 throw std::runtime_error("Port types do not match");
538 types = obj.types;
539 memcpy(backing, obj.backing, types->size());
542 size_t controller_frame_vector::walk_helper(size_t frame, bool sflag) throw()
544 size_t ret = sflag ? frame : 0;
545 if(frame >= frames)
546 return ret;
547 frame++;
548 ret++;
549 size_t page = frame / frames_per_page;
550 size_t offset = frame_size * (frame % frames_per_page);
551 size_t index = frame % frames_per_page;
552 if(cache_page_num != page) {
553 cache_page = &pages[page];
554 cache_page_num = page;
556 while(frame < frames) {
557 if(index == frames_per_page) {
558 page++;
559 cache_page = &pages[page];
560 cache_page_num = page;
562 if(controller_frame::sync(cache_page->content + offset))
563 break;
564 index++;
565 offset += frame_size;
566 frame++;
567 ret++;
569 return ret;
572 size_t controller_frame_vector::count_frames() throw()
574 size_t ret = 0;
575 if(!frames)
576 return 0;
577 cache_page_num = 0;
578 cache_page = &pages[0];
579 size_t offset = 0;
580 size_t index = 0;
581 for(size_t i = 0; i < frames; i++) {
582 if(index == frames_per_page) {
583 cache_page_num++;
584 cache_page = &pages[cache_page_num];
585 index = 0;
586 offset = 0;
588 if(controller_frame::sync(cache_page->content + offset))
589 ret++;
590 index++;
591 offset += frame_size;
594 return ret;
597 void controller_frame_vector::clear(const port_type_set& p) throw(std::runtime_error)
599 frame_size = p.size();
600 frames_per_page = CONTROLLER_PAGE_SIZE / frame_size;
601 frames = 0;
602 types = &p;
603 clear_cache();
604 pages.clear();
607 controller_frame_vector::~controller_frame_vector() throw()
609 pages.clear();
610 cache_page = NULL;
613 controller_frame_vector::controller_frame_vector() throw()
615 clear(dummytypes());
618 controller_frame_vector::controller_frame_vector(const port_type_set& p) throw()
620 clear(p);
623 void controller_frame_vector::append(controller_frame frame) throw(std::bad_alloc, std::runtime_error)
625 controller_frame check(*types);
626 if(!check.types_match(frame))
627 throw std::runtime_error("controller_frame_vector::append: Type mismatch");
628 if(frames % frames_per_page == 0) {
629 //Create new page.
630 pages[frames / frames_per_page];
632 //Write the entry.
633 size_t page = frames / frames_per_page;
634 size_t offset = frame_size * (frames % frames_per_page);
635 if(cache_page_num != page) {
636 cache_page_num = page;
637 cache_page = &pages[page];
639 controller_frame(cache_page->content + offset, *types) = frame;
640 frames++;
643 controller_frame_vector::controller_frame_vector(const controller_frame_vector& vector) throw(std::bad_alloc)
645 clear(*vector.types);
646 *this = vector;
649 controller_frame_vector& controller_frame_vector::operator=(const controller_frame_vector& v)
650 throw(std::bad_alloc)
652 if(this == &v)
653 return *this;
654 resize(v.frames);
655 clear_cache();
657 //Copy the fields.
658 frame_size = v.frame_size;
659 frames_per_page = v.frames_per_page;
660 types = v.types;
662 //This can't fail anymore. Copy the raw page contents.
663 size_t pagecount = (frames + frames_per_page - 1) / frames_per_page;
664 for(size_t i = 0; i < pagecount; i++) {
665 page& pg = pages[i];
666 const page& pg2 = v.pages.find(i)->second;
667 pg = pg2;
670 return *this;
676 void controller_frame_vector::resize(size_t newsize) throw(std::bad_alloc)
678 clear_cache();
679 if(newsize == 0) {
680 clear();
681 } else if(newsize < frames) {
682 //Shrink movie.
683 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
684 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
685 for(size_t i = pages_needed; i < current_pages; i++)
686 pages.erase(i);
687 //Now zeroize the excess memory.
688 if(newsize < pages_needed * frames_per_page) {
689 size_t offset = frame_size * (newsize % frames_per_page);
690 memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
692 frames = newsize;
693 } else if(newsize > frames) {
694 //Enlarge movie.
695 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
696 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
697 //Create the needed pages.
698 for(size_t i = current_pages; i < pages_needed; i++) {
699 try {
700 pages[i];
701 } catch(...) {
702 for(size_t i = current_pages; i < pages_needed; i++)
703 if(pages.count(i))
704 pages.erase(i);
705 throw;
708 frames = newsize;
712 controller_frame::controller_frame() throw()
714 memset(memory, 0, sizeof(memory));
715 backing = memory;
716 types = &dummytypes();