Extend Button/Key remap to support chording (#1063)
* Extend Button/Key remap to support chording * Add saved autofire setting to 'advanced/chord' dialog
This commit is contained in:
35
autofire.cpp
35
autofire.cpp
@@ -39,8 +39,10 @@ struct AutofireData {
|
||||
struct AutofireTable {
|
||||
int count; // number of entries
|
||||
int index[MAX_AF_CODES]; // index of matching autofire rate in autofiredata[]
|
||||
bool locked[MAX_AF_CODES];
|
||||
uint32_t mask[MAX_AF_CODES]; // bitmask representing which buttons this code represents
|
||||
uint32_t autofirecodes[MAX_AF_CODES]; // codes that have autofire set (or codes that had it set, then disabled)
|
||||
|
||||
};
|
||||
|
||||
static struct AutofireTable autofiretable[NUMPLAYERS]; // tracks autofire state per key per player
|
||||
@@ -49,6 +51,13 @@ static struct AutofireData autofiredata_default[MAX_AF_RATES]; // hardcoded fall
|
||||
static int num_af_rates_default = 0;
|
||||
static int num_af_rates = 0;
|
||||
|
||||
|
||||
int get_autofire_rate_count()
|
||||
{
|
||||
return num_af_rates;
|
||||
}
|
||||
|
||||
|
||||
static void set_autofire_name(struct AutofireData *data, const char *base_name) {
|
||||
float hz = data->cycle_length > 0 ? (60.0f / data->cycle_length) : 0.0f;
|
||||
if (base_name && base_name[0]) {
|
||||
@@ -68,17 +77,28 @@ int get_autofire_code_idx(int player, uint32_t code) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// returns the locked status for an autofire code
|
||||
bool get_autofire_locked(int player, uint32_t code)
|
||||
{
|
||||
for (int i = 0; i != autofiretable[player].count; i++)
|
||||
{
|
||||
if (autofiretable[player].autofirecodes[i] == code)
|
||||
return autofiretable[player].locked[i];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// autofire structs are private to this unit, so we offer a helper to clear them
|
||||
void clear_autofire(int player) {
|
||||
memset(&autofiretable[player], 0, sizeof(AutofireTable));
|
||||
}
|
||||
|
||||
// set autofire index for a code: >0 enable, 0 disable.
|
||||
void set_autofire_code(int player, uint32_t code, uint32_t mask, int index) {
|
||||
void set_autofire_code(int player, uint32_t code, uint32_t mask, int index, bool locked) {
|
||||
for (int i = 0; i != autofiretable[player].count; i++) {
|
||||
if (autofiretable[player].autofirecodes[i] == code) {
|
||||
autofiretable[player].index[i] = index;
|
||||
autofiretable[player].mask[i] = mask;
|
||||
autofiretable[player].locked[i] = locked;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -90,11 +110,15 @@ void set_autofire_code(int player, uint32_t code, uint32_t mask, int index) {
|
||||
autofiretable[player].autofirecodes[idx] = code;
|
||||
autofiretable[player].index[idx] = index;
|
||||
autofiretable[player].mask[idx] = mask;
|
||||
autofiretable[player].locked[idx] = locked;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// step autofire rate; wrap to disabled at max.
|
||||
void inc_autofire_code(int player, uint32_t code, uint32_t mask) {
|
||||
if (get_autofire_locked(player, code)) return;
|
||||
|
||||
int index = get_autofire_code_idx(player, code) + 1;
|
||||
if (index <= 0) index = 1;
|
||||
if (index >= num_af_rates || index < 0) index = 0;
|
||||
@@ -122,8 +146,8 @@ bool get_autofire_bit(int player, uint32_t code, uint32_t frame_count) {
|
||||
}
|
||||
|
||||
// display-only rate lookup for ui.
|
||||
const char *get_autofire_rate_hz(int player, uint32_t code) {
|
||||
int rate_idx = get_autofire_code_idx(player, code);
|
||||
//
|
||||
const char *get_autofire_rate_hz(int rate_idx) {
|
||||
if (rate_idx <= 0) {
|
||||
return "disabled";
|
||||
}
|
||||
@@ -133,6 +157,11 @@ const char *get_autofire_rate_hz(int player, uint32_t code) {
|
||||
return "disabled";
|
||||
}
|
||||
|
||||
const char *get_autofire_rate_hz_button(int player, uint32_t code) {
|
||||
int rate_idx = get_autofire_code_idx(player, code);
|
||||
return get_autofire_rate_hz(rate_idx);
|
||||
}
|
||||
|
||||
bool is_autofire_enabled(int player, uint32_t code) {
|
||||
return get_autofire_code_idx(player, code) > 0;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
const char *get_autofire_rate_hz(int player, uint32_t code);
|
||||
const char *get_autofire_rate_hz_button(int player, uint32_t code);
|
||||
const char *get_autofire_rate_hz(int rate_idx);
|
||||
int get_autofire_rate_count();
|
||||
bool is_autofire_enabled(int player, uint32_t code);
|
||||
void clear_autofire(int player);
|
||||
void inc_autofire_code(int player, uint32_t code, uint32_t mask);
|
||||
//void autofire_tick();
|
||||
bool parse_autofire_cfg();
|
||||
bool get_autofire_bit(int player, uint32_t code, uint32_t frame_count);
|
||||
void set_autofire_code(int player, uint32_t code, uint32_t mask, int index, bool locked = false);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -195,14 +195,15 @@ static int find_linux_code_for_button(char *btn_name, uint16_t *btn_map, uint16_
|
||||
#define test_bit(bit, array) (array [bit / 8] & (1 << (bit % 8)))
|
||||
|
||||
|
||||
static void get_ctrl_index_maps(int dev_fd, char *guid, uint16_t *btn_map, uint16_t *abs_map)
|
||||
void get_ctrl_index_maps(int dev_fd, char *guid, uint16_t *btn_map, uint16_t *abs_map)
|
||||
{
|
||||
unsigned char keybits[(KEY_MAX+7) / 8];
|
||||
unsigned char absbits[(ABS_MAX+7) / 8];
|
||||
uint16_t btn_cnt = 0;
|
||||
uint16_t abs_cnt = 0;
|
||||
|
||||
printf("Gamecontrollerdb: mapping buttons for %s ", guid);
|
||||
if (guid)
|
||||
printf("Gamecontrollerdb: mapping buttons for %s ", guid);
|
||||
if (ioctl(dev_fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits) >= 0)
|
||||
{
|
||||
for (int i = BTN_JOYSTICK; i < KEY_MAX; i++)
|
||||
@@ -223,11 +224,13 @@ static void get_ctrl_index_maps(int dev_fd, char *guid, uint16_t *btn_map, uint1
|
||||
btn_cnt++;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
if (guid)
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
|
||||
printf("Gamecontrollerdb: mapping analog axes for %s ", guid);
|
||||
if (guid)
|
||||
printf("Gamecontrollerdb: mapping analog axes for %s ", guid);
|
||||
if (ioctl(dev_fd, EVIOCGBIT(EV_ABS, sizeof(absbits)), absbits) >= 0)
|
||||
{
|
||||
//The "correct" way is to test all the way to ABS_MAX and skip any hats the device has.
|
||||
@@ -253,7 +256,8 @@ static void get_ctrl_index_maps(int dev_fd, char *guid, uint16_t *btn_map, uint1
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
if(guid)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void gcdb_show_string_for_ctrl_map(uint16_t bustype, uint16_t vid, uint16_t pid, uint16_t version,int dev_fd, const char *name, uint32_t *cur_map)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
bool gcdb_map_for_controller(uint16_t bustype, uint16_t vid, uint16_t pid, uint16_t version, int dev_fd, uint32_t *fill_map);
|
||||
void gcdb_show_string_for_ctrl_map(uint16_t bustype, uint16_t vid, uint16_t pid, uint16_t version,int dev_fd, const char *name, uint32_t *cur_map);
|
||||
void get_ctrl_index_maps(int dev_fd, char *guid, uint16_t *btn_map, uint16_t *abs_map);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
572
input.cpp
572
input.cpp
@@ -38,6 +38,8 @@
|
||||
#define NUMDEV 30
|
||||
#define UINPUT_NAME "MiSTer virtual input"
|
||||
|
||||
bool update_advanced_state(int devnum, uint16_t evcode, int evstate);
|
||||
|
||||
char joy_bnames[NUMBUTTONS][32] = {};
|
||||
int joy_bcount = 0;
|
||||
static struct pollfd pool[NUMDEV + 3];
|
||||
@@ -1083,6 +1085,7 @@ static int ev2archie[] =
|
||||
NONE //255 ???
|
||||
};
|
||||
|
||||
|
||||
uint8_t ps2_kbd_scan_set = 2;
|
||||
uint32_t get_ps2_code(uint16_t key)
|
||||
{
|
||||
@@ -1151,8 +1154,6 @@ typedef struct
|
||||
|
||||
uint8_t has_mmap;
|
||||
uint32_t mmap[NUMBUTTONS];
|
||||
uint8_t has_jkmap;
|
||||
uint16_t jkmap[1024];
|
||||
int stick_l[2];
|
||||
int stick_r[2];
|
||||
|
||||
@@ -1206,6 +1207,10 @@ typedef struct
|
||||
float max_range[2];
|
||||
|
||||
uint32_t deadzone;
|
||||
advancedButtonMap advanced_map[ADVANCED_MAP_MAX];
|
||||
advancedButtonState advanced_state[ADVANCED_MAP_MAX];
|
||||
bool has_advanced_map;
|
||||
uint16_t advanced_last_pressed_keycode;
|
||||
} devInput;
|
||||
|
||||
static devInput input[NUMDEV] = {};
|
||||
@@ -1399,15 +1404,20 @@ static int mapping_clear;
|
||||
static int mapping_finish;
|
||||
static int mapping_set;
|
||||
|
||||
|
||||
static int mapping_current_key = 0;
|
||||
static int mapping_current_dev = -1;
|
||||
static advancedButtonMap *mapping_store = NULL;
|
||||
|
||||
static uint32_t tmp_axis[4];
|
||||
static int tmp_axis_n = 0;
|
||||
|
||||
static int grabbed = 1;
|
||||
|
||||
void start_map_setting(int cnt, int set)
|
||||
static uint32_t osd_timer = 0;
|
||||
static uint32_t map_advance_timer = 0;
|
||||
|
||||
void start_map_setting(int cnt, int set, advancedButtonMap *abm_store)
|
||||
{
|
||||
mapping_current_key = 0;
|
||||
mapping_current_dev = -1;
|
||||
@@ -1415,8 +1425,18 @@ void start_map_setting(int cnt, int set)
|
||||
mapping_button = 0;
|
||||
mapping = 1;
|
||||
mapping_set = set;
|
||||
if (!mapping_set)
|
||||
|
||||
if (abm_store)
|
||||
{
|
||||
mapping_type = 3;
|
||||
mapping_store = abm_store;
|
||||
mapping_dev = -1;
|
||||
mapping_set = (cnt == 3) ? 1 : set;
|
||||
if (cnt != 3)
|
||||
memset((set == 1) ? abm_store->input_codes : abm_store->output_codes, 0, sizeof(abm_store->input_codes));
|
||||
osd_timer = 0;
|
||||
map_advance_timer = 0;
|
||||
} else if (!mapping_set) {
|
||||
mapping_dev = -1;
|
||||
mapping_type = (cnt < 0) ? 3 : cnt ? 1 : 2;
|
||||
}
|
||||
@@ -1432,6 +1452,16 @@ void start_map_setting(int cnt, int set)
|
||||
user_io_kbd(KEY_ENTER, 0);
|
||||
}
|
||||
|
||||
advancedButtonMap *get_map_code_store()
|
||||
{
|
||||
return mapping_store;
|
||||
}
|
||||
|
||||
int get_map_count()
|
||||
{
|
||||
return mapping_count;
|
||||
}
|
||||
|
||||
int get_map_set()
|
||||
{
|
||||
return mapping_set;
|
||||
@@ -1457,12 +1487,23 @@ int get_map_finish()
|
||||
return mapping_finish;
|
||||
}
|
||||
|
||||
static uint32_t osd_timer = 0;
|
||||
|
||||
int get_map_dev()
|
||||
{
|
||||
return mapping_dev;
|
||||
}
|
||||
|
||||
|
||||
int get_map_cancel()
|
||||
{
|
||||
return (mapping && !is_menu() && osd_timer && CheckTimer(osd_timer));
|
||||
}
|
||||
|
||||
int get_map_advance()
|
||||
{
|
||||
return (mapping && !is_menu() && map_advance_timer && CheckTimer(map_advance_timer));
|
||||
}
|
||||
|
||||
static char *get_unique_mapping(int dev, int force_unique = 0)
|
||||
{
|
||||
uint32_t vidpid = (input[dev].vid << 16) | input[dev].pid;
|
||||
@@ -1514,17 +1555,25 @@ void finish_map_setting(int dismiss)
|
||||
mapping = 0;
|
||||
if (mapping_dev<0) return;
|
||||
|
||||
if (mapping_type == 3)
|
||||
{
|
||||
if (!dismiss) return;
|
||||
if (mapping_count == 3)
|
||||
{
|
||||
input_advanced_clear(mapping_dev);
|
||||
if (mapping_store) memset(mapping_store, 0, sizeof(advancedButtonMap));
|
||||
} else if (mapping_store) {
|
||||
memset(mapping_set == 2 ? mapping_store->output_codes : mapping_store->input_codes, 0, sizeof(mapping_store->input_codes));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapping_type == 2)
|
||||
{
|
||||
input[mapping_dev].has_kbdmap = 0;
|
||||
if (dismiss) FileDeleteConfig(get_kbdmap_name(mapping_dev));
|
||||
else FileSaveConfig(get_kbdmap_name(mapping_dev), &input[mapping_dev].kbdmap, sizeof(input[mapping_dev].kbdmap));
|
||||
}
|
||||
else if (mapping_type == 3)
|
||||
{
|
||||
if (dismiss) memset(input[mapping_dev].jkmap, 0, sizeof(input[mapping_dev].jkmap));
|
||||
save_map(get_jkmap_name(mapping_dev), &input[mapping_dev].jkmap, sizeof(input[mapping_dev].jkmap));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < NUMDEV; i++)
|
||||
@@ -1643,9 +1692,10 @@ static int keyrah_trans(int key, int press)
|
||||
return key;
|
||||
}
|
||||
|
||||
static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int dev);
|
||||
static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int dev, bool menu_event = false);
|
||||
|
||||
static int kbd_toggle = 0;
|
||||
|
||||
static uint32_t crtgun_timeout[NUMDEV] = {};
|
||||
|
||||
static unsigned char mouse_btn = 0; //emulated mouse
|
||||
@@ -1881,7 +1931,7 @@ static bool handle_autofire_toggle(int num, uint32_t mask, uint32_t code, char p
|
||||
strat += sprintf(strat, "%s\n", joy_bnames[btn-4]);
|
||||
}
|
||||
|
||||
const char *rate = get_autofire_rate_hz(num, lastcode[num]);
|
||||
const char *rate = get_autofire_rate_hz_button(num, lastcode[num]);
|
||||
|
||||
if (!strcmp(rate, "disabled")) {
|
||||
strat += sprintf(strat, "Autofire disabled");
|
||||
@@ -1952,6 +2002,7 @@ static void set_key_state(int player, uint32_t key, bool press, uint32_t mask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (key_states[player].count < MAX_KEY_STATES)
|
||||
{
|
||||
if (press)
|
||||
@@ -2150,8 +2201,7 @@ static void joy_digital(int jnum, uint32_t mask, uint32_t code, char press, int
|
||||
default:
|
||||
ev.code = (bnum == BTN_OSD) ? KEY_MENU : 0;
|
||||
}
|
||||
|
||||
input_cb(&ev, 0, 0);
|
||||
input_cb(&ev, 0, 0, true);
|
||||
}
|
||||
else if (video_fb_state())
|
||||
{
|
||||
@@ -2444,7 +2494,6 @@ static void restore_player(int dev)
|
||||
input[input[dev].bind].map_shown = player[k].map_shown;
|
||||
}
|
||||
|
||||
memcpy(input[dev].jkmap, player[k].jkmap, sizeof(input[dev].jkmap));
|
||||
input[dev].lightgun = player[k].lightgun;
|
||||
break;
|
||||
}
|
||||
@@ -2565,7 +2614,7 @@ static void assign_player(int dev, int num, int force = 0)
|
||||
printf("Device %s %sassigned to player %d\n", input[dev].id, force ? "forcebly " : "", input[dev].num);
|
||||
}
|
||||
|
||||
static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int dev)
|
||||
static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int dev, bool menu_event)
|
||||
{
|
||||
if (ev->type != EV_KEY && ev->type != EV_ABS && ev->type != EV_REL) return;
|
||||
if (ev->type == EV_KEY && (!ev->code || ev->code == KEY_UNKNOWN)) return;
|
||||
@@ -2708,13 +2757,10 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
input[dev].has_map++;
|
||||
}
|
||||
|
||||
if (!input[dev].has_jkmap)
|
||||
if (!input[dev].has_advanced_map)
|
||||
{
|
||||
if (!load_map(get_jkmap_name(dev), &input[dev].jkmap, sizeof(input[dev].jkmap)))
|
||||
{
|
||||
memset(input[dev].jkmap, 0, sizeof(input[dev].jkmap));
|
||||
}
|
||||
input[dev].has_jkmap = 1;
|
||||
input_advanced_load(dev);
|
||||
input[dev].has_advanced_map = true;
|
||||
}
|
||||
|
||||
if (!input[dev].num)
|
||||
@@ -2828,7 +2874,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
if (old_combo != 3 && input[dev].osd_combo == 3)
|
||||
{
|
||||
osd_event = 1;
|
||||
if (mapping && !is_menu()) osd_timer = GetTimer(1000);
|
||||
if (mapping && !is_menu()) osd_timer = mapping_type == 3 ? ((mapping_count < 3 || mapping_set == 1) ? GetTimer(5000) : 0) : GetTimer(1000);
|
||||
}
|
||||
else if (old_combo == 3 && input[dev].osd_combo != 3)
|
||||
{
|
||||
@@ -2844,23 +2890,61 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
else
|
||||
{
|
||||
map_skip = 1;
|
||||
ev->value = 1;
|
||||
if (mapping_type != 3) ev->value = 1;
|
||||
}
|
||||
}
|
||||
osd_timer = 0;
|
||||
}
|
||||
|
||||
if (mapping && mapping_type == 3)
|
||||
{
|
||||
if (map_skip)
|
||||
{
|
||||
mapping_finish = 1;
|
||||
ev->value = 0;
|
||||
}
|
||||
osd_event = 0;
|
||||
}
|
||||
|
||||
//mapping
|
||||
|
||||
if (mapping && mapping_type == 3 && ev->type == EV_KEY)
|
||||
{
|
||||
bool jkm_can_intr = mapping_count == 3 && mapping_button <= 1 && mapping_set == 1;
|
||||
if (mapping_dev < 0) mapping_dev = dev;
|
||||
if (ev->value == 1 && ev->code == KEY_ENTER) map_skip = 1;
|
||||
if (map_skip && jkm_can_intr)
|
||||
mapping_finish = 1;
|
||||
|
||||
if (jkm_can_intr
|
||||
&& (ev->code == (input[mapping_dev].mmap[SYS_BTN_MENU_FUNC] & 0xFFFF) || ev->code == KEY_F12))
|
||||
map_advance_timer = ev->value ? (ev->code == KEY_F12) ? 1 : GetTimer(5000) : 0;
|
||||
|
||||
if (ev->value == 1)
|
||||
{
|
||||
uint16_t *code_store = mapping_set == 1 ? mapping_store->input_codes : mapping_store->output_codes;
|
||||
code_store[mapping_button++] = ev->code;
|
||||
mapping_current_dev = mapping_dev;
|
||||
if (mapping_button == sizeof(mapping_store->input_codes)/sizeof(mapping_store->input_codes[0])) //Don't overflow, just keep replacing the last entry
|
||||
mapping_button--;
|
||||
if (mapping_button > 1)
|
||||
osd_timer = map_advance_timer = 0;
|
||||
} else if (ev->value == 0 && mapping_button > 0) {
|
||||
if (ev->code == KEY_ESC && (jkm_can_intr || (mapping_count < 3 && mapping_button <= 1)))
|
||||
{
|
||||
osd_timer = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapping_count == 3)
|
||||
{
|
||||
mapping_set++;
|
||||
mapping_button = 0;
|
||||
if (mapping_set > 2)
|
||||
{
|
||||
mapping_set = 1;
|
||||
input_advanced_save_entry(mapping_store, mapping_dev);
|
||||
memset(mapping_store, 0, sizeof(advancedButtonMap));
|
||||
}
|
||||
} else {
|
||||
mapping_finish = 1;
|
||||
}
|
||||
osd_timer = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapping && (mapping_dev >= 0 || ev->value)
|
||||
&& !((mapping_type < 2 || !mapping_button) && (cancel || enter))
|
||||
&& input[dev].quirk != QUIRK_PDSP
|
||||
@@ -2933,33 +3017,6 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (mapping_type == 3) // button remap
|
||||
{
|
||||
if (input[dev].mmap[SYS_BTN_OSD_KTGL] == ev->code ||
|
||||
input[dev].mmap[SYS_BTN_OSD_KTGL + 1] == ev->code ||
|
||||
input[dev].mmap[SYS_BTN_OSD_KTGL + 2] == ev->code) return;
|
||||
|
||||
if (ev->value == 1 && !mapping_button)
|
||||
{
|
||||
if (mapping_dev < 0) mapping_dev = dev;
|
||||
if (mapping_dev == dev && ev->code < 1024) mapping_button = ev->code;
|
||||
mapping_current_dev = mapping_dev;
|
||||
}
|
||||
|
||||
if (mapping_dev >= 0 && (ev->code < 256 || mapping_dev == dev) && mapping_button && mapping_button != ev->code)
|
||||
{
|
||||
if (ev->value == 1)
|
||||
{
|
||||
// Technically it's hard to map the key to button as keyboards
|
||||
// are all the same while joysticks are personalized and numbered.
|
||||
input[mapping_dev].jkmap[mapping_button] = ev->code;
|
||||
mapping_current_dev = dev;
|
||||
}
|
||||
|
||||
if (ev->value == 0) mapping_button = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
int clear = (ev->code == KEY_F12 || ev->code == KEY_MENU || ev->code == KEY_HOMEPAGE) && !is_menu();
|
||||
@@ -3213,7 +3270,6 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
switch (ev->type)
|
||||
{
|
||||
case EV_KEY:
|
||||
if (ev->code < 1024 && input[dev].jkmap[ev->code] && !user_io_osd_is_visible()) ev->code = input[dev].jkmap[ev->code];
|
||||
|
||||
//joystick buttons, digital directions
|
||||
if (ev->code >= 256)
|
||||
@@ -3373,6 +3429,9 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
}
|
||||
}
|
||||
|
||||
if (!menu_event)
|
||||
update_advanced_state(dev, ev->code, ev->value);
|
||||
|
||||
if (ev->code == input[dev].mmap[SYS_MS_BTN_EMU] && (ev->value <= 1) && ((!(mouse_emu & 1)) ^ (!ev->value)))
|
||||
{
|
||||
mouse_emu = ev->value ? mouse_emu | 1 : mouse_emu & ~1;
|
||||
@@ -3413,6 +3472,11 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
if (ev->code == 111) reset_m |= 0x100;
|
||||
user_io_check_reset(reset_m, (keyrah && !cfg.reset_combo) ? 1 : cfg.reset_combo);
|
||||
|
||||
bool send_key = true;
|
||||
if (!menu_event)
|
||||
{
|
||||
send_key = update_advanced_state(dev, ev->code, ev->value);
|
||||
}
|
||||
if(!user_io_osd_is_visible() && ((user_io_get_kbdemu() == EMU_JOY0) || (user_io_get_kbdemu() == EMU_JOY1)) && !video_fb_state())
|
||||
{
|
||||
if (!kbd_toggle)
|
||||
@@ -3501,7 +3565,7 @@ static void input_cb(struct input_event *ev, struct input_absinfo *absinfo, int
|
||||
}
|
||||
|
||||
if (ev->code == KEY_HOMEPAGE) ev->code = KEY_MENU;
|
||||
user_io_kbd(ev->code, ev->value);
|
||||
if (send_key) user_io_kbd(ev->code, ev->value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -5183,6 +5247,7 @@ int input_test(int getchar)
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
if (cfg.rumble && !is_menu())
|
||||
{
|
||||
for (int i = 0; i < NUMDEV; i++)
|
||||
@@ -5197,6 +5262,7 @@ int input_test(int getchar)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int return_value = poll(pool, NUMDEV + 3, timeout);
|
||||
if (!return_value) break;
|
||||
|
||||
@@ -5222,7 +5288,6 @@ int input_test(int getchar)
|
||||
{
|
||||
int i = pos;
|
||||
|
||||
|
||||
if ((pool[i].fd >= 0) && (pool[i].revents & POLLIN))
|
||||
{
|
||||
if (!input[i].mouse)
|
||||
@@ -5871,6 +5936,8 @@ void key_update_frames_held()
|
||||
|
||||
int input_poll(int getchar)
|
||||
{
|
||||
|
||||
static int poll_cnt = 0;
|
||||
PROFILE_FUNCTION();
|
||||
static bool autofire_cfg_parsed = false;
|
||||
if (!autofire_cfg_parsed) autofire_cfg_parsed = parse_autofire_cfg();
|
||||
@@ -6088,3 +6155,382 @@ void parse_buttons()
|
||||
joy_bcount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void advanced_convert_jkmap(int devnum)
|
||||
{
|
||||
|
||||
int abmidx = 0;
|
||||
|
||||
uint16_t jkmap[1024];
|
||||
if (load_map(get_jkmap_name(devnum), jkmap, sizeof(jkmap)))
|
||||
{
|
||||
for(size_t i = 0; i < sizeof(jkmap)/sizeof(jkmap[0]); i++)
|
||||
{
|
||||
if (jkmap[i])
|
||||
{
|
||||
advancedButtonMap *abm = &input[devnum].advanced_map[abmidx++];
|
||||
memset(abm, 0, sizeof(advancedButtonMap));
|
||||
abm->input_codes[0] = i;
|
||||
abm->output_codes[0] = jkmap[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t advanced_get_btn_mask_for_code(uint16_t evcode, int devnum)
|
||||
{
|
||||
uint32_t mask = 0;
|
||||
|
||||
|
||||
for (uint i = 0; i < BTN_NUM; i++)
|
||||
{
|
||||
if (evcode == (input[devnum].map[i] & 0xFFFF)) mask |= 1 << i;
|
||||
else if (evcode == (input[devnum].map[i] >> 16)) mask |= 1 << i;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
//Only called when the pressed state changes for an entry
|
||||
static uint32_t process_abm_entry(advancedButtonMap *abm, advancedButtonState *abs, int devnum)
|
||||
{
|
||||
uint32_t retmask = 0;
|
||||
retmask = abm->button_mask;;
|
||||
for (uint k = 0; k < sizeof(abm->output_codes)/sizeof(abm->output_codes[0]); k++)
|
||||
{
|
||||
if (abm->output_codes[k])
|
||||
{
|
||||
uint32_t ocode = abm->output_codes[k];
|
||||
uint32_t omask = advanced_get_btn_mask_for_code(ocode, devnum);
|
||||
if (!omask && ocode <= 256) //Keyboard
|
||||
{
|
||||
user_io_kbd(ocode, abs->pressed);
|
||||
input[devnum].advanced_last_pressed_keycode = abs->pressed ? ocode : 0;
|
||||
} else {
|
||||
retmask |= omask;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retmask;
|
||||
}
|
||||
|
||||
uint8_t advanced_entry_pressed_state(advancedButtonMap *abm, advancedButtonState *abs, uint16_t evcode, int evstate, int devnum)
|
||||
{
|
||||
int code_cnt = 0;
|
||||
int pressed_cnt = 0;
|
||||
bool chord_has_osd = false;
|
||||
bool is_pressed = true;
|
||||
bool code_is_osd_btn = (evcode == input[devnum].mmap[SYS_BTN_OSD_KTGL+1] || evcode == input[devnum].mmap[SYS_BTN_OSD_KTGL+2]);
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(abm->input_codes)/sizeof(abm->input_codes[0]); i++)
|
||||
{
|
||||
if (!abm->input_codes[i])
|
||||
break;
|
||||
|
||||
if (abm->input_codes[i] == evcode)
|
||||
{
|
||||
if (evstate)
|
||||
abs->input_state |= 1<<i;
|
||||
else
|
||||
abs->input_state &= ~(1<<i);
|
||||
}
|
||||
code_cnt++;
|
||||
if (abs->input_state & 1<<i) pressed_cnt++;
|
||||
if (abm->input_codes[i] == input[devnum].mmap[SYS_BTN_OSD_KTGL+1] || abm->input_codes[i] == input[devnum].mmap[SYS_BTN_OSD_KTGL+2])
|
||||
chord_has_osd = true;
|
||||
}
|
||||
|
||||
if (code_cnt != pressed_cnt)
|
||||
is_pressed = false;
|
||||
|
||||
//if a chord contains the OSD button(s) they have to be first, otherwise it might
|
||||
//interfere with autofire chording.
|
||||
if (code_is_osd_btn && evstate && chord_has_osd && pressed_cnt > 1)
|
||||
is_pressed = false;
|
||||
|
||||
return (is_pressed ? 1 : 0) | ((chord_has_osd ? 1 : 0) << 1);
|
||||
}
|
||||
|
||||
bool update_advanced_state(int devnum, uint16_t evcode, int evstate)
|
||||
{
|
||||
|
||||
bool allow_keysend = true;
|
||||
|
||||
|
||||
if (evstate == 2 && input[devnum].advanced_last_pressed_keycode)
|
||||
{
|
||||
user_io_kbd(input[devnum].advanced_last_pressed_keycode, evstate);
|
||||
return false;
|
||||
}
|
||||
|
||||
int pnum = input[devnum].num;
|
||||
if (!input[devnum].num) {
|
||||
int kbd_emu = user_io_get_kbdemu();
|
||||
if (kbd_emu == EMU_JOY0)
|
||||
pnum = 1;
|
||||
else if (kbd_emu == EMU_JOY1)
|
||||
pnum = 2;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < ADVANCED_MAP_MAX; i++)
|
||||
{
|
||||
advancedButtonMap *abm = &input[devnum].advanced_map[i];
|
||||
advancedButtonState *abs = &input[devnum].advanced_state[i];
|
||||
if (!abm->input_codes[0]) break;
|
||||
|
||||
uint8_t pressed_state = advanced_entry_pressed_state(abm, abs, evcode, evstate, devnum);
|
||||
bool is_pressed = pressed_state & 1;
|
||||
bool chord_has_osd = pressed_state & (1 << 1);
|
||||
abs->last_pressed = abs->pressed;
|
||||
abs->pressed = is_pressed;
|
||||
|
||||
if (abs->last_pressed != abs->pressed)
|
||||
{
|
||||
if (abs->pressed && chord_has_osd && pnum > 0) osd_autofire_consumed[pnum-1] = true; //reuse autofire osd inhibit
|
||||
if (!abs->pressed) abs->input_btn_mask = 0;
|
||||
for(size_t cidx = 0; cidx < sizeof(abm->input_codes)/sizeof(abm->input_codes[0]); cidx++)
|
||||
{
|
||||
int icode = abm->input_codes[cidx];
|
||||
if (!icode) break;
|
||||
|
||||
if (!abs->pressed && !(abs->input_state & 1<<cidx))
|
||||
continue;
|
||||
|
||||
uint32_t imask = advanced_get_btn_mask_for_code(icode, devnum);
|
||||
if (!imask && icode <= 256) //Keyboard
|
||||
{
|
||||
|
||||
if (icode != evcode) user_io_kbd(icode, !abs->pressed);
|
||||
} else { //Joypad
|
||||
if (abs->pressed)
|
||||
{
|
||||
joy_digital(pnum, imask, icode, 0, 0, true);
|
||||
abs->input_btn_mask |= imask;
|
||||
} else {
|
||||
joy_digital(pnum, imask, icode, 1, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
allow_keysend = false;
|
||||
uint32_t usemask = process_abm_entry(abm, abs, devnum);
|
||||
//Update joy_adv mask, store fake button code for autofire support
|
||||
joy_digital(pnum, usemask, 0x8000 | i, abs->pressed, 0, false);
|
||||
if (abs->pressed && abm->autofire_idx)
|
||||
{
|
||||
set_autofire_code(pnum-1, 0x8000 | i, usemask, abm->autofire_idx, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If this return is true input_cb inhibits sending the keyboard event to the core.
|
||||
//Needed so the core doesn't see a keyboard event for the last key in a chord
|
||||
//(or when a single key has been remapped)
|
||||
return allow_keysend;
|
||||
}
|
||||
|
||||
advancedButtonMap *get_advanced_map_defs(int devnum)
|
||||
{
|
||||
if (devnum < 0 || devnum >= NUMDEV)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
devnum = input[devnum].bind;
|
||||
return input[devnum].advanced_map;
|
||||
}
|
||||
|
||||
void get_button_name_for_code(uint16_t btn_code, int devnum, char *bname, size_t bname_sz)
|
||||
{
|
||||
static int last_devnum = -1;
|
||||
static uint16_t btn_map[KEY_MAX - BTN_JOYSTICK] = {0};
|
||||
static uint16_t abs_map[ABS_MAX] = {0};
|
||||
if (devnum != last_devnum)
|
||||
{
|
||||
memset(btn_map, 0xFFFF, sizeof(btn_map));
|
||||
memset(abs_map, 0xFFFF, sizeof(abs_map));
|
||||
get_ctrl_index_maps(pool[devnum].fd, NULL, btn_map, abs_map);
|
||||
last_devnum = devnum;
|
||||
}
|
||||
|
||||
snprintf(bname, bname_sz, "??");
|
||||
if (btn_code >= KEY_EMU) //hat/analog
|
||||
{
|
||||
bool is_max = btn_code & 0x1;
|
||||
uint16_t axis_idx = (btn_code - KEY_EMU) >> 1;
|
||||
if (axis_idx >= ABS_HAT0X && axis_idx <= ABS_HAT3Y)
|
||||
{
|
||||
uint8_t hat_num = (axis_idx - ABS_HAT0X)/2;
|
||||
bool axis_is_y = (axis_idx - ABS_HAT0X)%2;
|
||||
uint8_t hat_sub = 0;
|
||||
|
||||
if (axis_is_y) hat_sub = is_max ? 4 : 1;
|
||||
else hat_sub = is_max ? 2 : 8;
|
||||
|
||||
if (hat_sub)
|
||||
snprintf(bname,bname_sz, "h%d.%d", hat_num, hat_sub);
|
||||
} else {
|
||||
//Mister 'fake' analog digital inputs.
|
||||
for(unsigned int j=0; j < sizeof(abs_map)/sizeof(uint16_t); j++)
|
||||
{
|
||||
if (abs_map[j] == axis_idx)
|
||||
{
|
||||
snprintf(bname, bname_sz, is_max ? "+a%d" : "-a%d", j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(unsigned int j=0; j < sizeof(btn_map)/sizeof(uint16_t); j++)
|
||||
{
|
||||
if (btn_map[j] == 0xFFFF) break;
|
||||
if (btn_map[j] == btn_code) {
|
||||
snprintf(bname, bname_sz, "b%d", j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void input_advanced_save_filename(char *fname, size_t pathlen, int dev_num, bool def=false)
|
||||
{
|
||||
char *id = get_unique_mapping(dev_num);
|
||||
|
||||
if (def || is_menu()) snprintf(fname, pathlen, "advanced_input_%s%s_v1.map", id, input[dev_num].mod ? "_m" : "");
|
||||
else snprintf(fname, pathlen, "%s_advanced_input_%s%s_v1.map", user_io_get_core_name(), id, input[dev_num].mod ? "_m" : "");
|
||||
}
|
||||
|
||||
void input_advanced_save(int dev_num, bool do_delete)
|
||||
{
|
||||
char path[256] = {JOYMAP_DIR};
|
||||
char fname[256] = {};
|
||||
|
||||
if (dev_num >= 0)
|
||||
{
|
||||
dev_num = input[dev_num].bind;
|
||||
int bufsize = sizeof(advancedButtonMap)*ADVANCED_MAP_MAX;
|
||||
input_advanced_save_filename(fname, sizeof(fname), dev_num);
|
||||
|
||||
strncat(path, fname, sizeof(path)-1);
|
||||
if (do_delete)
|
||||
FileDeleteConfig(path);
|
||||
else
|
||||
FileSaveConfig(path, input[dev_num].advanced_map, bufsize);
|
||||
}
|
||||
}
|
||||
|
||||
void input_advanced_load(int dev_num)
|
||||
{
|
||||
char path[256] = {JOYMAP_DIR};
|
||||
int bufsize = sizeof(advancedButtonMap)*ADVANCED_MAP_MAX;
|
||||
uint8_t *buf = new uint8_t[bufsize];
|
||||
if (buf)
|
||||
{
|
||||
dev_num = input[dev_num].bind;
|
||||
memset(buf, 0, bufsize);
|
||||
char fname[256] = {};
|
||||
input_advanced_save_filename(fname, sizeof(fname), dev_num, false);
|
||||
strncat(path, fname, sizeof(path)-1);
|
||||
if (FileLoadConfig(path, buf, bufsize))
|
||||
{
|
||||
memcpy(input[dev_num].advanced_map, buf, bufsize);
|
||||
for(int i = 0; i < ADVANCED_MAP_MAX; i++)
|
||||
{
|
||||
advancedButtonMap *abm = &input[dev_num].advanced_map[i];
|
||||
if (!abm->input_codes[0]) break;
|
||||
}
|
||||
} else {
|
||||
advanced_convert_jkmap(dev_num);
|
||||
}
|
||||
delete[](buf);
|
||||
}
|
||||
}
|
||||
|
||||
//If we stored them sorted we could just use memcmp....
|
||||
advancedButtonMap *input_advanced_find_match(advancedButtonMap *newMap, int devnum)
|
||||
{
|
||||
for (size_t i = 0; i < ADVANCED_MAP_MAX; i++)
|
||||
{
|
||||
int match_count = 0;
|
||||
int jcnt = 0;
|
||||
int kcnt = 0;
|
||||
advancedButtonMap *abm = &input[devnum].advanced_map[i];
|
||||
if (!abm->input_codes[0]) return NULL;
|
||||
for(size_t j = 0; j < 4; j++)
|
||||
{
|
||||
|
||||
uint16_t scode = newMap->input_codes[j];
|
||||
if (scode != 0) jcnt++;
|
||||
kcnt = 0;
|
||||
for(size_t k = 0; k < 4; k++)
|
||||
{
|
||||
uint16_t acode = abm->input_codes[k];
|
||||
if (acode != 0) kcnt++;
|
||||
if (acode && acode == scode) match_count++;
|
||||
}
|
||||
}
|
||||
if ((jcnt == kcnt) && match_count == jcnt) return abm;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void input_advanced_clear(int devnum)
|
||||
{
|
||||
if (devnum <0 || devnum >= NUMDEV) return;
|
||||
memset(input[devnum].advanced_map, 0, sizeof(input[devnum].advanced_map));
|
||||
input_advanced_save(devnum, true);
|
||||
}
|
||||
|
||||
void input_advanced_delete(advancedButtonMap *todel, int devnum)
|
||||
{
|
||||
if (devnum <0 || devnum >= NUMDEV) return;
|
||||
if (todel < input[devnum].advanced_map || todel > &input[devnum].advanced_map[ADVANCED_MAP_MAX-1])
|
||||
{
|
||||
memset(todel, 0, sizeof(advancedButtonMap));
|
||||
return;
|
||||
}
|
||||
|
||||
//endptr is not a valid ABM, but it is a pointer to just after the last one
|
||||
//only used for address calculation in memmove.
|
||||
advancedButtonMap *endptr = &input[devnum].advanced_map[ADVANCED_MAP_MAX];
|
||||
memmove(todel, todel+1, (sizeof(advancedButtonMap)*(endptr-(todel+1))));
|
||||
input_advanced_save(devnum);
|
||||
}
|
||||
|
||||
|
||||
void input_advanced_save_entry(advancedButtonMap *abm_entry, int devnum)
|
||||
{
|
||||
if (devnum <0 || devnum >= NUMDEV || !abm_entry) return;
|
||||
|
||||
if (!abm_entry->input_codes[0] || (!abm_entry->output_codes[0] && !abm_entry->button_mask))
|
||||
{
|
||||
input_advanced_delete(abm_entry, devnum);
|
||||
return;
|
||||
}
|
||||
|
||||
if (abm_entry >= input[devnum].advanced_map && abm_entry <= &input[devnum].advanced_map[ADVANCED_MAP_MAX-1])
|
||||
{
|
||||
input_advanced_save(devnum);
|
||||
return;
|
||||
}
|
||||
|
||||
advancedButtonMap *abm = input_advanced_find_match(abm_entry, devnum);
|
||||
if (!abm)
|
||||
{
|
||||
for (uint i = 0; i < ADVANCED_MAP_MAX; i++)
|
||||
{
|
||||
advancedButtonMap *check_abm = &input[devnum].advanced_map[i];
|
||||
if (!check_abm->input_codes[0] && !check_abm->output_codes[0])
|
||||
{
|
||||
abm = check_abm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (abm)
|
||||
{
|
||||
memcpy(abm, abm_entry, sizeof(advancedButtonMap));
|
||||
input_advanced_save(devnum);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
39
input.h
39
input.h
@@ -73,6 +73,26 @@
|
||||
|
||||
#define KEY_EMU (KEY_MAX+1)
|
||||
|
||||
|
||||
#define ADVANCED_MAP_MAX 32
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t button_mask;
|
||||
uint16_t output_codes[4];
|
||||
uint16_t input_codes[4];
|
||||
int autofire_idx;
|
||||
} advancedButtonMap;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint8_t input_state;
|
||||
uint32_t input_btn_mask;
|
||||
uint8_t pressed : 1;
|
||||
uint8_t last_pressed : 1;
|
||||
} advancedButtonState;
|
||||
|
||||
|
||||
void set_kbdled(int mask, int state);
|
||||
int get_kbdled(int mask);
|
||||
int toggle_kbdled(int mask);
|
||||
@@ -82,7 +102,7 @@ void input_notify_mode();
|
||||
int input_poll(int getchar);
|
||||
int is_key_pressed(int key);
|
||||
|
||||
void start_map_setting(int cnt, int set = 0);
|
||||
void start_map_setting(int cnt, int set = 0, advancedButtonMap *code_store = NULL);
|
||||
int get_map_set();
|
||||
int get_map_button();
|
||||
int get_map_type();
|
||||
@@ -92,6 +112,10 @@ int get_map_finish();
|
||||
void finish_map_setting(int dismiss);
|
||||
uint16_t get_map_vid();
|
||||
uint16_t get_map_pid();
|
||||
int get_map_dev();
|
||||
advancedButtonMap *get_map_code_store();
|
||||
int get_map_advance();
|
||||
int get_map_count();
|
||||
int has_default_map();
|
||||
void send_map_cmd(int key);
|
||||
void reset_players();
|
||||
@@ -119,5 +143,18 @@ void set_ovr_buttons(char *s, int type);
|
||||
#define FOR_EACH_SET_BIT(mask, bit) \
|
||||
for (uint32_t _m = (mask); _m; _m &= (_m - 1)) \
|
||||
for (int bit = __builtin_ctz(_m), _once = 1; _once; _once = 0)
|
||||
void start_code_capture(int dnum);
|
||||
void end_code_capture();
|
||||
uint16_t get_captured_code();
|
||||
int code_capture_osd_count();
|
||||
int get_last_input_dev();
|
||||
int get_dev_num(int dev);
|
||||
advancedButtonMap *get_advanced_map_defs(int devnum);
|
||||
void get_button_name_for_code(uint16_t btn_code, int devnum, char *bname, size_t bname_sz);
|
||||
void input_advanced_save(int dev_num, bool do_delete=false);
|
||||
void input_advanced_load(int dev_num);
|
||||
void input_advanced_save_entry(advancedButtonMap *abm_entry, int devnum);
|
||||
void input_advanced_clear(int devnum);
|
||||
void input_advanced_delete(advancedButtonMap *todel, int devnum);
|
||||
|
||||
#endif
|
||||
|
||||
532
menu.cpp
532
menu.cpp
@@ -64,6 +64,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "bootcore.h"
|
||||
#include "ide.h"
|
||||
#include "profiling.h"
|
||||
#include "str_util.h"
|
||||
#include "autofire.h"
|
||||
|
||||
/*menu states*/
|
||||
enum MENU
|
||||
@@ -110,7 +112,6 @@ enum MENU
|
||||
MENU_JOYRESET1,
|
||||
MENU_JOYKBDMAP,
|
||||
MENU_JOYKBDMAP1,
|
||||
MENU_JOYKBDMAP2,
|
||||
MENU_KBDMAP,
|
||||
MENU_KBDMAP1,
|
||||
MENU_KBDMAP2,
|
||||
@@ -204,6 +205,15 @@ enum MENU
|
||||
MENU_MT32PI_MAIN1,
|
||||
MENU_MT32PI_MAIN2,
|
||||
|
||||
//Advanced Button Map
|
||||
MENU_ADVANCED_MAP_LIST1,
|
||||
MENU_ADVANCED_MAP_LIST2,
|
||||
MENU_ADVANCED_MAP_EDIT1,
|
||||
MENU_ADVANCED_MAP_EDIT2,
|
||||
MENU_ADVANCED_MAP_EDIT3,
|
||||
MENU_ADVANCED_MAP_EDIT4,
|
||||
MENU_ADVANCED_MAP_CAPTURE1,
|
||||
MENU_ADVANCED_MAP_KEYCAPTURE1,
|
||||
// Atari 8bit cartridge type selection
|
||||
MENU_ATARI8BIT_CART1,
|
||||
MENU_ATARI8BIT_CART2,
|
||||
@@ -300,6 +310,10 @@ static uint32_t fs_Options;
|
||||
static uint32_t fs_MenuSelect;
|
||||
static uint32_t fs_MenuCancel;
|
||||
|
||||
static advancedButtonMap abm_edit_map = {};
|
||||
static advancedButtonMap *abm_edit_ptr = NULL;
|
||||
static int abm_dev_num = 0;
|
||||
|
||||
static char* GetExt(char *ext)
|
||||
{
|
||||
static char extlist[32];
|
||||
@@ -476,6 +490,38 @@ void SelectINI()
|
||||
select_ini = 1;
|
||||
}
|
||||
|
||||
void build_advanced_map_code_str(uint16_t *abm_codes, size_t abm_size, char *code_str, size_t code_size, int center_size = 0)
|
||||
{
|
||||
char str[128] = {};
|
||||
if(abm_codes[0])
|
||||
{
|
||||
strncat(str, "[", code_size);
|
||||
for (unsigned int i = 0; i < abm_size/sizeof(uint16_t); i++)
|
||||
{
|
||||
char cs[64] = {};
|
||||
if (!abm_codes[i]) break;
|
||||
if (abm_codes[i] < 256) //keyboard
|
||||
{
|
||||
sprintfz(cs, "k%X", abm_codes[i]);
|
||||
} else {
|
||||
get_button_name_for_code((abm_codes[i] & 0x7FFF), abm_dev_num, cs, sizeof(cs));
|
||||
}
|
||||
strncat(cs, ",", sizeof(cs)-1);
|
||||
strncat(str, cs, code_size);
|
||||
}
|
||||
int code_len = strlen(str);
|
||||
if (str[code_len-1] == ',') str[code_len-1] = 0;
|
||||
strcat(str, "]");
|
||||
}
|
||||
if (center_size)
|
||||
{
|
||||
snprintf(code_str, code_size, "%*s%*s", (int)(center_size+strlen(str)/2), str, (int)(center_size+strlen(str)/2), " ");
|
||||
} else {
|
||||
snprintf(code_str, code_size, "%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* the Atari core handles OSD keys competely inside the core */
|
||||
static uint32_t menu_key = 0;
|
||||
|
||||
@@ -933,6 +979,87 @@ static int gun_idx = 0;
|
||||
static int32_t gun_pos[4] = {};
|
||||
static int page = 0;
|
||||
|
||||
static void menu_button_name(int button, char *buf, size_t bsize)
|
||||
{
|
||||
switch(button)
|
||||
{
|
||||
case 0:
|
||||
strncpy(buf, "Right", bsize);
|
||||
break;
|
||||
case 1:
|
||||
strncpy(buf, "Left", bsize);
|
||||
break;
|
||||
case 2:
|
||||
strncpy(buf, "Down", bsize);
|
||||
break;
|
||||
case 3:
|
||||
strncpy(buf, "Up", bsize);
|
||||
break;
|
||||
case -1:
|
||||
strncpy(buf, "(None)", bsize);
|
||||
break;
|
||||
default:
|
||||
if ((button-4 < joy_bcount) && joy_bnames[button-4][0])
|
||||
{
|
||||
strncpy(buf, joy_bnames[button-4], bsize);
|
||||
} else {
|
||||
snprintf(buf, bsize, "%d", button-4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void menu_parse_buttons()
|
||||
{
|
||||
if (is_minimig())
|
||||
{
|
||||
joy_bcount = 7;
|
||||
strcpy(joy_bnames[0], "A(Red/Fire)");
|
||||
strcpy(joy_bnames[1], "B(Blue)");
|
||||
strcpy(joy_bnames[2], "C(Yellow)");
|
||||
strcpy(joy_bnames[3], "D(Green)");
|
||||
strcpy(joy_bnames[4], "RT");
|
||||
strcpy(joy_bnames[5], "LT");
|
||||
strcpy(joy_bnames[6], "Pause");
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_buttons();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void build_advanced_map_core_btn_str(advancedButtonMap *abm, char *dest_str, size_t dest_size)
|
||||
{
|
||||
int first_btn = -1;
|
||||
int btn_count = 0;
|
||||
for(unsigned int i = 0; i < sizeof(abm->button_mask)*8; i++)
|
||||
{
|
||||
if (abm->button_mask & 1<<i)
|
||||
{
|
||||
btn_count++;
|
||||
if (first_btn == -1) first_btn = i;
|
||||
}
|
||||
}
|
||||
if (btn_count > 1) snprintf(dest_str, dest_size, "(%d)", btn_count);
|
||||
else menu_button_name(first_btn, dest_str, dest_size);
|
||||
}
|
||||
|
||||
|
||||
void build_advanced_map_summary(advancedButtonMap *abm, char *dest_str, size_t dest_size)
|
||||
{
|
||||
char input_str[128] = {};
|
||||
char output_str[128] = {};
|
||||
build_advanced_map_code_str(abm->input_codes, sizeof(abm->input_codes), input_str, sizeof(input_str));
|
||||
if (abm->output_codes[0])
|
||||
{
|
||||
build_advanced_map_code_str(abm->output_codes, sizeof(abm->output_codes), output_str, sizeof(output_str));
|
||||
} else {
|
||||
build_advanced_map_core_btn_str(abm, output_str, sizeof(output_str));
|
||||
}
|
||||
snprintf(dest_str, dest_size, "%s->%s", input_str, output_str);
|
||||
}
|
||||
|
||||
void HandleUI(void)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
@@ -997,6 +1124,7 @@ void HandleUI(void)
|
||||
static int old_volume = 0;
|
||||
static uint32_t lock_pass_timeout = 0;
|
||||
static uint32_t menu_timeout = 0;
|
||||
static bool ignore_osd_release = false;
|
||||
|
||||
static char cp_MenuCancel;
|
||||
|
||||
@@ -1138,8 +1266,16 @@ void HandleUI(void)
|
||||
switch (c)
|
||||
{
|
||||
case KEY_F12:
|
||||
menu = true;
|
||||
menu_key_set(KEY_F12 | UPSTROKE);
|
||||
if (user_io_osd_is_visible())
|
||||
{
|
||||
menu = true;
|
||||
ignore_osd_release = true;
|
||||
}
|
||||
break;
|
||||
case KEY_F12 | UPSTROKE:
|
||||
if (!user_io_osd_is_visible() && !ignore_osd_release)
|
||||
menu = true;
|
||||
ignore_osd_release = false;
|
||||
if(video_fb_state()) video_menu_bg(user_io_status_get("[3:1]"));
|
||||
video_fb_enable(0);
|
||||
break;
|
||||
@@ -2445,8 +2581,10 @@ void HandleUI(void)
|
||||
if (is_n64())
|
||||
{
|
||||
uint32_t n64_crc;
|
||||
if (!n64_rom_tx(selPath, idx, load_addr, n64_crc)) Info("failed to load ROM");
|
||||
else if (user_io_use_cheats() && !store_name) cheats_init(selPath, n64_crc);
|
||||
if (!n64_rom_tx(selPath, idx, load_addr, n64_crc))
|
||||
Info("failed to load ROM");
|
||||
else if (user_io_use_cheats() && !store_name)
|
||||
cheats_init(selPath, n64_crc);
|
||||
}
|
||||
else if (is_c64() || is_c128())
|
||||
{
|
||||
@@ -2752,7 +2890,6 @@ void HandleUI(void)
|
||||
break;
|
||||
|
||||
case 3:
|
||||
start_map_setting(-1);
|
||||
menustate = MENU_JOYKBDMAP;
|
||||
menusub = 0;
|
||||
break;
|
||||
@@ -4148,76 +4285,83 @@ void HandleUI(void)
|
||||
break;
|
||||
|
||||
case MENU_JOYKBDMAP:
|
||||
{
|
||||
helptext_idx = 0;
|
||||
menumask = 1;
|
||||
menustate = MENU_JOYKBDMAP1;
|
||||
parentstate = MENU_JOYKBDMAP;
|
||||
|
||||
memset(&abm_edit_map, 0, sizeof(abm_edit_map));
|
||||
start_map_setting(3, 0, &abm_edit_map);
|
||||
|
||||
OsdSetTitle("Button/Key remap", 0);
|
||||
for (int i = 0; i < 5; i++) OsdWrite(i, "", 0, 0);
|
||||
OsdWrite(5, info_top, 0, 0);
|
||||
infowrite(6, "Supported mapping:");
|
||||
infowrite( 7, "");
|
||||
infowrite( 8, "Button -> Key");
|
||||
infowrite( 9, "Button -> Button same pad");
|
||||
infowrite(10, "Key -> Key");
|
||||
infowrite(11, "");
|
||||
infowrite(12, " Menu \x16 Finish ");
|
||||
infowrite(13, "Menu-hold \x16 Clear ");
|
||||
infowrite( 8, " Button(s)/Key(s) -> Key(s)");
|
||||
infowrite( 9, "Button(s) -> Button(s)");
|
||||
infowrite(10, "");
|
||||
if (abm_edit_map.input_codes[0] && abm_edit_map.input_codes[0] <= 256)
|
||||
{
|
||||
infowrite(11, " F12 \x16 Advanced ");
|
||||
infowrite(12, " Esc \x16 Clear ");
|
||||
infowrite(13, "Enter \x16 Finish ");
|
||||
} else {
|
||||
infowrite(11, " OK-hold \x16 Advanced ");
|
||||
infowrite(12, " Menu \x16 Finish ");
|
||||
infowrite(13, "Menu-hold \x16 Clear ");
|
||||
}
|
||||
OsdWrite(14, info_bottom, 0, 0);
|
||||
OsdWrite(OsdGetSize() - 1, " Cancel", menusub == 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_JOYKBDMAP1:
|
||||
if (!get_map_button())
|
||||
{
|
||||
OsdWrite(1, " Press button/key to change", 0, 0);
|
||||
if (get_map_vid())
|
||||
case MENU_JOYKBDMAP1:
|
||||
{
|
||||
OsdWrite(2, "", 0, 0);
|
||||
sprintf(s, " on device %04x:%04x", get_map_vid(), get_map_pid());
|
||||
OsdWrite(3, s, 0, 0);
|
||||
}
|
||||
OsdWrite(OsdGetSize() - 1, " Enter \x16 Finish, Esc \x16 Clear", menusub == 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_map_button() <= 256)
|
||||
{
|
||||
OsdWrite(1, " Press key to map to", 0, 0);
|
||||
OsdWrite(2, "", 0, 0);
|
||||
OsdWrite(3, " on a keyboard", 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
OsdWrite(1, " Press button to map to", 0, 0);
|
||||
OsdWrite(2, " on the same pad", 0, 0);
|
||||
OsdWrite(3, " or key on a keyboard", 0, 0);
|
||||
}
|
||||
OsdWrite(OsdGetSize() - 1);
|
||||
}
|
||||
|
||||
if (select || menu || get_map_finish() || get_map_cancel())
|
||||
{
|
||||
int clear = get_map_vid() && (menu || get_map_cancel());
|
||||
finish_map_setting(clear);
|
||||
menu_timeout = GetTimer(1000);
|
||||
OsdWrite(1);
|
||||
OsdWrite(2, clear ? " Clearing" : " Finishing");
|
||||
OsdWrite(3);
|
||||
OsdWrite(OsdGetSize() - 1);
|
||||
menustate = MENU_JOYKBDMAP2;
|
||||
}
|
||||
break;
|
||||
|
||||
case MENU_JOYKBDMAP2:
|
||||
if (CheckTimer(menu_timeout))
|
||||
{
|
||||
menustate = MENU_COMMON1;
|
||||
menusub = 3;
|
||||
}
|
||||
break;
|
||||
int map_clear = get_map_cancel();
|
||||
abm_dev_num = get_map_dev();
|
||||
|
||||
if (get_map_finish() || map_clear)
|
||||
{
|
||||
OsdWrite(1);
|
||||
OsdWrite(2, (map_clear) ? " Clearing" : " Finishing");
|
||||
OsdWrite(3);
|
||||
OsdWrite(OsdGetSize() - 1);
|
||||
OsdUpdate();
|
||||
finish_map_setting(map_clear);
|
||||
menustate = MENU_COMMON1;
|
||||
menusub = 3;
|
||||
sleep(1);
|
||||
} else if (get_map_advance()) {
|
||||
menustate = MENU_ADVANCED_MAP_LIST1;
|
||||
menusub = 0;
|
||||
finish_map_setting(0);
|
||||
} else if (get_map_set() == 2) {
|
||||
bool is_kbd = abm_edit_map.input_codes[0] && abm_edit_map.input_codes[0] <= 256;
|
||||
if (is_kbd)
|
||||
{
|
||||
OsdWrite(1, " Press key(s) to map to", 0, 0);
|
||||
OsdWrite(2, " on a keyboard", 0, 0);
|
||||
} else {
|
||||
OsdWrite(1, " Press button(s) to map to", 0, 0);
|
||||
OsdWrite(2, " on the same pad", 0, 0);
|
||||
OsdWrite(3, " or key(s) on a keyboard", 0, 0);
|
||||
}
|
||||
char str[128] = {};
|
||||
build_advanced_map_code_str(abm_edit_map.output_codes, sizeof(abm_edit_map.output_codes), str, sizeof(str), 14);
|
||||
OsdWrite(is_kbd ? 3 : 4, str, 0, 0);
|
||||
} else {
|
||||
char str[128] = {};
|
||||
build_advanced_map_code_str(abm_edit_map.input_codes, sizeof(abm_edit_map.input_codes), str, sizeof(str), 14);
|
||||
OsdWrite(1, " Press button(s) ", 0, 0);
|
||||
OsdWrite(2, " or key(s) to change", 0, 0);
|
||||
OsdWrite(3, str, 0, 0);
|
||||
OsdWrite(4, "", 0, 0);
|
||||
OsdWrite(OsdGetSize() - 1, " Esc \x16 Clear, Enter \x16 Finish", menusub == 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MENU_ABOUT1:
|
||||
OsdSetSize(16);
|
||||
menumask = 0;
|
||||
@@ -7034,6 +7178,274 @@ void HandleUI(void)
|
||||
SelectFile("", 0, SCANO_CORES, MENU_CORE_FILE_SELECTED1, cp_MenuCancel);
|
||||
break;
|
||||
|
||||
case MENU_ADVANCED_MAP_LIST1:
|
||||
{
|
||||
OsdSetTitle("Advanced");
|
||||
menu_parse_buttons();
|
||||
menustate = MENU_ADVANCED_MAP_LIST2;
|
||||
parentstate = MENU_ADVANCED_MAP_LIST1;
|
||||
while(1)
|
||||
{
|
||||
if (!menusub) firstmenu = 0;
|
||||
adjvisible = 0;
|
||||
|
||||
advancedButtonMap *abms = get_advanced_map_defs(abm_dev_num);
|
||||
menumask = 0x1;
|
||||
uint32_t menucnt = 1;
|
||||
MenuWrite(0, " New \x16", menusub == menucnt++, 0);
|
||||
|
||||
int n = 1;
|
||||
size_t map_cnt = 0;
|
||||
for(size_t i = 0; i < ADVANCED_MAP_MAX; i++)
|
||||
{
|
||||
advancedButtonMap *abm = abms+i;
|
||||
if (!abm->input_codes[0]) break;
|
||||
map_cnt++;
|
||||
build_advanced_map_summary(abm, s, sizeof(s));
|
||||
s[27] = '\x16';
|
||||
s[28] = 0;
|
||||
menumask |= 1<<(i+1);
|
||||
MenuWrite(n++, s, menusub == i+1, 0);
|
||||
}
|
||||
MenuWrite(0, " New \x16", menusub == 0, map_cnt >= ADVANCED_MAP_MAX);
|
||||
if (map_cnt >= ADVANCED_MAP_MAX)
|
||||
menumask &= ~0x1;
|
||||
for (; n < OsdGetSize(); n++) MenuWrite(n, "", 0, 0);
|
||||
if (!adjvisible) break;
|
||||
firstmenu += adjvisible;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_ADVANCED_MAP_LIST2:
|
||||
{
|
||||
if (select)
|
||||
{
|
||||
advancedButtonMap *abms = get_advanced_map_defs(abm_dev_num);
|
||||
memset(&abm_edit_map, 0, sizeof(abm_edit_map));
|
||||
menustate = MENU_ADVANCED_MAP_EDIT1;
|
||||
parentstate = MENU_ADVANCED_MAP_LIST1;
|
||||
if (menusub == 0) {
|
||||
abm_edit_ptr = &abm_edit_map;
|
||||
} else {
|
||||
abm_edit_ptr = &abms[menusub-1];
|
||||
}
|
||||
menusub = 0;
|
||||
}
|
||||
|
||||
if (left || back || menu)
|
||||
{
|
||||
menustate = MENU_COMMON1;
|
||||
input_advanced_save(abm_dev_num);
|
||||
parentstate = 0;
|
||||
menusub = 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_ADVANCED_MAP_EDIT1:
|
||||
{
|
||||
menustate = MENU_ADVANCED_MAP_EDIT2;
|
||||
parentstate = MENU_ADVANCED_MAP_EDIT1;
|
||||
menumask = 0;
|
||||
firstmenu = 0;
|
||||
adjvisible = 0;
|
||||
bool dev_kbd = false;
|
||||
if (abm_edit_ptr->input_codes[0] && abm_edit_ptr->input_codes[0] <= 256)
|
||||
dev_kbd = true;
|
||||
menu_parse_buttons();
|
||||
|
||||
char bname[32] = {};
|
||||
build_advanced_map_core_btn_str(abm_edit_ptr, bname, sizeof(bname));
|
||||
bool keyboard_only = dev_kbd && (user_io_get_kbdemu() == EMU_NONE);
|
||||
|
||||
uint32_t n = 0;
|
||||
char code_str[256] = {};
|
||||
|
||||
build_advanced_map_code_str(abm_edit_ptr->input_codes, sizeof(abm_edit_ptr->input_codes), code_str, sizeof(code_str));
|
||||
snprintf(s, sizeof(s), " Input Hotkey(s) %-20s\x16",code_str);
|
||||
MenuWrite(n, s, menusub == n, 0);
|
||||
menumask |= 1 << n++;
|
||||
|
||||
code_str[0] = 0;
|
||||
snprintf(s, sizeof(s), " Core Button(s): %-17s\x10 \x11", bname);
|
||||
MenuWrite(n, s, keyboard_only ? 0 : menusub == n, keyboard_only );
|
||||
if(!keyboard_only) menumask |= 1 << n;
|
||||
n++;
|
||||
|
||||
build_advanced_map_code_str(abm_edit_ptr->output_codes, sizeof(abm_edit_ptr->output_codes), code_str, sizeof(code_str));
|
||||
snprintf(s, sizeof(s), " Output(s): %-20s\x16", code_str);
|
||||
MenuWrite(n, s, menusub == n, 0);
|
||||
menumask |= 1 << n++;
|
||||
|
||||
const char *af_label = get_autofire_rate_hz(abm_edit_ptr->autofire_idx);
|
||||
snprintf(s, sizeof(s), " Autofire : %-20s\x16", af_label);
|
||||
MenuWrite(n, s, menusub == n, 0);
|
||||
menumask |= 1 << n++;
|
||||
|
||||
|
||||
MenuWrite(n, " Delete", menusub == n, 0);
|
||||
menumask |= 1 << n++;
|
||||
MenuWrite(n, " Done", menusub == n, 0);
|
||||
menumask |= 1 << n++;
|
||||
for (int i = n; i < OsdGetSize(); i++) MenuWrite(i, "", 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_ADVANCED_MAP_EDIT2:
|
||||
{
|
||||
if (select || left || right || plus || minus)
|
||||
{
|
||||
menustate = MENU_ADVANCED_MAP_EDIT1;
|
||||
char bname[32] = {0};
|
||||
switch(menusub)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
int mapped_button_cnt = 0;
|
||||
int first_map_idx = -1;
|
||||
for (uint bn = 0; bn < sizeof(abm_edit_ptr->button_mask)*8; bn++)
|
||||
{
|
||||
if (abm_edit_ptr->button_mask & 1<<bn)
|
||||
{
|
||||
mapped_button_cnt++;
|
||||
if (first_map_idx == -1) first_map_idx = bn;
|
||||
}
|
||||
}
|
||||
if (select)
|
||||
{
|
||||
menustate = MENU_ADVANCED_MAP_EDIT3;
|
||||
menusub = 0;
|
||||
} else if (mapped_button_cnt <= 1 && (left || right)) {
|
||||
menu_button_name(first_map_idx, bname, sizeof(bname));
|
||||
do {
|
||||
if (right) first_map_idx++;
|
||||
if (left) first_map_idx--;
|
||||
if (first_map_idx < 0) first_map_idx = joy_bcount +3;
|
||||
if (first_map_idx-4 >= joy_bcount) first_map_idx = 0;
|
||||
menu_button_name(first_map_idx, bname, sizeof(bname));
|
||||
} while (!strncmp("-", bname, sizeof(bname) ));
|
||||
abm_edit_ptr->button_mask = 1<<first_map_idx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
case 2:
|
||||
if (select) {
|
||||
menustate = MENU_ADVANCED_MAP_CAPTURE1;
|
||||
start_map_setting(1, menusub ? 2 : 1, abm_edit_ptr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (select || plus)
|
||||
{
|
||||
abm_edit_ptr->autofire_idx++;
|
||||
} else if (minus) {
|
||||
abm_edit_ptr->autofire_idx--;
|
||||
}
|
||||
if (abm_edit_ptr->autofire_idx >= get_autofire_rate_count())
|
||||
abm_edit_ptr->autofire_idx = 0;
|
||||
if (abm_edit_ptr->autofire_idx < 0)
|
||||
abm_edit_ptr->autofire_idx = get_autofire_rate_count()-1;
|
||||
break;
|
||||
case 4:
|
||||
if (select)
|
||||
{
|
||||
menustate = MENU_ADVANCED_MAP_LIST1;
|
||||
menusub = 0;
|
||||
input_advanced_delete(abm_edit_ptr, abm_dev_num);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (back || menu || (menusub == 5 && select))
|
||||
{
|
||||
input_advanced_save_entry(abm_edit_ptr, abm_dev_num);
|
||||
menustate = MENU_ADVANCED_MAP_LIST1;
|
||||
menusub = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MENU_ADVANCED_MAP_EDIT3:
|
||||
{
|
||||
menustate = MENU_ADVANCED_MAP_EDIT4;
|
||||
parentstate = MENU_ADVANCED_MAP_EDIT3;
|
||||
while (1) {
|
||||
menumask = 0;
|
||||
uint32_t n = 0;
|
||||
if (!menusub) firstmenu = 0;
|
||||
adjvisible = 0;
|
||||
for (int i = 0; i < joy_bcount+4; i++)
|
||||
{
|
||||
char bname[32];
|
||||
menu_button_name(i, bname, sizeof(bname));
|
||||
if (!strcmp("-", bname)) continue;
|
||||
bool b_used = abm_edit_ptr->button_mask & 1<<i;
|
||||
sprintfz(s, "%s %s", b_used ? "*":" ", bname);
|
||||
MenuWrite(n, s, menusub == n, 0);
|
||||
menumask |= 1<<n;
|
||||
n++;
|
||||
}
|
||||
if (!adjvisible) break;
|
||||
firstmenu += adjvisible;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MENU_ADVANCED_MAP_EDIT4:
|
||||
{
|
||||
if (back || menu)
|
||||
{
|
||||
menustate = MENU_ADVANCED_MAP_EDIT1;
|
||||
menusub = 1;
|
||||
} else if (select) {
|
||||
menustate = MENU_ADVANCED_MAP_EDIT3;
|
||||
uint32_t btn_cnt = 0;
|
||||
for(int i = 0; i < joy_bcount+4; i++)
|
||||
{
|
||||
char bname[32];
|
||||
menu_button_name(i, bname, sizeof(bname));
|
||||
if (!strcmp("-", bname)) continue;
|
||||
if (menusub == btn_cnt)
|
||||
{
|
||||
abm_edit_ptr->button_mask ^= 1<<i;
|
||||
break;
|
||||
}
|
||||
btn_cnt++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MENU_ADVANCED_MAP_CAPTURE1:
|
||||
{
|
||||
OsdSetTitle("Set Hotkey", 0);
|
||||
for (int i = 0; i < 4; i++) OsdWrite(i, "", 0, 0);
|
||||
OsdWrite(4, info_top, 0, 0);
|
||||
if (get_map_set() == 1 || abm_edit_ptr->input_codes[0] > 256)
|
||||
{
|
||||
infowrite(5, "Press button(s) on joypad");
|
||||
infowrite(6, "or key(s) on keyboard");
|
||||
} else {
|
||||
infowrite(5, "");
|
||||
infowrite(6, "Press Keyboard key(s)");
|
||||
}
|
||||
infowrite(7, "");
|
||||
infowrite(8, "Esc \x16 Clear");
|
||||
infowrite(9, "Menu-hold \x16 Clear");
|
||||
OsdWrite(10, info_bottom, 0, 0);
|
||||
char code_str[256] = {};
|
||||
build_advanced_map_code_str((get_map_set() == 2) ? abm_edit_ptr->output_codes : abm_edit_ptr->input_codes, sizeof(abm_edit_ptr->input_codes), code_str, sizeof(code_str), 14);
|
||||
OsdWrite(11, get_map_cancel() ? " Clearing" : code_str, 0, 0);
|
||||
|
||||
if (get_map_finish() || get_map_cancel())
|
||||
{
|
||||
menustate = MENU_ADVANCED_MAP_EDIT1;
|
||||
finish_map_setting(get_map_cancel());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MENU_ATARI8BIT_CART1:
|
||||
helptext_idx = 0;
|
||||
menumask = 0;
|
||||
|
||||
@@ -4113,7 +4113,7 @@ void user_io_kbd(uint16_t key, int press)
|
||||
if (key == KEY_MENU) key = KEY_F12;
|
||||
if (key != KEY_F12 || !block_F12)
|
||||
{
|
||||
if (osd_is_visible) menu_key_set(UPSTROKE | key);
|
||||
/*if (osd_is_visible)*/ menu_key_set(UPSTROKE | key);
|
||||
|
||||
// these modifiers should be passed to core even if OSD is open or they will get stuck!
|
||||
if (!osd_is_visible || key == KEY_LEFTALT || key == KEY_RIGHTALT || key == KEY_LEFTMETA || key == KEY_RIGHTMETA) send_keycode(key, press);
|
||||
@@ -4126,7 +4126,7 @@ void user_io_kbd(uint16_t key, int press)
|
||||
if (!osd_is_visible && !is_menu() && key == KEY_MENU && press == 3) open_joystick_setup();
|
||||
else if ((has_menu() || osd_is_visible || (get_key_mod() & (LALT | RALT | RGUI | LGUI))) && (((key == KEY_F12) && (!is_f12_mod_needed() || (get_key_mod() & (RGUI | LGUI)))) || key == KEY_MENU))
|
||||
{
|
||||
block_F12 = 1;
|
||||
//block_F12 = 1;
|
||||
if (press == 1) menu_key_set(KEY_F12);
|
||||
}
|
||||
else if (osd_is_visible)
|
||||
|
||||
Reference in New Issue
Block a user