diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index b7dfa25bf6f0..fad9b52eaa95 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -5,6 +5,7 @@ #include "Emu/Cell/lv2/sys_process.h" #include "Emu/Cell/lv2/sys_sync.h" #include "Emu/Io/pad_types.h" +#include "Emu/RSX/Overlays/overlay_debug_overlay.h" #include "Input/pad_thread.h" #include "Input/product_info.h" #include "cellPad.h" @@ -73,6 +74,67 @@ void pad_info::save(utils::serial& ar) sys_io_serialize(ar); } +void show_debug_overlay(const CellPadData& data) +{ + const u16 d1 = data.button[CELL_PAD_BTN_OFFSET_DIGITAL1]; + const u16 d2 = data.button[CELL_PAD_BTN_OFFSET_DIGITAL2]; + + std::string text = fmt::format( + "> D-Pad Up: %3d : %3d\n" + "> D-Pad Down: %3d : %3d\n" + "> D-Pad Left: %3d : %3d\n" + "> D-Pad Right: %3d : %3d\n" + "> Cross: %3d : %3d\n" + "> Square: %3d : %3d\n" + "> Circle: %3d : %3d\n" + "> Triangle: %3d : %3d\n" + "> Start: %3d\n" + "> Select: %3d\n" + "> PS: %3d\n" + "> L1: %3d : %3d\n" + "> L2: %3d : %3d\n" + "> L3: %3d\n" + "> R1: %3d : %3d\n" + "> R2: %3d : %3d\n" + "> R3: %3d\n" + "> LS X: %3d\n" + "> LS Y: %3d\n" + "> RS X: %3d\n" + "> RS Y: %3d\n" + "> Sensor X: %3d\n" + "> Sensor Y: %3d\n" + "> Sensor Z: %3d\n" + "> Sensor G: %3d\n", + !!(d1 & CELL_PAD_CTRL_UP), data.button[CELL_PAD_BTN_OFFSET_PRESS_UP], + !!(d1 & CELL_PAD_CTRL_DOWN), data.button[CELL_PAD_BTN_OFFSET_PRESS_DOWN], + !!(d1 & CELL_PAD_CTRL_LEFT), data.button[CELL_PAD_BTN_OFFSET_PRESS_LEFT], + !!(d1 & CELL_PAD_CTRL_RIGHT), data.button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT], + !!(d2 & CELL_PAD_CTRL_CROSS), data.button[CELL_PAD_BTN_OFFSET_PRESS_CROSS], + !!(d2 & CELL_PAD_CTRL_SQUARE), data.button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE], + !!(d2 & CELL_PAD_CTRL_CIRCLE), data.button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE], + !!(d2 & CELL_PAD_CTRL_TRIANGLE), data.button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE], + !!(d1 & CELL_PAD_CTRL_START), + !!(d1 & CELL_PAD_CTRL_SELECT), + !!(d1 & CELL_PAD_CTRL_PS), + !!(d2 & CELL_PAD_CTRL_L1), data.button[CELL_PAD_BTN_OFFSET_PRESS_L1], + !!(d2 & CELL_PAD_CTRL_L2), data.button[CELL_PAD_BTN_OFFSET_PRESS_L2], + !!(d1 & CELL_PAD_CTRL_L3), + !!(d2 & CELL_PAD_CTRL_R1), data.button[CELL_PAD_BTN_OFFSET_PRESS_R1], + !!(d2 & CELL_PAD_CTRL_R2), data.button[CELL_PAD_BTN_OFFSET_PRESS_R2], + !!(d1 & CELL_PAD_CTRL_R3), + data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X], + data.button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y], + data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X], + data.button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y], + data.button[CELL_PAD_BTN_OFFSET_SENSOR_X], + data.button[CELL_PAD_BTN_OFFSET_SENSOR_Y], + data.button[CELL_PAD_BTN_OFFSET_SENSOR_Z], + data.button[CELL_PAD_BTN_OFFSET_SENSOR_G] + ); + + rsx::overlays::set_debug_overlay_text(std::move(text)); +} + extern void send_sys_io_connect_event(usz index, u32 state); bool cellPad_NotifyStateChange(usz index, u64 /*state*/, bool locked, bool is_blocking = true) @@ -626,6 +688,12 @@ error_code cellPadGetData(u32 port_no, vm::ptr data) return not_an_error(CELL_PAD_ERROR_NO_DEVICE); pad_get_data(port_no, data.get_ptr()); + + if (g_cfg.io.debug_overlay && !g_cfg.video.overlay && port_no == 0) + { + show_debug_overlay(*data); + } + return CELL_OK; } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.cpp b/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.cpp index 31fde89f2926..2f6aca17a2c6 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_debug_overlay.cpp @@ -50,7 +50,7 @@ namespace rsx { auto overlay = manager->get(); - if (g_cfg.video.overlay) + if (g_cfg.video.overlay || g_cfg.io.debug_overlay) { if (!overlay) { @@ -66,7 +66,7 @@ namespace rsx extern void set_debug_overlay_text(std::string&& text) { - if (!g_cfg.misc.use_native_interface || !g_cfg.video.overlay) + if (!g_cfg.misc.use_native_interface || (!g_cfg.video.overlay && !g_cfg.io.debug_overlay)) return; if (auto manager = g_fxo->try_get()) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 9dc23e1f7f3c..236c4269d71a 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -281,6 +281,7 @@ struct cfg_root : cfg::node cfg::_bool lock_overlay_input_to_player_one{this, "Lock overlay input to player one", false, true}; cfg::string midi_devices{this, "Emulated Midi devices", "ßßß@@@ßßß@@@ßßß@@@"}; cfg::_bool load_sdl_mappings{ this, "Load SDL GameController Mappings", true }; + cfg::_bool debug_overlay{ this, "IO Debug overlay", false, true }; } io{ this }; diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 8a208c07d555..202b873f649d 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -162,6 +162,7 @@ enum class emu_settings_type GHLtar, MidiDevices, SDLMappings, + IoDebugOverlay, // Misc ExitRPCS3OnFinish, @@ -354,6 +355,7 @@ inline static const QMap settings_location = { emu_settings_type::GHLtar, { "Input/Output", "GHLtar emulated controller" }}, { emu_settings_type::MidiDevices, { "Input/Output", "Emulated Midi devices" }}, { emu_settings_type::SDLMappings, { "Input/Output", "Load SDL GameController Mappings" }}, + { emu_settings_type::IoDebugOverlay, { "Input/Output", "IO Debug overlay" }}, // 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 1a23d5d3883d..73563abcfd62 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -2437,6 +2437,10 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceCheckBox(ui->perfReport, emu_settings_type::PerformanceReport); SubscribeTooltip(ui->perfReport, tooltips.settings.enable_performance_report); + // Checkboxes: IO debug options + m_emu_settings->EnhanceCheckBox(ui->debugOverlayIO, emu_settings_type::IoDebugOverlay); + SubscribeTooltip(ui->debugOverlayIO, tooltips.settings.debug_overlay_io); + // Comboboxes m_emu_settings->EnhanceComboBox(ui->combo_accurate_ppu_128, emu_settings_type::AccuratePPU128Loop, true); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index ca7a5f9c878e..0678f87f5f85 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -4161,6 +4161,13 @@ + + + + Debug Overlay IO + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 8a5bd99c93fc..ecf1d340ac22 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -110,6 +110,7 @@ class Tooltips : public QObject const QString force_high_pz = tr("Only useful when debugging differences in GPU hardware.\nNot necessary for average users.\nIf unsure, don't use this option."); const QString debug_output = tr("Enables the selected API's inbuilt debugging functionality.\nWill cause severe performance degradation especially with Vulkan.\nOnly useful to developers.\nIf unsure, don't use this option."); const QString debug_overlay = tr("Provides a graphical overlay of various debugging information.\nIf unsure, don't use this option."); + const QString debug_overlay_io = tr("Provides a graphical overlay with pad input values for player 1.\nThis is only shown if the other debug overlay is disabled.\nIf unsure, don't use this option."); const QString log_shader_programs = tr("Dump game shaders to file. Only useful to developers.\nIf unsure, don't use this option."); const QString disable_occlusion_queries = tr("Disables running occlusion queries. Minor to moderate performance boost.\nMight introduce issues with broken occlusion e.g missing geometry and extreme pop-in."); const QString disable_video_output = tr("Disables all video output and PS3 graphical rendering.\nIts only use case is to evaluate performance on CELL for development.");