Fix movie corruption in certain cases
[lsnes.git] / src / core / controllerframe.cpp
blob60a74580a8ad10d57d6408e8e4907a4875620d25
1 #include "lsnes.hpp"
2 #include <snes/snes.hpp>
3 #include <ui-libsnes/libsnes.hpp>
5 #include "core/controllerframe.hpp"
6 #include "core/dispatch.hpp"
7 #include "core/misc.hpp"
9 #include <cstdio>
10 #include <iostream>
12 #define SYSTEM_BYTES 5
14 namespace
16 std::set<porttype_info*>& porttypes()
18 static std::set<porttype_info*> p;
19 return p;
22 const char* buttonnames[MAX_LOGICAL_BUTTONS] = {
23 "left", "right", "up", "down", "A", "B", "X", "Y", "L", "R", "select", "start", "trigger",
24 "cursor", "turbo", "pause"
27 template<unsigned type>
28 void set_core_controller_bsnes(unsigned port) throw()
30 if(port > 1)
31 return;
32 snes_set_controller_port_device(port != 0, type);
35 void set_core_controller_illegal(unsigned port) throw()
37 std::cerr << "Attempt to set core port type to INVALID port type" << std::endl;
38 exit(1);
41 struct porttype_invalid : public porttype_info
43 porttype_invalid() : porttype_info(PT_INVALID, "invalid-port-type", 0)
45 write = NULL;
46 read = NULL;
47 display = NULL;
48 serialize = NULL;
49 deserialize = NULL;
50 devicetype = generic_port_devicetype<0, DT_NONE>;
51 controllers = 0;
52 internal_type = 0;
53 legal = generic_port_legal<0xFFFFFFFFU>;
54 set_core_controller = set_core_controller_illegal;
57 int button_id(unsigned controller, unsigned lbid) const throw()
59 return -1;
63 struct porttype_gamepad : public porttype_info
65 porttype_gamepad() : porttype_info(PT_GAMEPAD, "gamepad", generic_port_size<1, 0, 12>())
67 write = generic_port_write<1, 0, 12>;
68 read = generic_port_read<1, 0, 12>;
69 display = generic_port_display<1, 0, 12, 0>;
70 serialize = generic_port_serialize<1, 0, 12, 0>;
71 deserialize = generic_port_deserialize<1, 0, 12>;
72 devicetype = generic_port_devicetype<1, DT_GAMEPAD>;
73 legal = generic_port_legal<3>;
74 controllers = 1;
75 internal_type = SNES_DEVICE_JOYPAD;
76 set_core_controller = set_core_controller_bsnes<SNES_DEVICE_JOYPAD>;
79 int button_id(unsigned controller, unsigned lbid) const throw()
81 if(controller > 0)
82 return -1;
83 switch(lbid) {
84 case LOGICAL_BUTTON_LEFT: return SNES_DEVICE_ID_JOYPAD_LEFT;
85 case LOGICAL_BUTTON_RIGHT: return SNES_DEVICE_ID_JOYPAD_RIGHT;
86 case LOGICAL_BUTTON_UP: return SNES_DEVICE_ID_JOYPAD_UP;
87 case LOGICAL_BUTTON_DOWN: return SNES_DEVICE_ID_JOYPAD_DOWN;
88 case LOGICAL_BUTTON_A: return SNES_DEVICE_ID_JOYPAD_A;
89 case LOGICAL_BUTTON_B: return SNES_DEVICE_ID_JOYPAD_B;
90 case LOGICAL_BUTTON_X: return SNES_DEVICE_ID_JOYPAD_X;
91 case LOGICAL_BUTTON_Y: return SNES_DEVICE_ID_JOYPAD_Y;
92 case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_JOYPAD_L;
93 case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_JOYPAD_R;
94 case LOGICAL_BUTTON_SELECT: return SNES_DEVICE_ID_JOYPAD_SELECT;
95 case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JOYPAD_START;
96 default: return -1;
99 } gamepad;
101 struct porttype_justifier : public porttype_info
103 porttype_justifier() : porttype_info(PT_JUSTIFIER, "justifier", generic_port_size<1, 2, 2>())
105 write = generic_port_write<1, 2, 2>;
106 read = generic_port_read<1, 2, 2>;
107 display = generic_port_display<1, 2, 2, 12>;
108 serialize = generic_port_serialize<1, 2, 2, 12>;
109 deserialize = generic_port_deserialize<1, 2, 2>;
110 devicetype = generic_port_devicetype<1, DT_LIGHTGUN>;
111 legal = generic_port_legal<2>;
112 controllers = 1;
113 internal_type = SNES_DEVICE_JUSTIFIER;
114 set_core_controller = set_core_controller_bsnes<SNES_DEVICE_JUSTIFIER>;
117 int button_id(unsigned controller, unsigned lbid) const throw()
119 if(controller > 0)
120 return -1;
121 switch(lbid) {
122 case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JUSTIFIER_START;
123 case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER;
124 default: return -1;
127 } justifier;
129 struct porttype_justifiers : public porttype_info
131 porttype_justifiers() : porttype_info(PT_JUSTIFIERS, "justifiers", generic_port_size<2, 2, 2>())
133 write = generic_port_write<2, 2, 2>;
134 read = generic_port_read<2, 2, 2>;
135 display = generic_port_display<2, 2, 2, 0>;
136 serialize = generic_port_serialize<2, 2, 2, 12>;
137 deserialize = generic_port_deserialize<2, 2, 2>;
138 devicetype = generic_port_devicetype<2, DT_LIGHTGUN>;
139 legal = generic_port_legal<2>;
140 controllers = 2;
141 internal_type = SNES_DEVICE_JUSTIFIERS;
142 set_core_controller = set_core_controller_bsnes<SNES_DEVICE_JUSTIFIERS>;
145 int button_id(unsigned controller, unsigned lbid) const throw()
147 if(controller > 1)
148 return -1;
149 switch(lbid) {
150 case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JUSTIFIER_START;
151 case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER;
152 default: return -1;
155 } justifiers;
157 struct porttype_mouse : public porttype_info
159 porttype_mouse() : porttype_info(PT_MOUSE, "mouse", generic_port_size<1, 2, 2>())
161 write = generic_port_write<1, 2, 2>;
162 read = generic_port_read<1, 2, 2>;
163 display = generic_port_display<1, 2, 2, 0>;
164 serialize = generic_port_serialize<1, 2, 2, 12>;
165 deserialize = generic_port_deserialize<1, 2, 2>;
166 devicetype = generic_port_devicetype<1, DT_MOUSE>;
167 legal = generic_port_legal<3>;
168 controllers = 1;
169 internal_type = SNES_DEVICE_MOUSE;
170 set_core_controller = set_core_controller_bsnes<SNES_DEVICE_MOUSE>;
173 int button_id(unsigned controller, unsigned lbid) const throw()
175 if(controller > 0)
176 return -1;
177 switch(lbid) {
178 case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_MOUSE_LEFT;
179 case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_MOUSE_RIGHT;
180 default: return -1;
183 } mouse;
185 struct porttype_multitap : public porttype_info
187 porttype_multitap() : porttype_info(PT_MULTITAP, "multitap", generic_port_size<4, 0, 12>())
189 write = generic_port_write<4, 0, 12>;
190 read = generic_port_read<4, 0, 12>;
191 display = generic_port_display<4, 0, 12, 0>;
192 serialize = generic_port_serialize<4, 0, 12, 0>;
193 deserialize = generic_port_deserialize<4, 0, 12>;
194 devicetype = generic_port_devicetype<4, DT_GAMEPAD>;
195 legal = generic_port_legal<3>;
196 controllers = 4;
197 internal_type = SNES_DEVICE_MULTITAP;
198 set_core_controller = set_core_controller_bsnes<SNES_DEVICE_MULTITAP>;
201 int button_id(unsigned controller, unsigned lbid) const throw()
203 if(controller > 3)
204 return -1;
205 switch(lbid) {
206 case LOGICAL_BUTTON_LEFT: return SNES_DEVICE_ID_JOYPAD_LEFT;
207 case LOGICAL_BUTTON_RIGHT: return SNES_DEVICE_ID_JOYPAD_RIGHT;
208 case LOGICAL_BUTTON_UP: return SNES_DEVICE_ID_JOYPAD_UP;
209 case LOGICAL_BUTTON_DOWN: return SNES_DEVICE_ID_JOYPAD_DOWN;
210 case LOGICAL_BUTTON_A: return SNES_DEVICE_ID_JOYPAD_A;
211 case LOGICAL_BUTTON_B: return SNES_DEVICE_ID_JOYPAD_B;
212 case LOGICAL_BUTTON_X: return SNES_DEVICE_ID_JOYPAD_X;
213 case LOGICAL_BUTTON_Y: return SNES_DEVICE_ID_JOYPAD_Y;
214 case LOGICAL_BUTTON_L: return SNES_DEVICE_ID_JOYPAD_L;
215 case LOGICAL_BUTTON_R: return SNES_DEVICE_ID_JOYPAD_R;
216 case LOGICAL_BUTTON_SELECT: return SNES_DEVICE_ID_JOYPAD_SELECT;
217 case LOGICAL_BUTTON_START: return SNES_DEVICE_ID_JOYPAD_START;
218 default: return -1;
221 } multitap;
223 struct porttype_none : public porttype_info
225 porttype_none() : porttype_info(PT_NONE, "none", generic_port_size<0, 0, 0>())
227 write = generic_port_write<0, 0, 0>;
228 read = generic_port_read<0, 0, 0>;
229 display = generic_port_display<0, 0, 0, 0>;
230 serialize = generic_port_serialize<0, 0, 0, 0>;
231 deserialize = generic_port_deserialize<0, 0, 0>;
232 devicetype = generic_port_devicetype<0, DT_GAMEPAD>;
233 legal = generic_port_legal<3>;
234 controllers = 0;
235 internal_type = SNES_DEVICE_NONE;
236 set_core_controller = set_core_controller_bsnes<SNES_DEVICE_NONE>;
239 int button_id(unsigned controller, unsigned lbid) const throw()
241 return -1;
243 } none;
245 struct porttype_superscope : public porttype_info
247 porttype_superscope() : porttype_info(PT_SUPERSCOPE, "superscope", generic_port_size<1, 2, 4>())
249 write = generic_port_write<1, 2, 4>;
250 read = generic_port_read<1, 2, 4>;
251 display = generic_port_display<1, 2, 4, 0>;
252 serialize = generic_port_serialize<1, 2, 4, 14>;
253 deserialize = generic_port_deserialize<1, 2, 4>;
254 devicetype = generic_port_devicetype<1, DT_LIGHTGUN>;
255 legal = generic_port_legal<2>;
256 controllers = 1;
257 internal_type = SNES_DEVICE_SUPER_SCOPE;
258 set_core_controller = set_core_controller_bsnes<SNES_DEVICE_SUPER_SCOPE>;
261 int button_id(unsigned controller, unsigned lbid) const throw()
263 if(controller > 0)
264 return -1;
265 switch(lbid) {
266 case LOGICAL_BUTTON_TRIGGER: return SNES_DEVICE_ID_SUPER_SCOPE_TRIGGER;
267 case LOGICAL_BUTTON_CURSOR: return SNES_DEVICE_ID_SUPER_SCOPE_CURSOR;
268 case LOGICAL_BUTTON_TURBO: return SNES_DEVICE_ID_SUPER_SCOPE_TURBO;
269 case LOGICAL_BUTTON_PAUSE: return SNES_DEVICE_ID_SUPER_SCOPE_PAUSE;
270 default: return -1;
273 } superscope;
275 porttype_invalid& get_invalid_port_type()
277 static porttype_invalid inv;
278 return inv;
283 * Get name of logical button.
285 * Parameter lbid: ID of logical button.
286 * Returns: The name of button.
287 * Throws std::bad_alloc: Not enough memory.
289 std::string get_logical_button_name(unsigned lbid) throw(std::bad_alloc)
291 if(lbid >= MAX_LOGICAL_BUTTONS)
292 return "";
293 return buttonnames[lbid];
296 const porttype_info& porttype_info::lookup(porttype_t p) throw(std::runtime_error)
298 get_invalid_port_type();
299 for(auto i : porttypes())
300 if(p == i->value)
301 return *i;
302 throw std::runtime_error("Bad port type");
305 const porttype_info& porttype_info::lookup(const std::string& p) throw(std::runtime_error)
307 get_invalid_port_type();
308 for(auto i : porttypes())
309 if(p == i->name && i->value != PT_INVALID)
310 return *i;
311 throw std::runtime_error("Bad port type");
314 porttype_info::~porttype_info() throw()
316 porttypes().erase(this);
319 porttype_info::porttype_info(porttype_t ptype, const std::string& pname, size_t psize) throw(std::bad_alloc)
321 value = ptype;
322 name = pname;
323 storage_size = psize;
324 porttypes().insert(this);
327 bool porttype_info::is_analog(unsigned controller) const throw()
329 devicetype_t d = devicetype(controller);
330 return (d == DT_MOUSE || d == DT_LIGHTGUN);
333 bool porttype_info::is_mouse(unsigned controller) const throw()
335 return (devicetype(controller) == DT_MOUSE);
338 pollcounter_vector::pollcounter_vector() throw()
340 clear();
343 void pollcounter_vector::clear() throw()
345 system_flag = false;
346 memset(ctrs, 0, sizeof(ctrs));
349 void pollcounter_vector::set_all_DRDY() throw()
351 for(size_t i = 0; i < MAX_BUTTONS ; i++)
352 ctrs[i] |= 0x80000000UL;
355 #define INDEXOF(pcid, ctrl) ((pcid) * MAX_CONTROLS_PER_CONTROLLER + (ctrl))
357 void pollcounter_vector::clear_DRDY(unsigned pcid, unsigned ctrl) throw()
359 ctrs[INDEXOF(pcid, ctrl)] &= 0x7FFFFFFFUL;
362 bool pollcounter_vector::get_DRDY(unsigned pcid, unsigned ctrl) throw()
364 return ((ctrs[INDEXOF(pcid, ctrl)] & 0x80000000UL) != 0);
367 bool pollcounter_vector::has_polled() throw()
369 uint32_t res = system_flag ? 1 : 0;
370 for(size_t i = 0; i < MAX_BUTTONS ; i++)
371 res |= ctrs[i];
372 return ((res & 0x7FFFFFFFUL) != 0);
375 uint32_t pollcounter_vector::get_polls(unsigned pcid, unsigned ctrl) throw()
377 return ctrs[INDEXOF(pcid, ctrl)] & 0x7FFFFFFFUL;
380 uint32_t pollcounter_vector::increment_polls(unsigned pcid, unsigned ctrl) throw()
382 size_t i = INDEXOF(pcid, ctrl);
383 uint32_t x = ctrs[i] & 0x7FFFFFFFUL;
384 ++ctrs[i];
385 return x;
388 void pollcounter_vector::set_system() throw()
390 system_flag = true;
393 bool pollcounter_vector::get_system() throw()
395 return system_flag;
398 uint32_t pollcounter_vector::max_polls() throw()
400 uint32_t max = system_flag ? 1 : 0;
401 for(unsigned i = 0; i < MAX_BUTTONS; i++) {
402 uint32_t tmp = ctrs[i] & 0x7FFFFFFFUL;
403 max = (max < tmp) ? tmp : max;
405 return max;
408 void pollcounter_vector::save_state(std::vector<uint32_t>& mem) throw(std::bad_alloc)
410 mem.resize(4 + MAX_BUTTONS );
411 //Compatiblity fun.
412 mem[0] = 0x80000000UL;
413 mem[1] = system_flag ? 1 : 0x80000000UL;
414 mem[2] = system_flag ? 1 : 0x80000000UL;
415 mem[3] = system_flag ? 1 : 0x80000000UL;
416 for(size_t i = 0; i < MAX_BUTTONS ; i++)
417 mem[4 + i] = ctrs[i];
420 void pollcounter_vector::load_state(const std::vector<uint32_t>& mem) throw()
422 system_flag = (mem[1] | mem[2] | mem[3]) & 0x7FFFFFFFUL;
423 for(size_t i = 0; i < MAX_BUTTONS ; i++)
424 ctrs[i] = mem[i + 4];
427 bool pollcounter_vector::check(const std::vector<uint32_t>& mem) throw()
429 return (mem.size() == MAX_BUTTONS + 4);
433 controller_frame::controller_frame(porttype_t p1, porttype_t p2) throw(std::runtime_error)
435 memset(memory, 0, sizeof(memory));
436 backing = memory;
437 types[0] = p1;
438 types[1] = p2;
439 set_types(types);
442 controller_frame::controller_frame(unsigned char* mem, porttype_t p1, porttype_t p2) throw(std::runtime_error)
444 if(!mem)
445 throw std::runtime_error("NULL backing memory not allowed");
446 memset(memory, 0, sizeof(memory));
447 backing = mem;
448 types[0] = p1;
449 types[1] = p2;
450 set_types(types);
453 controller_frame::controller_frame(const controller_frame& obj) throw()
455 memset(memory, 0, sizeof(memory));
456 backing = memory;
457 set_types(obj.types);
458 memcpy(backing, obj.backing, totalsize);
461 controller_frame& controller_frame::operator=(const controller_frame& obj) throw(std::runtime_error)
463 set_types(obj.types);
464 memcpy(backing, obj.backing, totalsize);
467 void controller_frame::set_types(const porttype_t* tarr)
469 for(unsigned i = 0; i < MAX_PORTS; i++) {
470 if(memory != backing && types[i] != tarr[i])
471 throw std::runtime_error("Controller_frame: Type mismatch");
472 if(!porttype_info::lookup(tarr[i]).legal(i))
473 throw std::runtime_error("Illegal port type for port index");
475 size_t offset = SYSTEM_BYTES;
476 for(unsigned i = 0; i < MAX_PORTS; i++) {
477 offsets[i] = offset;
478 types[i] = tarr[i];
479 pinfo[i] = &porttype_info::lookup(tarr[i]);
480 offset += pinfo[i]->storage_size;
482 totalsize = offset;
485 size_t controller_frame_vector::walk_helper(size_t frame, bool sflag) throw()
487 size_t ret = sflag ? frame : 0;
488 if(frame >= frames)
489 return ret;
490 frame++;
491 ret++;
492 size_t page = frame / frames_per_page;
493 size_t offset = frame_size * (frame % frames_per_page);
494 size_t index = frame % frames_per_page;
495 if(cache_page_num != page) {
496 cache_page = &pages[page];
497 cache_page_num = page;
499 while(frame < frames) {
500 if(index == frames_per_page) {
501 page++;
502 cache_page = &pages[page];
503 cache_page_num = page;
505 if(controller_frame::sync(cache_page->content + offset))
506 break;
507 index++;
508 offset += frame_size;
509 frame++;
510 ret++;
512 return ret;
515 size_t controller_frame_vector::count_frames() throw()
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(controller_frame::sync(cache_page->content + offset))
532 ret++;
533 index++;
534 offset += frame_size;
537 return ret;
540 void controller_frame_vector::clear(enum porttype_t p1, enum porttype_t p2) throw(std::runtime_error)
542 controller_frame check(p1, p2);
543 frame_size = check.size();
544 frames_per_page = CONTROLLER_PAGE_SIZE / frame_size;
545 frames = 0;
546 types[0] = p1;
547 types[1] = p2;
548 clear_cache();
549 pages.clear();
552 controller_frame_vector::~controller_frame_vector() throw()
554 pages.clear();
555 cache_page = NULL;
558 controller_frame_vector::controller_frame_vector(enum porttype_t p1, enum porttype_t p2) throw(std::runtime_error)
560 clear(p1, p2);
563 void controller_frame_vector::append(controller_frame frame) throw(std::bad_alloc, std::runtime_error)
565 controller_frame check(types[0], types[1]);
566 if(!check.types_match(frame))
567 throw std::runtime_error("controller_frame_vector::append: Type mismatch");
568 if(frames % frames_per_page == 0) {
569 //Create new page.
570 pages[frames / frames_per_page];
572 //Write the entry.
573 size_t page = frames / frames_per_page;
574 size_t offset = frame_size * (frames % frames_per_page);
575 if(cache_page_num != page) {
576 cache_page_num = page;
577 cache_page = &pages[page];
579 controller_frame(cache_page->content + offset, types[0], types[1]) = frame;
580 frames++;
583 controller_frame_vector::controller_frame_vector(const controller_frame_vector& vector) throw(std::bad_alloc)
585 clear(vector.types[0], vector.types[1]);
586 *this = vector;
589 controller_frame_vector& controller_frame_vector::operator=(const controller_frame_vector& v)
590 throw(std::bad_alloc)
592 if(this == &v)
593 return *this;
594 resize(v.frames);
595 clear_cache();
597 //Copy the fields.
598 frame_size = v.frame_size;
599 frames_per_page = v.frames_per_page;
600 for(size_t i = 0; i < MAX_PORTS; i++)
601 types[i] = v.types[i];
603 //This can't fail anymore. Copy the raw page contents.
604 size_t pagecount = (frames + frames_per_page - 1) / frames_per_page;
605 for(size_t i = 0; i < pagecount; i++) {
606 page& pg = pages[i];
607 const page& pg2 = v.pages.find(i)->second;
608 pg = pg2;
611 return *this;
614 size_t controller_frame::system_serialize(const unsigned char* buffer, char* textbuf)
616 char tmp[128];
617 if(buffer[1] || buffer[2] || buffer[3] || buffer[4])
618 sprintf(tmp, "%c%c %i %i", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'),
619 unserialize_short(buffer + 1), unserialize_short(buffer + 3));
620 else
621 sprintf(tmp, "%c%c", ((buffer[0] & 1) ? 'F' : '.'), ((buffer[0] & 2) ? 'R' : '.'));
622 size_t len = strlen(tmp);
623 memcpy(textbuf, tmp, len);
624 return len;
627 size_t controller_frame::system_deserialize(unsigned char* buffer, const char* textbuf)
629 buffer[0] = 0;
630 size_t idx = 0;
631 if(read_button_value(textbuf, idx))
632 buffer[0] |= 1;
633 if(read_button_value(textbuf, idx))
634 buffer[0] |= 2;
635 serialize_short(buffer + 1, read_axis_value(textbuf, idx));
636 serialize_short(buffer + 3, read_axis_value(textbuf, idx));
637 skip_rest_of_field(textbuf, idx, false);
638 return idx;
641 short read_axis_value(const char* buf, size_t& idx) throw()
643 char ch;
644 //Skip ws.
645 while(is_nonterminator(buf[idx])) {
646 char ch = buf[idx];
647 if(ch != ' ' && ch != '\t')
648 break;
649 idx++;
651 //Read the sign if any.
652 if(!is_nonterminator(buf[idx]))
653 return 0;
654 bool negative = false;
655 if(ch == '-') {
656 negative = true;
657 idx++;
659 if(ch == '+')
660 idx++;
662 //Read numeric value.
663 int numval = 0;
664 while(!is_nonterminator(buf[idx]) && isdigit(static_cast<unsigned char>(ch = buf[idx]))) {
665 numval = numval * 10 + (ch - '0');
666 idx++;
668 if(negative)
669 numval = -numval;
671 return static_cast<short>(numval);
674 void controller_frame_vector::resize(size_t newsize) throw(std::bad_alloc)
676 clear_cache();
677 if(newsize == 0) {
678 clear();
679 } else if(newsize < frames) {
680 //Shrink movie.
681 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
682 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
683 for(size_t i = pages_needed; i < current_pages; i++)
684 pages.erase(i);
685 //Now zeroize the excess memory.
686 if(newsize < pages_needed * frames_per_page) {
687 size_t offset = frame_size * (newsize % frames_per_page);
688 memset(pages[pages_needed - 1].content + offset, 0, CONTROLLER_PAGE_SIZE - offset);
690 frames = newsize;
691 } else if(newsize > frames) {
692 //Enlarge movie.
693 size_t current_pages = (frames + frames_per_page - 1) / frames_per_page;
694 size_t pages_needed = (newsize + frames_per_page - 1) / frames_per_page;
695 //Create the needed pages.
696 for(size_t i = current_pages; i < pages_needed; i++) {
697 try {
698 pages[i];
699 } catch(...) {
700 for(size_t i = current_pages; i < pages_needed; i++)
701 if(pages.count(i))
702 pages.erase(i);
703 throw;
706 frames = newsize;
710 controller_frame::controller_frame() throw()
712 memset(memory, 0, sizeof(memory));
713 backing = memory;
714 for(unsigned i = 0; i < MAX_PORTS; i++) {
715 offsets[i] = SYSTEM_BYTES;
716 types[i] = PT_INVALID;
717 pinfo[i] = NULL;
719 totalsize = SYSTEM_BYTES;
722 void controller_frame::set_port_type(unsigned port, porttype_t ptype) throw(std::runtime_error)
724 char tmp[MAXIMUM_CONTROLLER_FRAME_SIZE] = {0};
725 if(!porttype_info::lookup(ptype).legal(port))
726 throw std::runtime_error("Illegal port type for port index");
727 if(memory != backing)
728 throw std::runtime_error("Can't set port type on non-dedicated controller frame");
729 if(port >= MAX_PORTS)
730 return;
731 const porttype_info* newpinfo[MAX_PORTS];
732 size_t newoffsets[MAX_PORTS];
733 size_t offset = SYSTEM_BYTES;
734 for(size_t i = 0; i < MAX_PORTS; i++) {
735 if(i != port)
736 newpinfo[i] = pinfo[i];
737 else
738 newpinfo[i] = &porttype_info::lookup(ptype);
739 newoffsets[i] = offset;
740 if(newpinfo[i])
741 offset += newpinfo[i]->storage_size;
742 if(i != port && newpinfo[i] && newpinfo[i]->storage_size)
743 memcpy(tmp + newoffsets[i], backing + offsets[i], newpinfo[i]->storage_size);
745 memcpy(memory, tmp, MAXIMUM_CONTROLLER_FRAME_SIZE);
746 types[port] = ptype;
747 pinfo[port] = newpinfo[port];
748 for(size_t i = 0; i < MAX_PORTS; i++)
749 offsets[i] = newoffsets[i];
750 totalsize = offset;
753 controller_state::controller_state() throw()
755 for(size_t i = 0; i < MAX_ANALOG; i++) {
756 analog_indices[i] = -1;
757 analog_mouse[i] = false;
759 for(size_t i = 0; i < MAX_PORTS; i++) {
760 porttypes[i] = PT_INVALID;
761 porttypeinfo[i] = NULL;
765 int controller_state::lcid_to_pcid(unsigned lcid) throw()
767 if(!porttypeinfo[0] || !porttypeinfo[1])
768 return -1;
769 unsigned p1devs = porttypeinfo[0]->controllers;
770 unsigned p2devs = porttypeinfo[1]->controllers;
771 if(lcid >= p1devs + p2devs)
772 return -1;
773 //Exceptional: If p1 is none, map all to p2.
774 if(!p1devs)
775 return lcid + MAX_CONTROLLERS_PER_PORT;
776 //LID 0 Is always PID 0 unless out of range.
777 if(lcid == 0)
778 return 0;
779 //LID 1-n are on port 2.
780 else if(lcid < 1 + p2devs)
781 return lcid - 1 + MAX_CONTROLLERS_PER_PORT;
782 //From there, those are on port 1 (except for the first).
783 else
784 return lcid - p2devs;
787 int controller_state::acid_to_pcid(unsigned acid) throw()
789 if(acid > MAX_ANALOG)
790 return -1;
791 return analog_indices[acid];
794 bool controller_state::acid_is_mouse(unsigned acid) throw()
796 if(acid > MAX_ANALOG)
797 return -1;
798 return analog_mouse[acid];
802 devicetype_t controller_state::pcid_to_type(unsigned pcid) throw()
804 size_t port = pcid / MAX_CONTROLLERS_PER_PORT;
805 if(port >= MAX_PORTS)
806 return DT_NONE;
807 return porttypeinfo[port]->devicetype(pcid % MAX_CONTROLLERS_PER_PORT);
810 controller_frame controller_state::get(uint64_t framenum) throw()
812 if(_autofire.size())
813 return _input ^ _autohold ^ _autofire[framenum % _autofire.size()];
814 else
815 return _input ^ _autohold;
818 void controller_state::analog(unsigned acid, int x, int y) throw()
820 if(acid >= MAX_ANALOG || analog_indices[acid] < 0) {
821 messages << "No analog controller #" << acid << std::endl;
822 return;
824 _input.axis(analog_indices[acid], 0, x);
825 _input.axis(analog_indices[acid], 1, y);
828 void controller_state::reset(int32_t delay) throw()
830 if(delay >= 0) {
831 _input.reset(true);
832 _input.delay(std::make_pair(delay / 10000, delay % 10000));
833 } else {
834 _input.reset(false);
835 _input.delay(std::make_pair(0, 0));
839 void controller_state::autohold(unsigned pcid, unsigned pbid, bool newstate) throw()
841 _autohold.axis(pcid, pbid, newstate ? 1 : 0);
842 information_dispatch::do_autohold_update(pcid, pbid, newstate);
845 bool controller_state::autohold(unsigned pcid, unsigned pbid) throw()
847 return (_autohold.axis(pcid, pbid) != 0);
850 void controller_state::button(unsigned pcid, unsigned pbid, bool newstate) throw()
852 _input.axis(pcid, pbid, newstate ? 1 : 0);
855 bool controller_state::button(unsigned pcid, unsigned pbid) throw()
857 return (_input.axis(pcid, pbid) != 0);
860 void controller_state::autofire(std::vector<controller_frame> pattern) throw(std::bad_alloc)
862 _autofire = pattern;
865 int controller_state::button_id(unsigned pcid, unsigned lbid) throw()
867 size_t port = pcid / MAX_CONTROLLERS_PER_PORT;
868 if(port >= MAX_PORTS)
869 return -1;
870 return porttypeinfo[port]->button_id(pcid % MAX_CONTROLLERS_PER_PORT, lbid);
873 void controller_state::set_port(unsigned port, porttype_t ptype, bool set_core) throw(std::runtime_error)
875 if(port >= MAX_PORTS)
876 throw std::runtime_error("Port number invalid");
877 const porttype_info* info = &porttype_info::lookup(ptype);
878 if(!info->legal(port))
879 throw std::runtime_error("Port type not valid for port");
880 if(set_core)
881 info->set_core_controller(port);
882 porttype_t oldtype = porttypes[port];
883 if(oldtype != ptype) {
884 _input.set_port_type(port, ptype);
885 _autohold.set_port_type(port, ptype);
886 _committed.set_port_type(port, ptype);
887 //The old autofire pattern no longer applies.
888 _autofire.clear();
890 porttypes[port] = ptype;
891 porttypeinfo[port] = info;
892 int i = 0;
893 for(unsigned j = 0; j < MAX_ANALOG; j++)
894 analog_indices[j] = -1;
895 for(unsigned j = 0; j < MAX_PORTS * MAX_CONTROLLERS_PER_PORT; j++) {
896 if(!porttypeinfo[j / MAX_CONTROLLERS_PER_PORT])
897 continue;
898 devicetype_t d = porttypeinfo[j / MAX_CONTROLLERS_PER_PORT]->devicetype(j % MAX_CONTROLLERS_PER_PORT);
899 switch(d) {
900 case DT_NONE:
901 case DT_GAMEPAD:
902 break;
903 case DT_MOUSE:
904 analog_mouse[i] = true;
905 analog_indices[i++] = j;
906 break;
907 case DT_LIGHTGUN:
908 analog_mouse[i] = false;
909 analog_indices[i++] = j;
910 break;
912 if(i == MAX_ANALOG)
913 break;
915 information_dispatch::do_autohold_reconfigure();
918 controller_frame controller_state::get_blank() throw()
920 return _input.blank_frame();
923 controller_frame controller_state::commit(uint64_t framenum) throw()
925 controller_frame f = get(framenum);
926 _committed = f;
927 return _committed;
930 controller_frame controller_state::get_committed() throw()
932 return _committed;
935 controller_frame controller_state::commit(controller_frame controls) throw()
937 _committed = controls;
938 return _committed;
941 bool controller_state::is_analog(unsigned pcid) throw()
943 return _input.is_analog(pcid);
946 bool controller_state::is_mouse(unsigned pcid) throw()
948 return _input.is_mouse(pcid);