diff --git a/core/libs/prx/libSceMouse/Export.cpp b/core/libs/prx/libSceMouse/Export.cpp index a473646e65..b7e5fdb127 100644 --- a/core/libs/prx/libSceMouse/Export.cpp +++ b/core/libs/prx/libSceMouse/Export.cpp @@ -143,7 +143,7 @@ int APS5_VABI sceMouseExtensionScalePosition(std::uint16_t* position, std::uint1 if (!Mouse::IsInitialized()) return MOUSE_ERROR_NOT_INITIALIZED; if (position == nullptr || scale == 0) return MOUSE_ERROR_INVALID_ARG; const std::uint32_t scaled = static_cast(*position) * (scale - 1u); - *position = static_cast((scaled + 0x7fffu) / 0xffffu); + *position = static_cast((scaled + 0xfffeu) / 0xffffu); return MOUSE_OK; } diff --git a/core/libs/prx/libSceMouse/tests/MouseQueries.cpp b/core/libs/prx/libSceMouse/tests/MouseQueries.cpp index d9cab431f7..da9a34068d 100644 --- a/core/libs/prx/libSceMouse/tests/MouseQueries.cpp +++ b/core/libs/prx/libSceMouse/tests/MouseQueries.cpp @@ -70,10 +70,10 @@ int main() { Require(scale(nullptr, 1920) == InvalidArg, "ExtensionScalePosition took a null position"); Require(scale(&position, 0) == InvalidArg && position == 100, "ExtensionScalePosition took a scale of 0"); - const std::array, 6> rows{{{65535, 1920, 1919}, {32768, 1920, 960}, {0, 1920, 0}, {65535, 1, 0}, {1, 65535, 1}, {40000, 1080, 659}}}; + const std::array, 9> rows{{{65535, 1920, 1919}, {32768, 1920, 960}, {0, 1920, 0}, {65535, 1, 0}, {1, 65535, 1}, {40000, 1080, 659}, {1, 2, 1}, {32767, 2, 1}, {100, 1920, 3}}}; for (const auto& [input, size, expected] : rows) { position = input; - Require(scale(&position, size) == Ok && position == expected, "ExtensionScalePosition didn't round position * (scale - 1) / 65535"); + Require(scale(&position, size) == Ok && position == expected, "ExtensionScalePosition didn't round position * (scale - 1) / 65535 up"); } Require(setConfig(handle, nullptr) == InvalidArg, "ExtensionSetConfig took a null config"); diff --git a/docs/dev/debt/libSceMouse.md b/docs/dev/debt/libSceMouse.md index de9528c893..e38e0607fe 100644 --- a/docs/dev/debt/libSceMouse.md +++ b/docs/dev/debt/libSceMouse.md @@ -15,7 +15,7 @@ - [sceMouseGetHandle, sceMouseExtensionSetConfig and sceMouseExtensionScalePosition](../../../core/libs/prx/libSceMouse/src/mouse_impl.cpp) (libSceMouse) - follow the same [13.42 disassembly](https://github.com/boykopovar/AnyPS5/issues/15088#issuecomment-6580877653), not a console; none reaches the driver. - `GetHandle(userId, type, index)` returns the handle `sceMouseOpen` gave that user and type, or 0x80df0008. The console skips slots whose +0xc8 field is 1 when `index` is non-zero; that field's meaning is unknown, and no slot here has it. - `ExtensionSetConfig(handle, config)` refuses a null or a non-zero byte in 5..0x1f, then stores the u32 at 0 and the byte at 4; nothing here reads them yet. - - `ExtensionScalePosition(uint16* position, uint16 scale)` rounds `*position * (scale - 1) / 65535` to the nearest integer, which has no ties since 65535 is odd. The console divides with a multiply by 0x80008001 and a shift by 47, which equals that floor division for every product of two 16-bit values, then rounds with a compare whose exact form wasn't checked. + - `ExtensionScalePosition(uint16* position, uint16 scale)` rounds `*position * (scale - 1) / 65535` up. The console divides with a multiply by 0x80008001 and a shift by 47, which is the floor, and adds 1 when the remainder isn't 0, through a compare of `-(product * 65537)` with 0x10002 ([@BunnyFl's emulation]()). - [Publish](../../../core/libs/prx/libSceMouse/src/mouse_impl.cpp) (libSceMouse) - consecutive motion-only reports with the same buttons are summed into the newest unread entry, so a title that reads a few entries per frame gets current motion instead of a full queue of old reports. Reports with no motion and no button, wheel, tilt or connection change are dropped. Per-report granularity and the console's own report rate are not reproduced