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 cffd02bb35
10 changed files with 177 additions and 165 deletions
+54 -54
View File
@@ -1973,12 +1973,12 @@ static void ds3_input_to_pad(const u32 gem_num, be_t<u16>& digital_buttons, be_t
return; 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; return;
switch (btn) switch (value.btn)
{ {
case gem_btn::start: case gem_btn::start:
digital_buttons |= CELL_GEM_CTRL_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; break;
case gem_btn::t: case gem_btn::t:
digital_buttons |= CELL_GEM_CTRL_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; break;
default: default:
break; break;
@@ -2029,15 +2029,15 @@ static inline void ds3_get_stick_values(u32 gem_num, const std::shared_ptr<Pad>&
y_pos = 0; y_pos = 0;
const auto& cfg = ::at32(g_cfg_gem_fake.players, gem_num); 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; return;
switch (btn) switch (value.btn)
{ {
case gem_btn::x_axis: x_pos = value; break; case gem_btn::x_axis: x_pos = value.value; break;
case gem_btn::y_axis: y_pos = value; break; case gem_btn::y_axis: y_pos = value.value; break;
default: break; default: break;
} }
}); });
@@ -2180,9 +2180,9 @@ static u32 ext_device_id(gem_ext_id id)
} }
template <bool has_combo, bool is_combo> 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; return;
const auto set_firing_mode = [&ext](gem_btn btn) 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) 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_1:
case gem_btn::combo_sharpshooter_firing_mode_2: case gem_btn::combo_sharpshooter_firing_mode_2:
case gem_btn::combo_sharpshooter_firing_mode_3: case gem_btn::combo_sharpshooter_firing_mode_3:
set_firing_mode(btn); set_firing_mode(value.btn);
combos.insert(pad_btn); combos.insert(value.pad_btn);
break; break;
case gem_btn::combo_sharpshooter_trigger: case gem_btn::combo_sharpshooter_trigger:
case gem_btn::combo_sharpshooter_reload: case gem_btn::combo_sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn); ext.custom[0] |= ::at32(ext_btn_map, value.btn);
combos.insert(pad_btn); combos.insert(value.pad_btn);
break; break;
default: default:
break; 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) 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_throttle:
case gem_btn::combo_racing_wheel_l2: case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2: 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);
combos.insert(pad_btn); combos.insert(value.pad_btn);
break; break;
case gem_btn::combo_racing_wheel_paddle_l: case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r: 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);
combos.insert(pad_btn); combos.insert(value.pad_btn);
break; break;
case gem_btn::combo_racing_wheel_d_pad_up: 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_right:
case gem_btn::combo_racing_wheel_d_pad_down: case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left: case gem_btn::combo_racing_wheel_d_pad_left:
ext.digital1 |= ::at32(ext_btn_map, btn); ext.digital1 |= ::at32(ext_btn_map, value.btn);
combos.insert(pad_btn); combos.insert(value.pad_btn);
break; break;
case gem_btn::combo_racing_wheel_l1: case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1: case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn); ext.digital2 |= ::at32(ext_btn_map, value.btn);
combos.insert(pad_btn); combos.insert(value.pad_btn);
break; break;
default: default:
break; break;
@@ -2249,7 +2249,7 @@ static void input_to_ext(u32 external_device_id, CellGemExtPortData& ext, std::s
{ {
if constexpr (has_combo) if constexpr (has_combo)
{ {
if (combos.contains(pad_btn)) if (combos.contains(value.pad_btn))
{ {
return; 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) 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_1:
case gem_btn::sharpshooter_firing_mode_2: case gem_btn::sharpshooter_firing_mode_2:
case gem_btn::sharpshooter_firing_mode_3: case gem_btn::sharpshooter_firing_mode_3:
set_firing_mode(btn); set_firing_mode(value.btn);
break; break;
case gem_btn::sharpshooter_trigger: case gem_btn::sharpshooter_trigger:
case gem_btn::sharpshooter_reload: case gem_btn::sharpshooter_reload:
ext.custom[0] |= ::at32(ext_btn_map, btn); ext.custom[0] |= ::at32(ext_btn_map, value.btn);
break; break;
default: default:
break; 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) 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_throttle:
case gem_btn::combo_racing_wheel_l2: case gem_btn::combo_racing_wheel_l2:
case gem_btn::combo_racing_wheel_r2: 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; break;
case gem_btn::combo_racing_wheel_paddle_l: case gem_btn::combo_racing_wheel_paddle_l:
case gem_btn::combo_racing_wheel_paddle_r: 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; break;
case gem_btn::combo_racing_wheel_d_pad_up: 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_right:
case gem_btn::combo_racing_wheel_d_pad_down: case gem_btn::combo_racing_wheel_d_pad_down:
case gem_btn::combo_racing_wheel_d_pad_left: 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; break;
case gem_btn::combo_racing_wheel_l1: case gem_btn::combo_racing_wheel_l1:
case gem_btn::combo_racing_wheel_r1: case gem_btn::combo_racing_wheel_r1:
ext.digital2 |= ::at32(ext_btn_map, btn); ext.digital2 |= ::at32(ext_btn_map, value.btn);
break; break;
default: default:
break; break;
@@ -2370,10 +2370,10 @@ static void fake_input_to_ext(u32 gem_num, gem_config::gem_controller& controlle
// Restore firing mode // Restore firing mode
ext.custom[0] = controller.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 = {}; 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; 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; std::set<pad_button> combos;
// Check combo button first // 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; combo_active = true;
abort = true; abort = true;
@@ -2431,16 +2431,16 @@ static void mouse_input_to_ext(u32 mouse_no, gem_config::gem_controller& control
// Check combos // Check combos
if (combo_active) 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 // 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; 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 // 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; combo_active = true;
abort = 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 // Check combos
if (combo_active) 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; return;
switch (btn) switch (value.btn)
{ {
case gem_btn::combo_start: case gem_btn::combo_start:
case gem_btn::combo_select: 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_square:
case gem_btn::combo_move: case gem_btn::combo_move:
case gem_btn::combo_t: case gem_btn::combo_t:
digital_buttons |= ::at32(btn_map, btn); digital_buttons |= ::at32(btn_map, value.btn);
combos.insert(pad_btn); combos.insert(value.pad_btn);
break; break;
default: default:
break; 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 // 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; return;
switch (btn) switch (value.btn)
{ {
case gem_btn::start: case gem_btn::start:
case gem_btn::select: 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::move:
case gem_btn::t: case gem_btn::t:
// Ignore this gem_btn if the same pad_button was already used in a combo // 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; break;
default: default:
+3 -3
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]; 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; return;
switch (btn) switch (value.btn)
{ {
case buzz_btn::red: case buzz_btn::red:
buf[2 + (0 + 5 * index) / 8] |= 1 << ((0 + 5 * index) % 8); // Red buf[2 + (0 + 5 * index) / 8] |= 1 << ((0 + 5 * index) % 8); // Red
+10 -9
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); 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; return;
switch (btn) switch (value.btn)
{ {
case ghltar_btn::w1: case ghltar_btn::w1:
buf[0] += 0x01; // 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 buf[1] += 0x04; // GHTV Button
break; break;
case ghltar_btn::whammy: case ghltar_btn::whammy:
buf[6] = ~(value) + 0x01; // Whammy buf[6] = ~(value.to_8bit()) + 0x01; // Whammy
break; break;
case ghltar_btn::tilt: case ghltar_btn::tilt:
buf[19] = static_cast<u8>(value); // Tilt buf[19] = value.to_8bit(); // Tilt
if (buf[19] >= 0xF0)
buf[5] = 0xFF;
else if (buf[19] <= 0x10)
buf[5] = 0x00;
break; break;
case ghltar_btn::count: case ghltar_btn::count:
break; break;
} }
}); });
if (buf[19] >= 0xF0)
buf[5] = 0xFF;
else if (buf[19] <= 0x10)
buf[5] = 0x00;
} }
+7 -7
View File
@@ -227,12 +227,12 @@ void usb_device_guncon3::interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint,
return; 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; return;
switch (btn) switch (value.btn)
{ {
case guncon3_btn::trigger: gc.btn_trigger |= 1; break; case guncon3_btn::trigger: gc.btn_trigger |= 1; break;
case guncon3_btn::a1: gc.btn_a1 |= 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::b3: gc.btn_b3 |= 1; break;
case guncon3_btn::c1: gc.btn_c1 |= 1; break; case guncon3_btn::c1: gc.btn_c1 |= 1; break;
case guncon3_btn::c2: gc.btn_c2 |= 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_x: gc.stick_ax = static_cast<uint8_t>(value.value); break;
case guncon3_btn::as_y: gc.stick_ay = static_cast<uint8_t>(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); 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); break; case guncon3_btn::bs_y: gc.stick_by = static_cast<uint8_t>(value.value); break;
case guncon3_btn::count: break; case guncon3_btn::count: break;
} }
}; };
+7 -7
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; 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; return;
switch (btn) switch (value.btn)
{ {
case topshotelite_btn::trigger: ts.btn_trigger |= 1; break; case topshotelite_btn::trigger: ts.btn_trigger |= 1; break;
case topshotelite_btn::reload: ts.btn_reload |= 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_down: down = true; break;
case topshotelite_btn::dpad_left: left = true; break; case topshotelite_btn::dpad_left: left = true; break;
case topshotelite_btn::dpad_right: right = 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 // 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::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); 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); break; case topshotelite_btn::rs_y: ts.stick_ry = static_cast<uint8_t>(value.value); break;
case topshotelite_btn::count: break; case topshotelite_btn::count: break;
} }
}; };
+5 -5
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; 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; return;
switch (btn) switch (value.btn)
{ {
case topshotfearmaster_btn::trigger: ts.btn_trigger |= 1; break; case topshotfearmaster_btn::trigger: ts.btn_trigger |= 1; break;
case topshotfearmaster_btn::heartrate: ts.btn_heartrate |= 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_down: down = true; break;
case topshotfearmaster_btn::dpad_left: left = true; break; case topshotfearmaster_btn::dpad_left: left = true; break;
case topshotfearmaster_btn::dpad_right: right = 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_x: ts.stick_lx = static_cast<uint8_t>(value.value); break;
case topshotfearmaster_btn::ls_y: ts.stick_ly = static_cast<uint8_t>(value); break; case topshotfearmaster_btn::ls_y: ts.stick_ly = static_cast<uint8_t>(value.value); break;
case topshotfearmaster_btn::count: break; case topshotfearmaster_btn::count: break;
} }
}; };
+14 -31
View File
@@ -170,12 +170,12 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
return; return;
const auto& cfg = ::at32(g_cfg_turntable.players, m_controller_index); 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; return;
switch (btn) switch (value.btn)
{ {
case turntable_btn::blue: case turntable_btn::blue:
buf[0] |= 0x01; // Square Button buf[0] |= 0x01; // Square Button
@@ -276,7 +276,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
break; break;
case turntable_btn::right_turntable: case turntable_btn::right_turntable:
// DJ Hero does not register input if the turntable is 0, so force it to 1. // 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. // DJ Hero requires turntables to be centered at 128.
// If this axis ends up centered at 127, force it to 128. // If this axis ends up centered at 127, force it to 128.
if (buf[6] == 127) if (buf[6] == 127)
@@ -285,38 +285,21 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo
} }
break; break;
case turntable_btn::crossfader: 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; break;
}
case turntable_btn::effects_dial: 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; break;
}
case turntable_btn::count: case turntable_btn::count:
break; 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;
}
});
} }
+42 -15
View File
@@ -88,7 +88,32 @@ public:
button_map.clear(); 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()) if (!func || !pad || pad->is_copilot())
return; return;
@@ -97,7 +122,7 @@ public:
{ {
if (button.m_pressed || !press_only) 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; return;
} }
@@ -106,28 +131,22 @@ public:
for (const AnalogStickExternal& stick : pad->m_sticks_external) 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; 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) 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; 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++) for (int i = 0; i < 8; i++)
{ {
@@ -138,7 +157,7 @@ public:
const u32 offset = pad_button_offset(button); const u32 offset = pad_button_offset(button);
const u32 keycode = pad_button_keycode(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; return;
} }
@@ -187,7 +206,7 @@ protected:
return empty_set; 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; if (!func) return false;
@@ -206,7 +225,7 @@ protected:
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y: case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X: case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y: 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: default:
break; break;
} }
@@ -220,7 +239,15 @@ protected:
{ {
if (btn) 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; if (abort) break;
} }
} }
+33 -33
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()) 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); 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: case usio_btn::test:
if (player != 0) break; 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_on = !status.test_on;
status.test_key_pressed = pressed; status.test_key_pressed = value.pressed;
break; break;
case usio_btn::coin: case usio_btn::coin:
if (player != 0) break; 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_counter++;
status.coin_key_pressed = pressed; status.coin_key_pressed = value.pressed;
break; break;
case usio_btn::service: case usio_btn::service:
if (player == 0 && pressed) if (player == 0 && value.pressed)
digital_input |= 0x4000; digital_input |= 0x4000;
break; break;
case usio_btn::enter: case usio_btn::enter:
if (player == 0 && pressed) if (player == 0 && value.pressed)
digital_input |= 0x200; digital_input |= 0x200;
break; break;
case usio_btn::up: case usio_btn::up:
if (player == 0 && pressed) if (player == 0 && value.pressed)
digital_input |= 0x2000; digital_input |= 0x2000;
break; break;
case usio_btn::down: case usio_btn::down:
if (player == 0 && pressed) if (player == 0 && value.pressed)
digital_input |= 0x1000; digital_input |= 0x1000;
break; break;
case usio_btn::taiko_hit_side_left: case usio_btn::taiko_hit_side_left:
if (pressed) if (value.pressed)
std::memcpy(input_buf.data() + 32 + offset, &c_hit, sizeof(u16)); std::memcpy(input_buf.data() + 32 + offset, &c_hit, sizeof(u16));
break; break;
case usio_btn::taiko_hit_center_right: case usio_btn::taiko_hit_center_right:
if (pressed) if (value.pressed)
std::memcpy(input_buf.data() + 36 + offset, &c_hit, sizeof(u16)); std::memcpy(input_buf.data() + 36 + offset, &c_hit, sizeof(u16));
break; break;
case usio_btn::taiko_hit_side_right: case usio_btn::taiko_hit_side_right:
if (pressed) if (value.pressed)
std::memcpy(input_buf.data() + 38 + offset, &c_hit, sizeof(u16)); std::memcpy(input_buf.data() + 38 + offset, &c_hit, sizeof(u16));
break; break;
case usio_btn::taiko_hit_center_left: case usio_btn::taiko_hit_center_left:
if (pressed) if (value.pressed)
std::memcpy(input_buf.data() + 34 + offset, &c_hit, sizeof(u16)); std::memcpy(input_buf.data() + 34 + offset, &c_hit, sizeof(u16));
break; break;
case usio_btn::card_tapping: case usio_btn::card_tapping:
if (pressed) if (value.pressed)
tap_card(player); tap_card(player);
break; break;
default: 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()) 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); 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: case usio_btn::test:
if (player % 2 != 0) if (player % 2 != 0)
break; 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_on = !status.test_on;
status.test_key_pressed = pressed; status.test_key_pressed = value.pressed;
break; break;
case usio_btn::coin: case usio_btn::coin:
if (player % 2 != 0) if (player % 2 != 0)
break; 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_counter++;
status.coin_key_pressed = pressed; status.coin_key_pressed = value.pressed;
break; break;
case usio_btn::service: case usio_btn::service:
if (player % 2 == 0 && pressed) if (player % 2 == 0 && value.pressed)
input |= 0x4000; input |= 0x4000;
break; break;
case usio_btn::enter: case usio_btn::enter:
if (pressed) if (value.pressed)
{ {
input |= 0x800000ULL << shift; input |= 0x800000ULL << shift;
if (player == 0) if (player == 0)
@@ -347,7 +347,7 @@ void usb_device_usio::translate_input_tekken()
} }
break; break;
case usio_btn::up: case usio_btn::up:
if (pressed) if (value.pressed)
{ {
input |= 0x200000ULL << shift; input |= 0x200000ULL << shift;
if (player == 0) if (player == 0)
@@ -355,7 +355,7 @@ void usb_device_usio::translate_input_tekken()
} }
break; break;
case usio_btn::down: case usio_btn::down:
if (pressed) if (value.pressed)
{ {
input |= 0x100000ULL << shift; input |= 0x100000ULL << shift;
if (player == 0) if (player == 0)
@@ -363,7 +363,7 @@ void usb_device_usio::translate_input_tekken()
} }
break; break;
case usio_btn::left: case usio_btn::left:
if (pressed) if (value.pressed)
{ {
input |= 0x80000ULL << shift; input |= 0x80000ULL << shift;
if (player == 0) if (player == 0)
@@ -371,7 +371,7 @@ void usb_device_usio::translate_input_tekken()
} }
break; break;
case usio_btn::right: case usio_btn::right:
if (pressed) if (value.pressed)
{ {
input |= 0x40000ULL << shift; input |= 0x40000ULL << shift;
if (player == 0) if (player == 0)
@@ -379,7 +379,7 @@ void usb_device_usio::translate_input_tekken()
} }
break; break;
case usio_btn::tekken_button1: case usio_btn::tekken_button1:
if (pressed) if (value.pressed)
{ {
input |= 0x20000ULL << shift; input |= 0x20000ULL << shift;
if (player == 0) if (player == 0)
@@ -387,23 +387,23 @@ void usb_device_usio::translate_input_tekken()
} }
break; break;
case usio_btn::tekken_button2: case usio_btn::tekken_button2:
if (pressed) if (value.pressed)
input |= 0x10000ULL << shift; input |= 0x10000ULL << shift;
break; break;
case usio_btn::tekken_button3: case usio_btn::tekken_button3:
if (pressed) if (value.pressed)
input |= 0x40000000ULL << shift; input |= 0x40000000ULL << shift;
break; break;
case usio_btn::tekken_button4: case usio_btn::tekken_button4:
if (pressed) if (value.pressed)
input |= 0x20000000ULL << shift; input |= 0x20000000ULL << shift;
break; break;
case usio_btn::tekken_button5: case usio_btn::tekken_button5:
if (pressed) if (value.pressed)
input |= 0x80000000ULL << shift; input |= 0x80000000ULL << shift;
break; break;
case usio_btn::card_tapping: case usio_btn::card_tapping:
if (pressed) if (value.pressed)
tap_card(player); tap_card(player);
break; break;
default: default:
@@ -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++) for (int p = static_cast<int>(pad_button::motion_x); p < static_cast<int>(pad_button::pad_motion_max_enum); p++)
{ {