diff --git a/src/main/config/analogs.c b/src/main/config/analogs.c index 48c4881..5a7bcee 100644 --- a/src/main/config/analogs.c +++ b/src/main/config/analogs.c @@ -49,11 +49,13 @@ static INT_PTR analog_ui_handle_init(HWND hwnd, struct analog_def *def); static void analog_ui_handle_init_label(HWND hwnd); static void analog_ui_handle_init_dev(HWND hwnd); static void analog_ui_handle_init_sensitivity(HWND hwnd); +static void analog_ui_handle_init_invert(HWND hwnd); static bool analog_ui_match_device(struct hid_stub *hid); static void analog_ui_populate_controls(HWND hwnd); static INT_PTR analog_ui_handle_device_change(HWND hwnd); static INT_PTR analog_ui_handle_control_change(HWND hwnd); static INT_PTR analog_ui_handle_sensitivity_change(HWND hwnd); +static INT_PTR analog_ui_handle_invert_change(HWND hwnd); static INT_PTR analog_ui_handle_tick(HWND hwnd); static INT_PTR analog_ui_handle_fini(HWND hwnd); @@ -213,6 +215,15 @@ analog_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) return FALSE; } + case BN_CLICKED: + switch (LOWORD(wparam)) { + case IDC_ANALOG_INVERT: + return analog_ui_handle_invert_change(hwnd); + + default: + return FALSE; + } + default: return FALSE; } @@ -248,6 +259,7 @@ static INT_PTR analog_ui_handle_init(HWND hwnd, struct analog_def *def) analog_ui_handle_init_label(hwnd); analog_ui_handle_init_dev(hwnd); analog_ui_handle_init_sensitivity(hwnd); + analog_ui_handle_init_invert(hwnd); return TRUE; } @@ -343,6 +355,17 @@ static void analog_ui_handle_init_sensitivity(HWND hwnd) EnableWindow(slider, !mapper_is_analog_absolute(ui->def->tag)); } +static void analog_ui_handle_init_invert(HWND hwnd) +{ + struct analog_ui *ui; + + ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + + if (mapper_get_analog_invert(ui->def->tag)) { + SendMessage(GetDlgItem(hwnd, IDC_ANALOG_INVERT), BM_SETCHECK, BST_CHECKED, 0); + } +} + static bool analog_ui_match_device(struct hid_stub *hid) { struct hid_control *controls; @@ -519,6 +542,21 @@ static INT_PTR analog_ui_handle_sensitivity_change(HWND hwnd) return TRUE; } +static INT_PTR analog_ui_handle_invert_change(HWND hwnd) +{ + struct analog_ui *ui; + HWND btn; + bool invert; + + ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA); + btn = GetDlgItem(hwnd, IDC_ANALOG_INVERT); + invert = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED; + + mapper_set_analog_invert(ui->def->tag, invert); + + return TRUE; +} + static INT_PTR analog_ui_handle_tick(HWND hwnd) { struct analog_ui *ui; diff --git a/src/main/config/config.rc b/src/main/config/config.rc index 94c0891..9c06632 100644 --- a/src/main/config/config.rc +++ b/src/main/config/config.rc @@ -22,18 +22,19 @@ IDR_USAGES USAGES "config/usages.txt" // Dialog resources // LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -IDD_ANALOG DIALOG 0, 0, 220, 100 +IDD_ANALOG DIALOG 0, 0, 220, 115 STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW EXSTYLE WS_EX_CONTROLPARENT FONT 8, "Ms Shell Dlg" { - GROUPBOX "", IDC_GROUP, 5, 5, 210, 90 + GROUPBOX "", IDC_GROUP, 5, 5, 210, 105 CONTROL "", IDC_SENSITIVITY, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS, 10, 75, 200, 15 LTEXT "Device", IDC_STATIC, 15, 15, 24, 8, SS_LEFT COMBOBOX IDC_DEVICE, 15, 25, 135, 30, WS_GROUP | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS COMBOBOX IDC_CONTROL, 15, 50, 135, 30, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS LTEXT "Sensitivity", IDC_STATIC, 15, 65, 32, 8, SS_LEFT LTEXT "Control", IDC_STATIC, 15, 40, 23, 8, SS_LEFT + AUTOCHECKBOX "Invert Axis", IDC_ANALOG_INVERT, 15, 95, 141, 8 CONTROL "", IDC_POSITION, "spinner", 0x50020000, 160, 15, 50, 50, 0x02002000 } @@ -126,7 +127,7 @@ FONT 8, "Ms Shell Dlg" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -IDD_TAB_ANALOGS DIALOG 0, 0, 220, 215 +IDD_TAB_ANALOGS DIALOG 0, 0, 220, 230 STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU CAPTION "Analogs" FONT 8, "Ms Shell Dlg" diff --git a/src/main/config/resource.h b/src/main/config/resource.h index 3fb0863..0cf4907 100644 --- a/src/main/config/resource.h +++ b/src/main/config/resource.h @@ -30,6 +30,7 @@ #define IDC_DEVICE 1005 #define IDC_BINDING_EDIT 1006 #define IDC_CONTROL 1006 +#define IDC_ANALOG_INVERT 1007 #define IDC_BINDING_CLEAR 1007 #define IDC_BINDING_MIN 1008 #define IDC_PAGE_TEXT 1008 diff --git a/src/main/geninput/geninput.def b/src/main/geninput/geninput.def index 1f2fd92..6ef4cf3 100644 --- a/src/main/geninput/geninput.def +++ b/src/main/geninput/geninput.def @@ -35,6 +35,7 @@ EXPORTS mapper_get_action_map mapper_get_analog_map mapper_get_analog_sensitivity + mapper_get_analog_invert mapper_get_npages mapper_get_nanalogs mapper_get_nlights @@ -44,6 +45,7 @@ EXPORTS mapper_set_action_map mapper_set_analog_map mapper_set_analog_sensitivity + mapper_set_analog_invert mapper_set_light_map mapper_set_nanalogs mapper_set_nlights diff --git a/src/main/geninput/input-config.h b/src/main/geninput/input-config.h index 7bd1fc2..d7fe181 100644 --- a/src/main/geninput/input-config.h +++ b/src/main/geninput/input-config.h @@ -15,6 +15,7 @@ bool mapper_get_action_map( uint8_t action, uint8_t page, struct mapped_action *ma); bool mapper_get_analog_map(uint8_t analog, struct mapped_analog *ma); int32_t mapper_get_analog_sensitivity(uint8_t analog); +bool mapper_get_analog_invert(uint8_t analog); uint8_t mapper_get_nanalogs(void); uint8_t mapper_get_nlights(void); uint8_t mapper_get_npages(void); @@ -25,6 +26,7 @@ void mapper_set_action_map( uint8_t action, uint8_t page, uint8_t bit, const struct mapped_action *ma); bool mapper_set_analog_map(uint8_t analog, const struct mapped_analog *ma); bool mapper_set_analog_sensitivity(uint8_t analog, int32_t sensitivity); +bool mapper_set_analog_invert(uint8_t analog, bool invert); void mapper_set_nanalogs(uint8_t nanalogs); void mapper_set_nlights(uint8_t nlights); void mapper_set_light_map(const struct mapped_light *ml, uint8_t game_light); diff --git a/src/main/geninput/input.c b/src/main/geninput/input.c index ef5f4b0..60c94c2 100644 --- a/src/main/geninput/input.c +++ b/src/main/geninput/input.c @@ -25,10 +25,20 @@ static volatile long input_init_count; static FILE *mapper_config_open(const char *game_type, const char *mode) { char path[MAX_PATH]; + FILE *f; - str_format(path, sizeof(path), "%s_v5_00a07.bin", game_type); + str_format(path, sizeof(path), "%s.bin", game_type); + f = fopen_appdata("DJHACKERS", path, mode); - return fopen_appdata("DJHACKERS", path, mode); + // Try to load the old save file only if we're loading + if (f == NULL) { + if (strchr(mode, 'r') != NULL) { + str_format(path, sizeof(path), "%s_v5_00a07.bin", game_type); + f = fopen_appdata("DJHACKERS", path, mode); + } + } + + return f; } void input_set_loggers( @@ -144,6 +154,11 @@ int32_t mapper_get_analog_sensitivity(uint8_t analog) return mapper_impl_get_analog_sensitivity(mapper_inst, analog); } +bool mapper_get_analog_invert(uint8_t analog) +{ + return mapper_impl_get_analog_invert(mapper_inst, analog); +} + uint8_t mapper_get_nanalogs(void) { return mapper_impl_get_nanalogs(mapper_inst); @@ -190,6 +205,11 @@ bool mapper_set_analog_sensitivity(uint8_t analog, int32_t sensitivity) return mapper_impl_set_analog_sensitivity(mapper_inst, analog, sensitivity); } +bool mapper_set_analog_invert(uint8_t analog, bool invert) +{ + return mapper_impl_set_analog_invert(mapper_inst, analog, invert); +} + void mapper_set_light_map(const struct mapped_light *ml, uint8_t game_light) { mapper_impl_set_light_map(mapper_inst, ml, game_light); diff --git a/src/main/geninput/mapper-s11n.c b/src/main/geninput/mapper-s11n.c index 06b5d39..3dba127 100644 --- a/src/main/geninput/mapper-s11n.c +++ b/src/main/geninput/mapper-s11n.c @@ -6,9 +6,25 @@ #include "util/fs.h" #include "util/mem.h" -static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f); -static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f); -static bool mapper_impl_config_load_lights(struct mapper *m, FILE *f); +enum mapper_config_version { + MAPPER_VERSION_BEFORE_VERSIONING = 0, + MAPPER_VERSION_INVERT_AXIS, + + // --- Add new versions above this line --- // + MAPPER_VERSION_PLUS_ONE, + MAPPER_VERSION_LATEST = MAPPER_VERSION_PLUS_ONE - 1, +}; + +#define FOURCC(a, b, c, d) \ + ((uint32_t) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a))) + +// Bemanitools Mapper Data +static const uint32_t mapper_fourcc = FOURCC('B', 'T', 'M', 'D'); + +static uint32_t mapper_impl_config_load_version(FILE *f); +static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f, uint32_t version); +static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f, uint32_t version); +static bool mapper_impl_config_load_lights(struct mapper *m, FILE *f, uint32_t version); static void mapper_impl_config_save_actions(struct mapper *m, FILE *f); static void mapper_impl_config_save_analogs(struct mapper *m, FILE *f); static void mapper_impl_config_save_lights(struct mapper *m, FILE *f); @@ -16,14 +32,17 @@ static void mapper_impl_config_save_lights(struct mapper *m, FILE *f); struct mapper *mapper_impl_config_load(FILE *f) { struct mapper *m; + uint32_t version = MAPPER_VERSION_BEFORE_VERSIONING; hid_mgr_lock(); /* Need to convert from HID objects to /dev nodes */ + version = mapper_impl_config_load_version(f); + m = mapper_impl_create(); - if (!mapper_impl_config_load_actions(m, f) || - !mapper_impl_config_load_analogs(m, f) || - !mapper_impl_config_load_lights(m, f)) { + if (!mapper_impl_config_load_actions(m, f, version) || + !mapper_impl_config_load_analogs(m, f, version) || + !mapper_impl_config_load_lights(m, f, version)) { mapper_impl_destroy(m); m = NULL; } @@ -33,7 +52,29 @@ struct mapper *mapper_impl_config_load(FILE *f) return m; } -static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f) +static uint32_t mapper_impl_config_load_version(FILE *f) +{ + uint32_t fourcc = 0; + uint32_t version = MAPPER_VERSION_BEFORE_VERSIONING; + + if (!read_u32(f, &fourcc)) { + return 0; + } + + if (fourcc == mapper_fourcc) { + + if (!read_u32(f, &version)) { + fseek(f, -4, SEEK_CUR); + } + + } else { + fseek(f, -4, SEEK_CUR); + } + + return version; +} + +static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f, uint32_t version) { char *dev_node; struct mapped_action ma; @@ -69,11 +110,12 @@ static bool mapper_impl_config_load_actions(struct mapper *m, FILE *f) return true; } -static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f) +static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f, uint32_t version) { char *dev_node; struct mapped_analog ma; int32_t sensitivity; + bool invert; uint8_t nanalogs; uint8_t i; @@ -101,8 +143,19 @@ static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f) return false; } + if (version >= MAPPER_VERSION_INVERT_AXIS) { + + if (!read_u8(f, &invert)) { + return false; + } + + } else { + invert = false; + } + mapper_impl_set_analog_map(m, i, &ma); mapper_impl_set_analog_sensitivity(m, i, sensitivity); + mapper_impl_set_analog_invert(m, i, invert); } free(dev_node); @@ -111,7 +164,7 @@ static bool mapper_impl_config_load_analogs(struct mapper *m, FILE *f) return true; } -static bool mapper_impl_config_load_lights(struct mapper *m, FILE *f) +static bool mapper_impl_config_load_lights(struct mapper *m, FILE *f, uint32_t version) { char *dev_node; struct mapped_light ml; @@ -156,8 +209,13 @@ static bool mapper_impl_config_load_lights(struct mapper *m, FILE *f) void mapper_impl_config_save(struct mapper *m, FILE *f) { + const uint32_t mapper_latest_version = MAPPER_VERSION_LATEST; + hid_mgr_lock(); + write_u32(f, &mapper_fourcc); + write_u32(f, &mapper_latest_version); + mapper_impl_config_save_actions(m, f); mapper_impl_config_save_analogs(m, f); mapper_impl_config_save_lights(m, f); @@ -211,6 +269,7 @@ static void mapper_impl_config_save_analogs(struct mapper *m, FILE *f) { struct mapped_analog ma; int32_t sensitivity; + bool invert; uint8_t nanalogs; uint8_t i; @@ -224,10 +283,12 @@ static void mapper_impl_config_save_analogs(struct mapper *m, FILE *f) write_str(f, ""); } else { sensitivity = mapper_impl_get_analog_sensitivity(m, i); + invert = mapper_impl_get_analog_invert(m, i); write_str(f, hid_stub_get_dev_node(ma.hid)); write_u32(f, &ma.control_no); write_u32(f, &sensitivity); + write_u8(f, &invert); } } } diff --git a/src/main/geninput/mapper.c b/src/main/geninput/mapper.c index 96da997..c3d0214 100644 --- a/src/main/geninput/mapper.c +++ b/src/main/geninput/mapper.c @@ -26,8 +26,10 @@ struct analog_mapping { bool bound; bool valid; bool absolute; - double affine_scale; - double affine_bias; + bool invert; + double analog_min; + double analog_max; + double inv_analog_range; uint8_t pos; }; @@ -169,8 +171,9 @@ static void analog_mapping_bind(struct analog_mapping *am) ctl = &controls[am->src.control_no]; - am->affine_bias = ctl->value_min; - am->affine_scale = ctl->value_max - ctl->value_min; + am->analog_min = ctl->value_min; + am->analog_max = ctl->value_max; + am->inv_analog_range = 1.0 / ((int64_t)ctl->value_max - ctl->value_min); am->absolute = !(ctl->flags & HID_FLAG_RELATIVE); am->valid = true; @@ -187,6 +190,7 @@ static void analog_mapping_update(struct analog_mapping *am) { double tmp; int32_t value; + int8_t delta; if (!am->bound) { analog_mapping_bind(am); @@ -201,10 +205,24 @@ static void analog_mapping_update(struct analog_mapping *am) } if (am->absolute) { - tmp = (value - am->affine_bias) / am->affine_scale; + + if (am->invert) { + tmp = am->analog_max - value; + } else { + tmp = value - am->analog_min; + } + + // Scale the input value to [0,1] range + tmp *= am->inv_analog_range; am->pos = (uint8_t) ((tmp + 0.5) * 256.0); } else { - am->pos += (int8_t) (value * exp(am->sensitivity / 256.0)); + delta = (int8_t) (value * exp(am->sensitivity / 256.0)); + + if (am->invert) { + delta *= -1; + } + + am->pos += delta; } } @@ -406,6 +424,15 @@ int32_t mapper_impl_get_analog_sensitivity(struct mapper *m, uint8_t analog) return m->analogs[analog].sensitivity; } +bool mapper_impl_get_analog_invert(struct mapper* m, uint8_t analog) +{ + if (analog >= m->nanalogs) { + return 0; + } + + return m->analogs[analog].invert; +} + uint8_t mapper_impl_get_nanalogs(struct mapper *m) { return m->nanalogs; @@ -531,6 +558,18 @@ bool mapper_impl_set_analog_sensitivity( return true; } +bool mapper_impl_set_analog_invert( + struct mapper *m, uint8_t analog, bool invert) +{ + if (analog >= m->nanalogs) { + return false; + } + + m->analogs[analog].invert = invert; + + return true; +} + void mapper_impl_set_light_map( struct mapper *m, const struct mapped_light *ml, uint8_t game_light) { diff --git a/src/main/geninput/mapper.h b/src/main/geninput/mapper.h index c560507..7cc0ad4 100644 --- a/src/main/geninput/mapper.h +++ b/src/main/geninput/mapper.h @@ -57,6 +57,7 @@ bool mapper_impl_get_analog_map( bool mapper_impl_get_action_map( struct mapper *m, uint8_t action, uint8_t page, struct mapped_action *ma); int32_t mapper_impl_get_analog_sensitivity(struct mapper *m, uint8_t analog); +bool mapper_impl_get_analog_invert(struct mapper *m, uint8_t analog); uint8_t mapper_impl_get_nanalogs(struct mapper *m); uint8_t mapper_impl_get_nlights(struct mapper *m); uint8_t mapper_impl_get_npages(struct mapper *m); @@ -73,6 +74,8 @@ bool mapper_impl_set_analog_map( struct mapper *m, uint8_t analog, const struct mapped_analog *ma); bool mapper_impl_set_analog_sensitivity( struct mapper *m, uint8_t analog, int32_t sensitivity); +bool mapper_impl_set_analog_invert( + struct mapper *m, uint8_t analog, bool invert); void mapper_impl_set_light_map( struct mapper *m, const struct mapped_light *ml, uint8_t game_light); void mapper_impl_set_nanalogs(struct mapper *m, uint8_t nanalogs);