cellMouse: Add debug overlay
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux-aarch64.sh, gcc, rpcs3/rpcs3-ci-jammy-aarch64:1.6, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (/rpcs3/.ci/build-linux.sh, gcc, rpcs3/rpcs3-ci-jammy:1.6, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1, rpcs3/rpcs3-binaries-linux-arm64, /rpcs3/.ci/build-linux-aarch64.sh, clang, rpcs3/rpcs3-ci-jammy-aarch64:1.6, ubuntu-24.04-arm) (push) Waiting to run
Build RPCS3 / RPCS3 Linux ${{ matrix.os }} ${{ matrix.compiler }} (d812f1254a1157c80fd402f94446310560f54e5f, rpcs3/rpcs3-binaries-linux, /rpcs3/.ci/build-linux.sh, clang, rpcs3/rpcs3-ci-jammy:1.6, ubuntu-24.04) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (51ae32f468089a8169aaf1567de355ff4a3e0842, rpcs3/rpcs3-binaries-mac, arch -X86_64 .ci/build-mac.sh, Intel) (push) Waiting to run
Build RPCS3 / RPCS3 Mac ${{ matrix.name }} (8e21bdbc40711a3fccd18fbf17b742348b0f4281, rpcs3/rpcs3-binaries-mac-arm64, .ci/build-mac-arm64.sh, Apple Silicon) (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Build RPCS3 / RPCS3 Windows Clang (win64, clang, clang64) (push) Waiting to run
Build RPCS3 / RPCS3 FreeBSD (push) Waiting to run

This commit is contained in:
Megamouse 2025-09-12 02:34:33 +02:00
parent c36d01b46b
commit a2a3ce1d7a
13 changed files with 134 additions and 37 deletions

View file

@ -1,8 +1,9 @@
#include "stdafx.h"
#include "Emu/IdManager.h"
#include "Emu/system_config.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Io/MouseHandler.h"
#include "Emu/RSX/Overlays/overlay_debug_overlay.h"
#include "cellMouse.h"
@ -13,6 +14,54 @@ extern bool is_input_allowed();
LOG_CHANNEL(cellMouse);
void show_debug_overlay(const CellMouseData& data, const MouseData* _mouse)
{
// The cell mouse can be set empty without any new mouse input.
// Only update our mouse input if there is new data.
static MouseData mouse {};
if (_mouse)
{
mouse = *_mouse;
}
std::string text = fmt::format(
"> Name: Raw Value Pixel\n"
">\n"
"> Update: %5d %5d\n"
"> Wheel: %5d %5d\n"
"> Tilt: %5d %5d\n"
"> X: %5d %5d %5d\n"
"> Y: %5d %5d %5d\n"
">\n"
"> Buttons: 0x%04x 0x%04x\n"
"> Button 1: %5d %5d\n"
"> Button 2: %5d %5d\n"
"> Button 3: %5d %5d\n"
"> Button 4: %5d %5d\n"
"> Button 5: %5d %5d\n"
"> Button 6: %5d %5d\n"
"> Button 7: %5d %5d\n"
"> Button 8: %5d %5d\n"
,
mouse.update, data.update,
mouse.wheel, data.wheel,
mouse.tilt, data.tilt,
mouse.x_axis, data.x_axis, mouse.pixel_x,
mouse.y_axis, data.y_axis, mouse.pixel_y,
mouse.buttons, data.buttons,
!!(mouse.buttons & CELL_MOUSE_BUTTON_1), !!(data.buttons & CELL_MOUSE_BUTTON_1),
!!(mouse.buttons & CELL_MOUSE_BUTTON_2), !!(data.buttons & CELL_MOUSE_BUTTON_2),
!!(mouse.buttons & CELL_MOUSE_BUTTON_3), !!(data.buttons & CELL_MOUSE_BUTTON_3),
!!(mouse.buttons & CELL_MOUSE_BUTTON_4), !!(data.buttons & CELL_MOUSE_BUTTON_4),
!!(mouse.buttons & CELL_MOUSE_BUTTON_5), !!(data.buttons & CELL_MOUSE_BUTTON_5),
!!(mouse.buttons & CELL_MOUSE_BUTTON_6), !!(data.buttons & CELL_MOUSE_BUTTON_6),
!!(mouse.buttons & CELL_MOUSE_BUTTON_7), !!(data.buttons & CELL_MOUSE_BUTTON_7),
!!(mouse.buttons & CELL_MOUSE_BUTTON_8), !!(data.buttons & CELL_MOUSE_BUTTON_8)
);
rsx::overlays::set_debug_overlay_text(std::move(text));
}
template<>
void fmt_class_string<CellMouseError>::format(std::string& out, u64 arg)
{
@ -214,10 +263,16 @@ error_code cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
if (data_list.empty() || current_info.is_null_handler || (current_info.info & CELL_MOUSE_INFO_INTERCEPTED) || !is_input_allowed())
{
data_list.clear();
if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
{
show_debug_overlay(*data, nullptr);
}
return CELL_OK;
}
const MouseData current_data = data_list.front();
const MouseData& current_data = data_list.front();
data->update = current_data.update;
data->buttons = current_data.buttons;
data->x_axis = current_data.x_axis;
@ -225,6 +280,11 @@ error_code cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
data->wheel = current_data.wheel;
data->tilt = current_data.tilt;
if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
{
show_debug_overlay(*data, &current_data);
}
data_list.pop_front();
return CELL_OK;
@ -264,20 +324,31 @@ error_code cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
if (list.empty() || current_info.is_null_handler || (current_info.info & CELL_MOUSE_INFO_INTERCEPTED) || !is_input_allowed())
{
list.clear();
if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
{
show_debug_overlay(data->list[0], nullptr);
}
return CELL_OK;
}
data->list_num = std::min<u32>(CELL_MOUSE_MAX_DATA_LIST_NUM, static_cast<u32>(list.size()));
int i = 0;
for (auto it = list.begin(); it != list.end() && i < CELL_MOUSE_MAX_DATA_LIST_NUM; ++it, ++i)
for (size_t i = 0; i < list.size() && i < CELL_MOUSE_MAX_DATA_LIST_NUM; ++i)
{
data->list[i].update = it->update;
data->list[i].buttons = it->buttons;
data->list[i].x_axis = it->x_axis;
data->list[i].y_axis = it->y_axis;
data->list[i].wheel = it->wheel;
data->list[i].tilt = it->tilt;
const MouseData& current_data = list[i];
data->list[i].update = current_data.update;
data->list[i].buttons = current_data.buttons;
data->list[i].x_axis = current_data.x_axis;
data->list[i].y_axis = current_data.y_axis;
data->list[i].wheel = current_data.wheel;
data->list[i].tilt = current_data.tilt;
if (port_no == 0 && g_cfg.io.mouse_debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay)
{
show_debug_overlay(data->list[i], &current_data);
}
}
list.clear();

View file

@ -721,7 +721,7 @@ error_code cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
pad_get_data(port_no, data.get_ptr());
if (g_cfg.io.debug_overlay && !g_cfg.video.debug_overlay && port_no == 0)
if (g_cfg.io.pad_debug_overlay && !g_cfg.video.debug_overlay && port_no == 0)
{
show_debug_overlay(*data, *pad, config);
}

View file

@ -71,6 +71,8 @@ void MouseHandlerBase::Button(u32 index, u8 button, bool pressed)
MouseData new_data{};
new_data.update = CELL_MOUSE_DATA_UPDATE;
new_data.buttons = mouse.buttons;
new_data.pixel_x = mouse.x_pos;
new_data.pixel_y = mouse.y_pos;
datalist.push_back(std::move(new_data));
}
@ -100,6 +102,8 @@ void MouseHandlerBase::Scroll(u32 index, s8 x, s8 y)
new_data.buttons = mouse.buttons;
new_data.wheel = y;
new_data.tilt = x;
new_data.pixel_x = mouse.x_pos;
new_data.pixel_y = mouse.y_pos;
datalist.push_back(std::move(new_data));
}
@ -137,6 +141,8 @@ void MouseHandlerBase::Move(u32 index, s32 x_pos_new, s32 y_pos_new, s32 x_max,
new_data.x_axis = static_cast<s8>(std::clamp(x_delta, -127, 128));
new_data.y_axis = static_cast<s8>(std::clamp(y_delta, -127, 128));
new_data.pixel_x = x_pos_new;
new_data.pixel_y = y_pos_new;
mouse.x_max = x_max;
mouse.y_max = y_max;

View file

@ -1,6 +1,6 @@
#pragma once
#include <list>
#include <deque>
#include <vector>
#include "Utilities/StrFmt.h"
#include "Utilities/mutex.h"
@ -96,6 +96,9 @@ struct MouseData
s8 y_axis = 0;
s8 wheel = 0;
s8 tilt = 0;
s32 pixel_x = 0;
s32 pixel_y = 0;
};
struct MouseTabletData
@ -104,8 +107,8 @@ struct MouseTabletData
u8 data[MOUSE_MAX_CODES]{};
};
using MouseTabletDataList = std::list<MouseTabletData>;
using MouseDataList = std::list<MouseData>;
using MouseTabletDataList = std::deque<MouseTabletData>;
using MouseDataList = std::deque<MouseData>;
struct Mouse
{

View file

@ -133,7 +133,8 @@ namespace rsx
: home_menu_settings_page(x, y, width, height, use_separators, parent, get_localized_string(localized_string_id::HOME_MENU_SETTINGS_DEBUG))
{
add_checkbox(&g_cfg.video.debug_overlay, localized_string_id::HOME_MENU_SETTINGS_DEBUG_OVERLAY);
add_checkbox(&g_cfg.io.debug_overlay, localized_string_id::HOME_MENU_SETTINGS_DEBUG_INPUT_OVERLAY);
add_checkbox(&g_cfg.io.pad_debug_overlay, localized_string_id::HOME_MENU_SETTINGS_DEBUG_INPUT_OVERLAY);
add_checkbox(&g_cfg.io.mouse_debug_overlay, localized_string_id::HOME_MENU_SETTINGS_MOUSE_DEBUG_INPUT_OVERLAY);
add_checkbox(&g_cfg.video.disable_video_output, localized_string_id::HOME_MENU_SETTINGS_DEBUG_DISABLE_VIDEO_OUTPUT);
add_float_slider(&g_cfg.video.texture_lod_bias, localized_string_id::HOME_MENU_SETTINGS_DEBUG_TEXTURE_LOD_BIAS, "", 0.25f);

View file

@ -50,7 +50,7 @@ namespace rsx
{
auto overlay = manager->get<rsx::overlays::debug_overlay>();
if (g_cfg.video.debug_overlay || g_cfg.io.debug_overlay)
if (g_cfg.video.debug_overlay || g_cfg.io.pad_debug_overlay || g_cfg.io.mouse_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.debug_overlay && !g_cfg.io.debug_overlay))
if (!g_cfg.misc.use_native_interface || (!g_cfg.video.debug_overlay && !g_cfg.io.pad_debug_overlay && !g_cfg.io.mouse_debug_overlay))
return;
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())

View file

@ -264,6 +264,7 @@ enum class localized_string_id
HOME_MENU_SETTINGS_DEBUG,
HOME_MENU_SETTINGS_DEBUG_OVERLAY,
HOME_MENU_SETTINGS_DEBUG_INPUT_OVERLAY,
HOME_MENU_SETTINGS_MOUSE_DEBUG_INPUT_OVERLAY,
HOME_MENU_SETTINGS_DEBUG_DISABLE_VIDEO_OUTPUT,
HOME_MENU_SETTINGS_DEBUG_TEXTURE_LOD_BIAS,
HOME_MENU_SCREENSHOT,

View file

@ -285,7 +285,8 @@ 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 };
cfg::_bool pad_debug_overlay{ this, "IO Debug overlay", false, true };
cfg::_bool mouse_debug_overlay{ this, "Mouse Debug overlay", false, true };
cfg::uint<1, 180> fake_move_rotation_cone_h{ this, "Fake Move Rotation Cone", 10, true };
cfg::uint<1, 180> fake_move_rotation_cone_v{ this, "Fake Move Rotation Cone (Vertical)", 10, true };

View file

@ -168,6 +168,7 @@ enum class emu_settings_type
MidiDevices,
SDLMappings,
IoDebugOverlay,
MouseDebugOverlay,
// Misc
ExitRPCS3OnFinish,
@ -375,6 +376,7 @@ inline static const std::map<emu_settings_type, cfg_location> settings_location
{ 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" }},
{ emu_settings_type::MouseDebugOverlay, { "Input/Output", "Mouse Debug overlay" }},
// Misc
{ emu_settings_type::ExitRPCS3OnFinish, { "Miscellaneous", "Exit RPCS3 when process finishes" }},

View file

@ -285,6 +285,7 @@ private:
case localized_string_id::HOME_MENU_SETTINGS_DEBUG: return tr("Debug");
case localized_string_id::HOME_MENU_SETTINGS_DEBUG_OVERLAY: return tr("Debug Overlay", "Debug");
case localized_string_id::HOME_MENU_SETTINGS_DEBUG_INPUT_OVERLAY: return tr("Input Debug Overlay", "Debug");
case localized_string_id::HOME_MENU_SETTINGS_MOUSE_DEBUG_INPUT_OVERLAY: return tr("Mouse Debug Overlay", "Debug");
case localized_string_id::HOME_MENU_SETTINGS_DEBUG_DISABLE_VIDEO_OUTPUT: return tr("Disable Video Output", "Debug");
case localized_string_id::HOME_MENU_SETTINGS_DEBUG_TEXTURE_LOD_BIAS: return tr("Texture LOD Bias Addend", "Debug");
case localized_string_id::HOME_MENU_SCREENSHOT: return tr("Take Screenshot");

View file

@ -2522,6 +2522,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
m_emu_settings->EnhanceCheckBox(ui->debugOverlayIO, emu_settings_type::IoDebugOverlay);
SubscribeTooltip(ui->debugOverlayIO, tooltips.settings.debug_overlay_io);
m_emu_settings->EnhanceCheckBox(ui->debugOverlayMouse, emu_settings_type::MouseDebugOverlay);
SubscribeTooltip(ui->debugOverlayMouse, tooltips.settings.debug_overlay_mouse);
// Comboboxes
m_emu_settings->EnhanceComboBox(ui->combo_accurate_ppu_128, emu_settings_type::AccuratePPU128Loop, true);

View file

@ -4547,6 +4547,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="debugOverlayMouse">
<property name="text">
<string>Debug Overlay For Mouse Input</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View file

@ -113,7 +113,8 @@ public:
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 debug_overlay_io = tr("Provides a graphical overlay with pad input values for player 1.\nThis is only shown if the debug overlay is disabled.\nIf unsure, don't use this option.");
const QString debug_overlay_mouse = tr("Provides a graphical overlay with mouse input values.\nThis is only shown if the other debug overlays are 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.");