Add more motion control mappings to turntable and ghltar

This commit is contained in:
Megamouse 2026-06-28 11:41:03 +02:00
parent 5c55819b57
commit a94031b51a
10 changed files with 177 additions and 165 deletions

View File

@ -1973,12 +1973,12 @@ static void ds3_input_to_pad(const u32 gem_num, be_t<u16>& digital_buttons, be_t
return;
}
const auto handle_input = [&](gem_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
const auto handle_input = [&](const emulated_pad_config<gem_btn>::input_value& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case gem_btn::start:
digital_buttons |= CELL_GEM_CTRL_START;
@ -2003,7 +2003,7 @@ static void ds3_input_to_pad(const u32 gem_num, be_t<u16>& digital_buttons, be_t
break;
case gem_btn::t:
digital_buttons |= CELL_GEM_CTRL_T;
analog_t = std::max<u16>(analog_t, value);
analog_t = std::max<u16>(analog_t, value.value);
break;
default:
break;
@ -2029,15 +2029,15 @@ static inline void ds3_get_stick_values(u32 gem_num, const std::shared_ptr<Pad>&
y_pos = 0;
const auto& cfg = ::at32(g_cfg_gem_fake.players, gem_num);
cfg->handle_input(pad, true, [&](gem_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
cfg->handle_input(pad, true, [&](const auto& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case gem_btn::x_axis: x_pos = value; break;
case gem_btn::y_axis: y_pos = value; break;
case gem_btn::x_axis: x_pos = value.value; break;
case gem_btn::y_axis: y_pos = value.value; break;
default: break;
}
});
@ -2180,9 +2180,9 @@ static u32 ext_device_id(gem_ext_id id)
}
template <bool has_combo, bool is_combo>
static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::set<pad_button>& combos, gem_btn btn, pad_button pad_btn, u16 value, bool pressed)
static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::set<pad_button>& combos, const emulated_pad_config<gem_btn>::input_value& value)
{
if (!pressed)
if (!value.pressed)
return;
const auto set_firing_mode = [&ext](gem_btn btn)
@ -2196,18 +2196,18 @@ static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::s
{
if (external_device_id == SHARP_SHOOTER_DEVICE_ID)
{
switch (btn)
switch (value.btn)
{
case gem_btn::combo_sharpshooter_firing_mode_1:
case gem_btn::combo_sharpshooter_firing_mode_2:
case gem_btn::combo_sharpshooter_firing_mode_3:
set_firing_mode(btn);
combos.insert(pad_btn);
set_firing_mode(value.btn);
combos.insert(value.pad_btn);
break;
case gem_btn::combo_sharpshooter_trigger:
case gem_btn::combo_sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
ext.custom[0] |= ::at32(ext_btn_map, value.btn);
combos.insert(value.pad_btn);
break;
default:
break;
@ -2215,30 +2215,30 @@ static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::s
}
else if (external_device_id == RACING_WHEEL_DEVICE_ID)
{
switch (btn)
switch (value.btn)
{
case gem_btn::combo_racing_wheel_throttle:
case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2:
ext.custom[::at32(ext_btn_indices, btn)] = static_cast<u8>(value);
combos.insert(pad_btn);
ext.custom[::at32(ext_btn_indices, value.btn)] = static_cast<u8>(value.value);
combos.insert(value.pad_btn);
break;
case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r:
ext.custom[::at32(ext_btn_indices, btn)] |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
ext.custom[::at32(ext_btn_indices, value.btn)] |= ::at32(ext_btn_map, value.btn);
combos.insert(value.pad_btn);
break;
case gem_btn::combo_racing_wheel_d_pad_up:
case gem_btn::combo_racing_wheel_d_pad_right:
case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left:
ext.digital1 |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
ext.digital1 |= ::at32(ext_btn_map, value.btn);
combos.insert(value.pad_btn);
break;
case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn);
combos.insert(pad_btn);
ext.digital2 |= ::at32(ext_btn_map, value.btn);
combos.insert(value.pad_btn);
break;
default:
break;
@ -2249,7 +2249,7 @@ static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::s
{
if constexpr (has_combo)
{
if (combos.contains(pad_btn))
if (combos.contains(value.pad_btn))
{
return;
}
@ -2257,16 +2257,16 @@ static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::s
if (external_device_id == SHARP_SHOOTER_DEVICE_ID)
{
switch (btn)
switch (value.btn)
{
case gem_btn::sharpshooter_firing_mode_1:
case gem_btn::sharpshooter_firing_mode_2:
case gem_btn::sharpshooter_firing_mode_3:
set_firing_mode(btn);
set_firing_mode(value.btn);
break;
case gem_btn::sharpshooter_trigger:
case gem_btn::sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn);
ext.custom[0] |= ::at32(ext_btn_map, value.btn);
break;
default:
break;
@ -2274,26 +2274,26 @@ static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::s
}
else if (external_device_id == RACING_WHEEL_DEVICE_ID)
{
switch (btn)
switch (value.btn)
{
case gem_btn::combo_racing_wheel_throttle:
case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2:
ext.custom[::at32(ext_btn_indices, btn)] = static_cast<u8>(value);
ext.custom[::at32(ext_btn_indices, value.btn)] = static_cast<u8>(value.value);
break;
case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r:
ext.custom[::at32(ext_btn_indices, btn)] |= ::at32(ext_btn_map, btn);
ext.custom[::at32(ext_btn_indices, value.btn)] |= ::at32(ext_btn_map, value.btn);
break;
case gem_btn::combo_racing_wheel_d_pad_up:
case gem_btn::combo_racing_wheel_d_pad_right:
case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left:
ext.digital1 |= ::at32(ext_btn_map, btn);
ext.digital1 |= ::at32(ext_btn_map, value.btn);
break;
case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn);
ext.digital2 |= ::at32(ext_btn_map, value.btn);
break;
default:
break;
@ -2370,10 +2370,10 @@ static void fake_input_to_ext(u32 gem_num, gem_config::gem_controller& controlle
// Restore firing mode
ext.custom[0] = controller.firing_mode;
cfg->handle_input(pad, true, [&move_data, &ext](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
cfg->handle_input(pad, true, [&move_data, &ext](const auto& value, bool& /*abort*/)
{
static std::set<pad_button> s_combos = {};
input_to_ext<false, false>(move_data.external_device_id, ext, s_combos, btn, pad_btn, value, pressed);
input_to_ext<false, false>(move_data.external_device_id, ext, s_combos, value);
});
ext.status = controller.ext_status;
@ -2419,9 +2419,9 @@ static void mouse_input_to_ext(u32 mouse_no, gem_config::gem_controller& control
std::set<pad_button> combos;
// Check combo button first
cfg->handle_input(mouse_data, [&combo_active](gem_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& abort)
cfg->handle_input(mouse_data, [&combo_active](const auto& value, bool& abort)
{
if (pressed && btn == gem_btn::combo)
if (value.pressed && value.btn == gem_btn::combo)
{
combo_active = true;
abort = true;
@ -2431,16 +2431,16 @@ static void mouse_input_to_ext(u32 mouse_no, gem_config::gem_controller& control
// Check combos
if (combo_active)
{
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](const auto& value, bool& /*abort*/)
{
input_to_ext<true, true>(external_device_id, ext, combos, btn, pad_btn, value, pressed);
input_to_ext<true, true>(external_device_id, ext, combos, value);
});
}
// Check normal buttons
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](gem_btn btn, pad_button pad_btn, u16 value, bool pressed, bool& /*abort*/)
cfg->handle_input(mouse_data, [external_device_id, &ext, &combos](const auto& value, bool& /*abort*/)
{
input_to_ext<true, false>(external_device_id, ext, combos, btn, pad_btn, value, pressed);
input_to_ext<true, false>(external_device_id, ext, combos, value);
});
ext.status = controller.ext_status;
@ -2553,9 +2553,9 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
};
// Check combo button first
cfg->handle_input(mouse_data, [&combo_active](gem_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& abort)
cfg->handle_input(mouse_data, [&combo_active](const auto& value, bool& abort)
{
if (pressed && btn == gem_btn::combo)
if (value.pressed && value.btn == gem_btn::combo)
{
combo_active = true;
abort = true;
@ -2565,12 +2565,12 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
// Check combos
if (combo_active)
{
cfg->handle_input(mouse_data, [&digital_buttons, &combos](gem_btn btn, pad_button pad_btn, u16 /*value*/, bool pressed, bool& /*abort*/)
cfg->handle_input(mouse_data, [&digital_buttons, &combos](const auto& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case gem_btn::combo_start:
case gem_btn::combo_select:
@ -2580,8 +2580,8 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
case gem_btn::combo_square:
case gem_btn::combo_move:
case gem_btn::combo_t:
digital_buttons |= ::at32(btn_map, btn);
combos.insert(pad_btn);
digital_buttons |= ::at32(btn_map, value.btn);
combos.insert(value.pad_btn);
break;
default:
break;
@ -2590,12 +2590,12 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
}
// Check normal buttons
cfg->handle_input(mouse_data, [&digital_buttons, &combos](gem_btn btn, pad_button pad_btn, u16 /*value*/, bool pressed, bool& /*abort*/)
cfg->handle_input(mouse_data, [&digital_buttons, &combos](const auto& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case gem_btn::start:
case gem_btn::select:
@ -2606,9 +2606,9 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
case gem_btn::move:
case gem_btn::t:
// Ignore this gem_btn if the same pad_button was already used in a combo
if (!combos.contains(pad_btn))
if (!combos.contains(value.pad_btn))
{
digital_buttons |= ::at32(btn_map, btn);
digital_buttons |= ::at32(btn_map, value.btn);
}
break;
default:

View File

@ -179,12 +179,12 @@ void usb_device_buzz::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/
}
const auto& cfg = g_cfg_buzz.players[i];
cfg->handle_input(pad, true, [&buf, &index](buzz_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)
cfg->handle_input(pad, true, [&buf, &index](const auto& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case buzz_btn::red:
buf[2 + (0 + 5 * index) / 8] |= 1 << ((0 + 5 * index) % 8); // Red

View File

@ -158,12 +158,12 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint
}
const auto& cfg = ::at32(g_cfg_ghltar.players, m_controller_index);
cfg->handle_input(pad, true, [&buf](ghltar_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
cfg->handle_input(pad, true, [&buf](const auto& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case ghltar_btn::w1:
buf[0] += 0x01; // W1
@ -205,17 +205,18 @@ void usb_device_ghltar::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint
buf[1] += 0x04; // GHTV Button
break;
case ghltar_btn::whammy:
buf[6] = ~(value) + 0x01; // Whammy
buf[6] = ~(value.to_8bit()) + 0x01; // Whammy
break;
case ghltar_btn::tilt:
buf[19] = static_cast<u8>(value); // Tilt
if (buf[19] >= 0xF0)
buf[5] = 0xFF;
else if (buf[19] <= 0x10)
buf[5] = 0x00;
buf[19] = value.to_8bit(); // Tilt
break;
case ghltar_btn::count:
break;
}
});
if (buf[19] >= 0xF0)
buf[5] = 0xFF;
else if (buf[19] <= 0x10)
buf[5] = 0x00;
}

View File

@ -227,12 +227,12 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint,
return;
}
const auto input_callback = [&gc](guncon3_btn btn, pad_button /*pad_button*/, u16 value, bool pressed, bool& /*abort*/)
const auto input_callback = [&gc](const emulated_pad_config<guncon3_btn>::input_value& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case guncon3_btn::trigger: gc.btn_trigger |= 1; break;
case guncon3_btn::a1: gc.btn_a1 |= 1; break;
@ -243,10 +243,10 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint,
case guncon3_btn::b3: gc.btn_b3 |= 1; break;
case guncon3_btn::c1: gc.btn_c1 |= 1; break;
case guncon3_btn::c2: gc.btn_c2 |= 1; break;
case guncon3_btn::as_x: gc.stick_ax = static_cast<uint8_t>(value); break;
case guncon3_btn::as_y: gc.stick_ay = static_cast<uint8_t>(value); break;
case guncon3_btn::bs_x: gc.stick_bx = static_cast<uint8_t>(value); break;
case guncon3_btn::bs_y: gc.stick_by = static_cast<uint8_t>(value); break;
case guncon3_btn::as_x: gc.stick_ax = static_cast<uint8_t>(value.value); break;
case guncon3_btn::as_y: gc.stick_ay = static_cast<uint8_t>(value.value); break;
case guncon3_btn::bs_x: gc.stick_bx = static_cast<uint8_t>(value.value); break;
case guncon3_btn::bs_y: gc.stick_by = static_cast<uint8_t>(value.value); break;
case guncon3_btn::count: break;
}
};

View File

@ -280,12 +280,12 @@ void usb_device_topshotelite::interrupt_transfer(u32 buf_size, u8* buf, u32 /*en
}
bool up = false, right = false, down = false, left = false;
const auto input_callback = [&ts, &up, &down, &left, &right](topshotelite_btn btn, pad_button /*pad_button*/, u16 value, bool pressed, bool& /*abort*/)
const auto input_callback = [&ts, &up, &down, &left, &right](const emulated_pad_config<topshotelite_btn>::input_value& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case topshotelite_btn::trigger: ts.btn_trigger |= 1; break;
case topshotelite_btn::reload: ts.btn_reload |= 1; break;
@ -302,11 +302,11 @@ void usb_device_topshotelite::interrupt_transfer(u32 buf_size, u8* buf, u32 /*en
case topshotelite_btn::dpad_down: down = true; break;
case topshotelite_btn::dpad_left: left = true; break;
case topshotelite_btn::dpad_right: right = true; break;
case topshotelite_btn::ls_x: ts.stick_lx = static_cast<uint8_t>(value); break;
case topshotelite_btn::ls_x: ts.stick_lx = static_cast<uint8_t>(value.value); break;
// you know you have a «Top» controller when the games are programmed to ignore a perfect controller, so we have to simulate a drift
case topshotelite_btn::ls_y: ts.stick_ly = std::min(0xff, 1 + static_cast<uint8_t>(value)); break;
case topshotelite_btn::rs_x: ts.stick_rx = static_cast<uint8_t>(value); break;
case topshotelite_btn::rs_y: ts.stick_ry = static_cast<uint8_t>(value); break;
case topshotelite_btn::ls_y: ts.stick_ly = std::min(0xff, 1 + static_cast<uint8_t>(value.value)); break;
case topshotelite_btn::rs_x: ts.stick_rx = static_cast<uint8_t>(value.value); break;
case topshotelite_btn::rs_y: ts.stick_ry = static_cast<uint8_t>(value.value); break;
case topshotelite_btn::count: break;
}
};

View File

@ -308,12 +308,12 @@ void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32
}
bool up = false, right = false, down = false, left = false;
const auto input_callback = [&ts, &up, &down, &left, &right](topshotfearmaster_btn btn, pad_button /*pad_button*/, u16 value, bool pressed, bool& /*abort*/)
const auto input_callback = [&ts, &up, &down, &left, &right](const emulated_pad_config<topshotfearmaster_btn>::input_value& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case topshotfearmaster_btn::trigger: ts.btn_trigger |= 1; break;
case topshotfearmaster_btn::heartrate: ts.btn_heartrate |= 1; break;
@ -329,8 +329,8 @@ void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32
case topshotfearmaster_btn::dpad_down: down = true; break;
case topshotfearmaster_btn::dpad_left: left = true; break;
case topshotfearmaster_btn::dpad_right: right = true; break;
case topshotfearmaster_btn::ls_x: ts.stick_lx = static_cast<uint8_t>(value); break;
case topshotfearmaster_btn::ls_y: ts.stick_ly = static_cast<uint8_t>(value); break;
case topshotfearmaster_btn::ls_x: ts.stick_lx = static_cast<uint8_t>(value.value); break;
case topshotfearmaster_btn::ls_y: ts.stick_ly = static_cast<uint8_t>(value.value); break;
case topshotfearmaster_btn::count: break;
}
};

View File

@ -170,12 +170,12 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
return;
const auto& cfg = ::at32(g_cfg_turntable.players, m_controller_index);
cfg->handle_input(pad, true, [&buf](turntable_btn btn, pad_button /*pad_btn*/, u16 value, bool pressed, bool& /*abort*/)
cfg->handle_input(pad, true, [&buf](const auto& value, bool& /*abort*/)
{
if (!pressed)
if (!value.pressed)
return;
switch (btn)
switch (value.btn)
{
case turntable_btn::blue:
buf[0] |= 0x01; // Square Button
@ -276,7 +276,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
break;
case turntable_btn::right_turntable:
// DJ Hero does not register input if the turntable is 0, so force it to 1.
buf[6] = std::max(1, 255 - value); // Right Turntable
buf[6] = std::max(1, 255 - value.to_8bit()); // Right Turntable
// DJ Hero requires turntables to be centered at 128.
// If this axis ends up centered at 127, force it to 128.
if (buf[6] == 127)
@ -285,38 +285,21 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
}
break;
case turntable_btn::crossfader:
buf[21] = ((255 - value) & 0x3F) << 2; // Crossfader, lower 6 bits
buf[22] = ((255 - value) & 0xC0) >> 6; // Crossfader, upper 2 bits
{
const u16 val = value.to_10bit(); // ensure 10-bit range
buf[21] = (val & 0xFF); // Crossfader, lower 8 bits
buf[22] = (val >> 8) & 0x03; // Crossfader, upper 2 bits
break;
}
case turntable_btn::effects_dial:
buf[19] = (value & 0x3F) << 2; // Effects Dial, lower 6 bits
buf[20] = (value & 0xC0) >> 6; // Effects Dial, upper 2 bits
{
const u16 val = value.to_10bit(); // ensure 10-bit range
buf[19] = (val & 0xFF); // Effects Dial, lower 8 bits
buf[20] = (val >> 8) & 0x03; // Effects Dial, upper 2 bits
break;
}
case turntable_btn::count:
break;
}
});
cfg->handle_motion_input(pad, [&buf](turntable_btn btn, pad_button /*pad_btn*/, u16 value, bool /*pressed*/, bool& /*abort*/)
{
switch (btn)
{
case turntable_btn::crossfader:
{
const u16 v = value & 0x03FF; // ensure 10-bit range
buf[21] = (v & 0xFF); // Crossfader, lower 8 bits
buf[22] = (v >> 8) & 0x03; // Crossfader, upper 2 bits
break;
}
case turntable_btn::effects_dial:
{
const u16 v = value & 0x03FF; // ensure 10-bit range
buf[19] = (v & 0xFF); // Effects Dial, lower 8 bits
buf[20] = (v >> 8) & 0x03; // Effects Dial, upper 2 bits
break;
}
default:
break;
}
});
}

View File

@ -88,7 +88,32 @@ public:
button_map.clear();
}
void handle_input(std::shared_ptr<Pad> pad, bool press_only, const std::function<void(T, pad_button, u16, bool, bool&)>& func) const
struct input_value
{
public:
T btn = {};
pad_button pad_btn = pad_button::pad_button_max_enum;
u16 value = 0;
u16 max_value = 255;
bool pressed = false;
u8 to_8bit() const
{
if (max_value == 255) return static_cast<u8>(value & 0x00FF);
return static_cast<u8>(std::clamp(255.0f * (static_cast<f32>(std::min(value, max_value)) / ensure(max_value)), 0.0f, 255.0f));
}
u16 to_10bit() const
{
if (max_value == 1023) return value & 0x03FF;
return static_cast<u16>(std::clamp(1023.0f * (static_cast<f32>(std::min(value, max_value)) / ensure(max_value)), 0.0f, 1023.0f));
}
private:
};
void handle_input(std::shared_ptr<Pad> pad, bool press_only, const std::function<void(const input_value&, bool&)>& func) const
{
if (!func || !pad || pad->is_copilot())
return;
@ -97,7 +122,7 @@ public:
{
if (button.m_pressed || !press_only)
{
if (handle_input_internal(func, button.m_offset, button.m_outKeyCode, button.m_value, button.m_pressed, true))
if (handle_input_internal(func, button.m_offset, button.m_outKeyCode, button.m_value, 255, button.m_pressed, true))
{
return;
}
@ -106,28 +131,22 @@ public:
for (const AnalogStickExternal& stick : pad->m_sticks_external)
{
if (handle_input_internal(func, stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, true, true))
if (handle_input_internal(func, stick.m_offset, get_axis_keycode(stick.m_offset, stick.m_value), stick.m_value, 255, true, true))
{
return;
}
}
}
void handle_motion_input(std::shared_ptr<Pad> pad, const std::function<void(T, pad_button, u16, bool, bool&)>& func) const
{
if (!func || !pad || pad->is_copilot())
return;
for (const AnalogSensor& sensor : pad->m_sensors)
{
if (handle_input_internal(func, sensor.m_offset, sensor.m_keyCode, sensor.m_value, true, false))
if (handle_input_internal(func, sensor.m_offset, sensor.m_keyCode, sensor.m_value, 1023, true, false))
{
return;
}
}
}
void handle_input(const Mouse& mouse, const std::function<void(T, pad_button, u16, bool, bool&)>& func) const
void handle_input(const Mouse& mouse, const std::function<void(const input_value&, bool&)>& func) const
{
for (int i = 0; i < 8; i++)
{
@ -138,7 +157,7 @@ public:
const u32 offset = pad_button_offset(button);
const u32 keycode = pad_button_keycode(button);
if (handle_input_internal(func, offset, keycode, 255, true, true))
if (handle_input_internal(func, offset, keycode, 255, 255, true, true))
{
return;
}
@ -187,7 +206,7 @@ protected:
return empty_set;
}
bool handle_input_internal(const std::function<void(T, pad_button, u16, bool, bool&)>& func, u32 offset, u32 keycode, u16 value, bool pressed, bool check_axis) const
bool handle_input_internal(const std::function<void(const input_value&, bool&)>& func, u32 offset, u32 keycode, u16 value, u16 max_value, bool pressed, bool check_axis) const
{
if (!func) return false;
@ -206,7 +225,7 @@ protected:
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y:
return handle_input_internal(func, offset, static_cast<u32>(axis_direction::both), value, pressed, false);
return handle_input_internal(func, offset, static_cast<u32>(axis_direction::both), value, max_value, pressed, false);
default:
break;
}
@ -220,7 +239,15 @@ protected:
{
if (btn)
{
func(btn->btn_id(), btn->get(), value, pressed, abort);
const input_value params
{
.btn = btn->btn_id(),
.pad_btn = btn->get(),
.value = value,
.max_value = max_value,
.pressed = pressed
};
func(params, abort);
if (abort) break;
}
}

View File

@ -225,56 +225,56 @@ void usb_device_usio::translate_input_taiko()
if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && !pad->is_copilot() && is_input_allowed())
{
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)
cfg->handle_input(pad, false, [&](const auto& value, bool& /*abort*/)
{
switch (btn)
switch (value.btn)
{
case usio_btn::test:
if (player != 0) break;
if (pressed && !status.test_key_pressed) // Solve the need to hold the Test key
if (value.pressed && !status.test_key_pressed) // Solve the need to hold the Test key
status.test_on = !status.test_on;
status.test_key_pressed = pressed;
status.test_key_pressed = value.pressed;
break;
case usio_btn::coin:
if (player != 0) break;
if (pressed && !status.coin_key_pressed) // Ensure only one coin is inserted each time the Coin key is pressed
if (value.pressed && !status.coin_key_pressed) // Ensure only one coin is inserted each time the Coin key is pressed
status.coin_counter++;
status.coin_key_pressed = pressed;
status.coin_key_pressed = value.pressed;
break;
case usio_btn::service:
if (player == 0 && pressed)
if (player == 0 && value.pressed)
digital_input |= 0x4000;
break;
case usio_btn::enter:
if (player == 0 && pressed)
if (player == 0 && value.pressed)
digital_input |= 0x200;
break;
case usio_btn::up:
if (player == 0 && pressed)
if (player == 0 && value.pressed)
digital_input |= 0x2000;
break;
case usio_btn::down:
if (player == 0 && pressed)
if (player == 0 && value.pressed)
digital_input |= 0x1000;
break;
case usio_btn::taiko_hit_side_left:
if (pressed)
if (value.pressed)
std::memcpy(input_buf.data() + 32 + offset, &c_hit, sizeof(u16));
break;
case usio_btn::taiko_hit_center_right:
if (pressed)
if (value.pressed)
std::memcpy(input_buf.data() + 36 + offset, &c_hit, sizeof(u16));
break;
case usio_btn::taiko_hit_side_right:
if (pressed)
if (value.pressed)
std::memcpy(input_buf.data() + 38 + offset, &c_hit, sizeof(u16));
break;
case usio_btn::taiko_hit_center_left:
if (pressed)
if (value.pressed)
std::memcpy(input_buf.data() + 34 + offset, &c_hit, sizeof(u16));
break;
case usio_btn::card_tapping:
if (pressed)
if (value.pressed)
tap_card(player);
break;
default:
@ -316,30 +316,30 @@ void usb_device_usio::translate_input_tekken()
if (const auto& pad = ::at32(handler->GetPads(), pad_number); pad->is_connected() && !pad->is_copilot() && is_input_allowed())
{
const auto& cfg = ::at32(g_cfg_usio.players, pad_number);
cfg->handle_input(pad, false, [&](usio_btn btn, pad_button /*pad_btn*/, u16 /*value*/, bool pressed, bool& /*abort*/)
cfg->handle_input(pad, false, [&](const auto& value, bool& /*abort*/)
{
switch (btn)
switch (value.btn)
{
case usio_btn::test:
if (player % 2 != 0)
break;
if (pressed && !status.test_key_pressed) // Solve the need to hold the Test button
if (value.pressed && !status.test_key_pressed) // Solve the need to hold the Test button
status.test_on = !status.test_on;
status.test_key_pressed = pressed;
status.test_key_pressed = value.pressed;
break;
case usio_btn::coin:
if (player % 2 != 0)
break;
if (pressed && !status.coin_key_pressed) // Ensure only one coin is inserted each time the Coin button is pressed
if (value.pressed && !status.coin_key_pressed) // Ensure only one coin is inserted each time the Coin button is pressed
status.coin_counter++;
status.coin_key_pressed = pressed;
status.coin_key_pressed = value.pressed;
break;
case usio_btn::service:
if (player % 2 == 0 && pressed)
if (player % 2 == 0 && value.pressed)
input |= 0x4000;
break;
case usio_btn::enter:
if (pressed)
if (value.pressed)
{
input |= 0x800000ULL << shift;
if (player == 0)
@ -347,7 +347,7 @@ void usb_device_usio::translate_input_tekken()
}
break;
case usio_btn::up:
if (pressed)
if (value.pressed)
{
input |= 0x200000ULL << shift;
if (player == 0)
@ -355,7 +355,7 @@ void usb_device_usio::translate_input_tekken()
}
break;
case usio_btn::down:
if (pressed)
if (value.pressed)
{
input |= 0x100000ULL << shift;
if (player == 0)
@ -363,7 +363,7 @@ void usb_device_usio::translate_input_tekken()
}
break;
case usio_btn::left:
if (pressed)
if (value.pressed)
{
input |= 0x80000ULL << shift;
if (player == 0)
@ -371,7 +371,7 @@ void usb_device_usio::translate_input_tekken()
}
break;
case usio_btn::right:
if (pressed)
if (value.pressed)
{
input |= 0x40000ULL << shift;
if (player == 0)
@ -379,7 +379,7 @@ void usb_device_usio::translate_input_tekken()
}
break;
case usio_btn::tekken_button1:
if (pressed)
if (value.pressed)
{
input |= 0x20000ULL << shift;
if (player == 0)
@ -387,23 +387,23 @@ void usb_device_usio::translate_input_tekken()
}
break;
case usio_btn::tekken_button2:
if (pressed)
if (value.pressed)
input |= 0x10000ULL << shift;
break;
case usio_btn::tekken_button3:
if (pressed)
if (value.pressed)
input |= 0x40000000ULL << shift;
break;
case usio_btn::tekken_button4:
if (pressed)
if (value.pressed)
input |= 0x20000000ULL << shift;
break;
case usio_btn::tekken_button5:
if (pressed)
if (value.pressed)
input |= 0x80000000ULL << shift;
break;
case usio_btn::card_tapping:
if (pressed)
if (value.pressed)
tap_card(player);
break;
default:

View File

@ -280,7 +280,8 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
}
}
if (std::is_same_v<T, turntable_btn> && (static_cast<turntable_btn>(i) == turntable_btn::crossfader || static_cast<turntable_btn>(i) == turntable_btn::effects_dial))
if ((std::is_same_v<T, turntable_btn> && (static_cast<turntable_btn>(i) == turntable_btn::crossfader || static_cast<turntable_btn>(i) == turntable_btn::effects_dial || static_cast<turntable_btn>(i) == turntable_btn::right_turntable)) ||
(std::is_same_v<T, ghltar_btn> && (static_cast<ghltar_btn>(i) == ghltar_btn::whammy || static_cast<ghltar_btn>(i) == ghltar_btn::tilt)))
{
for (int p = static_cast<int>(pad_button::motion_x); p < static_cast<int>(pad_button::pad_motion_max_enum); p++)
{