From 81f1f49d5d205ab49a1fe57856dd1318d9464bc5 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 23 Jun 2024 07:10:55 +0200 Subject: [PATCH 01/30] Update 7zip to 24.07 --- 3rdparty/7zip/7zip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/7zip/7zip b/3rdparty/7zip/7zip index 89a73b9012..a7a1d4a241 160000 --- a/3rdparty/7zip/7zip +++ b/3rdparty/7zip/7zip @@ -1 +1 @@ -Subproject commit 89a73b901229c8550c172c9556ff8442ae7ac4b8 +Subproject commit a7a1d4a241492e81f659a920f7379c193593ebc6 From 7367f72f4a817806a57bebcc54d5a94c80becd2d Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 23 Jun 2024 07:11:10 +0200 Subject: [PATCH 02/30] Update SDL to 2.30.4 --- 3rdparty/libsdl-org/SDL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/libsdl-org/SDL b/3rdparty/libsdl-org/SDL index fb1497566c..92fe3b19c8 160000 --- a/3rdparty/libsdl-org/SDL +++ b/3rdparty/libsdl-org/SDL @@ -1 +1 @@ -Subproject commit fb1497566c5a05e2babdcf45ef0ab5c7cca2c4ae +Subproject commit 92fe3b19c868ad062c323dde2cfc9d8b4bfdd785 From 7e27e1420e9bf6545a6f642987f56ac335649bcd Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 23 Jun 2024 08:37:37 +0200 Subject: [PATCH 03/30] input: try to fix macOS SDL crash --- rpcs3/Input/sdl_pad_handler.cpp | 197 +++++++++++++++++--------------- 1 file changed, 107 insertions(+), 90 deletions(-) diff --git a/rpcs3/Input/sdl_pad_handler.cpp b/rpcs3/Input/sdl_pad_handler.cpp index 856250669e..7477f2200e 100644 --- a/rpcs3/Input/sdl_pad_handler.cpp +++ b/rpcs3/Input/sdl_pad_handler.cpp @@ -9,8 +9,110 @@ LOG_CHANNEL(sdl_log, "SDL"); -std::mutex g_sdl_mutex; -u32 g_sdl_handler_count = 0; +struct sdl_instance +{ +public: + sdl_instance() = default; + ~sdl_instance() + { + // Only quit SDL once on exit. SDL uses a global state internally... + if (m_initialized) + { + sdl_log.notice("Quitting SDL ..."); + SDL_Quit(); + } + } + + bool initialize() + { + // Only init SDL once. SDL uses a global state internally... + if (m_initialized) + { + return true; + } + + sdl_log.notice("Initializing SDL ..."); + + // Set non-dynamic hints before SDL_Init + if (!SDL_SetHint(SDL_HINT_JOYSTICK_THREAD, "1")) + { + sdl_log.error("Could not set SDL_HINT_JOYSTICK_THREAD: %s", SDL_GetError()); + } + + if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER) < 0) + { + sdl_log.error("Could not initialize! SDL Error: %s", SDL_GetError()); + return false; + } + + SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); + SDL_LogSetOutputFunction([](void*, int category, SDL_LogPriority priority, const char* message) + { + std::string category_name; + switch (category) + { + case SDL_LOG_CATEGORY_APPLICATION: + category_name = "app"; + break; + case SDL_LOG_CATEGORY_ERROR: + category_name = "error"; + break; + case SDL_LOG_CATEGORY_ASSERT: + category_name = "assert"; + break; + case SDL_LOG_CATEGORY_SYSTEM: + category_name = "system"; + break; + case SDL_LOG_CATEGORY_AUDIO: + category_name = "audio"; + break; + case SDL_LOG_CATEGORY_VIDEO: + category_name = "video"; + break; + case SDL_LOG_CATEGORY_RENDER: + category_name = "render"; + break; + case SDL_LOG_CATEGORY_INPUT: + category_name = "input"; + break; + case SDL_LOG_CATEGORY_TEST: + category_name = "test"; + break; + default: + category_name = fmt::format("unknown(%d)", category); + break; + } + + switch (priority) + { + case SDL_LOG_PRIORITY_VERBOSE: + case SDL_LOG_PRIORITY_DEBUG: + sdl_log.trace("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_INFO: + sdl_log.notice("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_WARN: + sdl_log.warning("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_ERROR: + sdl_log.error("%s: %s", category_name, message); + break; + case SDL_LOG_PRIORITY_CRITICAL: + sdl_log.error("%s: %s", category_name, message); + break; + default: + break; + } + }, nullptr); + + m_initialized = true; + return true; + } + +private: + bool m_initialized = false; +}; constexpr u32 rumble_duration_ms = 500; // Some high number to keep rumble updates at a minimum. constexpr u32 rumble_refresh_ms = rumble_duration_ms - 100; // We need to keep updating the rumble. Choose a refresh timeout that is unlikely to run into missed rumble updates. @@ -87,14 +189,6 @@ sdl_pad_handler::~sdl_pad_handler() controller.second->sdl.game_controller = nullptr; } } - - // Only quit SDL if this is the last instance of the handler. SDL uses a global state internally... - std::lock_guard lock(g_sdl_mutex); - if (g_sdl_handler_count > 0 && --g_sdl_handler_count == 0) - { - sdl_log.notice("Quitting SDL ..."); - SDL_Quit(); - } } void sdl_pad_handler::init_config(cfg_pad* cfg) @@ -159,86 +253,9 @@ bool sdl_pad_handler::Init() if (m_is_init) return true; - std::lock_guard lock(g_sdl_mutex); - - // Only init SDL if this is the first instance of the handler. SDL uses a global state internally... - if (g_sdl_handler_count++ == 0) - { - sdl_log.notice("Initializing SDL ..."); - - // Set non-dynamic hints before SDL_Init - if (!SDL_SetHint(SDL_HINT_JOYSTICK_THREAD, "1")) - { - sdl_log.error("Could not set SDL_HINT_JOYSTICK_THREAD: %s", SDL_GetError()); - } - - if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER) < 0) - { - sdl_log.error("Could not initialize! SDL Error: %s", SDL_GetError()); - return false; - } - - SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE); - SDL_LogSetOutputFunction([](void*, int category, SDL_LogPriority priority, const char* message) - { - std::string category_name; - switch (category) - { - case SDL_LOG_CATEGORY_APPLICATION: - category_name = "app"; - break; - case SDL_LOG_CATEGORY_ERROR: - category_name = "error"; - break; - case SDL_LOG_CATEGORY_ASSERT: - category_name = "assert"; - break; - case SDL_LOG_CATEGORY_SYSTEM: - category_name = "system"; - break; - case SDL_LOG_CATEGORY_AUDIO: - category_name = "audio"; - break; - case SDL_LOG_CATEGORY_VIDEO: - category_name = "video"; - break; - case SDL_LOG_CATEGORY_RENDER: - category_name = "render"; - break; - case SDL_LOG_CATEGORY_INPUT: - category_name = "input"; - break; - case SDL_LOG_CATEGORY_TEST: - category_name = "test"; - break; - default: - category_name = fmt::format("unknown(%d)", category); - break; - } - - switch (priority) - { - case SDL_LOG_PRIORITY_VERBOSE: - case SDL_LOG_PRIORITY_DEBUG: - sdl_log.trace("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_INFO: - sdl_log.notice("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_WARN: - sdl_log.warning("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_ERROR: - sdl_log.error("%s: %s", category_name, message); - break; - case SDL_LOG_PRIORITY_CRITICAL: - sdl_log.error("%s: %s", category_name, message); - break; - default: - break; - } - }, nullptr); - } + static sdl_instance s_sdl_instance {}; + if (!s_sdl_instance.initialize()) + return false; if (g_cfg.io.load_sdl_mappings) { From 7e274a1ff4e6e14087c4ca945b35536dc5413f88 Mon Sep 17 00:00:00 2001 From: MSuih <19759300+MSuih@users.noreply.github.com> Date: Sun, 23 Jun 2024 11:59:08 +0300 Subject: [PATCH 04/30] Fix locale on linux --- rpcs3/rpcs3qt/gui_application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index e56fec0d6a..0373cfd451 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -64,6 +64,7 @@ std::unique_ptr g_raw_mouse_handler; gui_application::gui_application(int& argc, char** argv) : QApplication(argc, argv) { + std::setlocale(LC_NUMERIC, "C"); // On linux Qt changes to system locale while initializing QCoreApplication } gui_application::~gui_application() From c2899ad4cb0fe3e34edee7e58981a309e7285de7 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 23 Jun 2024 09:22:42 +0200 Subject: [PATCH 05/30] Replace sys_io log channel with cell module log channels For more granular log filtering --- rpcs3/Emu/Cell/Modules/cellKb.cpp | 22 ++++++------ rpcs3/Emu/Cell/Modules/cellMouse.cpp | 22 ++++++------ rpcs3/Emu/Cell/Modules/cellPad.cpp | 50 ++++++++++++++-------------- 3 files changed, 47 insertions(+), 47 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellKb.cpp b/rpcs3/Emu/Cell/Modules/cellKb.cpp index 9bf9af5db3..0682d32fc8 100644 --- a/rpcs3/Emu/Cell/Modules/cellKb.cpp +++ b/rpcs3/Emu/Cell/Modules/cellKb.cpp @@ -11,7 +11,7 @@ error_code sys_config_stop(ppu_thread& ppu); extern bool is_input_allowed(); -LOG_CHANNEL(sys_io); +LOG_CHANNEL(cellKb); template<> void fmt_class_string::format(std::string& out, u64 arg) @@ -77,7 +77,7 @@ void KeyboardHandlerBase::save(utils::serial& ar) error_code cellKbInit(ppu_thread& ppu, u32 max_connect) { - sys_io.warning("cellKbInit(max_connect=%d)", max_connect); + cellKb.warning("cellKbInit(max_connect=%d)", max_connect); auto& handler = g_fxo->get(); @@ -102,7 +102,7 @@ error_code cellKbInit(ppu_thread& ppu, u32 max_connect) error_code cellKbEnd(ppu_thread& ppu) { - sys_io.notice("cellKbEnd()"); + cellKb.notice("cellKbEnd()"); auto& handler = g_fxo->get(); @@ -123,7 +123,7 @@ error_code cellKbEnd(ppu_thread& ppu) error_code cellKbClearBuf(u32 port_no) { - sys_io.trace("cellKbClearBuf(port_no=%d)", port_no); + cellKb.trace("cellKbClearBuf(port_no=%d)", port_no); auto& handler = g_fxo->get(); @@ -158,7 +158,7 @@ error_code cellKbClearBuf(u32 port_no) u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode) { - sys_io.trace("cellKbCnvRawCode(arrange=%d, mkey=%d, led=%d, rawcode=0x%x)", arrange, mkey, led, rawcode); + cellKb.trace("cellKbCnvRawCode(arrange=%d, mkey=%d, led=%d, rawcode=0x%x)", arrange, mkey, led, rawcode); // CELL_KB_RAWDAT if (rawcode <= CELL_KEYC_E_UNDEF || @@ -308,7 +308,7 @@ u16 cellKbCnvRawCode(u32 arrange, u32 mkey, u32 led, u16 rawcode) error_code cellKbGetInfo(vm::ptr info) { - sys_io.trace("cellKbGetInfo(info=*0x%x)", info); + cellKb.trace("cellKbGetInfo(info=*0x%x)", info); auto& handler = g_fxo->get(); @@ -340,7 +340,7 @@ error_code cellKbGetInfo(vm::ptr info) error_code cellKbRead(u32 port_no, vm::ptr data) { - sys_io.trace("cellKbRead(port_no=%d, data=*0x%x)", port_no, data); + cellKb.trace("cellKbRead(port_no=%d, data=*0x%x)", port_no, data); auto& handler = g_fxo->get(); @@ -397,7 +397,7 @@ error_code cellKbRead(u32 port_no, vm::ptr data) error_code cellKbSetCodeType(u32 port_no, u32 type) { - sys_io.trace("cellKbSetCodeType(port_no=%d, type=%d)", port_no, type); + cellKb.trace("cellKbSetCodeType(port_no=%d, type=%d)", port_no, type); auto& handler = g_fxo->get(); @@ -425,7 +425,7 @@ error_code cellKbSetCodeType(u32 port_no, u32 type) error_code cellKbSetLEDStatus(u32 port_no, u8 led) { - sys_io.trace("cellKbSetLEDStatus(port_no=%d, led=%d)", port_no, led); + cellKb.trace("cellKbSetLEDStatus(port_no=%d, led=%d)", port_no, led); auto& handler = g_fxo->get(); @@ -454,7 +454,7 @@ error_code cellKbSetLEDStatus(u32 port_no, u8 led) error_code cellKbSetReadMode(u32 port_no, u32 rmode) { - sys_io.trace("cellKbSetReadMode(port_no=%d, rmode=%d)", port_no, rmode); + cellKb.trace("cellKbSetReadMode(port_no=%d, rmode=%d)", port_no, rmode); auto& handler = g_fxo->get(); @@ -486,7 +486,7 @@ error_code cellKbSetReadMode(u32 port_no, u32 rmode) error_code cellKbGetConfiguration(u32 port_no, vm::ptr config) { - sys_io.trace("cellKbGetConfiguration(port_no=%d, config=*0x%x)", port_no, config); + cellKb.trace("cellKbGetConfiguration(port_no=%d, config=*0x%x)", port_no, config); auto& handler = g_fxo->get(); diff --git a/rpcs3/Emu/Cell/Modules/cellMouse.cpp b/rpcs3/Emu/Cell/Modules/cellMouse.cpp index 38df718fa6..8b8d54715a 100644 --- a/rpcs3/Emu/Cell/Modules/cellMouse.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMouse.cpp @@ -12,7 +12,7 @@ error_code sys_config_stop(ppu_thread& ppu); extern bool is_input_allowed(); -LOG_CHANNEL(sys_io); +LOG_CHANNEL(cellMouse); template<> void fmt_class_string::format(std::string& out, u64 arg) @@ -37,7 +37,7 @@ void fmt_class_string::format(std::string& out, u64 arg) error_code cellMouseInit(ppu_thread& ppu, u32 max_connect) { - sys_io.notice("cellMouseInit(max_connect=%d)", max_connect); + cellMouse.notice("cellMouseInit(max_connect=%d)", max_connect); auto& handler = g_fxo->get(); @@ -60,7 +60,7 @@ error_code cellMouseInit(ppu_thread& ppu, u32 max_connect) error_code cellMouseClearBuf(u32 port_no) { - sys_io.trace("cellMouseClearBuf(port_no=%d)", port_no); + cellMouse.trace("cellMouseClearBuf(port_no=%d)", port_no); auto& handler = g_fxo->get(); @@ -97,7 +97,7 @@ error_code cellMouseClearBuf(u32 port_no) error_code cellMouseEnd(ppu_thread& ppu) { - sys_io.notice("cellMouseEnd()"); + cellMouse.notice("cellMouseEnd()"); auto& handler = g_fxo->get(); @@ -113,7 +113,7 @@ error_code cellMouseEnd(ppu_thread& ppu) error_code cellMouseGetInfo(vm::ptr info) { - sys_io.trace("cellMouseGetInfo(info=*0x%x)", info); + cellMouse.trace("cellMouseGetInfo(info=*0x%x)", info); auto& handler = g_fxo->get(); @@ -146,7 +146,7 @@ error_code cellMouseGetInfo(vm::ptr info) error_code cellMouseInfoTabletMode(u32 port_no, vm::ptr info) { - sys_io.trace("cellMouseInfoTabletMode(port_no=%d, info=*0x%x)", port_no, info); + cellMouse.trace("cellMouseInfoTabletMode(port_no=%d, info=*0x%x)", port_no, info); auto& handler = g_fxo->get(); @@ -183,7 +183,7 @@ error_code cellMouseInfoTabletMode(u32 port_no, vm::ptr inf error_code cellMouseGetData(u32 port_no, vm::ptr data) { - sys_io.trace("cellMouseGetData(port_no=%d, data=*0x%x)", port_no, data); + cellMouse.trace("cellMouseGetData(port_no=%d, data=*0x%x)", port_no, data); auto& handler = g_fxo->get(); @@ -233,7 +233,7 @@ error_code cellMouseGetData(u32 port_no, vm::ptr data) error_code cellMouseGetDataList(u32 port_no, vm::ptr data) { - sys_io.trace("cellMouseGetDataList(port_no=%d, data=0x%x)", port_no, data); + cellMouse.trace("cellMouseGetDataList(port_no=%d, data=0x%x)", port_no, data); auto& handler = g_fxo->get(); @@ -288,7 +288,7 @@ error_code cellMouseGetDataList(u32 port_no, vm::ptr data) error_code cellMouseSetTabletMode(u32 port_no, u32 mode) { - sys_io.warning("cellMouseSetTabletMode(port_no=%d, mode=%d)", port_no, mode); + cellMouse.warning("cellMouseSetTabletMode(port_no=%d, mode=%d)", port_no, mode); auto& handler = g_fxo->get(); @@ -324,7 +324,7 @@ error_code cellMouseSetTabletMode(u32 port_no, u32 mode) error_code cellMouseGetTabletDataList(u32 port_no, vm::ptr data) { - sys_io.warning("cellMouseGetTabletDataList(port_no=%d, data=0x%x)", port_no, data); + cellMouse.warning("cellMouseGetTabletDataList(port_no=%d, data=0x%x)", port_no, data); auto& handler = g_fxo->get(); @@ -380,7 +380,7 @@ error_code cellMouseGetTabletDataList(u32 port_no, vm::ptr data) { - sys_io.trace("cellMouseGetRawData(port_no=%d, data=*0x%x)", port_no, data); + cellMouse.trace("cellMouseGetRawData(port_no=%d, data=*0x%x)", port_no, data); auto& handler = g_fxo->get(); diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index fa7f4e0206..50c523ce1d 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -14,7 +14,7 @@ error_code sys_config_stop(ppu_thread& ppu); extern bool is_input_allowed(); -LOG_CHANNEL(sys_io); +LOG_CHANNEL(cellPad); template<> void fmt_class_string::format(std::string& out, u64 arg) @@ -148,7 +148,7 @@ extern void pad_state_notify_state_change(usz index, u32 state) error_code cellPadInit(ppu_thread& ppu, u32 max_connect) { - sys_io.warning("cellPadInit(max_connect=%d)", max_connect); + cellPad.warning("cellPadInit(max_connect=%d)", max_connect); std::lock_guard lock(pad::g_pad_mutex); @@ -182,7 +182,7 @@ error_code cellPadInit(ppu_thread& ppu, u32 max_connect) error_code cellPadEnd(ppu_thread& ppu) { - sys_io.notice("cellPadEnd()"); + cellPad.notice("cellPadEnd()"); std::lock_guard lock(pad::g_pad_mutex); @@ -218,7 +218,7 @@ void clear_pad_buffer(const std::shared_ptr& pad) error_code cellPadClearBuf(u32 port_no) { - sys_io.trace("cellPadClearBuf(port_no=%d)", port_no); + cellPad.trace("cellPadClearBuf(port_no=%d)", port_no); std::lock_guard lock(pad::g_pad_mutex); @@ -579,7 +579,7 @@ void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false) error_code cellPadGetData(u32 port_no, vm::ptr data) { - sys_io.trace("cellPadGetData(port_no=%d, data=*0x%x)", port_no, data); + cellPad.trace("cellPadGetData(port_no=%d, data=*0x%x)", port_no, data); std::lock_guard lock(pad::g_pad_mutex); @@ -607,7 +607,7 @@ error_code cellPadGetData(u32 port_no, vm::ptr data) error_code cellPadPeriphGetInfo(vm::ptr info) { - sys_io.trace("cellPadPeriphGetInfo(info=*0x%x)", info); + cellPad.trace("cellPadPeriphGetInfo(info=*0x%x)", info); std::lock_guard lock(pad::g_pad_mutex); @@ -658,7 +658,7 @@ error_code cellPadPeriphGetInfo(vm::ptr info) error_code cellPadPeriphGetData(u32 port_no, vm::ptr data) { - sys_io.trace("cellPadPeriphGetData(port_no=%d, data=*0x%x)", port_no, data); + cellPad.trace("cellPadPeriphGetData(port_no=%d, data=*0x%x)", port_no, data); std::lock_guard lock(pad::g_pad_mutex); @@ -691,7 +691,7 @@ error_code cellPadPeriphGetData(u32 port_no, vm::ptr data) error_code cellPadGetRawData(u32 port_no, vm::ptr data) { - sys_io.todo("cellPadGetRawData(port_no=%d, data=*0x%x)", port_no, data); + cellPad.todo("cellPadGetRawData(port_no=%d, data=*0x%x)", port_no, data); std::lock_guard lock(pad::g_pad_mutex); @@ -720,7 +720,7 @@ error_code cellPadGetRawData(u32 port_no, vm::ptr data) error_code cellPadGetDataExtra(u32 port_no, vm::ptr device_type, vm::ptr data) { - sys_io.trace("cellPadGetDataExtra(port_no=%d, device_type=*0x%x, data=*0x%x)", port_no, device_type, data); + cellPad.trace("cellPadGetDataExtra(port_no=%d, device_type=*0x%x, data=*0x%x)", port_no, device_type, data); // TODO: This is used just to get data from a BD/CEC remote, // but if the port isnt a remote, device type is set to CELL_PAD_DEV_TYPE_STANDARD and just regular cellPadGetData is returned @@ -744,7 +744,7 @@ error_code cellPadGetDataExtra(u32 port_no, vm::ptr device_type, vm::ptr param) { - sys_io.trace("cellPadSetActDirect(port_no=%d, param=*0x%x)", port_no, param); + cellPad.trace("cellPadSetActDirect(port_no=%d, param=*0x%x)", port_no, param); std::lock_guard lock(pad::g_pad_mutex); @@ -788,7 +788,7 @@ error_code cellPadSetActDirect(u32 port_no, vm::ptr param) error_code cellPadGetInfo(vm::ptr info) { - sys_io.trace("cellPadGetInfo(info=*0x%x)", info); + cellPad.trace("cellPadGetInfo(info=*0x%x)", info); std::lock_guard lock(pad::g_pad_mutex); @@ -833,7 +833,7 @@ error_code cellPadGetInfo(vm::ptr info) error_code cellPadGetInfo2(vm::ptr info) { - sys_io.trace("cellPadGetInfo2(info=*0x%x)", info); + cellPad.trace("cellPadGetInfo2(info=*0x%x)", info); std::lock_guard lock(pad::g_pad_mutex); @@ -882,7 +882,7 @@ error_code cellPadGetInfo2(vm::ptr info) error_code cellPadGetCapabilityInfo(u32 port_no, vm::ptr info) { - sys_io.trace("cellPadGetCapabilityInfo(port_no=%d, data_addr:=0x%x)", port_no, info.addr()); + cellPad.trace("cellPadGetCapabilityInfo(port_no=%d, data_addr:=0x%x)", port_no, info.addr()); std::lock_guard lock(pad::g_pad_mutex); @@ -913,7 +913,7 @@ error_code cellPadGetCapabilityInfo(u32 port_no, vm::ptr error_code cellPadSetPortSetting(u32 port_no, u32 port_setting) { - sys_io.trace("cellPadSetPortSetting(port_no=%d, port_setting=0x%x)", port_no, port_setting); + cellPad.trace("cellPadSetPortSetting(port_no=%d, port_setting=0x%x)", port_no, port_setting); std::lock_guard lock(pad::g_pad_mutex); @@ -938,7 +938,7 @@ error_code cellPadSetPortSetting(u32 port_no, u32 port_setting) error_code cellPadInfoPressMode(u32 port_no) { - sys_io.trace("cellPadInfoPressMode(port_no=%d)", port_no); + cellPad.trace("cellPadInfoPressMode(port_no=%d)", port_no); std::lock_guard lock(pad::g_pad_mutex); @@ -965,7 +965,7 @@ error_code cellPadInfoPressMode(u32 port_no) error_code cellPadInfoSensorMode(u32 port_no) { - sys_io.trace("cellPadInfoSensorMode(port_no=%d)", port_no); + cellPad.trace("cellPadInfoSensorMode(port_no=%d)", port_no); std::lock_guard lock(pad::g_pad_mutex); @@ -992,7 +992,7 @@ error_code cellPadInfoSensorMode(u32 port_no) error_code cellPadSetPressMode(u32 port_no, u32 mode) { - sys_io.trace("cellPadSetPressMode(port_no=%d, mode=%d)", port_no, mode); + cellPad.trace("cellPadSetPressMode(port_no=%d, mode=%d)", port_no, mode); std::lock_guard lock(pad::g_pad_mutex); @@ -1026,7 +1026,7 @@ error_code cellPadSetPressMode(u32 port_no, u32 mode) error_code cellPadSetSensorMode(u32 port_no, u32 mode) { - sys_io.trace("cellPadSetSensorMode(port_no=%d, mode=%d)", port_no, mode); + cellPad.trace("cellPadSetSensorMode(port_no=%d, mode=%d)", port_no, mode); std::lock_guard lock(pad::g_pad_mutex); @@ -1060,7 +1060,7 @@ error_code cellPadSetSensorMode(u32 port_no, u32 mode) error_code cellPadLddRegisterController() { - sys_io.warning("cellPadLddRegisterController()"); + cellPad.warning("cellPadLddRegisterController()"); std::lock_guard lock(pad::g_pad_mutex); @@ -1085,7 +1085,7 @@ error_code cellPadLddRegisterController() error_code cellPadLddDataInsert(s32 handle, vm::ptr data) { - sys_io.trace("cellPadLddDataInsert(handle=%d, data=*0x%x)", handle, data); + cellPad.trace("cellPadLddDataInsert(handle=%d, data=*0x%x)", handle, data); std::lock_guard lock(pad::g_pad_mutex); @@ -1110,7 +1110,7 @@ error_code cellPadLddDataInsert(s32 handle, vm::ptr data) error_code cellPadLddGetPortNo(s32 handle) { - sys_io.trace("cellPadLddGetPortNo(handle=%d)", handle); + cellPad.trace("cellPadLddGetPortNo(handle=%d)", handle); std::lock_guard lock(pad::g_pad_mutex); @@ -1134,7 +1134,7 @@ error_code cellPadLddGetPortNo(s32 handle) error_code cellPadLddUnregisterController(s32 handle) { - sys_io.warning("cellPadLddUnregisterController(handle=%d)", handle); + cellPad.warning("cellPadLddUnregisterController(handle=%d)", handle); std::lock_guard lock(pad::g_pad_mutex); @@ -1160,7 +1160,7 @@ error_code cellPadLddUnregisterController(s32 handle) error_code cellPadFilterIIRInit(vm::ptr pSos, s32 cutoff) { - sys_io.todo("cellPadFilterIIRInit(pSos=*0x%x, cutoff=%d)", pSos, cutoff); + cellPad.todo("cellPadFilterIIRInit(pSos=*0x%x, cutoff=%d)", pSos, cutoff); if (!pSos) // TODO: does this check for cutoff > 2 ? { @@ -1172,7 +1172,7 @@ error_code cellPadFilterIIRInit(vm::ptr pSos, s32 cutoff) u32 cellPadFilterIIRFilter(vm::ptr pSos, u32 filterIn) { - sys_io.todo("cellPadFilterIIRFilter(pSos=*0x%x, filterIn=%d)", pSos, filterIn); + cellPad.todo("cellPadFilterIIRFilter(pSos=*0x%x, filterIn=%d)", pSos, filterIn); // TODO: apply filter @@ -1183,7 +1183,7 @@ s32 sys_io_3733EA3C(u32 port_no, vm::ptr device_type, vm::ptr { // Used by the ps1 emulator built into the firmware // Seems to call the same function that getdataextra does - sys_io.trace("sys_io_3733EA3C(port_no=%d, device_type=*0x%x, data=*0x%x)", port_no, device_type, data); + cellPad.trace("sys_io_3733EA3C(port_no=%d, device_type=*0x%x, data=*0x%x)", port_no, device_type, data); return cellPadGetDataExtra(port_no, device_type, data); } From 1cef7df0060a3e048d4da9462cdd959ecb1e1be9 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 23 Jun 2024 10:41:33 +0200 Subject: [PATCH 06/30] input: add missing control key to basic keyboard The meta key logic changed, so we now have to add it. --- rpcs3/Input/basic_keyboard_handler.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rpcs3/Input/basic_keyboard_handler.cpp b/rpcs3/Input/basic_keyboard_handler.cpp index c3d6301cf3..90f26dc902 100644 --- a/rpcs3/Input/basic_keyboard_handler.cpp +++ b/rpcs3/Input/basic_keyboard_handler.cpp @@ -179,17 +179,17 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard) std::vector buttons; // Meta Keys - //buttons.emplace_back(Qt::Key_Control, CELL_KB_MKEY_L_CTRL); + buttons.emplace_back(Qt::Key_Control, CELL_KB_MKEY_L_CTRL); buttons.emplace_back(Qt::Key_Shift, CELL_KB_MKEY_L_SHIFT); buttons.emplace_back(Qt::Key_Alt, CELL_KB_MKEY_L_ALT); buttons.emplace_back(Qt::Key_Super_L, CELL_KB_MKEY_L_WIN); - //buttons.emplace_back(, CELL_KB_MKEY_R_CTRL); - //buttons.emplace_back(, CELL_KB_MKEY_R_SHIFT); - //buttons.emplace_back(, CELL_KB_MKEY_R_ALT); + //buttons.emplace_back(, CELL_KB_MKEY_R_CTRL); // There is no way to know if it's left or right in Qt at the moment + //buttons.emplace_back(, CELL_KB_MKEY_R_SHIFT); // There is no way to know if it's left or right in Qt at the moment + //buttons.emplace_back(, CELL_KB_MKEY_R_ALT); // There is no way to know if it's left or right in Qt at the moment buttons.emplace_back(Qt::Key_Super_R, CELL_KB_MKEY_R_WIN); // CELL_KB_RAWDAT - //buttons.emplace_back(, CELL_KEYC_NO_EVENT); + //buttons.emplace_back(, CELL_KEYC_NO_EVENT); // Redundant, listed for completeness //buttons.emplace_back(, CELL_KEYC_E_ROLLOVER); //buttons.emplace_back(, CELL_KEYC_E_POSTFAIL); //buttons.emplace_back(, CELL_KEYC_E_UNDEF); @@ -221,7 +221,7 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard) buttons.emplace_back(Qt::Key_Left, CELL_KEYC_LEFT_ARROW); buttons.emplace_back(Qt::Key_Down, CELL_KEYC_DOWN_ARROW); buttons.emplace_back(Qt::Key_Up, CELL_KEYC_UP_ARROW); - //buttons.emplace_back(WXK_NUMLOCK, CELL_KEYC_NUM_LOCK); + //buttons.emplace_back(, CELL_KEYC_NUM_LOCK); buttons.emplace_back(Qt::Key_Meta, CELL_KEYC_APPLICATION); buttons.emplace_back(Qt::Key_Kana_Shift, CELL_KEYC_KANA); // maybe Key_Kana_Lock buttons.emplace_back(Qt::Key_Henkan, CELL_KEYC_HENKAN); From 945bfaf0ea2060ec19d8f5290295e2498eca59fa Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sun, 23 Jun 2024 11:26:34 +0200 Subject: [PATCH 07/30] input: differentiate between left and right modifier keys --- rpcs3/Emu/Io/KeyboardHandler.cpp | 91 +++++++++++++++++++------- rpcs3/Emu/Io/KeyboardHandler.h | 39 ++++++++++- rpcs3/Input/basic_keyboard_handler.cpp | 13 ++-- rpcs3/Input/keyboard_pad_handler.cpp | 33 ++++++---- 4 files changed, 134 insertions(+), 42 deletions(-) diff --git a/rpcs3/Emu/Io/KeyboardHandler.cpp b/rpcs3/Emu/Io/KeyboardHandler.cpp index d89eba24cd..7e70577a5b 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.cpp +++ b/rpcs3/Emu/Io/KeyboardHandler.cpp @@ -94,7 +94,7 @@ void KeyboardHandlerBase::RemoveConsumer(keyboard_consumer::identifier id) } } -bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key) +bool KeyboardHandlerBase::HandleKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key) { bool consumed = false; @@ -102,13 +102,13 @@ bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat, for (auto& [id, consumer] : m_consumers) { - consumed |= consumer.ConsumeKey(code, pressed, is_auto_repeat, key); + consumed |= consumer.ConsumeKey(qt_code, native_code, pressed, is_auto_repeat, key); } return consumed; } -bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key) +bool keyboard_consumer::ConsumeKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key) { bool consumed = false; @@ -124,22 +124,24 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, KbData& data = keyboard.m_data; const KbConfig& config = keyboard.m_config; - if (auto it = keyboard.m_keys.find(code); it != keyboard.m_keys.end()) + if (auto it = keyboard.m_keys.find(qt_code); it != keyboard.m_keys.end()) { KbButton& button = it->second; + const u32 out_key_code = get_out_key_code(qt_code, native_code, button.m_outKeyCode); + u16 kcode = CELL_KEYC_NO_EVENT; - bool is_meta_key = IsMetaKey(code); + bool is_meta_key = IsMetaKey(qt_code); if (!is_meta_key) { if (config.code_type == CELL_KB_CODETYPE_RAW) { - kcode = button.m_outKeyCode; + kcode = out_key_code; } else // config.code_type == CELL_KB_CODETYPE_ASCII { - kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, button.m_outKeyCode); + kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, out_key_code); } } @@ -153,33 +155,33 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, // Meta Keys if (is_meta_key) { - data.mkey |= button.m_outKeyCode; + data.mkey |= out_key_code; if (config.read_mode == CELL_KB_RMODE_INPUTCHAR) { - data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, true); + data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, true); } else { - data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, true); + data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, true); } } else { // Led Keys - if (code == Key_CapsLock) data.led ^= CELL_KB_LED_CAPS_LOCK; - if (code == Key_NumLock) data.led ^= CELL_KB_LED_NUM_LOCK; - if (code == Key_ScrollLock) data.led ^= CELL_KB_LED_SCROLL_LOCK; - // if (code == Key_Kana_Lock) data.led ^= CELL_KB_LED_KANA; - // if (code == ???) data.led ^= CELL_KB_LED_COMPOSE; + if (qt_code == Key_CapsLock) data.led ^= CELL_KB_LED_CAPS_LOCK; + if (qt_code == Key_NumLock) data.led ^= CELL_KB_LED_NUM_LOCK; + if (qt_code == Key_ScrollLock) data.led ^= CELL_KB_LED_SCROLL_LOCK; + // if (qt_code == Key_Kana_Lock) data.led ^= CELL_KB_LED_KANA; + // if (qt_code == ???) data.led ^= CELL_KB_LED_COMPOSE; if (config.read_mode == CELL_KB_RMODE_INPUTCHAR) { - data.buttons[0] = KbButton(kcode, button.m_outKeyCode, true); + data.buttons[0] = KbButton(kcode, out_key_code, true); } else { - data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(kcode, button.m_outKeyCode, true); + data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(kcode, out_key_code, true); } } @@ -190,13 +192,13 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, // Meta Keys if (is_meta_key) { - data.mkey &= ~button.m_outKeyCode; + data.mkey &= ~out_key_code; } // Needed to indicate key releases. Without this you have to tap another key before using the same key again if (config.read_mode == CELL_KB_RMODE_INPUTCHAR) { - data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, false); + data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, false); data.len = 1; } else @@ -205,7 +207,7 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, for (s32 i = 0; i < data.len; i++) { - if (data.buttons[i].m_keyCode == kcode && (!is_meta_key || data.buttons[i].m_outKeyCode == button.m_outKeyCode)) + if (data.buttons[i].m_keyCode == kcode && (!is_meta_key || data.buttons[i].m_outKeyCode == out_key_code)) { index = i; break; @@ -219,7 +221,7 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, if (data.len <= 1) { - data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, false); + data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, false); } data.len = std::max(1, data.len - 1); @@ -247,10 +249,32 @@ bool keyboard_consumer::IsMetaKey(u32 code) return code == Key_Control || code == Key_Shift || code == Key_Alt + || code == Key_Meta || code == Key_Super_L || code == Key_Super_R; } +u32 keyboard_consumer::get_out_key_code(u32 qt_code, u32 native_code, u32 out_key_code) +{ + // Parse native key codes to differentiate between left and right keys. (Qt sometimes really sucks) + // NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment + switch (qt_code) + { + case Key_Control: + return native_code == native_key::ctrl_l ? CELL_KB_MKEY_L_CTRL : CELL_KB_MKEY_R_CTRL; + case Key_Shift: + return native_code == native_key::shift_l ? CELL_KB_MKEY_L_SHIFT : CELL_KB_MKEY_R_SHIFT; + case Key_Alt: + return native_code == native_key::alt_l ? CELL_KB_MKEY_L_ALT : CELL_KB_MKEY_R_ALT; + case Key_Meta: + return native_code == native_key::meta_l ? CELL_KB_MKEY_L_WIN : CELL_KB_MKEY_R_WIN; + default: + break; + } + + return out_key_code; +} + void KeyboardHandlerBase::SetIntercepted(bool intercepted) { std::lock_guard lock(m_mutex); @@ -294,12 +318,33 @@ void keyboard_consumer::ReleaseAllKeys() { for (const auto& [key_code, button] : keyboard.m_keys) { - ConsumeKey(button.m_keyCode, false, false, {}); + switch (button.m_keyCode) + { + case Key_Control: + ConsumeKey(button.m_keyCode, native_key::ctrl_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::ctrl_r, false, false, {}); + break; + case Key_Shift: + ConsumeKey(button.m_keyCode, native_key::shift_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::shift_r, false, false, {}); + break; + case Key_Alt: + ConsumeKey(button.m_keyCode, native_key::alt_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::alt_r, false, false, {}); + break; + case Key_Meta: + ConsumeKey(button.m_keyCode, native_key::meta_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::meta_r, false, false, {}); + break; + default: + ConsumeKey(button.m_keyCode, 0, false, false, {}); + break; + } } for (const std::u32string& key : keyboard.m_extra_data.pressed_keys) { - ConsumeKey(CELL_KEYC_NO_EVENT, false, false, key); + ConsumeKey(CELL_KEYC_NO_EVENT, 0, false, false, key); } keyboard.m_extra_data.pressed_keys.clear(); diff --git a/rpcs3/Emu/Io/KeyboardHandler.h b/rpcs3/Emu/Io/KeyboardHandler.h index c62bb099b6..51404b72c4 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.h +++ b/rpcs3/Emu/Io/KeyboardHandler.h @@ -22,6 +22,39 @@ enum QtKeys Key_Super_R = 0x01000054 }; +// See https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values +enum native_key : u32 +{ +#ifdef _WIN32 + ctrl_l = 0x001D, + ctrl_r = 0xE01D, + shift_l = 0x002A, + shift_r = 0x0036, + alt_l = 0x0038, + alt_r = 0xE038, + meta_l = 0xE05B, + meta_r = 0xE05C, +#elif defined (__APPLE__) + ctrl_l = 0x3B, // kVK_Control + ctrl_r = 0x3E, // kVK_RightControl + shift_l = 0x38, // kVK_Shift + shift_r = 0x3C, // kVK_RightShift + alt_l = 0x3A, // kVK_Option + alt_r = 0x3D, // kVK_RightOption + meta_l = 0x37, // kVK_Command + meta_r = 0x36, // kVK_RightCommand +#else + ctrl_l = 0x0025, + ctrl_r = 0x0069, + shift_l = 0x0032, + shift_r = 0x003E, + alt_l = 0x0040, + alt_r = 0x006C, + meta_l = 0x0085, + meta_r = 0x0086, +#endif +}; + struct KbInfo { u32 max_connect = 0; @@ -88,7 +121,7 @@ public: keyboard_consumer() {} keyboard_consumer(identifier id) : m_id(id) {} - bool ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key); + bool ConsumeKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key); void SetIntercepted(bool intercepted); static bool IsMetaKey(u32 code); @@ -103,6 +136,8 @@ public: void ReleaseAllKeys(); protected: + u32 get_out_key_code(u32 qt_code, u32 native_code, u32 out_key_code); + identifier m_id = identifier::unknown; KbInfo m_info{}; std::vector m_keyboards; @@ -126,7 +161,7 @@ public: keyboard_consumer& GetConsumer(keyboard_consumer::identifier id); void RemoveConsumer(keyboard_consumer::identifier id); - bool HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key); + bool HandleKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key); void SetIntercepted(bool intercepted); stx::init_mutex init; diff --git a/rpcs3/Input/basic_keyboard_handler.cpp b/rpcs3/Input/basic_keyboard_handler.cpp index 90f26dc902..50ee435ead 100644 --- a/rpcs3/Input/basic_keyboard_handler.cpp +++ b/rpcs3/Input/basic_keyboard_handler.cpp @@ -110,7 +110,7 @@ void basic_keyboard_handler::keyPressEvent(QKeyEvent* keyEvent) const int key = getUnmodifiedKey(keyEvent); - if (key < 0 || !HandleKey(static_cast(key), true, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) + if (key < 0 || !HandleKey(static_cast(key), keyEvent->nativeScanCode(), true, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) { keyEvent->ignore(); } @@ -131,7 +131,7 @@ void basic_keyboard_handler::keyReleaseEvent(QKeyEvent* keyEvent) const int key = getUnmodifiedKey(keyEvent); - if (key < 0 || !HandleKey(static_cast(key), false, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) + if (key < 0 || !HandleKey(static_cast(key), keyEvent->nativeScanCode(), false, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) { keyEvent->ignore(); } @@ -182,11 +182,14 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard) buttons.emplace_back(Qt::Key_Control, CELL_KB_MKEY_L_CTRL); buttons.emplace_back(Qt::Key_Shift, CELL_KB_MKEY_L_SHIFT); buttons.emplace_back(Qt::Key_Alt, CELL_KB_MKEY_L_ALT); - buttons.emplace_back(Qt::Key_Super_L, CELL_KB_MKEY_L_WIN); + buttons.emplace_back(Qt::Key_Meta, CELL_KB_MKEY_L_WIN); //buttons.emplace_back(, CELL_KB_MKEY_R_CTRL); // There is no way to know if it's left or right in Qt at the moment //buttons.emplace_back(, CELL_KB_MKEY_R_SHIFT); // There is no way to know if it's left or right in Qt at the moment //buttons.emplace_back(, CELL_KB_MKEY_R_ALT); // There is no way to know if it's left or right in Qt at the moment - buttons.emplace_back(Qt::Key_Super_R, CELL_KB_MKEY_R_WIN); + //buttons.emplace_back(, CELL_KB_MKEY_R_WIN); // There is no way to know if it's left or right in Qt at the moment + + buttons.emplace_back(Qt::Key_Super_L, CELL_KB_MKEY_L_WIN); // The super keys are supposed to be the windows keys, but they trigger the meta key instead. Let's assign the windows keys to both. + buttons.emplace_back(Qt::Key_Super_R, CELL_KB_MKEY_R_WIN); // The super keys are supposed to be the windows keys, but they trigger the meta key instead. Let's assign the windows keys to both. // CELL_KB_RAWDAT //buttons.emplace_back(, CELL_KEYC_NO_EVENT); // Redundant, listed for completeness @@ -222,7 +225,7 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard) buttons.emplace_back(Qt::Key_Down, CELL_KEYC_DOWN_ARROW); buttons.emplace_back(Qt::Key_Up, CELL_KEYC_UP_ARROW); //buttons.emplace_back(, CELL_KEYC_NUM_LOCK); - buttons.emplace_back(Qt::Key_Meta, CELL_KEYC_APPLICATION); + //buttons.emplace_back(, CELL_KEYC_APPLICATION); // This is probably the PS key on the PS3 keyboard buttons.emplace_back(Qt::Key_Kana_Shift, CELL_KEYC_KANA); // maybe Key_Kana_Lock buttons.emplace_back(Qt::Key_Henkan, CELL_KEYC_HENKAN); buttons.emplace_back(Qt::Key_Muhenkan, CELL_KEYC_MUHENKAN); diff --git a/rpcs3/Input/keyboard_pad_handler.cpp b/rpcs3/Input/keyboard_pad_handler.cpp index 5179673226..fb25334850 100644 --- a/rpcs3/Input/keyboard_pad_handler.cpp +++ b/rpcs3/Input/keyboard_pad_handler.cpp @@ -1,6 +1,7 @@ #include "keyboard_pad_handler.h" #include "pad_thread.h" #include "Emu/Io/pad_config.h" +#include "Emu/Io/KeyboardHandler.h" #include "Input/product_info.h" #include "rpcs3qt/gs_frame.h" @@ -821,12 +822,16 @@ u32 keyboard_pad_handler::GetKeyCode(const QString& keyName) int keyboard_pad_handler::native_scan_code_from_string([[maybe_unused]] const std::string& key) { - // NOTE: Qt throws a Ctrl key at us when using Alt Gr, so there is no point in distinguishing left and right Alt at the moment + // NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment + if (key == "Shift Left") return native_key::shift_l; + if (key == "Shift Right") return native_key::shift_r; + if (key == "Ctrl Left") return native_key::ctrl_l; + if (key == "Ctrl Right") return native_key::ctrl_r; + if (key == "Alt Left") return native_key::alt_l; + if (key == "Alt Right") return native_key::alt_r; + if (key == "Meta Left") return native_key::meta_l; + if (key == "Meta Right") return native_key::meta_r; #ifdef _WIN32 - if (key == "Shift Left") return 42; - if (key == "Shift Right") return 54; - if (key == "Ctrl Left") return 29; - if (key == "Ctrl Right") return 285; if (key == "Num+0" || key == "Num+Ins") return 82; if (key == "Num+1" || key == "Num+End") return 79; if (key == "Num+2" || key == "Num+Down") return 80; @@ -851,15 +856,20 @@ int keyboard_pad_handler::native_scan_code_from_string([[maybe_unused]] const st std::string keyboard_pad_handler::native_scan_code_to_string(int native_scan_code) { + // NOTE: the other Qt function "nativeVirtualKey" does not distinguish between VK_SHIFT and VK_RSHIFT key in Qt at the moment + // NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment + // NOTE: for MacOs: nativeScanCode may not work switch (native_scan_code) { + case native_key::shift_l: return "Shift Left"; + case native_key::shift_r: return "Shift Right"; + case native_key::ctrl_l: return "Ctrl Left"; + case native_key::ctrl_r: return "Ctrl Right"; + case native_key::alt_l: return "Alt Left"; + case native_key::alt_r: return "Alt Right"; + case native_key::meta_l: return "Meta Left"; + case native_key::meta_r: return "Meta Right"; #ifdef _WIN32 - // NOTE: the other Qt function "nativeVirtualKey" does not distinguish between VK_SHIFT and VK_RSHIFT key in Qt at the moment - // NOTE: Qt throws a Ctrl key at us when using Alt Gr, so there is no point in distinguishing left and right Alt at the moment - case 42: return "Shift Left"; - case 54: return "Shift Right"; - case 29: return "Ctrl Left"; - case 285: return "Ctrl Right"; case 82: return "Num+0"; // Also "Num+Ins" depending on numlock case 79: return "Num+1"; // Also "Num+End" depending on numlock case 80: return "Num+2"; // Also "Num+Down" depending on numlock @@ -878,7 +888,6 @@ std::string keyboard_pad_handler::native_scan_code_to_string(int native_scan_cod case 284: return "Num+Enter"; #else // TODO - // NOTE for MacOs: nativeScanCode may not work #endif default: return ""; } From 87f5368d3c9c97bd71fb4dad015adff4e58618fd Mon Sep 17 00:00:00 2001 From: Elad Ashkenazi <18193363+elad335@users.noreply.github.com> Date: Sun, 23 Jun 2024 18:34:18 +0300 Subject: [PATCH 08/30] PPU: Fix access violation on logging --- rpcs3/Emu/Cell/PPUFunction.h | 10 ++++++++++ rpcs3/Emu/Cell/PPUThread.cpp | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/Cell/PPUFunction.h b/rpcs3/Emu/Cell/PPUFunction.h index e9ef4321b9..f8e02f20d9 100644 --- a/rpcs3/Emu/Cell/PPUFunction.h +++ b/rpcs3/Emu/Cell/PPUFunction.h @@ -305,6 +305,16 @@ public: return addr + index * 8 + (is_code_addr ? 4 : 0); } + bool is_func(u32 cia) const + { + if (cia % 4 || !addr || cia < addr) + { + return false; + } + + return (cia - addr) / 8 < access().size(); + } + // Allocation address u32 addr = 0; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index f0a7c11474..9668aadee9 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -2760,7 +2760,7 @@ void ppu_thread::fast_call(u32 addr, u64 rtoc, bool is_thread_entry) const auto cia = _this->cia; - if (_this->current_function && vm::read32(cia) != ppu_instructions::SC(0)) + if (_this->current_function && g_fxo->get().is_func(cia)) { return fmt::format("PPU[0x%x] Thread (%s) [HLE:0x%08x, LR:0x%08x]", _this->id, *name_cache.get(), cia, _this->lr); } From f18e3be4f279e1cc7d502c541d8c8f9a13ccdbfa Mon Sep 17 00:00:00 2001 From: Elad Ashkenazi <18193363+elad335@users.noreply.github.com> Date: Tue, 25 Jun 2024 10:02:53 +0300 Subject: [PATCH 09/30] Cut scenNpDrmIsAvailable sleep time by half --- rpcs3/Emu/Cell/Modules/sceNp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/Cell/Modules/sceNp.cpp b/rpcs3/Emu/Cell/Modules/sceNp.cpp index f09c970e76..1477d831d8 100644 --- a/rpcs3/Emu/Cell/Modules/sceNp.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNp.cpp @@ -744,7 +744,7 @@ error_code sceNpDrmIsAvailable(ppu_thread& ppu, vm::cptr k_licensee_addr, vm lv2_obj::sleep(ppu); const auto ret = npDrmIsAvailable(k_licensee_addr, drm_path); - lv2_sleep(50'000, &ppu); + lv2_sleep(25'000, &ppu); return ret; } From 8050e1f8531bfd202e3cfbdc874a0357e02596ad Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 24 Jun 2024 23:18:07 +0200 Subject: [PATCH 10/30] input: fix ds3 gyro offset --- rpcs3/Input/ds3_pad_handler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Input/ds3_pad_handler.h b/rpcs3/Input/ds3_pad_handler.h index 6dd164a391..b8dae2dae3 100644 --- a/rpcs3/Input/ds3_pad_handler.h +++ b/rpcs3/Input/ds3_pad_handler.h @@ -53,10 +53,10 @@ namespace u8 unknown_3[4]; u8 battery_status; u8 unknown_4[10]; - le_t gyro; le_t accel_x; le_t accel_z; le_t accel_y; + le_t gyro; }; static_assert(sizeof(ds3_input_report) == 49); } From 11ee80a070ce8872fb1d2c02e388f0ae969c153a Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 26 Jun 2024 21:19:18 +0200 Subject: [PATCH 11/30] input: add missing lock to keyboard handler ReleaseAllKeys This should fix a segfault I encountered when closing a game. I think the consumers were removed while the window went out of focus. --- rpcs3/Emu/Io/KeyboardHandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rpcs3/Emu/Io/KeyboardHandler.cpp b/rpcs3/Emu/Io/KeyboardHandler.cpp index 7e70577a5b..8b2a134986 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.cpp +++ b/rpcs3/Emu/Io/KeyboardHandler.cpp @@ -306,6 +306,8 @@ void keyboard_consumer::SetIntercepted(bool intercepted) void KeyboardHandlerBase::ReleaseAllKeys() { + std::lock_guard lock(m_mutex); + for (auto& [id, consumer] : m_consumers) { consumer.ReleaseAllKeys(); From b251d81065d8b8903afe8db8cfc643a803efe456 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 26 Jun 2024 22:11:58 +0200 Subject: [PATCH 12/30] input: fix minimum turntable input DJ Hero does not register input if the turntable is 0, so force it to 1. This will happen if you map it to the left stick and push it all the way down, or if you use a keyboard, which sends the max value on key press. --- rpcs3/Emu/Io/Turntable.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rpcs3/Emu/Io/Turntable.cpp b/rpcs3/Emu/Io/Turntable.cpp index 07908fd784..af5648d40b 100644 --- a/rpcs3/Emu/Io/Turntable.cpp +++ b/rpcs3/Emu/Io/Turntable.cpp @@ -264,7 +264,8 @@ void usb_device_turntable::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpo buf[1] |= 0x01; // Select break; case turntable_btn::right_turntable: - buf[6] = 255 - value; // 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 // 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) From 78cb7963fbb05458b02333e87c92deeb60fad5ec Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 26 Jun 2024 20:48:52 +0200 Subject: [PATCH 13/30] input: invalidate ds4/dualsense calibration instead of disabling the controller --- rpcs3/Input/ds4_pad_handler.cpp | 23 ++++++++++++++--------- rpcs3/Input/dualsense_pad_handler.cpp | 13 +++++++++---- rpcs3/Input/hid_pad_handler.h | 16 ++++++++-------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index 7107345199..a1ded567aa 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -2,6 +2,8 @@ #include "ds4_pad_handler.h" #include "Emu/Io/pad_config.h" +#include + LOG_CHANNEL(ds4_log, "DS4"); constexpr id_pair SONY_DS4_ID_0 = {0x054C, 0x0BA0}; // Dongle @@ -427,7 +429,6 @@ bool ds4_pad_handler::GetCalibrationData(DS4Device* ds4Dev) const pitchNeg >= 0 || yawNeg >= 0 || rollNeg >= 0) { ds4_log.error("GetCalibrationData: calibration data check failed! pitchPlus=%d, pitchNeg=%d, rollPlus=%d, rollNeg=%d, yawPlus=%d, yawNeg=%d", pitchPlus, pitchNeg, rollPlus, rollNeg, yawPlus, yawNeg); - return false; } const s32 gyroSpeedScale = read_s16(&buf[19]) + read_s16(&buf[21]); @@ -465,12 +466,16 @@ bool ds4_pad_handler::GetCalibrationData(DS4Device* ds4Dev) const // Make sure data 'looks' valid, dongle will report invalid calibration data with no controller connected - for (const auto& data : ds4Dev->calib_data) + for (size_t i = 0; i < ds4Dev->calib_data.size(); i++) { + CalibData& data = ds4Dev->calib_data[i]; + if (data.sens_denom == 0) { - ds4_log.error("GetCalibrationData: Failure: sens_denom == 0"); - return false; + ds4_log.error("GetCalibrationData: Invalid accelerometer calibration data for axis %d, disabling calibration.", i); + data.bias = 0; + data.sens_numer = 4 * DS4_ACC_RES_PER_G; + data.sens_denom = std::numeric_limits::max(); } } @@ -693,13 +698,13 @@ ds4_pad_handler::DataStatus ds4_pad_handler::get_data(DS4Device* device) if (device->has_calib_data) { - int calibOffset = offset + offsetof(ds4_input_report_common, gyro); + int calib_offset = offset + offsetof(ds4_input_report_common, gyro); for (int i = 0; i < CalibIndex::COUNT; ++i) { - const s16 rawValue = read_s16(&buf[calibOffset]); - const s16 calValue = apply_calibration(rawValue, device->calib_data[i]); - buf[calibOffset++] = (static_cast(calValue) >> 0) & 0xFF; - buf[calibOffset++] = (static_cast(calValue) >> 8) & 0xFF; + const s16 raw_value = read_s16(&buf[calib_offset]); + const s16 cal_value = apply_calibration(raw_value, device->calib_data[i]); + buf[calib_offset++] = (static_cast(cal_value) >> 0) & 0xFF; + buf[calib_offset++] = (static_cast(cal_value) >> 8) & 0xFF; } } diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index 806f6a770f..d53d532dca 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -2,6 +2,8 @@ #include "dualsense_pad_handler.h" #include "Emu/Io/pad_config.h" +#include + LOG_CHANNEL(dualsense_log, "DualSense"); template <> @@ -462,7 +464,6 @@ bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_devi { dualsense_log.error("get_calibration_data: calibration data check failed! pitch_plus=%d, pitch_minus=%d, roll_plus=%d, roll_minus=%d, yaw_plus=%d, yaw_minus=%d", pitch_plus, pitch_minus, roll_plus, roll_minus, yaw_plus, yaw_minus); - return false; } const s32 gyro_speed_scale = read_s16(&buf[19]) + read_s16(&buf[21]); @@ -501,12 +502,16 @@ bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_devi // Make sure data 'looks' valid, dongle will report invalid calibration data with no controller connected - for (const CalibData& data : dualsense_device->calib_data) + for (size_t i = 0; i < dualsense_device->calib_data.size(); i++) { + CalibData& data = dualsense_device->calib_data[i]; + if (data.sens_denom == 0) { - dualsense_log.error("get_calibration_data: Failure: sens_denom == 0"); - return false; + dualsense_log.error("GetCalibrationData: Invalid accelerometer calibration data for axis %d, disabling calibration.", i); + data.bias = 0; + data.sens_numer = 4 * DUALSENSE_ACC_RES_PER_G; + data.sens_denom = std::numeric_limits::max(); } } diff --git a/rpcs3/Input/hid_pad_handler.h b/rpcs3/Input/hid_pad_handler.h index ed66cf6b71..d9a4db0682 100644 --- a/rpcs3/Input/hid_pad_handler.h +++ b/rpcs3/Input/hid_pad_handler.h @@ -8,9 +8,9 @@ struct CalibData { - s16 bias; - s32 sens_numer; - s32 sens_denom; + s16 bias = 0; + s32 sens_numer = 0; + s32 sens_denom = 0; }; enum CalibIndex @@ -87,12 +87,12 @@ protected: virtual int send_output_report(Device* device) = 0; virtual DataStatus get_data(Device* device) = 0; - static s16 apply_calibration(s32 rawValue, const CalibData& calibData) + static s16 apply_calibration(s32 raw_value, const CalibData& calib_data) { - const s32 biased = rawValue - calibData.bias; - const s32 quot = calibData.sens_numer / calibData.sens_denom; - const s32 rem = calibData.sens_numer % calibData.sens_denom; - const s32 output = (quot * biased) + ((rem * biased) / calibData.sens_denom); + const s32 biased = raw_value - calib_data.bias; + const s32 quot = calib_data.sens_numer / calib_data.sens_denom; + const s32 rem = calib_data.sens_numer % calib_data.sens_denom; + const s32 output = (quot * biased) + ((rem * biased) / calib_data.sens_denom); return static_cast(std::clamp(output, s16{smin}, s16{smax})); } From df6bec236fd6ff2f817d5aa7f411bdbb3682df88 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 26 Jun 2024 20:52:18 +0200 Subject: [PATCH 14/30] input: Use same dualsense gyro values as linux kernel --- rpcs3/Input/dualsense_pad_handler.cpp | 31 ++++++--------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index d53d532dca..b3c3021ccd 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -432,31 +432,12 @@ bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_devi dualsense_device->calib_data[CalibIndex::YAW].bias = read_s16(&buf[3]); dualsense_device->calib_data[CalibIndex::ROLL].bias = read_s16(&buf[5]); - s16 pitch_plus, pitch_minus, roll_plus, roll_minus, yaw_plus, yaw_minus; - - // TODO: This was copied from DS4. Find out if it applies here. - // Check for calibration data format - // It's going to be either alternating +/- or +++--- - if (read_s16(&buf[9]) < 0 && read_s16(&buf[7]) > 0) - { - // Wired mode for OEM controllers - pitch_plus = read_s16(&buf[7]); - pitch_minus = read_s16(&buf[9]); - yaw_plus = read_s16(&buf[11]); - yaw_minus = read_s16(&buf[13]); - roll_plus = read_s16(&buf[15]); - roll_minus = read_s16(&buf[17]); - } - else - { - // Bluetooth mode and wired mode for some 3rd party controllers - pitch_plus = read_s16(&buf[7]); - yaw_plus = read_s16(&buf[9]); - roll_plus = read_s16(&buf[11]); - pitch_minus = read_s16(&buf[13]); - yaw_minus = read_s16(&buf[15]); - roll_minus = read_s16(&buf[17]); - } + const s16 pitch_plus = read_s16(&buf[7]); + const s16 pitch_minus = read_s16(&buf[9]); + const s16 yaw_plus = read_s16(&buf[11]); + const s16 yaw_minus = read_s16(&buf[13]); + const s16 roll_plus = read_s16(&buf[15]); + const s16 roll_minus = read_s16(&buf[17]); // Confirm correctness. Need confirmation with dongle with no active controller if (pitch_plus <= 0 || yaw_plus <= 0 || roll_plus <= 0 || From e635abe55235fb2c2b9493ee64975f21674f4037 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 26 Jun 2024 23:17:18 +0200 Subject: [PATCH 15/30] Fix warning: std::move of const variables --- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index dc8ada5098..533b267266 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -195,8 +195,8 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr Date: Wed, 26 Jun 2024 23:20:06 +0200 Subject: [PATCH 16/30] Fix warning: dangling pointer (construct string_view from temporary string) --- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 2 +- rpcs3/Emu/System.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 533b267266..781c9b44a4 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -17,7 +17,7 @@ #include "sys_memory.h" #include -extern void dump_executable(std::span data, ppu_module* _main, std::string_view title_id); +extern void dump_executable(std::span data, const ppu_module* _module, std::string_view title_id); extern std::shared_ptr ppu_load_prx(const ppu_prx_object&, bool virtual_load, const std::string&, s64, utils::serial* = nullptr); extern void ppu_unload_prx(const lv2_prx& prx); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e66a642ae2..5fad90df5a 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -301,14 +301,17 @@ static void fixup_settings(const psf::registry* _psf) } } -extern void dump_executable(std::span data, ppu_module* _module, std::string_view title_id) +extern void dump_executable(std::span data, const ppu_module* _module, std::string_view title_id) { - const std::string_view filename = _module->path.substr(_module->path.find_last_of('/') + 1); + std::string_view filename = _module->path; + filename = filename.substr(filename.find_last_of('/') + 1); + + const std::string lower = fmt::to_lower(filename); // Format filename and directory name // Make each directory for each file so tools like IDA can work on it cleanly const std::string dir_path = fs::get_cache_dir() + "ppu_progs/" + std::string{!title_id.empty() ? title_id : "untitled"} + fmt::format("-%s-%s", fmt::base57(_module->sha1), filename) + '/'; - const std::string file_path = dir_path + (fmt::to_lower(filename).ends_with(".prx") || fmt::to_lower(filename).ends_with(".sprx") ? "prog.prx" : "exec.elf"); + const std::string file_path = dir_path + (lower.ends_with(".prx") || lower.ends_with(".sprx") ? "prog.prx" : "exec.elf"); if (fs::create_dir(dir_path) || fs::g_tls_error == fs::error::exist) { From 33d6e6ce6cd6b8683fe6b2ea3e93351a2685f117 Mon Sep 17 00:00:00 2001 From: SuperSamus <40663462+SuperSamus@users.noreply.github.com> Date: Thu, 27 Jun 2024 00:46:08 +0200 Subject: [PATCH 17/30] skylander_dialog: Fix Drill Sergeant's name --- rpcs3/rpcs3qt/skylander_dialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/rpcs3qt/skylander_dialog.cpp b/rpcs3/rpcs3qt/skylander_dialog.cpp index 49d4f66618..0a6cfab09e 100644 --- a/rpcs3/rpcs3qt/skylander_dialog.cpp +++ b/rpcs3/rpcs3qt/skylander_dialog.cpp @@ -88,8 +88,8 @@ const std::map, const std::string> list_sk {{20, 0x0000}, "Drobot"}, {{20, 0x1801}, "Series 2 Drobot"}, {{20, 0x1206}, "LightCore Drobot"}, - {{21, 0x0000}, "Drill Seargeant"}, - {{21, 0x1801}, "Series 2 Drill Seargeant"}, + {{21, 0x0000}, "Drill Sergeant"}, + {{21, 0x1801}, "Series 2 Drill Sergeant"}, {{22, 0x0000}, "Boomer"}, {{22, 0x4810}, "Eon's Elite Boomer"}, {{23, 0x0000}, "Wrecking Ball"}, From 39049002436a99fe56e81be3b3db70214aadb134 Mon Sep 17 00:00:00 2001 From: shinra-electric <50119606+shinra-electric@users.noreply.github.com> Date: Sun, 16 Jun 2024 09:35:36 +0200 Subject: [PATCH 18/30] Update MoltenVK Updates from 1.2.7 to 1.2.9 Homebrew had problems with 1.2.8, so skip that version. --- 3rdparty/MoltenVK/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3rdparty/MoltenVK/CMakeLists.txt b/3rdparty/MoltenVK/CMakeLists.txt index c3bf229e16..a509582dcd 100644 --- a/3rdparty/MoltenVK/CMakeLists.txt +++ b/3rdparty/MoltenVK/CMakeLists.txt @@ -4,7 +4,7 @@ include(ExternalProject) ExternalProject_Add(moltenvk GIT_REPOSITORY https://github.com/KhronosGroup/MoltenVK.git - GIT_TAG 66f6ff1 + GIT_TAG bf097ed BUILD_IN_SOURCE 1 SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK CONFIGURE_COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/fetchDependencies" --macos From 50ce4cbea5736ba8dac893a06ce632c4b17261d3 Mon Sep 17 00:00:00 2001 From: shinra-electric <50119606+shinra-electric@users.noreply.github.com> Date: Sun, 16 Jun 2024 09:42:08 +0200 Subject: [PATCH 19/30] Update build script to MoltenVK 1.2.9 Updates from 1.2.7 to 1.2.9 Homebrew had issues with 1.2.8, so we skipped that version. --- .ci/build-mac.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/build-mac.sh b/.ci/build-mac.sh index c325e8060e..bc352389e1 100755 --- a/.ci/build-mac.sh +++ b/.ci/build-mac.sh @@ -15,8 +15,8 @@ arch -x86_64 /usr/local/bin/brew reinstall -f --build-from-source gnutls freetyp arch -x86_64 /usr/local/bin/brew install llvm@16 glew cmake sdl2 vulkan-headers coreutils arch -x86_64 /usr/local/bin/brew link -f llvm@16 ffmpeg@5 -# moltenvk based on commit for 1.2.7 release -wget https://raw.githubusercontent.com/Homebrew/homebrew-core/05a8770c483cfddf5b077667a392d846bc2ad719/Formula/m/molten-vk.rb +# moltenvk based on commit for 1.2.9 release +wget https://raw.githubusercontent.com/Homebrew/homebrew-core/c117dde3198d62817371984d04d50e653ca88f7d/Formula/m/molten-vk.rb arch -x86_64 /usr/local/bin/brew install -f --overwrite ./molten-vk.rb #export MACOSX_DEPLOYMENT_TARGET=12.0 export CXX=clang++ From 8ec6187dc7657d833cac446cf007f49b71705e3a Mon Sep 17 00:00:00 2001 From: Elad Ashkenazi <18193363+elad335@users.noreply.github.com> Date: Thu, 27 Jun 2024 09:52:03 +0300 Subject: [PATCH 20/30] SPU Analyzer: Fix support for multi-block value merge --- rpcs3/Emu/Cell/SPUCommonRecompiler.cpp | 215 ++++++++++++++++++------- rpcs3/Emu/Cell/SPURecompiler.h | 19 ++- 2 files changed, 177 insertions(+), 57 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index 69e1ace6e4..a069ab9eb8 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -2627,18 +2627,18 @@ reg_state_t reg_state_t::downgrade() const { if (flag & vf::is_const) { - return reg_state_t{vf::is_mask, 0, umax, this->value, ~this->value}; + return reg_state_t{vf::is_mask, 0, umax, this->value, ~this->value, this->origin}; } if (!(flag - vf::is_null)) { - return reg_state_t{vf::is_mask, 0, this->tag, 0, 0}; + return reg_state_t{vf::is_mask, 0, this->tag, 0, 0, this->origin}; } return *this; } -reg_state_t reg_state_t::merge(const reg_state_t& rhs) const +reg_state_t reg_state_t::merge(const reg_state_t& rhs, u32 current_pc) const { if (rhs == *this) { @@ -2661,12 +2661,13 @@ reg_state_t reg_state_t::merge(const reg_state_t& rhs) const { // Success (create new value tag) res.tag = reg_state_t::alloc_tag(); + res.origin = current_pc; return res; } } } - return make_unknown(); + return make_unknown(current_pc); } reg_state_t reg_state_t::build_on_top_of(const reg_state_t& rhs) const @@ -2728,9 +2729,17 @@ u32 reg_state_t::alloc_tag(bool reset) noexcept return ++g_tls_tag; } +void reg_state_t::invalidate_if_created(u32 current_pc) +{ + if (!is_const() && origin == current_pc) + { + tag = reg_state_t::alloc_tag(); + } +} + // Converge 2 register states to the same flow in execution template -static void merge(std::array& result, const std::array& lhs, const std::array& rhs) +static void merge(std::array& result, const std::array& lhs, const std::array& rhs, u32 current_pc) { usz index = umax; @@ -2738,7 +2747,7 @@ static void merge(std::array& result, const std::array create(u32 pc) noexcept { - auto ptr = new block_reg_info{ pc, reg_state_t::make_unknown() }; + auto ptr = new block_reg_info{ pc, reg_state_t::make_unknown(pc) }; for (reg_state_t& f : ptr->local_state) { @@ -4882,7 +4891,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s const bool should_search_patterns = target_count < 300u; // Treat start of function as an unknown value with tag (because it is) - const reg_state_t start_program_count = reg_state_t::make_unknown(); + const reg_state_t start_program_count = reg_state_t::make_unknown(entry_point - 1); // Initialize reg_state_it.emplace_back(entry_point); @@ -5375,10 +5384,20 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s vregs[reg] = reg_state_t::from_value(value); }; - const auto inherit_const_value = [&](u32 reg, bs_t flag, u32 value) + const auto inherit_const_value = [&](u32 reg, const reg_state_t& ra, const reg_state_t& rb, u32 value, u32 pos) { - flag -= vf::is_null; - vregs[reg] = reg_state_t{flag, value, flag & vf::is_const ? u32{umax} : reg_state_t::alloc_tag()}; + if (ra.origin != rb.origin) + { + pos = reg_state_it[wi].pc; + } + else + { + pos = ra.origin; + } + + const bs_t flag = (ra.flag & rb.flag) - vf::is_null; + + vregs[reg] = reg_state_t{flag, value, flag & vf::is_const ? u32{umax} : reg_state_t::alloc_tag(), 0, 0, pos}; }; const auto inherit_const_mask_value = [&](u32 reg, reg_state_t state, u32 mask_ones, u32 mask_zeroes) @@ -5407,12 +5426,12 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } ensure(state.tag != umax); - vregs[reg] = reg_state_t{vf::is_mask, 0, state.tag, ones, zeroes}; + vregs[reg] = reg_state_t{vf::is_mask, 0, state.tag, ones, zeroes, state.origin}; }; - const auto unconst = [&](u32 reg) + const auto unconst = [&](u32 reg, u32 pc) { - vregs[reg] = {{}, {}, reg_state_t::alloc_tag()}; + vregs[reg] = reg_state_t::make_unknown(pc); }; const auto add_block = [&](u32 target) @@ -5467,6 +5486,14 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } } + if (atomic16.active) + { + for (auto state : {&atomic16.lsa, &atomic16.ls, &atomic16.ls_offs}) + { + state->invalidate_if_created(pos); + } + } + const u32 data = std::bit_cast>(::at32(result.data, (pos - lsa) / 4)); const auto op = spu_opcode_t{data}; const auto type = g_spu_itype.decode(data); @@ -5650,7 +5677,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } case MFC_Cmd: { - const auto [af, av, atagg, _3, _5] = get_reg(op.rt); + const auto [af, av, atagg, _3, _5, apc] = get_reg(op.rt); if (!is_pattern_match) { @@ -5908,14 +5935,25 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s // Merge pattern attributes between different code paths, may cause detection of failures atomic16_t& existing = it->second; - if (existing.lsa_pc != atomic16.lsa_pc || existing.put_pc != atomic16.put_pc || existing.lsa != atomic16.lsa) + auto compare_tag_and_reg = [](std::pair a, std::pair b) + { + if (b.first->is_const() && a.first->is_const()) + { + return a.first->compare_with_mask_indifference(*b.first, SPU_LS_MASK_1); + } + + // Compare register source + return a.second == b.second; + }; + + if (existing.lsa_pc != atomic16.lsa_pc || existing.put_pc != atomic16.put_pc || !existing.lsa.compare_with_mask_indifference(atomic16.lsa, SPU_LS_MASK_128)) { // Register twice break_putllc16(22, atomic16.discard()); break_putllc16(22, existing.discard()); } - if (existing.active && existing.ls_access && atomic16.ls_access && (!existing.ls.compare_with_mask_indifference(atomic16.ls, SPU_LS_MASK_1) || existing.ls_offs != atomic16.ls_offs)) + if (existing.active && existing.ls_access && atomic16.ls_access && (!compare_tag_and_reg({&existing.ls, existing.reg}, {&atomic16.ls, atomic16.reg}) || existing.ls_offs != atomic16.ls_offs || existing.reg2 != atomic16.reg2)) { // Conflicting loads with stores in more than one code path break_putllc16(27, atomic16.set_invalid_ls(existing.ls_write || atomic16.ls_write)); @@ -5938,6 +5976,8 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s { // Propagate LS access existing.ls = atomic16.ls; + existing.reg = atomic16.reg; + existing.reg2 = atomic16.reg2; existing.ls_offs = atomic16.ls_offs; } @@ -5989,7 +6029,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s if (invalidate) { - unconst(op.rt); + unconst(op.rt, pos); } break; @@ -6068,7 +6108,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } // Unconst - unconst(op.rt); + unconst(op.rt, pos); break; } @@ -6237,7 +6277,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } // Unconst - unconst(op.rt); + unconst(op.rt, pos); break; } case spu_itype::STQA: @@ -6291,7 +6331,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } // Unconst - unconst(op.rt); + unconst(op.rt, pos); break; } @@ -6371,14 +6411,14 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } // Unconst - unconst(op.rt); + unconst(op.rt, pos); break; } case spu_itype::HBR: { hbr_loc = spu_branch_target(pos, op.roh << 7 | op.rt); - const auto [af, av, at, ao, az] = get_reg(op.ra); + const auto [af, av, at, ao, az, apc] = get_reg(op.ra); hbr_tg = af & vf::is_const && !op.c ? av & 0x3fffc : -1; break; } @@ -6443,9 +6483,13 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s break; } - const auto [af, av, at, ao, az] = get_reg(op.ra); - const auto [bf, bv, _2, _4, _6] = get_reg(op.rb); - inherit_const_value(op.rt, af & bf, bv | av); + const auto ra = get_reg(op.ra); + const auto rb = get_reg(op.rb); + + const auto [af, av, at, ao, az, apc] = ra; + const auto [bf, bv, bt, bo, bz, bpc] = rb; + + inherit_const_value(op.rt, ra, rb, av | bv, pos); break; } case spu_itype::XORI: @@ -6456,8 +6500,11 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s break; } - const auto [af, av, at, ao, az] = get_reg(op.ra); - inherit_const_value(op.rt, af, av ^ op.si10); + const auto ra = get_reg(op.ra); + + const auto [af, av, at, ao, az, apc] = ra; + + inherit_const_value(op.rt, ra, ra, av ^ op.si10, pos); break; } case spu_itype::XOR: @@ -6468,16 +6515,24 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s break; } - const auto [af, av, at, ao, az] = get_reg(op.ra); - const auto [bf, bv, _2, _4, _6] = get_reg(op.rb); - inherit_const_value(op.rt, af & bf, bv ^ av); + const auto ra = get_reg(op.ra); + const auto rb = get_reg(op.rb); + + const auto [af, av, at, ao, az, apc] = ra; + const auto [bf, bv, bt, bo, bz, bpc] = rb; + + inherit_const_value(op.rt, ra, rb, bv ^ av, pos); break; } case spu_itype::NOR: { - const auto [af, av, at, ao, az] = get_reg(op.ra); - const auto [bf, bv, _2, _4, _6] = get_reg(op.rb); - inherit_const_value(op.rt, af & bf, ~(bv | av)); + const auto ra = get_reg(op.ra); + const auto rb = get_reg(op.rb); + + const auto [af, av, at, ao, az, apc] = ra; + const auto [bf, bv, bt, bo, bz, bpc] = rb; + + inherit_const_value(op.rt, ra, rb, ~(bv | av), pos); break; } case spu_itype::ANDI: @@ -6494,9 +6549,13 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s break; } - const auto [af, av, at, ao, az] = get_reg(op.ra); - const auto [bf, bv, _2, _4, _6] = get_reg(op.rb); - inherit_const_value(op.rt, af & bf, bv & av); + const auto ra = get_reg(op.ra); + const auto rb = get_reg(op.rb); + + const auto [af, av, at, ao, az, apc] = ra; + const auto [bf, bv, bt, bo, bz, bpc] = rb; + + inherit_const_value(op.rt, ra, rb, bv & av, pos); break; } case spu_itype::AI: @@ -6508,9 +6567,9 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } const auto ra = get_reg(op.ra); - const auto [af, av, at, ao, az] = ra; + const auto [af, av, at, ao, az, apc] = ra; - inherit_const_value(op.rt, af, av + op.si10); + inherit_const_value(op.rt, ra, ra, av + op.si10, pos); if (u32 mask = ra.get_known_zeroes() & ~op.si10; mask & 1) { @@ -6525,10 +6584,10 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s const auto ra = get_reg(op.ra); const auto rb = get_reg(op.rb); - const auto [af, av, at, ao, az] = ra; - const auto [bf, bv, bt, bo, bz] = rb; + const auto [af, av, at, ao, az, apc] = ra; + const auto [bf, bv, bt, bo, bz, bpc] = rb; - inherit_const_value(op.rt, af & bf, bv + av); + inherit_const_value(op.rt, ra, rb, bv + av, pos); if (u32 mask = ra.get_known_zeroes() & rb.get_known_zeroes(); mask & 1) { @@ -6540,8 +6599,10 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } case spu_itype::SFI: { - const auto [af, av, at, ao, az] = get_reg(op.ra); - inherit_const_value(op.rt, af, op.si10 - av); + const auto ra = get_reg(op.ra); + const auto [af, av, at, ao, az, apc] = get_reg(op.ra); + + inherit_const_value(op.rt, ra, ra, op.si10 - av, pos); break; } case spu_itype::SF: @@ -6549,10 +6610,10 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s const auto ra = get_reg(op.ra); const auto rb = get_reg(op.rb); - const auto [af, av, at, ao, az] = ra; - const auto [bf, bv, bt, bo, bz] = rb; + const auto [af, av, at, ao, az, apc] = ra; + const auto [bf, bv, bt, bo, bz, bpc] = rb; - inherit_const_value(op.rt, af & bf, bv - av); + inherit_const_value(op.rt, ra, rb, bv - av, pos); if (u32 mask = ra.get_known_zeroes() & rb.get_known_zeroes(); mask & 1) { @@ -6588,8 +6649,10 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s break; } - const auto [af, av, at, ao, az] = get_reg(op.ra); - inherit_const_value(op.rt, af, av >> ((0 - op.i7) & 0x1f)); + const auto ra = get_reg(op.ra); + const auto [af, av, at, ao, az, apc] = get_reg(op.ra); + + inherit_const_value(op.rt, ra, ra, av >> ((0 - op.i7) & 0x1f), pos); break; } case spu_itype::SHLI: @@ -6606,8 +6669,10 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s break; } - const auto [af, av, at, ao, az] = get_reg(op.ra); - inherit_const_value(op.rt, af, av << (op.i7 & 0x1f)); + const auto ra = get_reg(op.ra); + const auto [af, av, at, ao, az, apc] = ra; + + inherit_const_value(op.rt, ra, ra, av << (op.i7 & 0x1f), pos); break; } case spu_itype::SELB: @@ -6616,7 +6681,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s const auto rb = get_reg(op.rb); // Ignore RC, perform a value merge which also respect bitwise information - vregs[op.rt4] = ra.merge(rb); + vregs[op.rt4] = ra.merge(rb, pos); break; } case spu_itype::SHLQBYI: @@ -6641,7 +6706,49 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s if (!(type & spu_itype::zregmod)) { const u32 op_rt = type & spu_itype::_quadrop ? +op.rt4 : +op.rt; - unconst(op_rt); + + u32 ra = s_reg_max, rb = s_reg_max, rc = s_reg_max; + + if (m_use_ra.test(pos / 4)) + { + ra = op.ra; + } + + if (m_use_rb.test(pos / 4)) + { + rb = op.rb; + } + + if (type & spu_itype::_quadrop && m_use_rc.test(pos / 4)) + { + rc = op.rc; + } + + u32 reg_pos = SPU_LS_SIZE; + + for (u32 reg : {ra, rb, rc}) + { + if (reg != s_reg_max) + { + if (reg_pos == SPU_LS_SIZE) + { + reg = vregs[reg].origin; + } + else if (reg_pos != vregs[reg].origin) + { + const u32 block_start = reg_state_it[wi].pc; + + // if (vregs[reg].origin >= block_start && vregs[reg].origin <= pos) + // { + // reg_pos = std::max(vregs[reg].origin, reg_pos); + // } + reg_pos = block_start; + break; + } + } + } + + unconst(op_rt, reg_pos == SPU_LS_SIZE ? pos : reg_pos); } break; @@ -7714,7 +7821,7 @@ std::array& block_reg_info::evaluate_start_state(const s } else { - merge(res_state, res_state, *arg_state); + merge(res_state, res_state, *arg_state, it->block_pc); } } diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 31e6022de0..c29a24c3f3 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -208,6 +208,7 @@ public: u32 tag = umax; u32 known_ones{}; u32 known_zeroes{}; + u32 origin = SPU_LS_SIZE; bool is_const() const; @@ -222,21 +223,33 @@ public: bool compare_with_mask_indifference(u32 imm, u32 mask_bits) const; bool unequal_with_mask_indifference(const reg_state_t& r, u32 mask_bits) const; + // Convert constant-based value to mask-based value reg_state_t downgrade() const; - reg_state_t merge(const reg_state_t& rhs) const; + + // Connect two register states between different blocks + reg_state_t merge(const reg_state_t& rhs, u32 current_pc) const; + + // Override value with newer value if needed reg_state_t build_on_top_of(const reg_state_t& rhs) const; + // Get known zeroes mask u32 get_known_zeroes() const; + + // Get known ones mask u32 get_known_ones() const; + // Invalidate value if non-constant and reached the point in history of its creation + void invalidate_if_created(u32 current_pc); + template - static std::conditional_t> make_unknown() noexcept + static std::conditional_t> make_unknown(u32 pc) noexcept { if constexpr (Count == 1) { reg_state_t v{}; v.tag = alloc_tag(); v.flag = {}; + v.origin = pc; return v; } else @@ -245,7 +258,7 @@ public: for (reg_state_t& state : result) { - state = make_unknown<1>(); + state = make_unknown<1>(pc); } return result; From 908082e7c319daa30a2301db10d500cdf36b59e0 Mon Sep 17 00:00:00 2001 From: Elad Ashkenazi <18193363+elad335@users.noreply.github.com> Date: Thu, 27 Jun 2024 10:02:41 +0300 Subject: [PATCH 21/30] Silence some cellGem logging --- rpcs3/Emu/Cell/Modules/cellGem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index 3f4538a36b..18f3fb2e0e 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -1759,7 +1759,7 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr flags) { - cellGem.todo("cellGemGetStatusFlags(gem_num=%d, flags=*0x%x)", gem_num, flags); + cellGem.trace("cellGemGetStatusFlags(gem_num=%d, flags=*0x%x)", gem_num, flags); auto& gem = g_fxo->get(); @@ -2094,7 +2094,7 @@ error_code cellGemReset(u32 gem_num) error_code cellGemSetRumble(u32 gem_num, u8 rumble) { - cellGem.warning("cellGemSetRumble(gem_num=%d, rumble=0x%x)", gem_num, rumble); + cellGem.trace("cellGemSetRumble(gem_num=%d, rumble=0x%x)", gem_num, rumble); auto& gem = g_fxo->get(); From a9d53e98de463a0701874df983672ae270831850 Mon Sep 17 00:00:00 2001 From: Elad Ashkenazi <18193363+elad335@users.noreply.github.com> Date: Thu, 27 Jun 2024 10:26:20 +0300 Subject: [PATCH 22/30] SPU LLVM: Fix LSA masking for PUTLLC16, disable RTIME checks --- rpcs3/Emu/Cell/SPUCommonRecompiler.cpp | 14 ++++++++++---- rpcs3/Emu/Cell/SPULLVMRecompiler.cpp | 6 +++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index a069ab9eb8..bf434967f5 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -5689,9 +5689,15 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s { case MFC_GETLLAR_CMD: { + // Get LSA and apply mask for GETLLAR + // TODO: Simplify this to be a value returning function + auto old_lsa = get_reg(s_reg_mfc_lsa); + inherit_const_mask_value(s_reg_mfc_lsa, old_lsa, 0, ~SPU_LS_MASK_128); + + // Restore LSA auto lsa = get_reg(s_reg_mfc_lsa); - inherit_const_mask_value(s_reg_mfc_lsa, lsa, 0, ~SPU_LS_MASK_128); - lsa = get_reg(s_reg_mfc_lsa); + vregs[s_reg_mfc_lsa] = old_lsa; + const u32 lsa_pc = atomic16.lsa_last_pc == SPU_LS_SIZE ? bpc : atomic16.lsa_last_pc; if (atomic16.active) @@ -5743,7 +5749,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s continue; } - if (vregs[s_reg_mfc_lsa].compare_with_mask_indifference(*val, SPU_LS_MASK_1)) + if (vregs[s_reg_mfc_lsa].compare_with_mask_indifference(*val, SPU_LS_MASK_16)) { regs[reg_it] = s_reg_mfc_lsa; continue; @@ -5753,7 +5759,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s { const auto& _reg = vregs[i]; - if (_reg == *val) + if (_reg.compare_with_mask_indifference(*val, SPU_LS_MASK_16)) { regs[reg_it] = i; break; diff --git a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp index 4868ed3d0f..b6d2b4f274 100644 --- a/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPULLVMRecompiler.cpp @@ -1292,7 +1292,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator const auto diff = m_ir->CreateZExt(m_ir->CreateSub(dest, _lsa), get_type()); const auto _new = m_ir->CreateAlignedLoad(get_type(), _ptr(m_lsptr, dest), llvm::MaybeAlign{16}); - const auto _rdata = m_ir->CreateAlignedLoad(get_type(), _ptr(spu_ptr(&spu_thread::rdata), m_ir->CreateAnd(diff, 0x7f)), llvm::MaybeAlign{16}); + const auto _rdata = m_ir->CreateAlignedLoad(get_type(), _ptr(spu_ptr(&spu_thread::rdata), m_ir->CreateAnd(diff, 0x70)), llvm::MaybeAlign{16}); const bool is_accurate_op = !!g_cfg.core.spu_accurate_reservations; @@ -1360,7 +1360,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator llvm::Value* old_val{}; - if (is_accurate_op) + if (true || is_accurate_op) { old_val = m_ir->CreateLoad(get_type(), spu_ptr(&spu_thread::rtime)); } @@ -1373,7 +1373,7 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator const auto cmp_res2 = m_ir->CreateAtomicCmpXchg(rptr2, old_val, m_ir->CreateAdd(old_val, m_ir->getInt64(128)), llvm::MaybeAlign{16}, llvm::AtomicOrdering::SequentiallyConsistent, llvm::AtomicOrdering::SequentiallyConsistent); - if (is_accurate_op) + if (true || is_accurate_op) { m_ir->CreateCondBr(m_ir->CreateExtractValue(cmp_res2, 1), _success, _fail); } From e79084200741c9800b584139ff7837c3e4bcbd1d Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 26 Jun 2024 18:57:41 +0200 Subject: [PATCH 23/30] input: allow dynamic change of mouse configs --- rpcs3/Emu/Io/RB3MidiDrums.cpp | 6 +++--- rpcs3/Emu/Io/mouse_config.cpp | 4 +++- rpcs3/Emu/Io/mouse_config.h | 20 +++++++++++--------- rpcs3/Input/basic_mouse_handler.cpp | 26 ++++++++++++++++++-------- rpcs3/Input/basic_mouse_handler.h | 3 ++- rpcs3/Input/raw_mouse_config.cpp | 2 ++ rpcs3/Input/raw_mouse_config.h | 17 +++++++++-------- rpcs3/Input/raw_mouse_handler.cpp | 29 +++++++++++++++++++++++++---- rpcs3/Input/raw_mouse_handler.h | 3 +++ rpcs3/rpcs3qt/skylander_dialog.cpp | 10 +++++----- 10 files changed, 81 insertions(+), 39 deletions(-) diff --git a/rpcs3/Emu/Io/RB3MidiDrums.cpp b/rpcs3/Emu/Io/RB3MidiDrums.cpp index 855f3f7a23..427e50e317 100644 --- a/rpcs3/Emu/Io/RB3MidiDrums.cpp +++ b/rpcs3/Emu/Io/RB3MidiDrums.cpp @@ -314,9 +314,9 @@ std::unordered_map create_id_to_note_mapping() Note id_to_note(Id id) { - static auto mapping = create_id_to_note_mapping(); - auto it = mapping.find(id); - return it != std::end(mapping) ? it->second : Note::Invalid; + static const auto mapping = create_id_to_note_mapping(); + const auto it = mapping.find(id); + return it != mapping.cend() ? it->second : Note::Invalid; } namespace combo diff --git a/rpcs3/Emu/Io/mouse_config.cpp b/rpcs3/Emu/Io/mouse_config.cpp index 4538d92caa..d299e43dfd 100644 --- a/rpcs3/Emu/Io/mouse_config.cpp +++ b/rpcs3/Emu/Io/mouse_config.cpp @@ -27,7 +27,7 @@ bool mouse_config::load() return false; } -void mouse_config::save() const +void mouse_config::save() { fs::pending_file file(cfg_name); @@ -36,6 +36,8 @@ void mouse_config::save() const file.file.write(to_string()); file.commit(); } + + reload_requested = true; } cfg::string& mouse_config::get_button(int code) diff --git a/rpcs3/Emu/Io/mouse_config.h b/rpcs3/Emu/Io/mouse_config.h index fd9cf52a80..8b583a95fb 100644 --- a/rpcs3/Emu/Io/mouse_config.h +++ b/rpcs3/Emu/Io/mouse_config.h @@ -9,18 +9,20 @@ struct mouse_config final : cfg::node const std::string cfg_name; - cfg::string mouse_button_1{this, "Button 1", "Mouse Left"}; - cfg::string mouse_button_2{this, "Button 2", "Mouse Right"}; - cfg::string mouse_button_3{this, "Button 3", "Mouse Middle"}; - cfg::string mouse_button_4{this, "Button 4", ""}; - cfg::string mouse_button_5{this, "Button 5", ""}; - cfg::string mouse_button_6{this, "Button 6", ""}; - cfg::string mouse_button_7{this, "Button 7", ""}; - cfg::string mouse_button_8{this, "Button 8", ""}; + cfg::string mouse_button_1{ this, "Button 1", "Mouse Left", true }; + cfg::string mouse_button_2{ this, "Button 2", "Mouse Right", true }; + cfg::string mouse_button_3{ this, "Button 3", "Mouse Middle", true }; + cfg::string mouse_button_4{ this, "Button 4", "", true }; + cfg::string mouse_button_5{ this, "Button 5", "", true }; + cfg::string mouse_button_6{ this, "Button 6", "", true }; + cfg::string mouse_button_7{ this, "Button 7", "", true }; + cfg::string mouse_button_8{ this, "Button 8", "", true }; + + atomic_t reload_requested = true; bool exist() const; bool load(); - void save() const; + void save(); cfg::string& get_button(int code); }; diff --git a/rpcs3/Input/basic_mouse_handler.cpp b/rpcs3/Input/basic_mouse_handler.cpp index fea4e4cdd8..b69983dcfe 100644 --- a/rpcs3/Input/basic_mouse_handler.cpp +++ b/rpcs3/Input/basic_mouse_handler.cpp @@ -23,14 +23,7 @@ void basic_mouse_handler::Init(const u32 max_connect) g_cfg_mouse.from_default(); g_cfg_mouse.load(); - m_buttons[CELL_MOUSE_BUTTON_1] = get_mouse_button(g_cfg_mouse.mouse_button_1); - m_buttons[CELL_MOUSE_BUTTON_2] = get_mouse_button(g_cfg_mouse.mouse_button_2); - m_buttons[CELL_MOUSE_BUTTON_3] = get_mouse_button(g_cfg_mouse.mouse_button_3); - m_buttons[CELL_MOUSE_BUTTON_4] = get_mouse_button(g_cfg_mouse.mouse_button_4); - m_buttons[CELL_MOUSE_BUTTON_5] = get_mouse_button(g_cfg_mouse.mouse_button_5); - m_buttons[CELL_MOUSE_BUTTON_6] = get_mouse_button(g_cfg_mouse.mouse_button_6); - m_buttons[CELL_MOUSE_BUTTON_7] = get_mouse_button(g_cfg_mouse.mouse_button_7); - m_buttons[CELL_MOUSE_BUTTON_8] = get_mouse_button(g_cfg_mouse.mouse_button_8); + reload_config(); m_mice.clear(); m_mice.emplace_back(Mouse()); @@ -52,6 +45,18 @@ void basic_mouse_handler::Init(const u32 max_connect) type = mouse_handler::basic; } +void basic_mouse_handler::reload_config() +{ + m_buttons[CELL_MOUSE_BUTTON_1] = get_mouse_button(g_cfg_mouse.mouse_button_1); + m_buttons[CELL_MOUSE_BUTTON_2] = get_mouse_button(g_cfg_mouse.mouse_button_2); + m_buttons[CELL_MOUSE_BUTTON_3] = get_mouse_button(g_cfg_mouse.mouse_button_3); + m_buttons[CELL_MOUSE_BUTTON_4] = get_mouse_button(g_cfg_mouse.mouse_button_4); + m_buttons[CELL_MOUSE_BUTTON_5] = get_mouse_button(g_cfg_mouse.mouse_button_5); + m_buttons[CELL_MOUSE_BUTTON_6] = get_mouse_button(g_cfg_mouse.mouse_button_6); + m_buttons[CELL_MOUSE_BUTTON_7] = get_mouse_button(g_cfg_mouse.mouse_button_7); + m_buttons[CELL_MOUSE_BUTTON_8] = get_mouse_button(g_cfg_mouse.mouse_button_8); +} + /* Sets the target window for the event handler, and also installs an event filter on the target. */ void basic_mouse_handler::SetTargetWindow(QWindow* target) { @@ -80,6 +85,11 @@ bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev) // !m_target->isVisible() is a hack since currently a guiless application will STILL inititialize a gsrender (providing a valid target) if (!m_target || !m_target->isVisible() || target == m_target) { + if (g_cfg_mouse.reload_requested.exchange(false)) + { + reload_config(); + } + switch (ev->type()) { case QEvent::MouseButtonPress: diff --git a/rpcs3/Input/basic_mouse_handler.h b/rpcs3/Input/basic_mouse_handler.h index 95262b7b78..ccd4224bd8 100644 --- a/rpcs3/Input/basic_mouse_handler.h +++ b/rpcs3/Input/basic_mouse_handler.h @@ -27,9 +27,10 @@ public: bool eventFilter(QObject* obj, QEvent* ev) override; private: - QWindow* m_target = nullptr; + void reload_config(); bool get_mouse_lock_state() const; static int get_mouse_button(const cfg::string& button); + QWindow* m_target = nullptr; std::map m_buttons; }; diff --git a/rpcs3/Input/raw_mouse_config.cpp b/rpcs3/Input/raw_mouse_config.cpp index ba4d606a98..88023df0f5 100644 --- a/rpcs3/Input/raw_mouse_config.cpp +++ b/rpcs3/Input/raw_mouse_config.cpp @@ -102,4 +102,6 @@ void raw_mice_config::save() { cfg_log.error("Failed to save %s config to '%s' (error=%s)", cfg_id, cfg_name, fs::g_tls_error); } + + reload_requested = true; } diff --git a/rpcs3/Input/raw_mouse_config.h b/rpcs3/Input/raw_mouse_config.h index 985d29a133..b1ae83883d 100644 --- a/rpcs3/Input/raw_mouse_config.h +++ b/rpcs3/Input/raw_mouse_config.h @@ -18,14 +18,14 @@ public: cfg::_float<10, 1000> mouse_acceleration{ this, "Mouse Acceleration", 100.0f, true }; - cfg::string mouse_button_1{this, "Button 1", "Button 1"}; - cfg::string mouse_button_2{this, "Button 2", "Button 2"}; - cfg::string mouse_button_3{this, "Button 3", "Button 3"}; - cfg::string mouse_button_4{this, "Button 4", "Button 4"}; - cfg::string mouse_button_5{this, "Button 5", "Button 5"}; - cfg::string mouse_button_6{this, "Button 6", ""}; - cfg::string mouse_button_7{this, "Button 7", ""}; - cfg::string mouse_button_8{this, "Button 8", ""}; + cfg::string mouse_button_1{ this, "Button 1", "Button 1", true }; + cfg::string mouse_button_2{ this, "Button 2", "Button 2", true }; + cfg::string mouse_button_3{ this, "Button 3", "Button 3", true }; + cfg::string mouse_button_4{ this, "Button 4", "Button 4", true }; + cfg::string mouse_button_5{ this, "Button 5", "Button 5", true }; + cfg::string mouse_button_6{ this, "Button 6", "", true }; + cfg::string mouse_button_7{ this, "Button 7", "", true }; + cfg::string mouse_button_8{ this, "Button 8", "", true }; cfg::string& get_button_by_index(int index); cfg::string& get_button(int code); @@ -38,6 +38,7 @@ struct raw_mice_config : cfg::node shared_mutex m_mutex; static constexpr std::string_view cfg_id = "raw_mouse"; std::array, 4> players; + atomic_t reload_requested = false; bool load(); void save(); diff --git a/rpcs3/Input/raw_mouse_handler.cpp b/rpcs3/Input/raw_mouse_handler.cpp index 628877d9f6..18f4f5ceb0 100644 --- a/rpcs3/Input/raw_mouse_handler.cpp +++ b/rpcs3/Input/raw_mouse_handler.cpp @@ -35,6 +35,15 @@ u32 g_registered_handlers = 0; raw_mouse::raw_mouse(u32 index, const std::string& device_name, void* handle, raw_mouse_handler* handler) : m_index(index), m_device_name(device_name), m_handle(handle), m_handler(handler) +{ + reload_config(); +} + +raw_mouse::~raw_mouse() +{ +} + +void raw_mouse::reload_config() { if (m_index < ::size32(g_cfg_raw_mouse.players)) { @@ -54,10 +63,6 @@ raw_mouse::raw_mouse(u32 index, const std::string& device_name, void* handle, ra } } -raw_mouse::~raw_mouse() -{ -} - std::pair raw_mouse::get_mouse_button(const cfg::string& button) { const std::string value = button.to_string(); @@ -119,6 +124,11 @@ void raw_mouse::update_values(const RAWMOUSE& state) // Update window handle and size update_window_handle(); + if (std::exchange(reload_requested, false)) + { + reload_config(); + } + const auto get_button_pressed = [this](u8 button, int button_flags) { const auto& [down, up] = ::at32(m_buttons, button); @@ -142,6 +152,9 @@ void raw_mouse::update_values(const RAWMOUSE& state) get_button_pressed(CELL_MOUSE_BUTTON_3, state.usButtonFlags); get_button_pressed(CELL_MOUSE_BUTTON_4, state.usButtonFlags); get_button_pressed(CELL_MOUSE_BUTTON_5, state.usButtonFlags); + get_button_pressed(CELL_MOUSE_BUTTON_6, state.usButtonFlags); + get_button_pressed(CELL_MOUSE_BUTTON_7, state.usButtonFlags); + get_button_pressed(CELL_MOUSE_BUTTON_8, state.usButtonFlags); // Get mouse wheel if ((state.usButtonFlags & RI_MOUSE_WHEEL)) @@ -556,6 +569,14 @@ void raw_mouse_handler::handle_native_event(const MSG& msg) { std::lock_guard lock(m_raw_mutex); + if (g_cfg_raw_mouse.reload_requested.exchange(false)) + { + for (auto& [handle, mouse] : m_raw_mice) + { + mouse.request_reload(); + } + } + if (auto it = m_raw_mice.find(raw_input.header.hDevice); it != m_raw_mice.end()) { it->second.update_values(raw_input.data.mouse); diff --git a/rpcs3/Input/raw_mouse_handler.h b/rpcs3/Input/raw_mouse_handler.h index 601d31dc7a..41f84572d3 100644 --- a/rpcs3/Input/raw_mouse_handler.h +++ b/rpcs3/Input/raw_mouse_handler.h @@ -43,8 +43,10 @@ public: const std::string& device_name() const { return m_device_name; } u32 index() const { return m_index; } void set_index(u32 index) { m_index = index; } + void request_reload() { reload_requested = true; } private: + void reload_config(); static std::pair get_mouse_button(const cfg::string& button); u32 m_index = 0; @@ -60,6 +62,7 @@ private: float m_mouse_acceleration = 1.0f; raw_mouse_handler* m_handler{}; std::map> m_buttons; + bool reload_requested = false; }; class raw_mouse_handler final : public MouseHandlerBase diff --git a/rpcs3/rpcs3qt/skylander_dialog.cpp b/rpcs3/rpcs3qt/skylander_dialog.cpp index 0a6cfab09e..4ca8348505 100644 --- a/rpcs3/rpcs3qt/skylander_dialog.cpp +++ b/rpcs3/rpcs3qt/skylander_dialog.cpp @@ -748,9 +748,9 @@ skylander_dialog* skylander_dialog::get_dlg(QWidget* parent) void skylander_dialog::clear_skylander(u8 slot) { - if (auto slot_infos = sky_slots[slot]) + if (const auto& slot_infos = sky_slots[slot]) { - auto [cur_slot, id, var] = slot_infos.value(); + const auto& [cur_slot, id, var] = slot_infos.value(); g_skyportal.remove_skylander(cur_slot); sky_slots[slot] = {}; update_edits(); @@ -811,10 +811,10 @@ void skylander_dialog::update_edits() for (auto i = 0; i < UI_SKY_NUM; i++) { QString display_string; - if (auto sd = sky_slots[i]) + if (const auto& sd = sky_slots[i]) { - auto [portal_slot, sky_id, sky_var] = sd.value(); - auto found_sky = list_skylanders.find(std::make_pair(sky_id, sky_var)); + const auto& [portal_slot, sky_id, sky_var] = sd.value(); + const auto found_sky = list_skylanders.find(std::make_pair(sky_id, sky_var)); if (found_sky != list_skylanders.end()) { display_string = QString::fromStdString(found_sky->second); From 0679b502f2fe13559d7b375a4e6d5e4439307219 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 26 Jun 2024 19:29:29 +0200 Subject: [PATCH 24/30] input: allow dynamic change of midi drum config --- rpcs3/Emu/Io/RB3MidiDrums.cpp | 146 +++++++++---------------------- rpcs3/Emu/Io/RB3MidiDrums.h | 96 ++++++++++++++++++-- rpcs3/Emu/Io/rb3drums_config.cpp | 4 +- rpcs3/Emu/Io/rb3drums_config.h | 12 +-- 4 files changed, 139 insertions(+), 119 deletions(-) diff --git a/rpcs3/Emu/Io/RB3MidiDrums.cpp b/rpcs3/Emu/Io/RB3MidiDrums.cpp index 427e50e317..df6acecfd2 100644 --- a/rpcs3/Emu/Io/RB3MidiDrums.cpp +++ b/rpcs3/Emu/Io/RB3MidiDrums.cpp @@ -9,9 +9,6 @@ using namespace std::chrono_literals; LOG_CHANNEL(rb3_midi_drums_log); -namespace -{ - namespace controller { @@ -158,67 +155,6 @@ u8 min_velocity() return g_cfg_rb3drums.minimum_velocity; } -enum class Id : u8 -{ - // Each 'Note' can be triggered by multiple different numbers. - // Keeping them flattened in an enum for simplicity / switch statement usage. - - // These follow the rockband 3 midi pro adapter support. - Snare0 = 38, - Snare1 = 31, - Snare2 = 34, - Snare3 = 37, - Snare4 = 39, - HiTom0 = 48, - HiTom1 = 50, - LowTom0 = 45, - LowTom1 = 47, - FloorTom0 = 41, - FloorTom1 = 43, - Hihat0 = 22, - Hihat1 = 26, - Hihat2 = 42, - Hihat3 = 54, - Ride0 = 51, - Ride1 = 53, - Ride2 = 56, - Ride3 = 59, - Crash0 = 49, - Crash1 = 52, - Crash2 = 55, - Crash3 = 57, - Kick0 = 33, - Kick1 = 35, - Kick2 = 36, - HihatPedal = 44, - - // These are from alesis nitro mesh max. ymmv. - SnareRim = 40, // midi pro adapter counts this as snare. - HihatWithPedalUp = 46, // The midi pro adapter considers this a normal hihat hit. - HihatPedalPartial = 23, // If pedal is not 100% down, this will be sent instead of a normal hihat hit. - - // Internal value used for converting midi CC. - // Values past 127 are not used in midi notes. - MidiCC = 255, -}; - -// Intermediate mapping regardless of which midi ids triggered it. -enum class Note : u8 -{ - Invalid, - Kick, - HihatPedal, - Snare, - SnareRim, - HiTom, - LowTom, - FloorTom, - HihatWithPedalUp, - Hihat, - Ride, - Crash, -}; - Note str_to_note(const std::string_view name) { static const std::unordered_map mapping{ @@ -298,27 +234,21 @@ std::unordered_map create_id_to_note_mapping() {Id::Crash2, Note::Crash}, {Id::Crash3, Note::Crash}, }; + // Apply configured overrides. - auto split = fmt::split(g_cfg_rb3drums.midi_overrides.to_string(), {","}); - for (const auto& segment : split) + const std::vector segments = fmt::split(g_cfg_rb3drums.midi_overrides.to_string(), {","}); + for (const std::string& segment : segments) { - if (auto midi_override = parse_midi_override(segment)) + if (const auto midi_override = parse_midi_override(segment)) { - auto id = midi_override->first; - auto note = midi_override->second; + const auto id = midi_override->first; + const auto note = midi_override->second; mapping[id] = note; } } return mapping; } -Note id_to_note(Id id) -{ - static const auto mapping = create_id_to_note_mapping(); - const auto it = mapping.find(id); - return it != mapping.cend() ? it->second : Note::Invalid; -} - namespace combo { @@ -345,39 +275,18 @@ std::vector parse_combo(const std::string_view name, const std::string_view return notes; } -struct Definition -{ - std::string name; - std::vector notes; - std::function create_state; - - Definition(std::string name, const std::string_view csv, const std::function create_state) - : name{std::move(name)} - , notes{parse_combo(this->name, csv)} - , create_state{create_state} - {} -}; - std::chrono::milliseconds window() { return std::chrono::milliseconds{g_cfg_rb3drums.combo_window_ms}; } -const std::vector& definitions() -{ - // Only parse once and cache. - static const std::vector defs{ - {"start", g_cfg_rb3drums.combo_start.to_string(), []{ return drum::start_state(); }}, - {"select", g_cfg_rb3drums.combo_select.to_string(), []{ return drum::select_state(); }}, - {"hold kick", g_cfg_rb3drums.combo_toggle_hold_kick.to_string(), []{ return drum::toggle_hold_kick_state(); }} - }; - return defs; -} - } } // namespace midi +namespace +{ + void set_flag(u8* buf, [[maybe_unused]] std::string_view name, const controller::FlagByIndex& fbi) { auto i = fbi[drum::INDEX]; @@ -397,6 +306,12 @@ void set_flag_if_any(u8* buf, std::string_view name, const controller::FlagByInd } +usb_device_rb3_midi_drums::Definition::Definition(std::string name, const std::string_view csv, const std::function create_state) + : name{std::move(name)} + , notes{midi::combo::parse_combo(this->name, csv)} + , create_state{create_state} +{} + usb_device_rb3_midi_drums::usb_device_rb3_midi_drums(const std::array& location, const std::string& device_name) : usb_device_emulated(location) { @@ -603,6 +518,12 @@ void usb_device_rb3_midi_drums::interrupt_transfer(u32 buf_size, u8* buf, u32 /* } memcpy(buf, bytes.data(), bytes.size()); + if (g_cfg_rb3drums.reload_requested) + { + m_id_to_note_mapping = midi::create_id_to_note_mapping(); + combo.reload_definitions(); + } + while (true) { u8 midi_msg[32]; @@ -712,6 +633,12 @@ rb3drums::KitState usb_device_rb3_midi_drums::parse_midi_message(u8* msg, usz si return rb3drums::KitState{}; } +midi::Note usb_device_rb3_midi_drums::id_to_note(midi::Id id) +{ + const auto it = m_id_to_note_mapping.find(id); + return it != m_id_to_note_mapping.cend() ? it->second : midi::Note::Invalid; +} + rb3drums::KitState usb_device_rb3_midi_drums::parse_midi_note(const u8 id, const u8 velocity) { if (velocity < midi::min_velocity()) @@ -722,7 +649,7 @@ rb3drums::KitState usb_device_rb3_midi_drums::parse_midi_note(const u8 id, const rb3drums::KitState kit_state{}; kit_state.expiry = std::chrono::steady_clock::now() + drum::hit_duration(); - auto note = midi::id_to_note(static_cast(id)); + const midi::Note note = id_to_note(static_cast(id)); switch (note) { case midi::Note::Kick: kit_state.kick_pedal = velocity; break; @@ -751,7 +678,8 @@ bool usb_device_rb3_midi_drums::is_midi_cc(const u8 id, const u8 value) { return false; } - auto is_past_threshold = [](u8 value) + + const auto is_past_threshold = [](u8 value) { const u8 threshold = g_cfg_rb3drums.midi_cc_threshold; return g_cfg_rb3drums.midi_cc_invert_threshold @@ -834,6 +762,15 @@ bool rb3drums::KitState::is_drum() const return std::max({snare, hi_tom, low_tom, floor_tom}) >= midi::min_velocity(); } +void usb_device_rb3_midi_drums::ComboTracker::reload_definitions() +{ + m_definitions = { + {"start", g_cfg_rb3drums.combo_start.to_string(), []{ return drum::start_state(); }}, + {"select", g_cfg_rb3drums.combo_select.to_string(), []{ return drum::select_state(); }}, + {"hold kick", g_cfg_rb3drums.combo_toggle_hold_kick.to_string(), []{ return drum::toggle_hold_kick_state(); }} + }; +} + void usb_device_rb3_midi_drums::ComboTracker::add(u8 note) { if (!midi_notes.empty() && std::chrono::steady_clock::now() >= expiry) @@ -843,9 +780,8 @@ void usb_device_rb3_midi_drums::ComboTracker::add(u8 note) } const usz i = midi_notes.size(); - const auto& defs = midi::combo::definitions(); bool is_in_combo = false; - for (const auto& def : defs) + for (const auto& def : m_definitions) { if (i < def.notes.size() && note == def.notes[i]) { @@ -879,7 +815,7 @@ std::optional usb_device_rb3_midi_drums::ComboTracker::take_ { return {}; } - for (const auto& combo : midi::combo::definitions()) + for (const auto& combo : m_definitions) { if (midi_notes == combo.notes) { diff --git a/rpcs3/Emu/Io/RB3MidiDrums.h b/rpcs3/Emu/Io/RB3MidiDrums.h index 8c6bd4cf99..9d13a81812 100644 --- a/rpcs3/Emu/Io/RB3MidiDrums.h +++ b/rpcs3/Emu/Io/RB3MidiDrums.h @@ -38,10 +38,83 @@ struct KitState bool is_drum() const; }; -}; // namespace rb3drums +} // namespace rb3drums + +namespace midi +{ + +enum class Id : u8 +{ + // Each 'Note' can be triggered by multiple different numbers. + // Keeping them flattened in an enum for simplicity / switch statement usage. + + // These follow the rockband 3 midi pro adapter support. + Snare0 = 38, + Snare1 = 31, + Snare2 = 34, + Snare3 = 37, + Snare4 = 39, + HiTom0 = 48, + HiTom1 = 50, + LowTom0 = 45, + LowTom1 = 47, + FloorTom0 = 41, + FloorTom1 = 43, + Hihat0 = 22, + Hihat1 = 26, + Hihat2 = 42, + Hihat3 = 54, + Ride0 = 51, + Ride1 = 53, + Ride2 = 56, + Ride3 = 59, + Crash0 = 49, + Crash1 = 52, + Crash2 = 55, + Crash3 = 57, + Kick0 = 33, + Kick1 = 35, + Kick2 = 36, + HihatPedal = 44, + + // These are from alesis nitro mesh max. ymmv. + SnareRim = 40, // midi pro adapter counts this as snare. + HihatWithPedalUp = 46, // The midi pro adapter considers this a normal hihat hit. + HihatPedalPartial = 23, // If pedal is not 100% down, this will be sent instead of a normal hihat hit. + + // Internal value used for converting midi CC. + // Values past 127 are not used in midi notes. + MidiCC = 255, +}; + +// Intermediate mapping regardless of which midi ids triggered it. +enum class Note : u8 +{ + Invalid, + Kick, + HihatPedal, + Snare, + SnareRim, + HiTom, + LowTom, + FloorTom, + HihatWithPedalUp, + Hihat, + Ride, + Crash, +}; + +} class usb_device_rb3_midi_drums : public usb_device_emulated { +public: + usb_device_rb3_midi_drums(const std::array& location, const std::string& device_name); + ~usb_device_rb3_midi_drums(); + + void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; + void interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, UsbTransfer* transfer) override; + private: usz response_pos{}; bool buttons_enabled{}; @@ -50,9 +123,19 @@ private: bool hold_kick{}; bool midi_cc_triggered{}; + struct Definition + { + std::string name; + std::vector notes; + std::function create_state; + + Definition(std::string name, const std::string_view csv, const std::function create_state); + }; + class ComboTracker { public: + void reload_definitions(); void add(u8 note); void reset(); std::optional take_state(); @@ -60,18 +143,15 @@ private: private: std::chrono::steady_clock::time_point expiry; std::vector midi_notes; + std::vector m_definitions; }; ComboTracker combo; + std::unordered_map m_id_to_note_mapping; + + midi::Note id_to_note(midi::Id id); rb3drums::KitState parse_midi_message(u8* msg, usz size); rb3drums::KitState parse_midi_note(u8 id, u8 velocity); bool is_midi_cc(u8 id, u8 value); void write_state(u8* buf, const rb3drums::KitState&); - -public: - usb_device_rb3_midi_drums(const std::array& location, const std::string& device_name); - ~usb_device_rb3_midi_drums(); - - void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override; - void interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, UsbTransfer* transfer) override; }; diff --git a/rpcs3/Emu/Io/rb3drums_config.cpp b/rpcs3/Emu/Io/rb3drums_config.cpp index 2d40bfb431..1e308d8b70 100644 --- a/rpcs3/Emu/Io/rb3drums_config.cpp +++ b/rpcs3/Emu/Io/rb3drums_config.cpp @@ -33,7 +33,7 @@ bool cfg_rb3drums::load() return false; } -void cfg_rb3drums::save() const +void cfg_rb3drums::save() { cfg_log.notice("Saving rb3drums config to '%s'", path); @@ -41,4 +41,6 @@ void cfg_rb3drums::save() const { cfg_log.error("Failed to save rb3drums config to '%s' (error=%s)", path, fs::g_tls_error); } + + reload_requested = true; } diff --git a/rpcs3/Emu/Io/rb3drums_config.h b/rpcs3/Emu/Io/rb3drums_config.h index cd638e0270..5910d88d72 100644 --- a/rpcs3/Emu/Io/rb3drums_config.h +++ b/rpcs3/Emu/Io/rb3drums_config.h @@ -6,22 +6,24 @@ struct cfg_rb3drums final : cfg::node { cfg_rb3drums(); bool load(); - void save() const; + void save(); cfg::uint<1, 100> pulse_ms{this, "Pulse width ms", 30, true}; cfg::uint<1, 127> minimum_velocity{this, "Minimum velocity", 10, true}; cfg::uint<1, 5000> combo_window_ms{this, "Combo window in milliseconds", 2000, true}; cfg::_bool stagger_cymbals{this, "Stagger cymbal hits", true, true}; - cfg::string midi_overrides{this, "Midi id to note override", ""}; - cfg::string combo_start{this, "Combo Start", "HihatPedal,HihatPedal,HihatPedal,Snare"}; - cfg::string combo_select{this, "Combo Select", "HihatPedal,HihatPedal,HihatPedal,SnareRim"}; - cfg::string combo_toggle_hold_kick{this, "Combo Toggle Hold Kick", "HihatPedal,HihatPedal,HihatPedal,Kick"}; + cfg::string midi_overrides{this, "Midi id to note override", "", true}; + cfg::string combo_start{this, "Combo Start", "HihatPedal,HihatPedal,HihatPedal,Snare", true}; + cfg::string combo_select{this, "Combo Select", "HihatPedal,HihatPedal,HihatPedal,SnareRim", true}; + cfg::string combo_toggle_hold_kick{this, "Combo Toggle Hold Kick", "HihatPedal,HihatPedal,HihatPedal,Kick", true}; cfg::uint<0, 255> midi_cc_status{this, "Midi CC status", 0xB0, true}; cfg::uint<0, 127> midi_cc_number{this, "Midi CC control number", 4, true}; cfg::uint<0, 127> midi_cc_threshold{this, "Midi CC threshold", 64, true}; cfg::_bool midi_cc_invert_threshold{this, "Midi CC invert threshold", false, true}; const std::string path; + + atomic_t reload_requested = false; }; extern cfg_rb3drums g_cfg_rb3drums; From 8343e3514684aaadbbe9f97f18cf860230cf1ff2 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 27 Jun 2024 03:47:32 +0200 Subject: [PATCH 25/30] cellCamera: improve error logging --- rpcs3/Emu/Cell/Modules/cellCamera.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellCamera.cpp b/rpcs3/Emu/Cell/Modules/cellCamera.cpp index b18d782d7b..89ab8ef9f9 100644 --- a/rpcs3/Emu/Cell/Modules/cellCamera.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCamera.cpp @@ -1679,9 +1679,9 @@ void camera_context::operator()() data3 = 0; // unused } - if (queue->send(evt_data.source, CELL_CAMERA_FRAME_UPDATE, data2, data3) != 0) [[unlikely]] + if (CellError err = queue->send(evt_data.source, CELL_CAMERA_FRAME_UPDATE, data2, data3)) [[unlikely]] { - cellCamera.warning("Failed to send frame update event"); + cellCamera.warning("Failed to send frame update event (error=0x%x)", err); } frame_update_event_sent = true; @@ -1819,9 +1819,9 @@ void camera_context::send_attach_state(bool attached) { if (auto queue = lv2_event_queue::find(key)) { - if (queue->send(evt_data.source, attached ? CELL_CAMERA_ATTACH : CELL_CAMERA_DETACH, 0, 0) != 0) [[unlikely]] + if (CellError err = queue->send(evt_data.source, attached ? CELL_CAMERA_ATTACH : CELL_CAMERA_DETACH, 0, 0)) [[unlikely]] { - cellCamera.warning("Failed to send attach event (attached=%d)", attached); + cellCamera.warning("Failed to send attach event (attached=%d, error=0x%x)", attached, err); } } } From 703de01ebf7399ab4e1bddab40a3466d0bbfa3bf Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 27 Jun 2024 21:28:18 +0200 Subject: [PATCH 26/30] input: actually initialize midi drum notes and combos --- rpcs3/Emu/Io/RB3MidiDrums.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rpcs3/Emu/Io/RB3MidiDrums.cpp b/rpcs3/Emu/Io/RB3MidiDrums.cpp index df6acecfd2..67ff121d77 100644 --- a/rpcs3/Emu/Io/RB3MidiDrums.cpp +++ b/rpcs3/Emu/Io/RB3MidiDrums.cpp @@ -315,6 +315,9 @@ usb_device_rb3_midi_drums::Definition::Definition(std::string name, const std::s usb_device_rb3_midi_drums::usb_device_rb3_midi_drums(const std::array& location, const std::string& device_name) : usb_device_emulated(location) { + m_id_to_note_mapping = midi::create_id_to_note_mapping(); + combo.reload_definitions(); + UsbDeviceDescriptor descriptor{}; descriptor.bcdDevice = 0x0200; descriptor.bDeviceClass = 0x00; From a5956cfa82883831822f634fbf0bb6643872824f Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 27 Jun 2024 01:12:53 +0300 Subject: [PATCH 27/30] rsx: Fix wrapped/clamped MSAA sampling behavior with dynamic flags --- rpcs3/Emu/RSX/Common/TextureUtils.cpp | 22 +++++++++++++++++++ rpcs3/Emu/RSX/Common/TextureUtils.h | 2 ++ rpcs3/Emu/RSX/Program/GLSLCommon.cpp | 3 +++ rpcs3/Emu/RSX/Program/GLSLCommon.h | 3 +++ .../RSXFragmentTextureMSAAOpsInternal.glsl | 14 +++++++++++- .../RSXProg/RSXFragmentTextureOps.glsl | 3 +++ rpcs3/Emu/RSX/RSXThread.cpp | 15 +++++++++++-- 7 files changed, 59 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.cpp b/rpcs3/Emu/RSX/Common/TextureUtils.cpp index e8f265d2dd..ff934431ad 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.cpp +++ b/rpcs3/Emu/RSX/Common/TextureUtils.cpp @@ -1549,4 +1549,26 @@ namespace rsx { return get_format_block_size_in_bytes(format) == 2 ? 0xFFFF : 0xFFFFFF; } + + bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode) + { + switch (mode) + { + // Clamping modes + default: + rsx_log.error("Unknown texture wrap mode: %d", static_cast(mode)); + [[ fallthrough ]]; + case rsx::texture_wrap_mode::border: + case rsx::texture_wrap_mode::clamp: + case rsx::texture_wrap_mode::clamp_to_edge: + case rsx::texture_wrap_mode::mirror_once_clamp_to_edge: + case rsx::texture_wrap_mode::mirror_once_border: + case rsx::texture_wrap_mode::mirror_once_clamp: + return false; + // Wrapping modes + case rsx::texture_wrap_mode::wrap: + case rsx::texture_wrap_mode::mirror: + return true; + } + } } diff --git a/rpcs3/Emu/RSX/Common/TextureUtils.h b/rpcs3/Emu/RSX/Common/TextureUtils.h index ade53ae788..17069587c2 100644 --- a/rpcs3/Emu/RSX/Common/TextureUtils.h +++ b/rpcs3/Emu/RSX/Common/TextureUtils.h @@ -286,4 +286,6 @@ namespace rsx format_class classify_format(rsx::surface_depth_format2 format); format_class classify_format(u32 gcm_format); + + bool is_texcoord_wrapping_mode(rsx::texture_wrap_mode mode); } diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp index 8c1fc79686..5bd2278b77 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.cpp +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.cpp @@ -332,6 +332,9 @@ namespace glsl { "SEXT_G_BIT" , rsx::texture_control_bits::SEXT_G }, { "SEXT_B_BIT" , rsx::texture_control_bits::SEXT_B }, { "SEXT_A_BIT" , rsx::texture_control_bits::SEXT_A }, + { "WRAP_S_BIT", rsx::texture_control_bits::WRAP_S }, + { "WRAP_T_BIT", rsx::texture_control_bits::WRAP_T }, + { "WRAP_R_BIT", rsx::texture_control_bits::WRAP_R }, { "ALPHAKILL ", rsx::texture_control_bits::ALPHAKILL }, { "RENORMALIZE ", rsx::texture_control_bits::RENORMALIZE }, diff --git a/rpcs3/Emu/RSX/Program/GLSLCommon.h b/rpcs3/Emu/RSX/Program/GLSLCommon.h index b9c1f2fda4..942374436e 100644 --- a/rpcs3/Emu/RSX/Program/GLSLCommon.h +++ b/rpcs3/Emu/RSX/Program/GLSLCommon.h @@ -34,6 +34,9 @@ namespace rsx FILTERED_MIN, UNNORMALIZED_COORDS, CLAMP_TEXCOORDS_BIT, + WRAP_S, + WRAP_T, + WRAP_R, GAMMA_CTRL_MASK = (1 << GAMMA_R) | (1 << GAMMA_G) | (1 << GAMMA_B) | (1 << GAMMA_A), EXPAND_MASK = (1 << EXPAND_R) | (1 << EXPAND_G) | (1 << EXPAND_B) | (1 << EXPAND_A), diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl index 4509a66e50..e7c21f0621 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl @@ -1,4 +1,16 @@ R"( +vec2 texture2DMSCoord(const in vec2 coords, const in uint flags) +{ + if (0u == (flags & (WRAP_S_MASK | WRAP_T_MASK))) + { + return coords; + } + + const vec2 wrapped_coords = mod(coords, vec2(1.0)); + const bvec2 wrap_control_mask = bvec2(uvec2(flags) & uvec2(WRAP_S_MASK, WRAP_T_MASK)); + return _select(coords, wrapped_coords, wrap_control_mask); +} + vec4 texelFetch2DMS(in _MSAA_SAMPLER_TYPE_ tex, const in vec2 sample_count, const in ivec2 icoords, const in int index, const in ivec2 offset) { const vec2 resolve_coords = vec2(icoords + offset); @@ -12,7 +24,7 @@ vec4 sampleTexture2DMS(in _MSAA_SAMPLER_TYPE_ tex, const in vec2 coords, const i { const uint flags = TEX_FLAGS(index); const vec2 scaled_coords = COORD_SCALE2(index, coords); - const vec2 normalized_coords = mod(scaled_coords, vec2(1.0)); + const vec2 normalized_coords = texture2DMSCoord(scaled_coords, flags); const vec2 sample_count = vec2(2., textureSamples(tex) * 0.5); const vec2 image_size = textureSize(tex) * sample_count; const ivec2 icoords = ivec2(normalized_coords * image_size); diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl index 2b04b9f392..16e420d547 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureOps.glsl @@ -11,6 +11,9 @@ R"( #define SEXT_G_MASK (1 << SEXT_G_BIT) #define SEXT_B_MASK (1 << SEXT_B_BIT) #define SEXT_A_MASK (1 << SEXT_A_BIT) +#define WRAP_S_MASK (1 << WRAP_S_BIT) +#define WRAP_T_MASK (1 << WRAP_T_BIT) +#define WRAP_R_MASK (1 << WRAP_R_BIT) #define GAMMA_CTRL_MASK (GAMMA_R_MASK | GAMMA_G_MASK | GAMMA_B_MASK | GAMMA_A_MASK) #define SIGN_EXPAND_MASK (EXPAND_R_MASK | EXPAND_G_MASK | EXPAND_B_MASK | EXPAND_A_MASK) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 43e2319b97..5c36664b4c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2525,14 +2525,25 @@ namespace rsx } } - if (backend_config.supports_hw_msaa && - sampler_descriptors[i]->samples > 1) + if (backend_config.supports_hw_msaa && sampler_descriptors[i]->samples > 1) { current_fp_texture_state.multisampled_textures |= (1 << i); texture_control |= (static_cast(tex.zfunc()) << texture_control_bits::DEPTH_COMPARE_OP); texture_control |= (static_cast(tex.mag_filter() != rsx::texture_magnify_filter::nearest) << texture_control_bits::FILTERED_MAG); texture_control |= (static_cast(tex.min_filter() != rsx::texture_minify_filter::nearest) << texture_control_bits::FILTERED_MIN); texture_control |= (((tex.format() & CELL_GCM_TEXTURE_UN) >> 6) << texture_control_bits::UNNORMALIZED_COORDS); + + if (rsx::is_texcoord_wrapping_mode(tex.wrap_s())) { + texture_control |= (1 << texture_control_bits::WRAP_S); + } + + if (rsx::is_texcoord_wrapping_mode(tex.wrap_t())) { + texture_control |= (1 << texture_control_bits::WRAP_T); + } + + if (rsx::is_texcoord_wrapping_mode(tex.wrap_r())) { + texture_control |= (1 << texture_control_bits::WRAP_R); + } } if (sampler_descriptors[i]->format_class != RSX_FORMAT_CLASS_COLOR) From ef136acb6c5c2a1ba3cd237f36d23963588793a2 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 27 Jun 2024 01:34:19 +0300 Subject: [PATCH 28/30] Whitespace fix --- rpcs3/Emu/RSX/RSXThread.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 5c36664b4c..6606351b62 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2533,15 +2533,18 @@ namespace rsx texture_control |= (static_cast(tex.min_filter() != rsx::texture_minify_filter::nearest) << texture_control_bits::FILTERED_MIN); texture_control |= (((tex.format() & CELL_GCM_TEXTURE_UN) >> 6) << texture_control_bits::UNNORMALIZED_COORDS); - if (rsx::is_texcoord_wrapping_mode(tex.wrap_s())) { + if (rsx::is_texcoord_wrapping_mode(tex.wrap_s())) + { texture_control |= (1 << texture_control_bits::WRAP_S); } - if (rsx::is_texcoord_wrapping_mode(tex.wrap_t())) { + if (rsx::is_texcoord_wrapping_mode(tex.wrap_t())) + { texture_control |= (1 << texture_control_bits::WRAP_T); } - if (rsx::is_texcoord_wrapping_mode(tex.wrap_r())) { + if (rsx::is_texcoord_wrapping_mode(tex.wrap_r())) + { texture_control |= (1 << texture_control_bits::WRAP_R); } } From d5923ef808b16500efe681eb01f20e920f1421c6 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 27 Jun 2024 20:37:33 +0200 Subject: [PATCH 29/30] Fix weird new gcc namespace warning --- rpcs3/Input/ds3_pad_handler.cpp | 2 ++ rpcs3/Input/ds3_pad_handler.h | 4 ++-- rpcs3/Input/ds4_pad_handler.cpp | 2 ++ rpcs3/Input/ds4_pad_handler.h | 6 +++--- rpcs3/Input/dualsense_pad_handler.cpp | 2 ++ rpcs3/Input/dualsense_pad_handler.h | 4 ++-- rpcs3/Input/skateboard_pad_handler.cpp | 2 ++ rpcs3/Input/skateboard_pad_handler.h | 4 ++-- 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/rpcs3/Input/ds3_pad_handler.cpp b/rpcs3/Input/ds3_pad_handler.cpp index b78d7bcbfa..7ce3660974 100644 --- a/rpcs3/Input/ds3_pad_handler.cpp +++ b/rpcs3/Input/ds3_pad_handler.cpp @@ -6,6 +6,8 @@ LOG_CHANNEL(ds3_log, "DS3"); +using namespace reports; + constexpr std::array battery_capacity = {0, 1, 25, 50, 75, 100}; constexpr id_pair SONY_DS3_ID_0 = {0x054C, 0x0268}; diff --git a/rpcs3/Input/ds3_pad_handler.h b/rpcs3/Input/ds3_pad_handler.h index b8dae2dae3..b6b423eff3 100644 --- a/rpcs3/Input/ds3_pad_handler.h +++ b/rpcs3/Input/ds3_pad_handler.h @@ -4,7 +4,7 @@ #include -namespace +namespace reports { struct ds3_rumble { @@ -67,7 +67,7 @@ public: #ifdef _WIN32 u8 report_id = 0; #endif - ds3_input_report report{}; + reports::ds3_input_report report{}; }; class ds3_pad_handler final : public hid_pad_handler diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index a1ded567aa..71d69609ac 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -6,6 +6,8 @@ LOG_CHANNEL(ds4_log, "DS4"); +using namespace reports; + constexpr id_pair SONY_DS4_ID_0 = {0x054C, 0x0BA0}; // Dongle constexpr id_pair SONY_DS4_ID_1 = {0x054C, 0x05C4}; // CUH-ZCT1x constexpr id_pair SONY_DS4_ID_2 = {0x054C, 0x09CC}; // CUH-ZCT2x diff --git a/rpcs3/Input/ds4_pad_handler.h b/rpcs3/Input/ds4_pad_handler.h index a6873b8748..aab8b49623 100644 --- a/rpcs3/Input/ds4_pad_handler.h +++ b/rpcs3/Input/ds4_pad_handler.h @@ -4,7 +4,7 @@ #include -namespace +namespace reports { constexpr u32 DS4_ACC_RES_PER_G = 8192; constexpr u32 DS4_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision @@ -119,8 +119,8 @@ public: bool bt_controller{false}; bool has_calib_data{false}; std::array calib_data{}; - ds4_input_report_usb report_usb{}; - ds4_input_report_bt report_bt{}; + reports::ds4_input_report_usb report_usb{}; + reports::ds4_input_report_bt report_bt{}; }; class ds4_pad_handler final : public hid_pad_handler diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index b3c3021ccd..58856f89cd 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -6,6 +6,8 @@ LOG_CHANNEL(dualsense_log, "DualSense"); +using namespace reports; + template <> void fmt_class_string::format(std::string& out, u64 arg) { diff --git a/rpcs3/Input/dualsense_pad_handler.h b/rpcs3/Input/dualsense_pad_handler.h index 32b56be4e7..8598927b63 100644 --- a/rpcs3/Input/dualsense_pad_handler.h +++ b/rpcs3/Input/dualsense_pad_handler.h @@ -4,7 +4,7 @@ #include -namespace +namespace reports { constexpr u32 DUALSENSE_ACC_RES_PER_G = 8192; constexpr u32 DUALSENSE_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision @@ -172,7 +172,7 @@ public: u8 bt_sequence{0}; bool has_calib_data{false}; std::array calib_data{}; - dualsense_input_report_common report{}; // No need to have separate reports for usb and bluetooth + reports::dualsense_input_report_common report{}; // No need to have separate reports for usb and bluetooth DualSenseDataMode data_mode{DualSenseDataMode::Simple}; DualSenseFeatureSet feature_set{DualSenseFeatureSet::Normal}; bool init_lightbar{true}; diff --git a/rpcs3/Input/skateboard_pad_handler.cpp b/rpcs3/Input/skateboard_pad_handler.cpp index 36b5b21397..93b4ae423f 100644 --- a/rpcs3/Input/skateboard_pad_handler.cpp +++ b/rpcs3/Input/skateboard_pad_handler.cpp @@ -4,6 +4,8 @@ LOG_CHANNEL(skateboard_log, "Skateboard"); +using namespace reports; + namespace { constexpr id_pair SKATEBOARD_ID_0 = {0x12BA, 0x0400}; // Tony Hawk RIDE Skateboard diff --git a/rpcs3/Input/skateboard_pad_handler.h b/rpcs3/Input/skateboard_pad_handler.h index 626fbb521f..db1e3536d8 100644 --- a/rpcs3/Input/skateboard_pad_handler.h +++ b/rpcs3/Input/skateboard_pad_handler.h @@ -5,7 +5,7 @@ #include #include -namespace +namespace reports { // Descriptor // 0x09, 0x05, // Usage (0x05) @@ -143,7 +143,7 @@ class skateboard_device : public HidDevice { public: bool skateboard_is_on = false; - skateboard_input_report report{}; + reports::skateboard_input_report report{}; }; class skateboard_pad_handler final : public hid_pad_handler From 71524271e948316d57515422bd0da0159a55d24d Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 28 Jun 2024 12:25:52 +0300 Subject: [PATCH 30/30] rsx: Fix codegen when depth-conversion is enabled --- .../RSXProg/RSXFragmentTextureMSAAOps.glsl | 12 ++++++++++++ .../RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl | 12 ------------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl index 7b79719857..d250e2efb4 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOps.glsl @@ -27,4 +27,16 @@ vec3 compute2x2DownsampleWeights(const in float coord, const in float uv_step, c return vec3(1.0 - (computed_weights.x + computed_weights.y), computed_weights.xy); } +vec2 texture2DMSCoord(const in vec2 coords, const in uint flags) +{ + if (0u == (flags & (WRAP_S_MASK | WRAP_T_MASK))) + { + return coords; + } + + const vec2 wrapped_coords = mod(coords, vec2(1.0)); + const bvec2 wrap_control_mask = bvec2(uvec2(flags) & uvec2(WRAP_S_MASK, WRAP_T_MASK)); + return _select(coords, wrapped_coords, wrap_control_mask); +} + )" diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl index e7c21f0621..0bf734ab35 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl @@ -1,16 +1,4 @@ R"( -vec2 texture2DMSCoord(const in vec2 coords, const in uint flags) -{ - if (0u == (flags & (WRAP_S_MASK | WRAP_T_MASK))) - { - return coords; - } - - const vec2 wrapped_coords = mod(coords, vec2(1.0)); - const bvec2 wrap_control_mask = bvec2(uvec2(flags) & uvec2(WRAP_S_MASK, WRAP_T_MASK)); - return _select(coords, wrapped_coords, wrap_control_mask); -} - vec4 texelFetch2DMS(in _MSAA_SAMPLER_TYPE_ tex, const in vec2 sample_count, const in ivec2 icoords, const in int index, const in ivec2 offset) { const vec2 resolve_coords = vec2(icoords + offset);