schellingb / dosbox-pure

DOSBox Pure is a new fork of DOSBox built for RetroArch/Libretro aiming for simplicity and ease of use.
GNU General Public License v2.0
731 stars 61 forks source link

How to determine the current mouse speed? #494

Closed sergystepanov closed 2 months ago

sergystepanov commented 2 months ago

Hey,

@schellingb, I'm working on the integration of the DOSBox-Pure core into my own Libretro frontend, and there is a slight problem with the mouse movement. Basically, the frontend streams the core's framebuffer in real-time as an x264 or VPx video into the browser. The intrinsic dimensions of the video are always equal to whatever the core happens to report with the base_width and height in the geometry/av_info callbacks, but the rendered size of the video element on the screen can be of any size (for example, stretched to a 4K screen or fullscreened). So, in order to match the cursor speed of the user in the browser, you have to scale that mouse position to the dimensions of the real screen (which is the core's framebuffer).

Initially, I thought that the DOSBox core re-calculates relative mouse movements (what you pass into RETRO_DEVICE_IDMOUSE callbacks) based on the current framebuffer size (geometry), but this is not the case. I tested some games on the default core settings, and it seems many of them work OK with the hardcoded 640x480 resolution in my cursor DPI calculations. But in some games, like Warcraft 2, the cursor is too slow (because, for some reason, it uses a 1280x960 resolution for the cursor despite the 640x480 framebuffer size).

The question is: is there a way of knowing in the frontend how DOSBox will be calculating its relative mouse movements (the values to which mouse movement is relative to)? It would be great if you could help. :/

This is how it looks:

Bad Warcraft (640x480) ![wc2_bad](https://github.com/schellingb/dosbox-pure/assets/846874/54fcbd8a-94e1-42a6-86fc-4fe93020e219)
Good Warcraft (1280x960) ![wc2_good](https://github.com/schellingb/dosbox-pure/assets/846874/5f3a4510-0afb-4dc9-a43a-bdac6fdd09e9)
schellingb commented 2 months ago

Relative mouse movement are forwarded to the DOS mouse driver as is. The core can't know what scaling is happening on the desktop (what size the emulated screen is actually being shown as to the user) it only knows its own emulated monitor resolution (the geometry). Also the libretro API doesn't really state what the input values of RETRO_DEVICE_ID_MOUSE_X and RETRO_DEVICE_ID_MOUSE_Y are. I think in RetroArch it is just the amount of pixels the mouse cursor has moved.

But it shouldn't apply any scaling anyway. The relative mouse movement is supposed to match the amount of physical movement applied to the mouse device, which should be independent of any resolution (emulation or host side). We don't know what the game does with mouse movement. It could be controlling a mouse cursor or it could be controlling head movement in a FPS game.

You can set the mouse speed with the "Mouse Sensitivity" core option. As an alternative you can switch the "Mouse Input Mode" core option from "Virtual mouse (default)" to "Direct controlled mouse (not supported by all games)" which works fine in Warcraft 2.