diff --git a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp index 62d8f14b7a..34dc3338d2 100644 --- a/rpcs3/Emu/Cell/lv2/sys_usbd.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_usbd.cpp @@ -242,10 +242,15 @@ usb_handler_thread::usb_handler_thread() usb_devices.push_back(std::make_shared()); } - if (!found_turntable) + if (g_cfg.io.turntable == turntable_handler::one_controller || g_cfg.io.turntable == turntable_handler::two_controllers) { - sys_usbd.notice("Adding emulated turntable"); - usb_devices.push_back(std::make_shared()); + sys_usbd.notice("Adding emulated turntable (1 player)"); + usb_devices.push_back(std::make_shared(0)); + } + if (g_cfg.io.turntable == turntable_handler::two_controllers) + { + sys_usbd.notice("Adding emulated turntable (2 players)"); + usb_devices.push_back(std::make_shared(1)); } if (g_cfg.io.buzz == buzz_handler::one_controller || g_cfg.io.buzz == buzz_handler::two_controllers) diff --git a/rpcs3/Emu/Io/Turntable.cpp b/rpcs3/Emu/Io/Turntable.cpp index e5fe6b7b22..ec6096cb52 100644 --- a/rpcs3/Emu/Io/Turntable.cpp +++ b/rpcs3/Emu/Io/Turntable.cpp @@ -7,7 +7,7 @@ LOG_CHANNEL(turntable_log); -usb_device_turntable::usb_device_turntable() +usb_device_turntable::usb_device_turntable(int controller_index) : m_controller_index(controller_index) { device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE, UsbDeviceDescriptor{0x0100, 0x00, 0x00, 0x00, 0x40, 0x12BA, 0x0140, 0x0005, 0x01, 0x02, 0x00, 0x01}); auto& config0 = device.add_node(UsbDescriptorNode(USB_DESCRIPTOR_CONFIG, UsbDeviceConfiguration{0x0029, 0x01, 0x01, 0x00, 0x80, 0x19})); @@ -117,7 +117,7 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo // All other bufs are always 0x00 const auto handler = pad::get_current_handler(); - const auto& pad = handler->GetPads()[6]; + const auto& pad = handler->GetPads()[m_controller_index]; if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) return; diff --git a/rpcs3/Emu/Io/Turntable.h b/rpcs3/Emu/Io/Turntable.h index 45962c6d97..d816f690d6 100644 --- a/rpcs3/Emu/Io/Turntable.h +++ b/rpcs3/Emu/Io/Turntable.h @@ -4,8 +4,11 @@ class usb_device_turntable : public usb_device_emulated { +private: + int m_controller_index; + public: - usb_device_turntable(); + usb_device_turntable(int controller_index); ~usb_device_turntable(); void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 3a9cf2165a..54b382872c 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -245,6 +245,7 @@ struct cfg_root : cfg::node cfg::_enum camera_type{ this, "Camera type", fake_camera_type::unknown }; cfg::_enum move{ this, "Move", move_handler::null }; cfg::_enum buzz{ this, "Buzz emulated controller", buzz_handler::null }; + cfg::_enum turntable{this, "Turntable emulated controller", turntable_handler::null}; } io{ this }; struct node_sys : cfg::node diff --git a/rpcs3/Emu/system_config_types.cpp b/rpcs3/Emu/system_config_types.cpp index cc70c4f1d1..3432817879 100644 --- a/rpcs3/Emu/system_config_types.cpp +++ b/rpcs3/Emu/system_config_types.cpp @@ -389,6 +389,22 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } +template <> +void fmt_class_string::format(std::string& out, u64 arg) +{ + format_enum(out, arg, [](auto value) + { + switch (value) + { + case turntable_handler::null: return "Null"; + case turntable_handler::one_controller: return "1 controller"; + case turntable_handler::two_controllers: return "2 controllers"; + } + + return unknown; + }); +} + template <> void fmt_class_string::format(std::string& out, u64 arg) { diff --git a/rpcs3/Emu/system_config_types.h b/rpcs3/Emu/system_config_types.h index 7d5650d30f..bd4907cca6 100644 --- a/rpcs3/Emu/system_config_types.h +++ b/rpcs3/Emu/system_config_types.h @@ -102,6 +102,13 @@ enum class buzz_handler two_controllers, }; +enum class turntable_handler +{ + null, + one_controller, + two_controllers, +}; + enum class microphone_handler { null, diff --git a/rpcs3/rpcs3qt/emu_settings.cpp b/rpcs3/rpcs3qt/emu_settings.cpp index e479f210b2..f79a0eb449 100644 --- a/rpcs3/rpcs3qt/emu_settings.cpp +++ b/rpcs3/rpcs3qt/emu_settings.cpp @@ -1030,6 +1030,14 @@ QString emu_settings::GetLocalizedSetting(const QString& original, emu_settings_ case buzz_handler::two_controllers: return tr("2 controllers (5-7 players)", "Buzz handler"); } break; + case emu_settings_type::Turntable: + switch (static_cast(index)) + { + case turntable_handler::null: return tr("Null", "Turntable handler"); + case turntable_handler::one_controller: return tr("1 controller", "Turntable handler"); + case turntable_handler::two_controllers: return tr("2 controllers", "Turntable handler"); + } + break; case emu_settings_type::InternetStatus: switch (static_cast(index)) { diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 652d68733a..f4acec0d31 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -127,6 +127,7 @@ enum class emu_settings_type CameraType, Move, Buzz, + Turntable, // Misc ExitRPCS3OnFinish, @@ -279,6 +280,7 @@ inline static const QMap settings_location = { emu_settings_type::CameraType, { "Input/Output", "Camera type"}}, { emu_settings_type::Move, { "Input/Output", "Move" }}, { emu_settings_type::Buzz, { "Input/Output", "Buzz emulated controller" }}, + { emu_settings_type::Turntable, { "Input/Output", "Turntable emulated controller" }}, // Misc { emu_settings_type::ExitRPCS3OnFinish, { "Miscellaneous", "Exit RPCS3 when process finishes" }}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 7c31f4e7f5..e29a956f71 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -961,6 +961,9 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceComboBox(ui->buzzBox, emu_settings_type::Buzz); SubscribeTooltip(ui->gb_buzz_emulated, tooltips.settings.buzz); + m_emu_settings->EnhanceComboBox(ui->turntableBox, emu_settings_type::Turntable); + SubscribeTooltip(ui->gb_turntable_emulated, tooltips.settings.turntable); + // _____ _ _______ _ // / ____| | | |__ __| | | // | (___ _ _ ___| |_ ___ _ __ ___ | | __ _| |__ diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index f015a2df7b..e455ab8e62 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -1412,9 +1412,9 @@ I/O - + - + @@ -1454,7 +1454,7 @@ - + @@ -1493,6 +1493,28 @@ + + + + + + DJ Hero emulated turntable + + + + + + + + + + + + + + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 63edfb074a..d3015da0b6 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -196,6 +196,7 @@ public: const QString camera_type = tr("Camera support is not implemented, leave this on unknown."); const QString move = tr("PlayStation Move support.\nFake: Experimental! This maps Move controls to DS3 controller mappings.\nMouse: Emulate PSMove with Mouse handler."); const QString buzz = tr("Buzz! support.\nSelect 1 or 2 controllers if the game requires Buzz! controllers and you don't have real controllers.\nSelect Null if the game has support for DualShock or if you have real Buzz! controllers."); + const QString turntable = tr("DJ Hero Turntable controller support.\nSelect 1 or 2 controllers if the game requires DJ Hero Turntable controllers and you don't have real turntable controllers.\nSelect Null if the game has support for DualShock or if you have real turntable controllers.\nA real turntable controller can be used at the same time as an emulated turntable controller."); // network