1 #include "core/controllerframe.hpp"
2 #include "core/dispatch.hpp"
3 #include "core/misc.hpp"
12 std::set
<porttype_info
*>& porttypes()
14 static std::set
<porttype_info
*> p
;
18 const char* buttonnames
[MAX_LOGICAL_BUTTONS
] = {
19 "left", "right", "up", "down", "A", "B", "X", "Y", "L", "R", "select", "start", "trigger",
20 "cursor", "turbo", "pause"
25 * Get name of logical button.
27 * Parameter lbid: ID of logical button.
28 * Returns: The name of button.
29 * Throws std::bad_alloc: Not enough memory.
31 std::string
get_logical_button_name(unsigned lbid
) throw(std::bad_alloc
)
33 if(lbid
>= MAX_LOGICAL_BUTTONS
)
35 return buttonnames
[lbid
];
38 const porttype_info
& porttype_info::lookup(porttype_t p
) throw(std::runtime_error
)
40 for(auto i
: porttypes())
43 throw std::runtime_error("Bad port type");
46 const porttype_info
& porttype_info::lookup(const std::string
& p
) throw(std::runtime_error
)
48 for(auto i
: porttypes())
51 throw std::runtime_error("Bad port type");
54 porttype_info::~porttype_info() throw()
56 porttypes().erase(this);
59 porttype_info::porttype_info(porttype_t ptype
, const std::string
& pname
, size_t psize
) throw(std::bad_alloc
)
64 porttypes().insert(this);
67 pollcounter_vector::pollcounter_vector() throw()
72 void pollcounter_vector::clear() throw()
75 memset(ctrs
, 0, sizeof(ctrs
));
78 void pollcounter_vector::set_all_DRDY() throw()
80 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
81 ctrs
[i
] |= 0x80000000UL
;
84 #define INDEXOF(pcid, ctrl) ((pcid) * MAX_CONTROLS_PER_CONTROLLER + (ctrl))
86 void pollcounter_vector::clear_DRDY(unsigned pcid
, unsigned ctrl
) throw()
88 ctrs
[INDEXOF(pcid
, ctrl
)] &= 0x7FFFFFFFUL
;
91 bool pollcounter_vector::get_DRDY(unsigned pcid
, unsigned ctrl
) throw()
93 return ((ctrs
[INDEXOF(pcid
, ctrl
)] & 0x80000000UL
) != 0);
96 bool pollcounter_vector::has_polled() throw()
98 uint32_t res
= system_flag
? 1 : 0;
99 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
101 return ((res
& 0x7FFFFFFFUL
) != 0);
104 uint32_t pollcounter_vector::get_polls(unsigned pcid
, unsigned ctrl
) throw()
106 return ctrs
[INDEXOF(pcid
, ctrl
)] & 0x7FFFFFFFUL
;
109 uint32_t pollcounter_vector::increment_polls(unsigned pcid
, unsigned ctrl
) throw()
111 size_t i
= INDEXOF(pcid
, ctrl
);
112 uint32_t x
= ctrs
[i
] & 0x7FFFFFFFUL
;
117 void pollcounter_vector::set_system() throw()
122 bool pollcounter_vector::get_system() throw()
127 uint32_t pollcounter_vector::max_polls() throw()
129 uint32_t max
= system_flag
? 1 : 0;
130 for(unsigned i
= 0; i
< MAX_BUTTONS
; i
++) {
131 uint32_t tmp
= ctrs
[i
] & 0x7FFFFFFFUL
;
132 max
= (max
< tmp
) ? tmp
: max
;
137 void pollcounter_vector::save_state(std::vector
<uint32_t>& mem
) throw(std::bad_alloc
)
139 mem
.resize(4 + MAX_BUTTONS
);
141 mem
[0] = 0x80000000UL
;
142 mem
[1] = system_flag
? 1 : 0x80000000UL
;
143 mem
[2] = system_flag
? 1 : 0x80000000UL
;
144 mem
[3] = system_flag
? 1 : 0x80000000UL
;
145 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
146 mem
[4 + i
] = ctrs
[i
];
149 void pollcounter_vector::load_state(const std::vector
<uint32_t>& mem
) throw()
151 system_flag
= (mem
[1] | mem
[2] | mem
[3]) & 0x7FFFFFFFUL
;
152 for(size_t i
= 0; i
< MAX_BUTTONS
; i
++)
153 ctrs
[i
] = mem
[i
+ 4];
156 bool pollcounter_vector::check(const std::vector
<uint32_t>& mem
) throw()
158 return (mem
.size() == MAX_BUTTONS
+ 4);
162 controller_frame::controller_frame(porttype_t p1
, porttype_t p2
) throw(std::runtime_error
)
164 memset(memory
, 0, sizeof(memory
));
171 controller_frame::controller_frame(unsigned char* mem
, porttype_t p1
, porttype_t p2
) throw(std::runtime_error
)
174 throw std::runtime_error("NULL backing memory not allowed");
175 memset(memory
, 0, sizeof(memory
));
182 controller_frame::controller_frame(const controller_frame
& obj
) throw()
184 memset(memory
, 0, sizeof(memory
));
186 set_types(obj
.types
);
187 memcpy(backing
, obj
.backing
, totalsize
);
190 controller_frame
& controller_frame::operator=(const controller_frame
& obj
) throw(std::runtime_error
)
192 set_types(obj
.types
);
193 memcpy(backing
, obj
.backing
, totalsize
);
196 void controller_frame::set_types(const porttype_t
* tarr
)
198 for(unsigned i
= 0; i
< MAX_PORTS
; i
++) {
199 if(memory
!= backing
&& types
[i
] != tarr
[i
])
200 throw std::runtime_error("Controller_frame: Type mismatch");
201 if(!porttype_info::lookup(tarr
[i
]).legal(i
))
202 throw std::runtime_error("Illegal port type for port index");
204 size_t offset
= SYSTEM_BYTES
;
205 for(unsigned i
= 0; i
< MAX_PORTS
; i
++) {
208 pinfo
[i
] = &porttype_info::lookup(tarr
[i
]);
209 offset
+= pinfo
[i
]->storage_size
;
214 size_t controller_frame_vector::walk_helper(size_t frame
, bool sflag
) throw()
216 size_t ret
= sflag
? frame
: 0;
221 size_t page
= frame
/ frames_per_page
;
222 size_t offset
= frame_size
* (frame
% frames_per_page
);
223 size_t index
= frame
% frames_per_page
;
224 if(cache_page_num
!= page
) {
225 cache_page
= &pages
[page
];
226 cache_page_num
= page
;
228 while(frame
< frames
) {
229 if(index
== frames_per_page
) {
231 cache_page
= &pages
[page
];
232 cache_page_num
= page
;
234 if(controller_frame::sync(cache_page
->content
+ offset
))
237 offset
+= frame_size
;
244 size_t controller_frame_vector::count_frames() throw()
250 cache_page
= &pages
[0];
253 for(size_t i
= 0; i
< frames
; i
++) {
254 if(index
== frames_per_page
) {
256 cache_page
= &pages
[cache_page_num
];
260 if(controller_frame::sync(cache_page
->content
+ offset
))
263 offset
+= frame_size
;
269 void controller_frame_vector::clear(enum porttype_t p1
, enum porttype_t p2
) throw(std::runtime_error
)
271 controller_frame
check(p1
, p2
);
272 frame_size
= check
.size();
273 frames_per_page
= CONTROLLER_PAGE_SIZE
/ frame_size
;
281 controller_frame_vector::~controller_frame_vector() throw()
287 controller_frame_vector::controller_frame_vector(enum porttype_t p1
, enum porttype_t p2
) throw(std::runtime_error
)
292 void controller_frame_vector::append(controller_frame frame
) throw(std::bad_alloc
, std::runtime_error
)
294 controller_frame
check(types
[0], types
[1]);
295 if(!check
.types_match(frame
))
296 throw std::runtime_error("controller_frame_vector::append: Type mismatch");
297 if(frames
% frames_per_page
== 0) {
299 pages
[frames
/ frames_per_page
];
302 size_t page
= frames
/ frames_per_page
;
303 size_t offset
= frame_size
* (frames
% frames_per_page
);
304 if(cache_page_num
!= page
) {
305 cache_page_num
= page
;
306 cache_page
= &pages
[page
];
308 controller_frame(cache_page
->content
+ offset
, types
[0], types
[1]) = frame
;
312 controller_frame_vector::controller_frame_vector(const controller_frame_vector
& vector
) throw(std::bad_alloc
)
314 clear(vector
.types
[0], vector
.types
[1]);
318 controller_frame_vector
& controller_frame_vector::operator=(const controller_frame_vector
& v
)
319 throw(std::bad_alloc
)
327 frame_size
= v
.frame_size
;
328 frames_per_page
= v
.frames_per_page
;
329 for(size_t i
= 0; i
< MAX_PORTS
; i
++)
330 types
[i
] = v
.types
[i
];
332 //This can't fail anymore. Copy the raw page contents.
333 size_t pagecount
= (frames
+ frames_per_page
- 1) / frames_per_page
;
334 for(size_t i
= 0; i
< pagecount
; i
++) {
336 const page
& pg2
= v
.pages
.find(i
)->second
;
343 size_t controller_frame::system_serialize(const unsigned char* buffer
, char* textbuf
)
346 if(buffer
[1] || buffer
[2] || buffer
[3] || buffer
[4])
347 sprintf(tmp
, "%c%c %i %i", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'),
348 unserialize_short(buffer
+ 1), unserialize_short(buffer
+ 3));
350 sprintf(tmp
, "%c%c", ((buffer
[0] & 1) ? 'F' : '.'), ((buffer
[0] & 2) ? 'R' : '.'));
351 size_t len
= strlen(tmp
);
352 memcpy(textbuf
, tmp
, len
);
356 size_t controller_frame::system_deserialize(unsigned char* buffer
, const char* textbuf
)
360 if(read_button_value(textbuf
, idx
))
362 if(read_button_value(textbuf
, idx
))
364 serialize_short(buffer
+ 1, read_axis_value(textbuf
, idx
));
365 serialize_short(buffer
+ 3, read_axis_value(textbuf
, idx
));
366 skip_rest_of_field(textbuf
, idx
, false);
370 short read_axis_value(const char* buf
, size_t& idx
) throw()
374 while(is_nonterminator(buf
[idx
])) {
376 if(ch
!= ' ' && ch
!= '\t')
380 //Read the sign if any.
381 if(!is_nonterminator(buf
[idx
]))
383 bool negative
= false;
391 //Read numeric value.
393 while(!is_nonterminator(buf
[idx
]) && isdigit(static_cast<unsigned char>(ch
= buf
[idx
]))) {
394 numval
= numval
* 10 + (ch
- '0');
400 return static_cast<short>(numval
);
403 void controller_frame_vector::resize(size_t newsize
) throw(std::bad_alloc
)
408 } else if(newsize
< frames
) {
410 size_t current_pages
= (frames
+ frames_per_page
- 1) / frames_per_page
;
411 size_t pages_needed
= (newsize
+ frames_per_page
- 1) / frames_per_page
;
412 for(size_t i
= pages_needed
; i
< current_pages
; i
++)
414 //Now zeroize the excess memory.
415 size_t offset
= frame_size
* (newsize
% frames_per_page
);
416 memset(pages
[pages_needed
- 1].content
+ offset
, 0, CONTROLLER_PAGE_SIZE
- offset
);
418 } else if(newsize
> frames
) {
420 size_t current_pages
= (frames
+ frames_per_page
- 1) / frames_per_page
;
421 size_t pages_needed
= (newsize
+ frames_per_page
- 1) / frames_per_page
;
422 //Create the needed pages.
423 for(size_t i
= current_pages
; i
< pages_needed
; i
++) {
427 for(size_t i
= current_pages
; i
< pages_needed
; i
++)
437 controller_frame::controller_frame() throw()
439 memset(memory
, 0, sizeof(memory
));
441 for(unsigned i
= 0; i
< MAX_PORTS
; i
++) {
442 offsets
[i
] = SYSTEM_BYTES
;
443 types
[i
] = PT_INVALID
;
446 totalsize
= SYSTEM_BYTES
;
449 void controller_frame::set_port_type(unsigned port
, porttype_t ptype
) throw(std::runtime_error
)
451 char tmp
[MAXIMUM_CONTROLLER_FRAME_SIZE
] = {0};
452 if(!porttype_info::lookup(ptype
).legal(port
))
453 throw std::runtime_error("Illegal port type for port index");
454 if(memory
!= backing
)
455 throw std::runtime_error("Can't set port type on non-dedicated controller frame");
456 if(port
>= MAX_PORTS
)
458 const porttype_info
* newpinfo
[MAX_PORTS
];
459 size_t newoffsets
[MAX_PORTS
];
460 size_t offset
= SYSTEM_BYTES
;
461 for(size_t i
= 0; i
< MAX_PORTS
; i
++) {
463 newpinfo
[i
] = pinfo
[i
];
465 newpinfo
[i
] = &porttype_info::lookup(ptype
);
466 newoffsets
[i
] = offset
;
468 offset
+= newpinfo
[i
]->storage_size
;
469 if(i
!= port
&& newpinfo
[i
] && newpinfo
[i
]->storage_size
)
470 memcpy(tmp
+ newoffsets
[i
], backing
+ offsets
[i
], newpinfo
[i
]->storage_size
);
472 memcpy(memory
, tmp
, MAXIMUM_CONTROLLER_FRAME_SIZE
);
474 pinfo
[port
] = newpinfo
[port
];
475 for(size_t i
= 0; i
< MAX_PORTS
; i
++)
476 offsets
[i
] = newoffsets
[i
];
480 controller_state::controller_state() throw()
482 for(size_t i
= 0; i
< MAX_ANALOG
; i
++) {
483 analog_indices
[i
] = -1;
484 analog_mouse
[i
] = false;
486 for(size_t i
= 0; i
< MAX_PORTS
; i
++) {
487 porttypes
[i
] = PT_INVALID
;
488 porttypeinfo
[i
] = NULL
;
492 int controller_state::lcid_to_pcid(unsigned lcid
) throw()
494 if(!porttypeinfo
[0] || !porttypeinfo
[1])
496 unsigned p1devs
= porttypeinfo
[0]->controllers();
497 unsigned p2devs
= porttypeinfo
[1]->controllers();
498 if(lcid
>= p1devs
+ p2devs
)
500 //Exceptional: If p1 is none, map all to p2.
502 return lcid
+ MAX_CONTROLLERS_PER_PORT
;
503 //LID 0 Is always PID 0 unless out of range.
506 //LID 1-n are on port 2.
507 else if(lcid
< 1 + p2devs
)
508 return lcid
- 1 + MAX_CONTROLLERS_PER_PORT
;
509 //From there, those are on port 1 (except for the first).
511 return lcid
- p2devs
;
514 int controller_state::acid_to_pcid(unsigned acid
) throw()
516 if(acid
> MAX_ANALOG
)
518 return analog_indices
[acid
];
521 bool controller_state::acid_is_mouse(unsigned acid
) throw()
523 if(acid
> MAX_ANALOG
)
525 return analog_mouse
[acid
];
529 devicetype_t
controller_state::pcid_to_type(unsigned pcid
) throw()
531 size_t port
= pcid
/ MAX_CONTROLLERS_PER_PORT
;
532 if(port
>= MAX_PORTS
)
534 return porttypeinfo
[port
]->devicetype(pcid
% MAX_CONTROLLERS_PER_PORT
);
537 controller_frame
controller_state::get(uint64_t framenum
) throw()
540 return _input
^ _autohold
^ _autofire
[framenum
% _autofire
.size()];
542 return _input
^ _autohold
;
545 void controller_state::analog(unsigned acid
, int x
, int y
) throw()
547 if(acid
>= MAX_ANALOG
|| analog_indices
[acid
] < 0) {
548 messages
<< "No analog controller #" << acid
<< std::endl
;
551 _input
.axis(analog_indices
[acid
], 0, x
);
552 _input
.axis(analog_indices
[acid
], 1, y
);
555 void controller_state::reset(int32_t delay
) throw()
559 _input
.delay(std::make_pair(delay
/ 10000, delay
% 10000));
562 _input
.delay(std::make_pair(0, 0));
566 void controller_state::autohold(unsigned pcid
, unsigned pbid
, bool newstate
) throw()
568 _autohold
.axis(pcid
, pbid
, newstate
? 1 : 0);
569 information_dispatch::do_autohold_update(pcid
, pbid
, newstate
);
572 bool controller_state::autohold(unsigned pcid
, unsigned pbid
) throw()
574 return (_autohold
.axis(pcid
, pbid
) != 0);
577 void controller_state::button(unsigned pcid
, unsigned pbid
, bool newstate
) throw()
579 _input
.axis(pcid
, pbid
, newstate
? 1 : 0);
582 bool controller_state::button(unsigned pcid
, unsigned pbid
) throw()
584 return (_input
.axis(pcid
, pbid
) != 0);
587 void controller_state::autofire(std::vector
<controller_frame
> pattern
) throw(std::bad_alloc
)
592 int controller_state::button_id(unsigned pcid
, unsigned lbid
) throw()
594 size_t port
= pcid
/ MAX_CONTROLLERS_PER_PORT
;
595 if(port
>= MAX_PORTS
)
597 return porttypeinfo
[port
]->button_id(pcid
% MAX_CONTROLLERS_PER_PORT
, lbid
);
600 void controller_state::set_port(unsigned port
, porttype_t ptype
, bool set_core
) throw(std::runtime_error
)
602 if(port
>= MAX_PORTS
)
603 throw std::runtime_error("Port number invalid");
604 const porttype_info
* info
= &porttype_info::lookup(ptype
);
605 if(!info
->legal(port
))
606 throw std::runtime_error("Port type not valid for port");
608 info
->set_core_controller(port
);
609 porttype_t oldtype
= porttypes
[port
];
610 if(oldtype
!= ptype
) {
611 _input
.set_port_type(port
, ptype
);
612 _autohold
.set_port_type(port
, ptype
);
613 _committed
.set_port_type(port
, ptype
);
614 //The old autofire pattern no longer applies.
617 porttypes
[port
] = ptype
;
618 porttypeinfo
[port
] = info
;
620 for(unsigned j
= 0; j
< MAX_ANALOG
; j
++)
621 analog_indices
[j
] = -1;
622 for(unsigned j
= 0; j
< MAX_PORTS
* MAX_CONTROLLERS_PER_PORT
; j
++) {
623 if(!porttypeinfo
[j
/ MAX_CONTROLLERS_PER_PORT
])
625 devicetype_t d
= porttypeinfo
[j
/ MAX_CONTROLLERS_PER_PORT
]->devicetype(j
% MAX_CONTROLLERS_PER_PORT
);
631 analog_mouse
[i
] = true;
632 analog_indices
[i
++] = j
;
636 analog_mouse
[i
] = false;
637 analog_indices
[i
++] = j
;
643 information_dispatch::do_autohold_reconfigure();
646 controller_frame
controller_state::get_blank() throw()
648 return _input
.blank_frame();
651 std::string
controller_state::lcid_to_typestring(unsigned lcid
) throw(std::bad_alloc
)
653 int pcid
= lcid_to_pcid(lcid
);
654 devicetype_t dtype
= DT_NONE
;
656 dtype
= pcid_to_type(pcid
);
658 case DT_NONE
: return "disconnected";
659 case DT_GAMEPAD
: return "gamepad";
660 case DT_MOUSE
: return "mouse";
661 case DT_SUPERSCOPE
: return "superscope";
662 case DT_JUSTIFIER
: return "justifier";
663 default: return "unknown";
667 controller_frame
controller_state::commit(uint64_t framenum
) throw()
669 controller_frame f
= get(framenum
);
674 controller_frame
controller_state::get_committed() throw()
679 controller_frame
controller_state::commit(controller_frame controls
) throw()
681 _committed
= controls
;