diff options
author | FeralChild64 <unknown> | 2022-10-12 13:45:03 +0300 |
---|---|---|
committer | kcgen <1557255+kcgen@users.noreply.github.com> | 2022-10-22 21:15:34 +0300 |
commit | 8dbfbf9e7a6c9ef4ad476967a2d705731457ecc6 (patch) | |
tree | b8bb323abf850cc11fa591a0514946b52497fd1f | |
parent | ec9df4708b60715772d1322d7de42eb8e4c67459 (diff) |
Handle code review remarks
23 files changed, 431 insertions, 289 deletions
diff --git a/include/math_utils.h b/include/math_utils.h index 34d4f37f3..81fce34a6 100644 --- a/include/math_utils.h +++ b/include/math_utils.h @@ -127,6 +127,33 @@ constexpr T1 left_shift_signed(T1 value, T2 amount) return static_cast<T1>(shifted); } +template <typename T> +int8_t clamp_to_int8(const T val) +{ + const auto tmp = std::clamp(val, + static_cast<T>(INT8_MIN), + static_cast<T>(INT8_MAX)); + return static_cast<int8_t>(tmp); +} + +template <typename T> +int16_t clamp_to_int16(const T val) +{ + const auto tmp = std::clamp(val, + static_cast<T>(INT16_MIN), + static_cast<T>(INT16_MAX)); + return static_cast<int16_t>(tmp); +} + +template <typename T> +int32_t clamp_to_int32(const T val) +{ + const auto tmp = std::clamp(val, + static_cast<T>(INT32_MIN), + static_cast<T>(INT32_MAX)); + return static_cast<int32_t>(tmp); +} + inline float decibel_to_gain(const float decibel) { return powf(10.0f, decibel / 20.0f); diff --git a/include/mouse.h b/include/mouse.h index 7f0bb4260..ad93aa28c 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * Copyright (C) 2002-2021 The DOSBox Team * * This program is free software; you can redistribute it and/or modify @@ -88,13 +88,11 @@ void MOUSE_NewScreenParams(const uint16_t clip_x, const uint16_t clip_y, const uint16_t y_abs); // *************************************************************************** -// Variables shared with external modules +// Information for the GFX subsystem // *************************************************************************** -// If driver with seamless pointer support is running -extern bool mouse_seamless_driver; -// If user selected seamless mode is in effect -extern bool mouse_seamless_user; +bool MOUSE_IsUsingSeamlessDriver(); // if driver with seamless pointer support is running +bool MOUSE_IsUsingSeamlessSetting(); // if user selected seamless mode is in effect // *************************************************************************** // BIOS mouse interface for PS/2 mouse @@ -168,15 +166,15 @@ private: const MousePhysical &Physical() const; }; -class MouseConfigAPI final { +class MouseControlAPI final { public: // Always destroy the object once it is not needed anymore // (configuration tool finishes it's job) and we are returning // to normal code execution! - MouseConfigAPI(); - ~MouseConfigAPI(); + MouseControlAPI(); + ~MouseControlAPI(); // Empty list = performs operation on all emulated interfaces typedef std::vector<MouseInterfaceId> ListIDs; @@ -213,13 +211,13 @@ public: static const std::vector<uint16_t> &GetValidMinRateList(); static const std::string &GetValidMinRateStr(); - bool SetMinRate(const MouseConfigAPI::ListIDs &list_ids, + bool SetMinRate(const MouseControlAPI::ListIDs &list_ids, const uint16_t value_hz); - bool ResetMinRate(const MouseConfigAPI::ListIDs &list_ids); + bool ResetMinRate(const MouseControlAPI::ListIDs &list_ids); private: - MouseConfigAPI(const MouseConfigAPI &) = delete; - MouseConfigAPI &operator=(const MouseConfigAPI &) = delete; + MouseControlAPI(const MouseControlAPI &) = delete; + MouseControlAPI &operator=(const MouseControlAPI &) = delete; }; #endif // DOSBOX_MOUSE_H diff --git a/meson.build b/meson.build index cc0ea267a..23440a1ff 100644 --- a/meson.build +++ b/meson.build @@ -529,13 +529,6 @@ coreaudio_dep = optional_dep coremidi_dep = optional_dep corefoundation_dep = optional_dep iokit_dep = optional_dep -iokit_code = ''' -#include <IOKit/hid/IOHIDLib.h> -int main() { - dispatch_block_t test_var; - return 0; -} -''' if host_machine.system() == 'darwin' # ObjectiveC parsing, if possible @@ -585,6 +578,13 @@ if host_machine.system() == 'darwin' ) if iokit_dep.found() if cxx.check_header('IOKit/IOKitLib.h') + iokit_code = ''' + #include <IOKit/hid/IOHIDLib.h> + int main() { + dispatch_block_t test_var; + return 0; + } + ''' is_iokit_compilable = cxx.links( iokit_code, name: 'compiler is capable of compiling IOKit', diff --git a/src/dos/program_mousectl.cpp b/src/dos/program_mousectl.cpp index 7f529321b..705037a71 100644 --- a/src/dos/program_mousectl.cpp +++ b/src/dos/program_mousectl.cpp @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: GPL-2.0-or-later * - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,7 +56,7 @@ bool MOUSECTL::ParseAndRun() { if (idx >= params.size()) return false; - return (0 == strcasecmp(params[idx].c_str(), string)); + return iequals(params[idx].c_str(), string); }; // CmdShow @@ -120,8 +120,8 @@ bool MOUSECTL::ParseAndRun() bool MOUSECTL::ParseInterfaces(std::vector<std::string> ¶ms) { - auto add_if_is_interface = [&](const std::string ¶m) { - for (const auto id : { + auto add_if_is_interface = [&](const std::string ¶m) { + for (const auto id : { MouseInterfaceId::DOS, MouseInterfaceId::PS2, MouseInterfaceId::COM1, @@ -129,11 +129,16 @@ bool MOUSECTL::ParseInterfaces(std::vector<std::string> ¶ms) MouseInterfaceId::COM3, MouseInterfaceId::COM4, }) { - const auto is_interface = string_iequals(param, GetInterfaceStr(id)); - if (is_interface) + if (iequals(param, GetInterfaceStr(id))) { list_ids.push_back(id); - return is_interface; + return true; + } } + if (iequals(param, "PS2")) { // syntax sugar, easier to type than 'PS/2' + list_ids.push_back(MouseInterfaceId::PS2); + return true; + } + return false; }; while (!params.empty() && add_if_is_interface(params.front())) params.erase(params.begin()); // pop @@ -150,16 +155,15 @@ bool MOUSECTL::ParseInterfaces(std::vector<std::string> ¶ms) bool MOUSECTL::CheckInterfaces() { - if (!MouseConfigAPI::CheckInterfaces(list_ids)) - { - if (list_ids.empty()) - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_INTERFACES")); - else - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MISSING_INTERFACES")); - return false; - } + if (MouseControlAPI::CheckInterfaces(list_ids)) + return true; - return true; + if (list_ids.empty()) + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_INTERFACES")); + else + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MISSING_INTERFACES")); + + return false; } const char *MOUSECTL::GetInterfaceStr(const MouseInterfaceId interface_id) const @@ -197,7 +201,7 @@ const char *MOUSECTL::GetMapStatusStr(const MouseMapStatus map_status) const bool MOUSECTL::CmdShow(const bool show_all) { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; const auto info_interfaces = mouse_config_api.GetInfoInterfaces(); bool show_mapped = false; @@ -213,8 +217,9 @@ bool MOUSECTL::CmdShow(const bool show_all) continue; const auto interface_id = entry.GetInterfaceId(); const auto rate_hz = entry.GetRate(); + const bool rate_enforced = entry.GetMinRate(); - if (entry.GetMinRate()) + if (rate_enforced) hint_rate_min = true; if (interface_id == MouseInterfaceId::COM1 || @@ -227,7 +232,7 @@ bool MOUSECTL::CmdShow(const bool show_all) GetInterfaceStr(interface_id), entry.GetSensitivityX(), entry.GetSensitivityY(), - hint_rate_min ? "*" : "", + rate_enforced ? "*" : "", rate_hz ? std::to_string(rate_hz).c_str() : "-", convert_ansi_markup(GetMapStatusStr(entry.GetMapStatus())).c_str()); WriteOut("\n"); @@ -304,17 +309,17 @@ void MOUSECTL::FinalizeMapping() bool MOUSECTL::CmdMap(const MouseInterfaceId interface_id, const std::string &pattern) { std::regex regex; - if (!MouseConfigAPI::PatternToRegex(pattern, regex)) { + if (!MouseControlAPI::PatternToRegex(pattern, regex)) { WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_PATTERN")); return false; } - if (MouseConfigAPI::IsNoMouseMode()) { + if (MouseControlAPI::IsNoMouseMode()) { WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE")); return false; } - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; if (!mouse_config_api.Map(interface_id, regex)) { WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_MATCH")); return false; @@ -328,12 +333,12 @@ bool MOUSECTL::CmdMap() { assert(list_ids.size() >= 1); - if (MouseConfigAPI::IsNoMouseMode()) { + if (MouseControlAPI::IsNoMouseMode()) { WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE")); return false; } - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; const auto info_physical = mouse_config_api.GetInfoPhysical(); if (info_physical.empty()) { @@ -375,71 +380,71 @@ bool MOUSECTL::CmdMap() bool MOUSECTL::CmdUnMap() { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.UnMap(list_ids); return true; } bool MOUSECTL::CmdOnOff(const bool enable) { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.OnOff(list_ids, enable); return true; } bool MOUSECTL::CmdReset() { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.Reset(list_ids); return true; } bool MOUSECTL::CmdSensitivity(const int8_t value) { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.SetSensitivity(list_ids, value, value); return true; } bool MOUSECTL::CmdSensitivityX(const int8_t value) { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.SetSensitivityX(list_ids, value); return true; } bool MOUSECTL::CmdSensitivityY(const int8_t value) { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.SetSensitivityY(list_ids, value); return true; } bool MOUSECTL::CmdSensitivity() { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.ResetSensitivity(list_ids); return true; } bool MOUSECTL::CmdSensitivityX() { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.ResetSensitivityX(list_ids); return true; } bool MOUSECTL::CmdSensitivityY() { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.ResetSensitivityY(list_ids); return true; } bool MOUSECTL::CmdMinRate(const std::string ¶m) { - const auto &valid_list = MouseConfigAPI::GetValidMinRateList(); - const auto &valid_str = MouseConfigAPI::GetValidMinRateStr(); + const auto &valid_list = MouseControlAPI::GetValidMinRateList(); + const auto &valid_str = MouseControlAPI::GetValidMinRateStr(); const auto tmp = std::atoi(param.c_str()); if (tmp < 0 || tmp > UINT16_MAX) { @@ -455,14 +460,14 @@ bool MOUSECTL::CmdMinRate(const std::string ¶m) return false; } - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.SetMinRate(list_ids, value_hz); return true; } bool MOUSECTL::CmdMinRate() { - MouseConfigAPI mouse_config_api; + MouseControlAPI mouse_config_api; mouse_config_api.ResetMinRate(list_ids); return true; } diff --git a/src/dos/program_mousectl.h b/src/dos/program_mousectl.h index d59b9dcd0..5aa8d543d 100644 --- a/src/dos/program_mousectl.h +++ b/src/dos/program_mousectl.h @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: GPL-2.0-or-later * - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,6 +48,9 @@ private: const char *GetInterfaceStr(const MouseInterfaceId interface_id) const; const char *GetMapStatusStr(const MouseMapStatus map_status) const; + // Methods below exectute specific commands requested by the user, + // they return 'true' if DOS error code should indicate success, + // and 'false' if we should report a failure bool CmdShow(const bool show_all); bool CmdMap(const MouseInterfaceId interface_id, const std::string &pattern); diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 6ef1c74c6..a4e8d6677 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -2278,7 +2278,8 @@ void GFX_UpdateMouseState() // it's auto-captured (but not manually requested) and // in seamless-mode } else if (!sdl.desktop.fullscreen && mouse_is_captured && - (mouse_seamless_driver || (!mouse_capture_requested && mouse_seamless_user))) { + (MOUSE_IsUsingSeamlessDriver() || + (!mouse_capture_requested && MOUSE_IsUsingSeamlessSetting()))) { GFX_ToggleMouseCapture(); SDL_ShowCursor(SDL_DISABLE); @@ -2291,7 +2292,7 @@ void GFX_UpdateMouseState() if (sdl.mouse.control_choice == CaptureOnStart) { SDL_RaiseWindow(sdl.window); toggle_mouse_capture_from_user(true); - } else if (mouse_seamless_driver || + } else if (MOUSE_IsUsingSeamlessDriver() || (sdl.mouse.control_choice & (Seamless | NoMouse))) { SDL_ShowCursor(SDL_DISABLE); } @@ -3659,7 +3660,7 @@ static void HandleMouseButton(SDL_MouseButtonEvent * button) assert(button->state == SDL_PRESSED); - if (sdl.desktop.fullscreen || mouse_seamless_driver) { + if (sdl.desktop.fullscreen || MOUSE_IsUsingSeamlessDriver()) { notify_button(button->button, state_pressed); return; } diff --git a/src/hardware/mouse/README.md b/src/hardware/mouse/README.md new file mode 100644 index 000000000..9b0715d92 --- /dev/null +++ b/src/hardware/mouse/README.md @@ -0,0 +1,70 @@ + +Few comments on mouse emulation code organization: + + +###### `mouse.cpp` + +Entry point for all the notifications and requests from external subsystems - +see `include/mouse.h` for API definition. Interacts mainly with GFX subsystem +(SDL-based at the moment of writing this code), but contains a configuration +API (`MouseControlAPI` class) for interaction with command-line configuration +tool and yet-to-be-written GUI. + +###### `../dos/program_mousectl.cpp` + +Implementation of the command line tool, allowing to change settings (like +sensitivity or emulated sampling rate) during the runtime. The tool can also +be used to map a single physical mouse to the given emulated interface, thus +allowing for dual-mice gaming. + +###### `mouse_common.cpp` + +Various helper methods, like implementation of mouse ballistics acceleration +model). + +###### `mouse_config.cpp` + +Handles `[mouse]` section of the DOSBox configuration file. + +###### `mouse_interfaces.cpp` + +Common object-oriented API, abstracting various emulated mouse interfaces for +`mouse.cpp` and `mouse_manymouse.cpp`. + +###### `mouse_manymouse.cpp` + +Object-oriented wrapper around a 3rd party _ManyMouse_ library, used for +dual-mice gaming. Used as a source of mouse events - but only when a physical +mouse is mapped to the emulated interface, otherwise all mouse events come +from SDL-based GFX subsystem. + +###### `mouse_queue.cpp` + +A 'queue' - delays and aggregates mouse events from host OS to simulate +the desired mouse scanning rate. + +###### `mouseif_*.cpp` + +Implementations (non-object oriented) of various mouse interfaces: + +- a simulated DOS driver, compatible with _MOUSE.COM_, with some extensions +(like _CtMouse_ wheel API or direct support for _INT33_ Windows driver from +_javispedro_) +- PS/2 (currently only via BIOS calls, physical mouse port is not emulated +yet) +- a _VMWare_ mouse protocol (actually a PS/2 mouse extension), allowing for +seamless integration with host mouse cursor if a proper driver is running + +Future (not yet implemented) planned interfaces include: + +- _VirtualBox_ mouse protocol extension; very similar to the _VMWare_ one, +but requires a PCI device +(see <https://wiki.osdev.org/VirtualBox_Guest_Additions> for description) +- InPort / Bus mouse - I know no description, but Bochs contains an emulation +code, under GPL2-or-above license + +###### `../serialport/serialmouse.cpp` + +Serial mice emulation - idea is similar to `mouseif_*.cpp` files, but +implemented in object-oriented way, as a serial port device; multiple +instances can exist, for each serial port. diff --git a/src/hardware/mouse/mouse.cpp b/src/hardware/mouse/mouse.cpp index 1f7b4ea68..4db2275aa 100644 --- a/src/hardware/mouse/mouse.cpp +++ b/src/hardware/mouse/mouse.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * Copyright (C) 2002-2021 The DOSBox Team * * This program is free software; you can redistribute it and/or modify @@ -37,8 +37,8 @@ CHECK_NARROWING(); -bool mouse_seamless_driver = false; -bool mouse_seamless_user = false; +bool seamless_driver = false; +bool seamless_setting = false; static Bitu int74_ret_callback = 0; @@ -114,6 +114,21 @@ Bitu int74_ret_handler() return CBRET_NONE; } + +// *************************************************************************** +// Information for the GFX subsystem +// *************************************************************************** + +bool MOUSE_IsUsingSeamlessDriver() +{ + return seamless_driver; +} + +bool MOUSE_IsUsingSeamlessSetting() +{ + return seamless_setting; +} + // *************************************************************************** // External notifications // *************************************************************************** @@ -144,8 +159,8 @@ void MOUSE_NotifyResetDOS() void MOUSE_NotifyStateChanged() { - const auto old_seamless_driver = mouse_seamless_driver; - const auto old_seamless_user = mouse_seamless_user; + const auto old_seamless_driver = seamless_driver; + const auto old_seamless_setting = seamless_setting; const auto is_mapping_in_effect = manymouse.IsMappingInEffect(); @@ -157,16 +172,16 @@ void MOUSE_NotifyStateChanged() } // Prepare suggestions to the GFX subsystem - mouse_seamless_driver = mouse_shared.active_vmm && - !mouse_video.fullscreen && - !is_mapping_in_effect; - mouse_seamless_user = mouse_config.seamless && - !mouse_video.fullscreen && - !is_mapping_in_effect; + seamless_driver = mouse_shared.active_vmm && + !mouse_video.fullscreen && + !is_mapping_in_effect; + seamless_setting = mouse_config.seamless && + !mouse_video.fullscreen && + !is_mapping_in_effect; // If state has really changed, update GFX subsystem - if (mouse_seamless_driver != old_seamless_driver || - mouse_seamless_user != old_seamless_user) + if (seamless_driver != old_seamless_driver || + seamless_setting != old_seamless_setting) GFX_UpdateMouseState(); } @@ -179,7 +194,7 @@ void MOUSE_NotifyDisconnect(const MouseInterfaceId interface_id) void MOUSE_NotifyFakePS2() { - auto interface = MouseInterface::GetPS2(); + const auto interface = MouseInterface::GetPS2(); if (interface && interface->IsUsingEvents()) { MouseEvent ev; @@ -201,9 +216,7 @@ void MOUSE_EventMoved(const float x_rel, const uint16_t y_abs) { // Drop unneeded events - if (!mouse_is_captured && - !mouse_seamless_user && - !mouse_seamless_driver) + if (!mouse_is_captured && !seamless_driver && !seamless_setting) return; // From the GUI we are getting mouse movement data in two @@ -289,11 +302,9 @@ void MOUSE_EventWheel(const int16_t w_rel, // MOUSECTL.COM / GUI configurator interface // *************************************************************************** -void get_relevant_interfaces(std::vector<MouseInterface *> &list_out, - const std::vector<MouseInterfaceId> &list_ids) +static std::vector<MouseInterface *> get_relevant_interfaces(const std::vector<MouseInterfaceId> &list_ids) { - list_out.clear(); - auto list_tmp = list_out; + std::vector<MouseInterface *> list_tmp = {}; if (list_ids.empty()) // If command does not specify interfaces, @@ -307,42 +318,44 @@ void get_relevant_interfaces(std::vector<MouseInterface *> &list_out, } // Filter out not emulated ones + std::vector<MouseInterface *> list_out = {}; for (const auto &interface : list_tmp) if (interface->IsEmulated()) list_out.push_back(interface); + + return list_out; } -MouseConfigAPI::MouseConfigAPI() +MouseControlAPI::MouseControlAPI() { manymouse.StartConfigAPI(); } -MouseConfigAPI::~MouseConfigAPI() +MouseControlAPI::~MouseControlAPI() { manymouse.StopConfigAPI(); MOUSE_NotifyStateChanged(); } -bool MouseConfigAPI::IsNoMouseMode() +bool MouseControlAPI::IsNoMouseMode() { return mouse_config.no_mouse; } -const std::vector<MouseInterfaceInfoEntry> &MouseConfigAPI::GetInfoInterfaces() const +const std::vector<MouseInterfaceInfoEntry> &MouseControlAPI::GetInfoInterfaces() const { return mouse_info.interfaces; } -const std::vector<MousePhysicalInfoEntry> &MouseConfigAPI::GetInfoPhysical() +const std::vector<MousePhysicalInfoEntry> &MouseControlAPI::GetInfoPhysical() { manymouse.RescanIfSafe(); return mouse_info.physical; } -bool MouseConfigAPI::CheckInterfaces(const MouseConfigAPI::ListIDs &list_ids) +bool MouseControlAPI::CheckInterfaces(const MouseControlAPI::ListIDs &list_ids) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); + const auto list = get_relevant_interfaces(list_ids); if (list_ids.empty() && list.empty()) return false; // no emulated mouse interfaces @@ -354,8 +367,8 @@ bool MouseConfigAPI::CheckInterfaces(const MouseConfigAPI::ListIDs &list_ids) return true; } -bool MouseConfigAPI::PatternToRegex(const std::string &pattern, - std::regex ®ex) +bool MouseControlAPI::PatternToRegex(const std::string &pattern, + std::regex ®ex) { // Convert DOS wildcard pattern to a regular expression std::stringstream pattern_regex; @@ -381,7 +394,7 @@ bool MouseConfigAPI::PatternToRegex(const std::string &pattern, return true; } -bool MouseConfigAPI::ProbeForMapping(uint8_t &device_id) +bool MouseControlAPI::ProbeForMapping(uint8_t &device_id) { if (mouse_config.no_mouse) return false; @@ -390,7 +403,7 @@ bool MouseConfigAPI::ProbeForMapping(uint8_t &device_id) return manymouse.ProbeForMapping(device_id); } -bool MouseConfigAPI::Map(const MouseInterfaceId interface_id, +bool MouseControlAPI::Map(const MouseInterfaceId interface_id, const uint8_t device_idx) { if (mouse_config.no_mouse) @@ -403,8 +416,8 @@ bool MouseConfigAPI::Map(const MouseInterfaceId interface_id, return mouse_interface->ConfigMap(device_idx); } -bool MouseConfigAPI::Map(const MouseInterfaceId interface_id, - const std::regex ®ex) +bool MouseControlAPI::Map(const MouseInterfaceId interface_id, + const std::regex ®ex) { if (mouse_config.no_mouse) return false; @@ -417,43 +430,37 @@ bool MouseConfigAPI::Map(const MouseInterfaceId interface_id, return Map(interface_id, idx); } -bool MouseConfigAPI::UnMap(const MouseConfigAPI::ListIDs &list_ids) +bool MouseControlAPI::UnMap(const MouseControlAPI::ListIDs &list_ids) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigUnMap(); return !list.empty(); } -bool MouseConfigAPI::OnOff(const MouseConfigAPI::ListIDs &list_ids, - const bool enable) +bool MouseControlAPI::OnOff(const MouseControlAPI::ListIDs &list_ids, + const bool enable) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigOnOff(enable); return !list.empty(); } -bool MouseConfigAPI::Reset(const MouseConfigAPI::ListIDs &list_ids) +bool MouseControlAPI::Reset(const MouseControlAPI::ListIDs &list_ids) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigReset(); return !list.empty(); } -bool MouseConfigAPI::SetSensitivity(const MouseConfigAPI::ListIDs &list_ids, - const int8_t sensitivity_x, - const int8_t sensitivity_y) +bool MouseControlAPI::SetSensitivity(const MouseControlAPI::ListIDs &list_ids, + const int8_t sensitivity_x, + const int8_t sensitivity_y) { if (sensitivity_x > mouse_predefined.sensitivity_user_max || sensitivity_x < -mouse_predefined.sensitivity_user_max || @@ -461,86 +468,74 @@ bool MouseConfigAPI::SetSensitivity(const MouseConfigAPI::ListIDs &list_ids, sensitivity_y < -mouse_predefined.sensitivity_user_max) return false; - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigSetSensitivity(sensitivity_x, sensitivity_y); return !list.empty(); } -bool MouseConfigAPI::SetSensitivityX(const MouseConfigAPI::ListIDs &list_ids, - const int8_t sensitivity_x) +bool MouseControlAPI::SetSensitivityX(const MouseControlAPI::ListIDs &list_ids, + const int8_t sensitivity_x) { if (sensitivity_x > mouse_predefined.sensitivity_user_max || sensitivity_x < -mouse_predefined.sensitivity_user_max) return false; - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigSetSensitivityX(sensitivity_x); return !list.empty(); } -bool MouseConfigAPI::SetSensitivityY(const MouseConfigAPI::ListIDs &list_ids, - const int8_t sensitivity_y) +bool MouseControlAPI::SetSensitivityY(const MouseControlAPI::ListIDs &list_ids, + const int8_t sensitivity_y) { if (sensitivity_y > mouse_predefined.sensitivity_user_max || sensitivity_y < -mouse_predefined.sensitivity_user_max) return false; - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigSetSensitivityY(sensitivity_y); return !list.empty(); } -bool MouseConfigAPI::ResetSensitivity(const MouseConfigAPI::ListIDs &list_ids) +bool MouseControlAPI::ResetSensitivity(const MouseControlAPI::ListIDs &list_ids) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigResetSensitivity(); return !list.empty(); } -bool MouseConfigAPI::ResetSensitivityX(const MouseConfigAPI::ListIDs &list_ids) +bool MouseControlAPI::ResetSensitivityX(const MouseControlAPI::ListIDs &list_ids) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigResetSensitivityX(); return !list.empty(); } -bool MouseConfigAPI::ResetSensitivityY(const MouseConfigAPI::ListIDs &list_ids) +bool MouseControlAPI::ResetSensitivityY(const MouseControlAPI::ListIDs &list_ids) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigResetSensitivityY(); return !list.empty(); } -const std::vector<uint16_t> &MouseConfigAPI::GetValidMinRateList() +const std::vector<uint16_t> &MouseControlAPI::GetValidMinRateList() { return MouseConfig::GetValidMinRateList(); } -const std::string &MouseConfigAPI::GetValidMinRateStr() +const std::string &MouseControlAPI::GetValidMinRateStr() { static std::string out_str = ""; @@ -560,27 +555,23 @@ const std::string &MouseConfigAPI::GetValidMinRateStr() return out_str; } -bool MouseConfigAPI::SetMinRate(const MouseConfigAPI::ListIDs &list_ids, - const uint16_t value_hz) +bool MouseControlAPI::SetMinRate(const MouseControlAPI::ListIDs &list_ids, + const uint16_t value_hz) { const auto &valid_list = GetValidMinRateList(); if (std::find(valid_list.begin(), valid_list.end(), value_hz) == valid_list.end()) return false; // invalid value - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigSetMinRate(value_hz); return !list.empty(); } -bool MouseConfigAPI::ResetMinRate(const MouseConfigAPI::ListIDs &list_ids) +bool MouseControlAPI::ResetMinRate(const MouseControlAPI::ListIDs &list_ids) { - std::vector<MouseInterface *> list; - get_relevant_interfaces(list, list_ids); - + auto list = get_relevant_interfaces(list_ids); for (auto &interface : list) interface->ConfigResetMinRate(); diff --git a/src/hardware/mouse/mouse_common.cpp b/src/hardware/mouse/mouse_common.cpp index 75e2f5d08..fb1350dad 100644 --- a/src/hardware/mouse/mouse_common.cpp +++ b/src/hardware/mouse/mouse_common.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +42,9 @@ float MOUSE_GetBallisticsCoeff(const float speed) // This routine provides a function for mouse ballistics // (cursor acceleration), to be reused by various mouse interfaces. // Since this is a DOS emulator, the acceleration model is - // based on a historic PS/2 mouse specification. + // based on a historic PS/2 mouse scaling specification, desribed + // for exampel here: + // - https://wiki.osdev.org/Mouse_Input // Input: mouse speed // Output: acceleration coefficient (1.0f for speed >= 6.0f) @@ -93,39 +95,20 @@ float MOUSE_ClampRelativeMovement(const float rel) uint16_t MOUSE_ClampRateHz(const uint16_t rate_hz) { - constexpr auto rate_min = static_cast<uint16_t>(10); - constexpr auto rate_max = static_cast<uint16_t>(500); + constexpr uint16_t rate_min = 10; + constexpr uint16_t rate_max = 500; return std::clamp(rate_hz, rate_min, rate_max); } -int8_t MOUSE_ClampToInt8(const int32_t val) -{ - const auto tmp = std::clamp(val, - static_cast<int32_t>(INT8_MIN), - static_cast<int32_t>(INT8_MAX)); - - return static_cast<int8_t>(tmp); -} - -int16_t MOUSE_ClampToInt16(const int32_t val) -{ - const auto tmp = std::clamp(val, - static_cast<int32_t>(INT16_MIN), - static_cast<int32_t>(INT16_MAX)); - - return static_cast<int16_t>(tmp); -} - // *************************************************************************** // Mouse speed calculation // *************************************************************************** MouseSpeedCalculator::MouseSpeedCalculator(const float scaling) : + ticks_start(PIC_Ticks), scaling(scaling * 1000.0f) // to convert from units/ms to units/s { - clock_time_start = std::chrono::steady_clock::now(); - pic_ticks_start = PIC_Ticks; } float MouseSpeedCalculator::Get() const @@ -135,44 +118,40 @@ float MouseSpeedCalculator::Get() const void MouseSpeedCalculator::Update(const float delta) { - constexpr auto n = static_cast<float>(std::chrono::steady_clock::period::num); - constexpr auto d = static_cast<float>(std::chrono::steady_clock::period::den); - constexpr auto period_ms = 1000.0f * n / d; - // For the measurement duration require no more than 400 milliseconds - // and at least 10 times the clock granularity - constexpr uint32_t max_diff_ms = 400; - constexpr uint32_t min_diff_ms = std::max(static_cast<uint32_t>(1), - static_cast<uint32_t>(period_ms * 10)); - // Require at least 40 ticks of PIC emulator to pass - constexpr uint32_t min_diff_ticks = 40; - - // Get current time, calculate difference - const auto time_now = std::chrono::steady_clock::now(); - const auto diff_time = time_now - clock_time_start; - const auto diff_ticks = PIC_Ticks - pic_ticks_start; - const auto diff_ms = - std::chrono::duration_cast<std::chrono::milliseconds>(diff_time).count(); + // For the measurement require at least certain amount + // of PIC ticks; if too much time passes without meaningful + // movement, consider mouse speed to be 0 + constexpr uint32_t min_ticks = 40; + constexpr uint32_t max_ticks = 400; + + // Calculate time from the beginning of measurement + const auto diff_ticks = PIC_Ticks - ticks_start; // Try to calculate cursor speed - if (diff_ms > std::max(max_diff_ms, static_cast<uint32_t>(10 * period_ms))) { - // Do not wait any more for movement, consider speed to be 0 - speed = 0.0f; - } else if (diff_ms >= 0) { - // Update distance travelled by the cursor - distance += delta; - - // Make sure enough time passed for accurate speed calculation - if (diff_ms < min_diff_ms || (diff_ticks < min_diff_ticks && diff_ticks > 0)) - return; - - // Update cursor speed - speed = scaling * distance / static_cast<float>(diff_ms); + if (PIC_Ticks >= ticks_start) { + if (diff_ticks > max_ticks) + // Do not wait any more for the movement, consider speed to be 0 + speed = 0.0f; + else { + // Update distance travelled by the cursor + distance += delta; + + // Make sure enough time passed for accurate speed calculation + if (diff_ticks < min_ticks) + return; + + // Calculate cursor speed + speed = scaling * distance / static_cast<float>(diff_ticks); + } } + // Note: if PIC_Ticks < ticks_start, we have a counter overflow - this + // can only happen if emulator is run for many weeks at a time. In such + // case we just assume previous speed is still valid, for simplicity. + // Start new measurement - distance = 0.0f; - clock_time_start = time_now; - pic_ticks_start = PIC_Ticks; + distance = 0.0f; + ticks_start = PIC_Ticks; } // *************************************************************************** diff --git a/src/hardware/mouse/mouse_common.h b/src/hardware/mouse/mouse_common.h index 5c54b26d1..ff9a7e0bb 100644 --- a/src/hardware/mouse/mouse_common.h +++ b/src/hardware/mouse/mouse_common.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +21,6 @@ #include "mouse.h" -#include <chrono> - #include "bit_view.h" // *************************************************************************** @@ -79,9 +77,6 @@ uint8_t MOUSE_GetDelayFromRateHz(const uint16_t rate_hz); float MOUSE_ClampRelativeMovement(const float rel); uint16_t MOUSE_ClampRateHz(const uint16_t rate_hz); -int8_t MOUSE_ClampToInt8(const int32_t val); -int16_t MOUSE_ClampToInt16(const int32_t val); - // *************************************************************************** // Mouse speed calculation // *************************************************************************** @@ -100,8 +95,7 @@ private: MouseSpeedCalculator(const MouseSpeedCalculator &) = delete; MouseSpeedCalculator &operator=(const MouseSpeedCalculator &) = delete; - std::chrono::time_point<std::chrono::steady_clock> clock_time_start = std::chrono::steady_clock::now(); - uint32_t pic_ticks_start = 0; + uint32_t ticks_start = 0; const float scaling; diff --git a/src/hardware/mouse/mouse_config.cpp b/src/hardware/mouse/mouse_config.cpp index 87efb66b2..89cd4e3da 100644 --- a/src/hardware/mouse/mouse_config.cpp +++ b/src/hardware/mouse/mouse_config.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,10 +22,13 @@ #include "checks.h" #include "control.h" +#include "math_utils.h" #include "setup.h" #include "support.h" #include "video.h" +#include <cmath> + CHECK_NARROWING(); @@ -40,7 +43,7 @@ CHECK_NARROWING(); MouseConfig mouse_config; MousePredefined mouse_predefined; -static std::vector<std::string> list_models_ps2 = { +static const std::vector<std::string> list_models_ps2 = { "standard", "intellimouse", #ifdef ENABLE_EXPLORER_MOUSE @@ -48,7 +51,7 @@ static std::vector<std::string> list_models_ps2 = { #endif }; -static std::vector<std::string> list_models_com = { +static const std::vector<std::string> list_models_com = { "2button", "3button", "wheel", @@ -58,7 +61,7 @@ static std::vector<std::string> list_models_com = { "wheel+msm", }; -static std::vector<uint16_t> list_rates = { +static const std::vector<uint16_t> list_rates = { // Commented out values are probably not interesting // for the end user as "boosted" sampling rate // 10", // PS/2 mouse @@ -148,9 +151,63 @@ static void config_read(Section *section) // Default mouse sensitivity + auto sensitivity_from_str = [](const std::string &str) { + const int32_t base_value = 50; + int32_t ret_val = base_value; // default + bool invalid_input = false; + + if (str.find('.') != std::string::npos) { + // Parameter supplied in a form of floating point + float tmp_float = 1.0f; + try { + tmp_float = std::stof(str); + } catch (...) { + invalid_input = true; + tmp_float = 1.0f; + } + // We need 'tmp_float' to be positive for further calculations + if (tmp_float < 0.0f) { + tmp_float = -tmp_float; + ret_val = -1; + } else if (tmp_float > 0.0f) + ret_val = 1; + else + ret_val = 0; + // Now calculate user steps as a logarithm + if (ret_val != 0) { + tmp_float = std::log(tmp_float) / std::log(2.0f); // log tmp_float at base 2.0f + tmp_float *= mouse_predefined.sensitivity_double_steps; + tmp_float += static_cast<float>(base_value); + const auto tmp_rounded = std::lround(std::max(tmp_float, 1.0f)); + ret_val = clamp_to_int8(ret_val * tmp_rounded); + } + } else if (!str.empty()) { + // Parameter supplied in a form of integer + try { + ret_val = std::stoi(str); + } catch (...) { + invalid_input = true; + ret_val = base_value; + } + } + + if (invalid_input) + LOG_ERR("MOUSE: Invalid sensitivity value"); + + const auto min = clamp_to_int8(-mouse_predefined.sensitivity_user_max); + const auto max = clamp_to_int8(mouse_predefined.sensitivity_user_max); + return std::clamp(clamp_to_int8(ret_val), min, max); + }; + PropMultiVal *prop_multi = conf->GetMultiVal("mouse_sensitivity"); - mouse_config.sensitivity_x = static_cast<int8_t>(prop_multi->GetSection()->Get_int("xsens")); - mouse_config.sensitivity_y = static_cast<int8_t>(prop_multi->GetSection()->Get_int("ysens")); + const std::string xsens = prop_multi->GetSection()->Get_string("xsens"); + const std::string ysens = prop_multi->GetSection()->Get_string("ysens"); + + mouse_config.sensitivity_x = sensitivity_from_str(xsens); + if (ysens.empty()) + mouse_config.sensitivity_y = mouse_config.sensitivity_x; + else + mouse_config.sensitivity_y = sensitivity_from_str(ysens); // DOS driver configuration @@ -206,23 +263,23 @@ static void config_init(Section_prop &secprop) constexpr auto only_at_start = Property::Changeable::OnlyAtStart; Prop_bool *prop_bool = nullptr; - Prop_int *prop_int = nullptr; + // XXX Prop_int *prop_int = nullptr; Prop_string *prop_str = nullptr; PropMultiVal *prop_multi = nullptr; // General configuration prop_multi = secprop.AddMultiVal("mouse_sensitivity", only_at_start, ","); - prop_multi->Set_help("Default mouse sensitivity. Works exponentially, add 10 to double the effect.\n" + prop_multi->Set_help("Default mouse sensitivity.\n" + "Integer values work exponentially, add 10 to double the effect.\n" + "Alternatively, put 1.0 for base sensitivity, 1.5 do double sensitivity, etc.\n" "Negative values reverse mouse direction, 0 disables the movement completely.\n" - "The optional second parameter specifies vertical sensitivity (e.g. 30,40).\n" + "The optional second parameter specifies vertical sensitivity (e.g. 1.5,3.0).\n" "Setting can be adjusted in runtime (also per mouse interface) using internal\n" "MOUSECTL.COM tool, available on drive Z:."); - prop_multi->SetValue("50"); - prop_int = prop_multi->GetSection()->Add_int("xsens", only_at_start, 50); - prop_int->SetMinMax(-99, 99); - prop_int = prop_multi->GetSection()->Add_int("ysens", only_at_start, 50); - prop_int->SetMinMax(-99, 99); + prop_multi->SetValue("1.0"); + prop_str = prop_multi->GetSection()->Add_string("xsens", only_at_start, "1.0"); + prop_str = prop_multi->GetSection()->Add_string("ysens", only_at_start, "1.0"); prop_bool = secprop.Add_bool("mouse_raw_input", always, true); prop_bool->Set_help("Enable to bypass your operating system's mouse acceleration and sensitivity\n" diff --git a/src/hardware/mouse/mouse_config.h b/src/hardware/mouse/mouse_config.h index 0d41cfc39..65570622c 100644 --- a/src/hardware/mouse/mouse_config.h +++ b/src/hardware/mouse/mouse_config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,7 +43,11 @@ struct MousePredefined { const float acceleration_dos = 1.0f; const float acceleration_vmm = 1.0f; + // Maximum allowe user sensitivity value const int8_t sensitivity_user_max = 99; + // How many user steps causes sensitivity to double + // (sensitivity works exponentially) + const float sensitivity_double_steps = 10.0f; }; extern MousePredefined mouse_predefined; diff --git a/src/hardware/mouse/mouse_interfaces.cpp b/src/hardware/mouse/mouse_interfaces.cpp index 067b4c6cf..1e4f4bbe3 100644 --- a/src/hardware/mouse/mouse_interfaces.cpp +++ b/src/hardware/mouse/mouse_interfaces.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -560,9 +560,6 @@ void MouseInterface::UpdateSensitivity() // 5.0 and 5.4 times sensitivity increase is rather hard to // notice in a real life - // Increase user_val by 10 steps = double the sensitivity - constexpr float double_steps = 10.0f; - float power = 0.0f; float scaling = 0.0f; @@ -575,7 +572,8 @@ void MouseInterface::UpdateSensitivity() } else // user_cal == 0 return 0.0f; - return scaling * std::pow(2.0f, power / double_steps); + power /= mouse_predefined.sensitivity_double_steps; + return scaling * std::pow(2.0f, power); }; sensitivity_coeff_x = calculate(sensitivity_user_x); diff --git a/src/hardware/mouse/mouse_interfaces.h b/src/hardware/mouse/mouse_interfaces.h index dec05244e..4eddf1bc4 100644 --- a/src/hardware/mouse/mouse_interfaces.h +++ b/src/hardware/mouse/mouse_interfaces.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/mouse/mouse_manymouse.cpp b/src/hardware/mouse/mouse_manymouse.cpp index cc71216e1..e732a700b 100644 --- a/src/hardware/mouse/mouse_manymouse.cpp +++ b/src/hardware/mouse/mouse_manymouse.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include "callback.h" #include "checks.h" +#include "math_utils.h" #include "pic.h" #include "string_utils.h" @@ -163,12 +164,16 @@ void ManyMouseGlue::Rescan() std::string name; UTF8_RenderForDos(name_utf8, name); + const char character_nbsp = 0x7f; // non-breaking space + const char character_space = 0x20; + for (auto pos = name.size(); pos > 0; pos--) { // Replace non-breaking space with a regular space - if (name[pos - 1] == 0x7f) - name[pos - 1] = 0x20; + if (name[pos - 1] == character_nbsp) + name[pos - 1] = character_space; // Remove non-ASCII and control characters - if (name[pos - 1] < 0x20 || name[pos - 1] > 0x7e) + if (name[pos - 1] < character_space || + name[pos - 1] >= character_nbsp) name.erase(pos - 1, 1); } @@ -248,7 +253,7 @@ bool ManyMouseGlue::ProbeForMapping(uint8_t &device_id) // Do not accept already mapped devices bool already_mapped = false; - for (auto &interface : mouse_interfaces) + for (const auto &interface : mouse_interfaces) if (interface->IsMapped(device_id)) already_mapped = true; if (already_mapped) @@ -282,7 +287,7 @@ uint8_t ManyMouseGlue::GetIdx(const std::regex ®ex) return static_cast<uint8_t>(i); } - return max_mice; + return max_mice; // return value which will be considered out of range } void ManyMouseGlue::Map(const uint8_t physical_idx, @@ -356,8 +361,10 @@ void ManyMouseGlue::HandleEvent(const ManyMouseEvent &event, case MANYMOUSE_EVENT_RELMOTION: // LOG_INFO("MANYMOUSE #%u RELMOTION axis %d, %d", event.device, event.item, event.value); - if (no_interface || critical_only || (event.item != 0 && event.item != 1)) - break; + if (no_interface || critical_only) + break; // movements not relevant at this moment + if (event.item != 0 && event.item != 1) + break; // only movements related to x and y axis are relevant if (rel_x.size() <= device_idx) { rel_x.resize(static_cast<size_t>(device_idx + 1), 0); @@ -365,9 +372,9 @@ void ManyMouseGlue::HandleEvent(const ManyMouseEvent &event, } if (event.item) - rel_y[event.device] += event.value; + rel_y[event.device] += event.value; // event.item 1 else - rel_x[event.device] += event.value; + rel_x[event.device] += event.value; // event.item 0 break; case MANYMOUSE_EVENT_BUTTON: @@ -386,7 +393,7 @@ void ManyMouseGlue::HandleEvent(const ManyMouseEvent &event, // LOG_INFO("MANYMOUSE #%u WHEEL #%u %d", event.device, event.item, event.value); if (no_interface || critical_only || (event.item != 0)) break; // only the 1st wheel is supported - MOUSE_EventWheel(MOUSE_ClampToInt16(-event.value), interface_id); + MOUSE_EventWheel(clamp_to_int16(-event.value), interface_id); break; case MANYMOUSE_EVENT_DISCONNECT: diff --git a/src/hardware/mouse/mouse_manymouse.h b/src/hardware/mouse/mouse_manymouse.h index d8cb9b65f..4853982c3 100644 --- a/src/hardware/mouse/mouse_manymouse.h +++ b/src/hardware/mouse/mouse_manymouse.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/mouse/mouse_queue.cpp b/src/hardware/mouse/mouse_queue.cpp index e793b41e0..095013fe4 100644 --- a/src/hardware/mouse/mouse_queue.cpp +++ b/src/hardware/mouse/mouse_queue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/mouse/mouse_queue.h b/src/hardware/mouse/mouse_queue.h index 7286b0826..7268cc4d1 100644 --- a/src/hardware/mouse/mouse_queue.h +++ b/src/hardware/mouse/mouse_queue.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/hardware/mouse/mouseif_dos_driver.cpp b/src/hardware/mouse/mouseif_dos_driver.cpp index 31ac9e361..fea52df11 100644 --- a/src/hardware/mouse/mouseif_dos_driver.cpp +++ b/src/hardware/mouse/mouseif_dos_driver.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * Copyright (C) 2002-2021 The DOSBox Team * * This program is free software; you can redistribute it and/or modify @@ -30,6 +30,7 @@ #include "checks.h" #include "cpu.h" #include "dos_inc.h" +#include "math_utils.h" #include "pic.h" #include "regs.h" @@ -104,7 +105,9 @@ static struct { // Multiply by 6.0f to compensate for 'MOUSE_GetBallisticsCoeff', which uses // 6 as intersection point (just like 2:1 scaling model from PS/2 specification) -static MouseSpeedCalculator speed_mickeys(mouse_predefined.acceleration_dos * 6.0f); +constexpr float acceleration_multiplier = 6.0f; +static MouseSpeedCalculator speed_mickeys(acceleration_multiplier * + mouse_predefined.acceleration_dos); static struct { // DOS driver state @@ -1046,7 +1049,7 @@ uint8_t MOUSEDOS_UpdateButtons(const MouseButtons12S new_buttons_12S) static uint8_t move_wheel() { - counter_w = MOUSE_ClampToInt8(static_cast<int32_t>(counter_w + pending.w_rel)); + counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + pending.w_rel)); // Pending wheel scroll is now consummed pending.w_rel = 0; @@ -1121,7 +1124,7 @@ bool MOUSEDOS_NotifyWheel(const int16_t w_rel) // wheel counter in 16-bit format, scrolling hundreds of lines in one // go would be insane - thus, limit the wheel counter to 8 bits and // reuse the code written for other mouse modules - pending.w_rel = MOUSE_ClampToInt8(pending.w_rel + w_rel); + pending.w_rel = clamp_to_int8(pending.w_rel + w_rel); if (pending.w_rel == 0) return 0; diff --git a/src/hardware/mouse/mouseif_ps2_bios.cpp b/src/hardware/mouse/mouseif_ps2_bios.cpp index 461c59b99..210ecfaf1 100644 --- a/src/hardware/mouse/mouseif_ps2_bios.cpp +++ b/src/hardware/mouse/mouseif_ps2_bios.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * Copyright (C) 2002-2021 The DOSBox Team * * This program is free software; you can redistribute it and/or modify @@ -29,6 +29,7 @@ #include "callback.h" #include "checks.h" #include "cpu.h" +#include "math_utils.h" #include "pic.h" #include "regs.h" @@ -342,7 +343,7 @@ bool MOUSEPS2_NotifyWheel(const int16_t w_rel) return false; auto old_counter_w = counter_w; - counter_w = MOUSE_ClampToInt8(static_cast<int32_t>(counter_w + w_rel)); + counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + w_rel)); return (old_counter_w != counter_w); } diff --git a/src/hardware/mouse/mouseif_virtual_machines.cpp b/src/hardware/mouse/mouseif_virtual_machines.cpp index db65f34a1..32f4a5fca 100644 --- a/src/hardware/mouse/mouseif_virtual_machines.cpp +++ b/src/hardware/mouse/mouseif_virtual_machines.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "checks.h" #include "inout.h" +#include "math_utils.h" #include "pic.h" #include "regs.h" @@ -83,7 +84,9 @@ static float pos_y = 0.0f; // Multiply scale by 0.02f to put acceleration_vmm in a reasonable // range, similar to sensitivity_dos or sensitivity_vmm) -static MouseSpeedCalculator speed_xy(0.02f * mouse_predefined.acceleration_vmm); +constexpr float acceleration_multiplier = 0.02f; +static MouseSpeedCalculator speed_xy(acceleration_multiplier * + mouse_predefined.acceleration_vmm); // *************************************************************************** // VMware interface implementation @@ -269,7 +272,7 @@ bool MOUSEVMM_NotifyWheel(const int16_t w_rel) return false; const auto old_counter_w = counter_w; - counter_w = MOUSE_ClampToInt8(static_cast<int32_t>(counter_w + w_rel)); + counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + w_rel)); if (GCC_UNLIKELY(old_counter_w == counter_w)) return false; diff --git a/src/hardware/serialport/serialmouse.cpp b/src/hardware/serialport/serialmouse.cpp index bcdaf5ecf..7063da017 100644 --- a/src/hardware/serialport/serialmouse.cpp +++ b/src/hardware/serialport/serialmouse.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * Copyright (C) 2002-2021 The DOSBox Team * * This program is free software; you can redistribute it and/or modify @@ -28,6 +28,7 @@ #include "serialmouse.h" #include "checks.h" +#include "math_utils.h" #include "../mouse/mouse_interfaces.h" @@ -209,11 +210,11 @@ void CSerialMouse::SetModel(const MouseModelCOM new_model) void CSerialMouse::AbortPacket() { - packet_len = 0; - xmit_idx = 0xff; - xmit_2part = false; - another_move = false; - another_button = false; + packet_len = 0; + xmit_idx = 0xff; + need_xmit_part2 = false; + got_another_move = false; + got_another_button = false; } void CSerialMouse::ClearCounters() @@ -244,8 +245,8 @@ void CSerialMouse::NotifyMoved(const float x_rel, const float y_rel) if (dx == 0 && dy == 0) return; // movement not significant enough - counter_x = MOUSE_ClampToInt8(counter_x + dx); - counter_y = MOUSE_ClampToInt8(counter_y + dy); + counter_x = clamp_to_int8(counter_x + dx); + counter_y = clamp_to_int8(counter_y + dy); delta_x -= dx; delta_y -= dy; @@ -257,7 +258,7 @@ void CSerialMouse::NotifyMoved(const float x_rel, const float y_rel) if (xmit_idx >= packet_len) StartPacketData(); else - another_move = true; + got_another_move = true; } void CSerialMouse::NotifyButton(const uint8_t new_buttons, const uint8_t idx) @@ -270,7 +271,7 @@ void CSerialMouse::NotifyButton(const uint8_t new_buttons, const uint8_t idx) if (xmit_idx >= packet_len) StartPacketData(idx > 1); else - another_button = true; + got_another_button = true; } void CSerialMouse::NotifyWheel(const int16_t w_rel) @@ -278,12 +279,12 @@ void CSerialMouse::NotifyWheel(const int16_t w_rel) if (!has_wheel) return; - counter_w = MOUSE_ClampToInt8(static_cast<int32_t>(counter_w + w_rel)); + counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + w_rel)); if (xmit_idx >= packet_len) StartPacketData(true); else - another_button = true; + got_another_button = true; } void CSerialMouse::StartPacketId() // send the mouse identifier @@ -358,7 +359,7 @@ void CSerialMouse::StartPacketData(const bool extended) } else { packet_len = 3; } - xmit_2part = false; + need_xmit_part2 = false; } else if (model == MouseModelCOM::MouseSystems) { // -- -- -- -- -- -- -- -- @@ -374,8 +375,8 @@ void CSerialMouse::StartPacketData(const bool extended) packet[1] = ClampCounter(counter_x); packet[2] = ClampCounter(-counter_y); packet_len = 3; - xmit_2part = true; // next part contains mouse movement since - // the start of the 1st part + need_xmit_part2 = true; // next part contains mouse movement since + // the start of the 1st part } else assert(false); // unimplemented @@ -383,9 +384,9 @@ void CSerialMouse::StartPacketData(const bool extended) ClearCounters(); // send packet - xmit_idx = 0; - another_button = false; - another_move = false; + xmit_idx = 0; + got_another_button = false; + got_another_move = false; SetEventRX(); } @@ -402,15 +403,15 @@ void CSerialMouse::StartPacketPart2() packet[1] = ClampCounter(-counter_y); packet_len = 2; - xmit_2part = false; + need_xmit_part2 = false; } else assert(false); // unimplemented ClearCounters(); // send packet - xmit_idx = 0; - another_move = false; + xmit_idx = 0; + got_another_move = false; SetEventRX(); } @@ -452,10 +453,10 @@ void CSerialMouse::handleUpperEvent(const uint16_t event_type) StartPacketId(); } else if (xmit_idx < packet_len) { CSerial::receiveByte(packet[xmit_idx++]); - if (xmit_idx >= packet_len && xmit_2part) + if (xmit_idx >= packet_len && need_xmit_part2) StartPacketPart2(); else if (xmit_idx >= packet_len && - (another_move || another_button)) + (got_another_move || got_another_button)) StartPacketData(); else SetEventRX(); diff --git a/src/hardware/serialport/serialmouse.h b/src/hardware/serialport/serialmouse.h index 1cf05eb19..8bb29beb5 100644 --- a/src/hardware/serialport/serialmouse.h +++ b/src/hardware/serialport/serialmouse.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2022-2022 The DOSBox Staging Team * Copyright (C) 2002-2021 The DOSBox Team * * This program is free software; you can redistribute it and/or modify @@ -80,14 +80,14 @@ private: bool send_ack = true; uint8_t packet[6] = {}; uint8_t packet_len = 0; - uint8_t xmit_idx = UINT8_MAX; // index of byte to send, if >= packet_len - // it means transmission ended - bool xmit_2part = false; // true = packet has a second part, which could - // not be evaluated yet - bool another_move = false; // true = while transmitting a packet we - // received mouse move event - bool another_button = false; // true = while transmitting a packet we - // received mouse button event + uint8_t xmit_idx = UINT8_MAX; // index of byte to send, if >= packet_len + // it means transmission ended + bool need_xmit_part2 = false; // true = packet has a second part, which could + // not be evaluated yet + bool got_another_move = false; // true = while transmitting a packet we + // received mouse move event + bool got_another_button = false; // true = while transmitting a packet we + // received mouse button event uint8_t buttons = 0; // bit 0 = left, bit 1 = right, bit 2 = middle float delta_x = 0.0f; // accumulated movements not yet reported float delta_y = 0.0f; |