Compare commits

..

6 Commits
5.47 ... 5.48

Author SHA1 Message Date
icex2
e1008576ce chore: Update changelog for release 2024-01-31 21:52:05 +01:00
icex2
f41cdba8b8 chore: Bump version to 5.48 to start next development cycle 2024-01-31 21:42:14 +01:00
ahnada
1379c1e11b New filename (without version string) for the new save files 2024-01-31 21:40:22 +01:00
ahnada
d1525a98dd Mapper serialization versioning
Add a "BTMD" FOURCC + version in the beginning of the mapper data file.
Is backwards compatible with the current data format.
2024-01-31 21:40:22 +01:00
ahnada
329d6a80a3 Properly save/load the new analog invert option 2024-01-31 21:40:22 +01:00
ahnada
f37f216c69 Add invert analog input option 2024-01-31 21:40:22 +01:00
11 changed files with 196 additions and 21 deletions

View File

@@ -2,6 +2,14 @@
Note for CI/CD: Ensure the version formatting in the sections is kept identical to the versions
given in tags. The pipeline will pick this up and cuts out the relevant section for release notes.
## 5.48
### Features
* feat(config): Add invert analog input option. Remark: The old configuration file format is
upgraded but downgrading is not possible anymore. The new saves are using a new filename
and it doesn't delete the old files, see `C:\Users\<YOUR_USERNAME>\AppData\Roaming\DJHACKERS`
### Fixes
## 5.47
### Features
N/A

View File

@@ -1,6 +1,6 @@
# Bemanitools 5
Version: `5.47`
Version: `5.48`
[Changelog](CHANGELOG.md)

View File

@@ -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;

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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)
{

View File

@@ -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);