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"
12 #define SYSTEM_BYTES 5
16 std::set
<porttype_info
*>& porttypes()
18 static std::set
<porttype_info
*> 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()
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
;
41 struct porttype_invalid
: public porttype_info
43 porttype_invalid() : porttype_info(PT_INVALID
, "invalid-port-type", 0)
50 devicetype
= generic_port_devicetype
<0, DT_NONE
>;
53 legal
= generic_port_legal
<0xFFFFFFFFU
>;
54 set_core_controller
= set_core_controller_illegal
;
57 int button_id(unsigned controller
, unsigned lbid
) const throw()
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>;
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()
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
;
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>;
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()
122 case LOGICAL_BUTTON_START
: return SNES_DEVICE_ID_JUSTIFIER_START
;
123 case LOGICAL_BUTTON_TRIGGER
: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER
;
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>;
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()
150 case LOGICAL_BUTTON_START
: return SNES_DEVICE_ID_JUSTIFIER_START
;
151 case LOGICAL_BUTTON_TRIGGER
: return SNES_DEVICE_ID_JUSTIFIER_TRIGGER
;
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>;
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()
178 case LOGICAL_BUTTON_L
: return SNES_DEVICE_ID_MOUSE_LEFT
;
179 case LOGICAL_BUTTON_R
: return SNES_DEVICE_ID_MOUSE_RIGHT
;
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>;
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()
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
;
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>;
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()
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>;
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()
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
;
275 porttype_invalid
& get_invalid_port_type()
277 static porttype_invalid 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
)
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())
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
)
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
)
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()
343 void pollcounter_vector::clear() throw()
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
++)
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
;
388 void pollcounter_vector::set_system() throw()
393 bool pollcounter_vector::get_system() throw()
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
;
408 void pollcounter_vector::save_state(std::vector
<uint32_t>& mem
) throw(std::bad_alloc
)
410 mem
.resize(4 + MAX_BUTTONS
);
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
));
442 controller_frame::controller_frame(unsigned char* mem
, porttype_t p1
, porttype_t p2
) throw(std::runtime_error
)
445 throw std::runtime_error("NULL backing memory not allowed");
446 memset(memory
, 0, sizeof(memory
));
453 controller_frame::controller_frame(const controller_frame
& obj
) throw()
455 memset(memory
, 0, sizeof(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
++) {
479 pinfo
[i
] = &porttype_info::lookup(tarr
[i
]);
480 offset
+= pinfo
[i
]->storage_size
;
485 size_t controller_frame_vector::walk_helper(size_t frame
, bool sflag
) throw()
487 size_t ret
= sflag
? frame
: 0;
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
) {
502 cache_page
= &pages
[page
];
503 cache_page_num
= page
;
505 if(controller_frame::sync(cache_page
->content
+ offset
))
508 offset
+= frame_size
;
515 size_t controller_frame_vector::count_frames() throw()
521 cache_page
= &pages
[0];
524 for(size_t i
= 0; i
< frames
; i
++) {
525 if(index
== frames_per_page
) {
527 cache_page
= &pages
[cache_page_num
];
531 if(controller_frame::sync(cache_page
->content
+ offset
))
534 offset
+= frame_size
;
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
;
552 controller_frame_vector::~controller_frame_vector() throw()
558 controller_frame_vector::controller_frame_vector(enum porttype_t p1
, enum porttype_t p2
) throw(std::runtime_error
)
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) {
570 pages
[frames
/ frames_per_page
];
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
;
583 controller_frame_vector::controller_frame_vector(const controller_frame_vector
& vector
) throw(std::bad_alloc
)
585 clear(vector
.types
[0], vector
.types
[1]);
589 controller_frame_vector
& controller_frame_vector::operator=(const controller_frame_vector
& v
)
590 throw(std::bad_alloc
)
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
++) {
607 const page
& pg2
= v
.pages
.find(i
)->second
;
614 size_t controller_frame::system_serialize(const unsigned char* buffer
, char* textbuf
)
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));
621 sprintf(tmp
, "%c%c", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'));
622 size_t len
= strlen(tmp
);
623 memcpy(textbuf
, tmp
, len
);
627 size_t controller_frame::system_deserialize(unsigned char* buffer
, const char* textbuf
)
631 if(read_button_value(textbuf
, idx
))
633 if(read_button_value(textbuf
, idx
))
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);
641 short read_axis_value(const char* buf
, size_t& idx
) throw()
645 while(is_nonterminator(buf
[idx
])) {
647 if(ch
!= ' ' && ch
!= '\t')
651 //Read the sign if any.
652 if(!is_nonterminator(buf
[idx
]))
654 bool negative
= false;
662 //Read numeric value.
664 while(!is_nonterminator(buf
[idx
]) && isdigit(static_cast<unsigned char>(ch
= buf
[idx
]))) {
665 numval
= numval
* 10 + (ch
- '0');
671 return static_cast<short>(numval
);
674 void controller_frame_vector::resize(size_t newsize
) throw(std::bad_alloc
)
679 } else if(newsize
< frames
) {
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
++)
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
);
691 } else if(newsize
> frames
) {
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
++) {
700 for(size_t i
= current_pages
; i
< pages_needed
; i
++)
710 controller_frame::controller_frame() throw()
712 memset(memory
, 0, sizeof(memory
));
714 for(unsigned i
= 0; i
< MAX_PORTS
; i
++) {
715 offsets
[i
] = SYSTEM_BYTES
;
716 types
[i
] = PT_INVALID
;
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
)
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
++) {
736 newpinfo
[i
] = pinfo
[i
];
738 newpinfo
[i
] = &porttype_info::lookup(ptype
);
739 newoffsets
[i
] = offset
;
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
);
747 pinfo
[port
] = newpinfo
[port
];
748 for(size_t i
= 0; i
< MAX_PORTS
; i
++)
749 offsets
[i
] = newoffsets
[i
];
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])
769 unsigned p1devs
= porttypeinfo
[0]->controllers
;
770 unsigned p2devs
= porttypeinfo
[1]->controllers
;
771 if(lcid
>= p1devs
+ p2devs
)
773 //Exceptional: If p1 is none, map all to p2.
775 return lcid
+ MAX_CONTROLLERS_PER_PORT
;
776 //LID 0 Is always PID 0 unless out of range.
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).
784 return lcid
- p2devs
;
787 int controller_state::acid_to_pcid(unsigned acid
) throw()
789 if(acid
> MAX_ANALOG
)
791 return analog_indices
[acid
];
794 bool controller_state::acid_is_mouse(unsigned acid
) throw()
796 if(acid
> MAX_ANALOG
)
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
)
807 return porttypeinfo
[port
]->devicetype(pcid
% MAX_CONTROLLERS_PER_PORT
);
810 controller_frame
controller_state::get(uint64_t framenum
) throw()
813 return _input
^ _autohold
^ _autofire
[framenum
% _autofire
.size()];
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
;
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()
832 _input
.delay(std::make_pair(delay
/ 10000, delay
% 10000));
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
)
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
)
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");
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.
890 porttypes
[port
] = ptype
;
891 porttypeinfo
[port
] = info
;
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
])
898 devicetype_t d
= porttypeinfo
[j
/ MAX_CONTROLLERS_PER_PORT
]->devicetype(j
% MAX_CONTROLLERS_PER_PORT
);
904 analog_mouse
[i
] = true;
905 analog_indices
[i
++] = j
;
908 analog_mouse
[i
] = false;
909 analog_indices
[i
++] = j
;
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
);
930 controller_frame
controller_state::get_committed() throw()
935 controller_frame
controller_state::commit(controller_frame controls
) throw()
937 _committed
= controls
;
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
);