Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dosbox-staging/dosbox-staging.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFeralChild64 <unknown>2022-10-12 13:45:03 +0300
committerkcgen <1557255+kcgen@users.noreply.github.com>2022-10-22 21:15:34 +0300
commit8dbfbf9e7a6c9ef4ad476967a2d705731457ecc6 (patch)
treeb8bb323abf850cc11fa591a0514946b52497fd1f
parentec9df4708b60715772d1322d7de42eb8e4c67459 (diff)
Handle code review remarks
-rw-r--r--include/math_utils.h27
-rw-r--r--include/mouse.h24
-rw-r--r--meson.build14
-rw-r--r--src/dos/program_mousectl.cpp79
-rw-r--r--src/dos/program_mousectl.h5
-rw-r--r--src/gui/sdlmain.cpp7
-rw-r--r--src/hardware/mouse/README.md70
-rw-r--r--src/hardware/mouse/mouse.cpp165
-rw-r--r--src/hardware/mouse/mouse_common.cpp93
-rw-r--r--src/hardware/mouse/mouse_common.h10
-rw-r--r--src/hardware/mouse/mouse_config.cpp85
-rw-r--r--src/hardware/mouse/mouse_config.h6
-rw-r--r--src/hardware/mouse/mouse_interfaces.cpp8
-rw-r--r--src/hardware/mouse/mouse_interfaces.h2
-rw-r--r--src/hardware/mouse/mouse_manymouse.cpp29
-rw-r--r--src/hardware/mouse/mouse_manymouse.h2
-rw-r--r--src/hardware/mouse/mouse_queue.cpp2
-rw-r--r--src/hardware/mouse/mouse_queue.h2
-rw-r--r--src/hardware/mouse/mouseif_dos_driver.cpp11
-rw-r--r--src/hardware/mouse/mouseif_ps2_bios.cpp5
-rw-r--r--src/hardware/mouse/mouseif_virtual_machines.cpp9
-rw-r--r--src/hardware/serialport/serialmouse.cpp47
-rw-r--r--src/hardware/serialport/serialmouse.h18
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> &params)
{
- auto add_if_is_interface = [&](const std::string &param) {
- for (const auto id : {
+ auto add_if_is_interface = [&](const std::string &param) {
+ for (const auto id : {
MouseInterfaceId::DOS,
MouseInterfaceId::PS2,
MouseInterfaceId::COM1,
@@ -129,11 +129,16 @@ bool MOUSECTL::ParseInterfaces(std::vector<std::string> &params)
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> &params)
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 &param)
{
- 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 &param)
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 &regex)
+bool MouseControlAPI::PatternToRegex(const std::string &pattern,
+ std::regex &regex)
{
// 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 &regex)
+bool MouseControlAPI::Map(const MouseInterfaceId interface_id,
+ const std::regex &regex)
{
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 &regex)
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;