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++ 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 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 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 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); } } } 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(); 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); } 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; } 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); } diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index 69e1ace6e4..bf434967f5 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) { @@ -5662,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) @@ -5716,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; @@ -5726,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; @@ -5908,14 +5941,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 +5982,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 +6035,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 +6114,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 +6283,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 +6337,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 +6417,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 +6489,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 +6506,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 +6521,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 +6555,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 +6573,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 +6590,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 +6605,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 +6616,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 +6655,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 +6675,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 +6687,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 +6712,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 +7827,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/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); } 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; diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index dc8ada5098..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); @@ -195,8 +195,8 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptrsecond; + 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); @@ -282,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(); @@ -294,12 +320,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/Emu/Io/RB3MidiDrums.cpp b/rpcs3/Emu/Io/RB3MidiDrums.cpp index 855f3f7a23..67ff121d77 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 auto mapping = create_id_to_note_mapping(); - auto it = mapping.find(id); - return it != std::end(mapping) ? 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,9 +306,18 @@ 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) { + m_id_to_note_mapping = midi::create_id_to_note_mapping(); + combo.reload_definitions(); + UsbDeviceDescriptor descriptor{}; descriptor.bcdDevice = 0x0200; descriptor.bDeviceClass = 0x00; @@ -603,6 +521,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 +636,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 +652,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 +681,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 +765,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 +783,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 +818,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/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) 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/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; 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/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 4509a66e50..0bf734ab35 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXFragmentTextureMSAAOpsInternal.glsl @@ -12,7 +12,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..6606351b62 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2525,14 +2525,28 @@ 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) 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) { diff --git a/rpcs3/Input/basic_keyboard_handler.cpp b/rpcs3/Input/basic_keyboard_handler.cpp index c3d6301cf3..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(); } @@ -179,17 +179,20 @@ 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(Qt::Key_Super_R, CELL_KB_MKEY_R_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(, 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); + //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,8 +224,8 @@ 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(Qt::Key_Meta, CELL_KEYC_APPLICATION); + //buttons.emplace_back(, CELL_KEYC_NUM_LOCK); + //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/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/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 6dd164a391..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 { @@ -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); } @@ -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 7107345199..71d69609ac 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -2,8 +2,12 @@ #include "ds4_pad_handler.h" #include "Emu/Io/pad_config.h" +#include + 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 @@ -427,7 +431,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 +468,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 +700,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/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 806f6a770f..58856f89cd 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -2,8 +2,12 @@ #include "dualsense_pad_handler.h" #include "Emu/Io/pad_config.h" +#include + LOG_CHANNEL(dualsense_log, "DualSense"); +using namespace reports; + template <> void fmt_class_string::format(std::string& out, u64 arg) { @@ -430,31 +434,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 || @@ -462,7 +447,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 +485,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/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/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})); } 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 ""; } 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/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) { 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 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() diff --git a/rpcs3/rpcs3qt/skylander_dialog.cpp b/rpcs3/rpcs3qt/skylander_dialog.cpp index 49d4f66618..4ca8348505 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"}, @@ -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);