mirror of
https://github.com/djhackersdev/legacy-tools.git
synced 2026-10-07 13:07:55 +03:00
303 lines
6.3 KiB
C
303 lines
6.3 KiB
C
#include "libutil/stdafx.h"
|
|
|
|
#include "libutil/dinput.h"
|
|
#include "libutil/input.h"
|
|
#include "libutil/joystick.h"
|
|
#include "libutil/keyboard.h"
|
|
#include "libutil/midi.h"
|
|
#include "libutil/mouse.h"
|
|
|
|
static const char config_file[] = "config.dat";
|
|
static u8_t state[16];
|
|
static u8_t state_prev[16];
|
|
static struct input_binding *bindings;
|
|
static int nbindings;
|
|
|
|
/*
|
|
* Binding utils
|
|
*/
|
|
|
|
static int binding_cmp(const void *p1, const void *p2)
|
|
{
|
|
const struct input_binding *lhs = p1;
|
|
const struct input_binding *rhs = p2;
|
|
int diff;
|
|
|
|
diff = lhs->code.dev_class - rhs->code.dev_class;
|
|
if (diff != 0) return diff;
|
|
|
|
diff = lhs->code.dev_id - rhs->code.dev_id;
|
|
if (diff != 0) return diff;
|
|
|
|
diff = lhs->code.control_id - rhs->code.control_id;
|
|
return diff;
|
|
}
|
|
|
|
static void input_add_binding(enum dev_class dev_class, u8_t dev_id, u8_t control_id, int action)
|
|
{
|
|
/* Expand bindings[] and perform an insert, preserving binding_cmp() order */
|
|
|
|
struct input_binding new_binding;
|
|
struct input_binding *new_bindings;
|
|
int i;
|
|
|
|
new_binding.code.dev_class = dev_class;
|
|
new_binding.code.dev_id = dev_id;
|
|
new_binding.code.control_id = control_id;
|
|
new_binding.action = action;
|
|
|
|
new_bindings = malloc(sizeof(struct input_binding) * (nbindings + 1));
|
|
|
|
for (i = 0 ; i < nbindings && binding_cmp(&bindings[i], &new_binding) < 0 ; i++) {
|
|
new_bindings[i] = bindings[i];
|
|
}
|
|
|
|
new_bindings[i] = new_binding;
|
|
|
|
for ( ; i < nbindings ; i++) {
|
|
new_bindings[i + 1] = bindings[i];
|
|
}
|
|
|
|
free(bindings);
|
|
|
|
bindings = new_bindings;
|
|
nbindings++;
|
|
}
|
|
|
|
/*
|
|
* Public API
|
|
*/
|
|
|
|
void input_init(void)
|
|
{
|
|
dinput_init();
|
|
joystick_init();
|
|
keyboard_init();
|
|
midi_init();
|
|
mouse_init();
|
|
}
|
|
|
|
const wchar_t *input_describe(enum dev_class dev_class, u8_t dev_id, u8_t control_id)
|
|
{
|
|
switch (dev_class) {
|
|
case DEV_CLASS_KEYBOARD:
|
|
return keyboard_describe(control_id);
|
|
|
|
case DEV_CLASS_JOYSTICK:
|
|
return joystick_describe(dev_id, control_id);
|
|
|
|
case DEV_CLASS_MIDI:
|
|
return midi_describe(dev_id, control_id);
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
bool input_get_binding(enum dev_class dev_class, u8_t dev_id, u8_t control_id, u8_t *action)
|
|
{
|
|
struct input_binding *binding;
|
|
struct input_binding dummy;
|
|
|
|
dummy.code.dev_class = dev_class;
|
|
dummy.code.dev_id = dev_id;
|
|
dummy.code.control_id = control_id;
|
|
binding = bsearch(&dummy, bindings, nbindings, sizeof(struct input_binding), binding_cmp);
|
|
|
|
if (binding) {
|
|
*action = binding->action;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
const struct input_binding *input_get_bindings(void)
|
|
{
|
|
return bindings;
|
|
}
|
|
|
|
const wchar_t *input_get_name(enum dev_class dev_class, u8_t dev_id)
|
|
{
|
|
switch (dev_class) {
|
|
case DEV_CLASS_KEYBOARD:
|
|
return L"Keyboard";
|
|
|
|
case DEV_CLASS_JOYSTICK:
|
|
return joystick_get_name(dev_id);
|
|
|
|
case DEV_CLASS_MIDI:
|
|
return midi_get_name(dev_id);
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
int input_get_nbindings(void)
|
|
{
|
|
return nbindings;
|
|
}
|
|
|
|
int input_get_ncontrols(enum dev_class dev_class)
|
|
{
|
|
switch (dev_class) {
|
|
case DEV_CLASS_KEYBOARD:
|
|
return KEYBOARD_NCONTROLS;
|
|
|
|
case DEV_CLASS_JOYSTICK:
|
|
return JOYSTICK_NCONTROLS;
|
|
|
|
case DEV_CLASS_MIDI:
|
|
return MIDI_NCONTROLS;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int input_get_ndevs(enum dev_class dev_class)
|
|
{
|
|
switch (dev_class) {
|
|
case DEV_CLASS_KEYBOARD:
|
|
return 1;
|
|
|
|
case DEV_CLASS_JOYSTICK:
|
|
return joystick_get_ndevs();
|
|
|
|
case DEV_CLASS_MIDI:
|
|
return midi_get_ndevs();
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
const u8_t *input_get_state(enum dev_class dev_class, u8_t dev_id)
|
|
{
|
|
switch (dev_class) {
|
|
case DEV_CLASS_KEYBOARD:
|
|
return dev_id == 0 ? keyboard_get_state() : NULL;
|
|
|
|
case DEV_CLASS_JOYSTICK:
|
|
return joystick_get_state(dev_id);
|
|
|
|
case DEV_CLASS_MIDI:
|
|
return midi_get_state(dev_id);
|
|
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
void input_scan(input_callback_t cb, void *ctx)
|
|
{
|
|
int i;
|
|
u8_t bit;
|
|
u8_t byte;
|
|
const u8_t *dev_state;
|
|
|
|
input_update();
|
|
memset(state, 0, sizeof(state));
|
|
|
|
for (i = 0 ; i < nbindings ; i++) {
|
|
/* Get state of bound control */
|
|
switch (bindings[i].code.dev_class) {
|
|
case DEV_CLASS_KEYBOARD:
|
|
dev_state = keyboard_get_state();
|
|
break;
|
|
|
|
case DEV_CLASS_JOYSTICK:
|
|
dev_state = joystick_get_state(bindings[i].code.dev_id);
|
|
break;
|
|
|
|
case DEV_CLASS_MIDI:
|
|
dev_state = midi_get_state(bindings[i].code.dev_id);
|
|
break;
|
|
}
|
|
|
|
if (dev_state != NULL && dev_state[bindings[i].code.control_id]) {
|
|
/* Locate action bit in state[] */
|
|
bit = 1 << (bindings[i].action % 8);
|
|
byte = bindings[i].action / 8;
|
|
|
|
/* Fire callback, set action state bit */
|
|
cb(bindings[i].action, (state_prev[byte] & bit) == 0, ctx);
|
|
state[byte] |= bit;
|
|
}
|
|
}
|
|
|
|
memcpy(state_prev, state, sizeof(state));
|
|
}
|
|
|
|
void input_set_binding(enum dev_class dev_class, u8_t dev_id, u8_t control_id, u8_t action)
|
|
{
|
|
struct input_binding dummy;
|
|
struct input_binding *binding;
|
|
|
|
trace(L"input_set_binding(%d, %d, %d, %d)\n", dev_class, dev_id, control_id, action);
|
|
|
|
dummy.code.dev_class = dev_class;
|
|
dummy.code.dev_id = dev_id;
|
|
dummy.code.control_id = control_id;
|
|
binding = bsearch(&dummy, bindings, nbindings, sizeof(struct input_binding), binding_cmp);
|
|
|
|
if (binding != NULL) {
|
|
binding->action = action;
|
|
} else {
|
|
input_add_binding(dev_class, dev_id, control_id, action);
|
|
}
|
|
}
|
|
|
|
void input_set_bindings(struct input_binding *new_bindings, int new_nbindings)
|
|
{
|
|
free(bindings);
|
|
|
|
bindings = new_bindings;
|
|
nbindings = new_nbindings;
|
|
}
|
|
|
|
void input_unbind(enum dev_class dev_class, u8_t dev_id, u8_t control_id)
|
|
{
|
|
struct input_binding dummy;
|
|
int i;
|
|
|
|
trace(L"input_unbind(%d, %d, %d)\n", dev_class, dev_id, control_id);
|
|
|
|
dummy.code.dev_class = dev_class;
|
|
dummy.code.dev_id = dev_id;
|
|
dummy.code.control_id = control_id;
|
|
|
|
/* Locate the offending binding */
|
|
for (i = 0 ; i < nbindings && binding_cmp(&bindings[i], &dummy) != 0 ; i++);
|
|
|
|
/* Move everything else down to cover the gap */
|
|
if (i < nbindings) {
|
|
for ( ; i + 1 < nbindings ; i++) {
|
|
bindings[i] = bindings[i + 1];
|
|
}
|
|
|
|
nbindings--;
|
|
}
|
|
}
|
|
|
|
void input_update(void)
|
|
{
|
|
joystick_update();
|
|
keyboard_update();
|
|
midi_update();
|
|
}
|
|
|
|
void input_fini(void)
|
|
{
|
|
free(bindings);
|
|
bindings = NULL;
|
|
nbindings = 0;
|
|
|
|
mouse_fini();
|
|
midi_fini();
|
|
keyboard_fini();
|
|
joystick_fini();
|
|
dinput_fini();
|
|
}
|