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
path: root/src
diff options
context:
space:
mode:
authorFeralChild64 <unknown>2022-10-14 13:22:04 +0300
committerkcgen <1557255+kcgen@users.noreply.github.com>2022-10-22 21:15:34 +0300
commitffc06cae7a0665c08f363c4cb2c6a364fdccd640 (patch)
tree457b21b0adda1b36abe761521f9f04c42dbfcdd0 /src
parent8dbfbf9e7a6c9ef4ad476967a2d705731457ecc6 (diff)
Fix mouse code formatting
Diffstat (limited to 'src')
-rw-r--r--src/hardware/mouse/mouse.cpp754
-rw-r--r--src/hardware/mouse/mouse_common.cpp195
-rw-r--r--src/hardware/mouse/mouse_common.h156
-rw-r--r--src/hardware/mouse/mouse_config.cpp543
-rw-r--r--src/hardware/mouse/mouse_config.h98
-rw-r--r--src/hardware/mouse/mouse_interfaces.cpp813
-rw-r--r--src/hardware/mouse/mouse_interfaces.h195
-rw-r--r--src/hardware/mouse/mouse_manymouse.cpp648
-rw-r--r--src/hardware/mouse/mouse_manymouse.h104
-rw-r--r--src/hardware/mouse/mouse_queue.cpp388
-rw-r--r--src/hardware/mouse/mouse_queue.h101
-rw-r--r--src/hardware/mouse/mouseif_dos_driver.cpp2705
-rw-r--r--src/hardware/mouse/mouseif_ps2_bios.cpp600
-rw-r--r--src/hardware/mouse/mouseif_virtual_machines.cpp315
-rw-r--r--src/hardware/serialport/serialmouse.cpp812
-rw-r--r--src/hardware/serialport/serialmouse.h122
16 files changed, 4247 insertions, 4302 deletions
diff --git a/src/hardware/mouse/mouse.cpp b/src/hardware/mouse/mouse.cpp
index 4db2275aa..6db7b6e52 100644
--- a/src/hardware/mouse/mouse.cpp
+++ b/src/hardware/mouse/mouse.cpp
@@ -24,8 +24,8 @@
#include "mouse_queue.h"
#include <algorithm>
-#include <string>
#include <sstream>
+#include <string>
#include <vector>
#include "callback.h"
@@ -36,13 +36,12 @@
CHECK_NARROWING();
-
bool seamless_driver = false;
bool seamless_setting = false;
static Bitu int74_ret_callback = 0;
-static MouseQueue &queue = MouseQueue::GetInstance();
+static MouseQueue &queue = MouseQueue::GetInstance();
static ManyMouseGlue &manymouse = ManyMouseGlue::GetInstance();
// ***************************************************************************
@@ -51,82 +50,84 @@ static ManyMouseGlue &manymouse = ManyMouseGlue::GetInstance();
static Bitu int74_exit()
{
- SegSet16(cs, RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
- reg_ip = RealOff(CALLBACK_RealPointer(int74_ret_callback));
+ SegSet16(cs, RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
+ reg_ip = RealOff(CALLBACK_RealPointer(int74_ret_callback));
- return CBRET_NONE;
+ return CBRET_NONE;
}
static Bitu int74_handler()
{
- MouseEvent ev;
- queue.FetchEvent(ev);
-
- // Handle DOS events
- if (ev.request_dos) {
-
- uint8_t mask = 0;
- if (ev.dos_moved) {
- mask = MOUSEDOS_UpdateMoved();
-
- // Taken from DOSBox X: HERE within the IRQ 12 handler is the
- // appropriate place to redraw the cursor. OSes like Windows 3.1
- // expect real-mode code to do it in response to IRQ 12, not
- // "out of the blue" from the SDL event handler like the
- // original DOSBox code did it. Doing this allows the INT 33h
- // emulation to draw the cursor while not causing Windows 3.1 to
- // crash or behave erratically.
- if (mask)
- MOUSEDOS_DrawCursor();
- }
- if (ev.dos_button)
- mask = static_cast<uint8_t>(mask | MOUSEDOS_UpdateButtons(ev.dos_buttons));
- if (ev.dos_wheel)
- mask = static_cast<uint8_t>(mask | MOUSEDOS_UpdateWheel());
-
- // If DOS driver's client is not interested in this particular
- // type of event - skip it
- if (!MOUSEDOS_HasCallback(mask))
- return int74_exit();
-
- CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
- CPU_Push16(RealOff(static_cast<RealPt>(CALLBACK_RealPointer(int74_ret_callback)) + 7));
-
- return MOUSEDOS_DoCallback(mask, ev.dos_buttons);
- }
-
- // Handle PS/2 and BIOS mouse events
- if (ev.request_ps2 && mouse_shared.active_bios) {
- CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
- CPU_Push16(RealOff(CALLBACK_RealPointer(int74_ret_callback)));
-
- MOUSEPS2_UpdatePacket();
- return MOUSEBIOS_DoCallback();
- }
-
- // No mouse emulation module is interested in event
- return int74_exit();
+ MouseEvent ev;
+ queue.FetchEvent(ev);
+
+ // Handle DOS events
+ if (ev.request_dos) {
+ uint8_t mask = 0;
+ if (ev.dos_moved) {
+ mask = MOUSEDOS_UpdateMoved();
+
+ // Taken from DOSBox X: HERE within the IRQ 12 handler
+ // is the appropriate place to redraw the cursor. OSes
+ // like Windows 3.1 expect real-mode code to do it in
+ // response to IRQ 12, not "out of the blue" from the
+ // SDL event handler like the original DOSBox code did
+ // it. Doing this allows the INT 33h emulation to draw
+ // the cursor while not causing Windows 3.1 to crash or
+ // behave erratically.
+ if (mask)
+ MOUSEDOS_DrawCursor();
+ }
+ if (ev.dos_button)
+ mask = static_cast<uint8_t>(
+ mask | MOUSEDOS_UpdateButtons(ev.dos_buttons));
+ if (ev.dos_wheel)
+ mask = static_cast<uint8_t>(mask | MOUSEDOS_UpdateWheel());
+
+ // If DOS driver's client is not interested in this particular
+ // type of event - skip it
+ if (!MOUSEDOS_HasCallback(mask))
+ return int74_exit();
+
+ CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
+ CPU_Push16(RealOff(static_cast<RealPt>(CALLBACK_RealPointer(
+ int74_ret_callback)) +
+ 7));
+
+ return MOUSEDOS_DoCallback(mask, ev.dos_buttons);
+ }
+
+ // Handle PS/2 and BIOS mouse events
+ if (ev.request_ps2 && mouse_shared.active_bios) {
+ CPU_Push16(RealSeg(CALLBACK_RealPointer(int74_ret_callback)));
+ CPU_Push16(RealOff(CALLBACK_RealPointer(int74_ret_callback)));
+
+ MOUSEPS2_UpdatePacket();
+ return MOUSEBIOS_DoCallback();
+ }
+
+ // No mouse emulation module is interested in event
+ return int74_exit();
}
Bitu int74_ret_handler()
{
- queue.StartTimerIfNeeded();
- return CBRET_NONE;
+ queue.StartTimerIfNeeded();
+ return CBRET_NONE;
}
-
// ***************************************************************************
// Information for the GFX subsystem
// ***************************************************************************
bool MOUSE_IsUsingSeamlessDriver()
{
- return seamless_driver;
+ return seamless_driver;
}
bool MOUSE_IsUsingSeamlessSetting()
{
- return seamless_setting;
+ return seamless_setting;
}
// ***************************************************************************
@@ -138,444 +139,433 @@ void MOUSE_NewScreenParams(const uint16_t clip_x, const uint16_t clip_y,
const bool fullscreen, const uint16_t x_abs,
const uint16_t y_abs)
{
- mouse_video.clip_x = clip_x;
- mouse_video.clip_y = clip_y;
+ mouse_video.clip_x = clip_x;
+ mouse_video.clip_y = clip_y;
- // Protection against strange window sizes,
- // to prevent division by 0 in some places
- mouse_video.res_x = std::max(res_x, static_cast<uint16_t>(2));
- mouse_video.res_y = std::max(res_y, static_cast<uint16_t>(2));
+ // Protection against strange window sizes,
+ // to prevent division by 0 in some places
+ mouse_video.res_x = std::max(res_x, static_cast<uint16_t>(2));
+ mouse_video.res_y = std::max(res_y, static_cast<uint16_t>(2));
- mouse_video.fullscreen = fullscreen;
+ mouse_video.fullscreen = fullscreen;
- MOUSEVMM_NewScreenParams(x_abs, y_abs);
- MOUSE_NotifyStateChanged();
+ MOUSEVMM_NewScreenParams(x_abs, y_abs);
+ MOUSE_NotifyStateChanged();
}
void MOUSE_NotifyResetDOS()
{
- queue.ClearEventsDOS();
+ queue.ClearEventsDOS();
}
void MOUSE_NotifyStateChanged()
{
- const auto old_seamless_driver = seamless_driver;
- const auto old_seamless_setting = seamless_setting;
+ const auto old_seamless_driver = seamless_driver;
+ const auto old_seamless_setting = seamless_setting;
- const auto is_mapping_in_effect = manymouse.IsMappingInEffect();
+ const auto is_mapping_in_effect = manymouse.IsMappingInEffect();
- static bool already_warned = false;
- if (!already_warned && is_mapping_in_effect &&
- (mouse_shared.active_vmm || mouse_config.seamless)) {
- LOG_WARNING("MOUSE: Mapping disables seamless pointer integration");
- already_warned = true;
- }
+ static bool already_warned = false;
+ if (!already_warned && is_mapping_in_effect &&
+ (mouse_shared.active_vmm || mouse_config.seamless)) {
+ LOG_WARNING("MOUSE: Mapping disables seamless pointer integration");
+ already_warned = true;
+ }
- // Prepare suggestions to the GFX subsystem
- 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;
+ // Prepare suggestions to the GFX subsystem
+ 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 (seamless_driver != old_seamless_driver ||
- seamless_setting != old_seamless_setting)
- GFX_UpdateMouseState();
+ // If state has really changed, update GFX subsystem
+ if (seamless_driver != old_seamless_driver ||
+ seamless_setting != old_seamless_setting)
+ GFX_UpdateMouseState();
}
void MOUSE_NotifyDisconnect(const MouseInterfaceId interface_id)
{
- auto interface = MouseInterface::Get(interface_id);
- if (interface)
- interface->NotifyDisconnect();
+ auto interface = MouseInterface::Get(interface_id);
+ if (interface)
+ interface->NotifyDisconnect();
}
void MOUSE_NotifyFakePS2()
{
- const auto interface = MouseInterface::GetPS2();
+ const auto interface = MouseInterface::GetPS2();
- if (interface && interface->IsUsingEvents()) {
- MouseEvent ev;
- ev.request_ps2 = true;
- queue.AddEvent(ev);
- }
+ if (interface && interface->IsUsingEvents()) {
+ MouseEvent ev;
+ ev.request_ps2 = true;
+ queue.AddEvent(ev);
+ }
}
void MOUSE_NotifyBooting()
{
- for (auto &interface : mouse_interfaces)
- interface->NotifyBooting();
+ for (auto &interface : mouse_interfaces)
+ interface->NotifyBooting();
}
-
-void MOUSE_EventMoved(const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs)
+void MOUSE_EventMoved(const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs)
{
- // Drop unneeded events
- if (!mouse_is_captured && !seamless_driver && !seamless_setting)
- return;
+ // Drop unneeded events
+ if (!mouse_is_captured && !seamless_driver && !seamless_setting)
+ return;
- // From the GUI we are getting mouse movement data in two
- // distinct formats:
- //
- // - relative; this one has a chance to be raw movements,
- // it has to be fed to PS/2 mouse emulation, serial port
- // mouse emulation, etc.; any guest side software accessing
- // these mouse interfaces will most likely implement it's
- // own mouse acceleration/smoothing/etc.
- // - absolute; this follows host OS mouse behavior and should
- // be fed to VMware seamless mouse emulation and similar
- // interfaces
- //
- // Our DOS mouse driver (INT 33h) is a bit special, as it can
- // act both ways (seamless and non-seamless mouse pointer),
- // so it needs data in both formats.
+ // From the GUI we are getting mouse movement data in two
+ // distinct formats:
+ //
+ // - relative; this one has a chance to be raw movements,
+ // it has to be fed to PS/2 mouse emulation, serial port
+ // mouse emulation, etc.; any guest side software accessing
+ // these mouse interfaces will most likely implement it's
+ // own mouse acceleration/smoothing/etc.
+ // - absolute; this follows host OS mouse behavior and should
+ // be fed to VMware seamless mouse emulation and similar
+ // interfaces
+ //
+ // Our DOS mouse driver (INT 33h) is a bit special, as it can
+ // act both ways (seamless and non-seamless mouse pointer),
+ // so it needs data in both formats.
- // Notify mouse interfaces
+ // Notify mouse interfaces
- MouseEvent ev;
- for (auto &interface : mouse_interfaces)
- if (interface->IsUsingHostPointer())
- interface->NotifyMoved(ev, x_rel, y_rel, x_abs, y_abs);
- queue.AddEvent(ev);
+ MouseEvent ev;
+ for (auto &interface : mouse_interfaces)
+ if (interface->IsUsingHostPointer())
+ interface->NotifyMoved(ev, x_rel, y_rel, x_abs, y_abs);
+ queue.AddEvent(ev);
}
-void MOUSE_EventMoved(const float x_rel,
- const float y_rel,
+void MOUSE_EventMoved(const float x_rel, const float y_rel,
const MouseInterfaceId interface_id)
{
- auto interface = MouseInterface::Get(interface_id);
- if (interface && interface->IsUsingEvents()) {
- MouseEvent ev;
- interface->NotifyMoved(ev, x_rel, y_rel, 0, 0);
- queue.AddEvent(ev);
- }
+ auto interface = MouseInterface::Get(interface_id);
+ if (interface && interface->IsUsingEvents()) {
+ MouseEvent ev;
+ interface->NotifyMoved(ev, x_rel, y_rel, 0, 0);
+ queue.AddEvent(ev);
+ }
}
-void MOUSE_EventButton(const uint8_t idx,
- const bool pressed)
+void MOUSE_EventButton(const uint8_t idx, const bool pressed)
{
- MouseEvent ev;
- for (auto &interface : mouse_interfaces)
- if (interface->IsUsingHostPointer())
- interface->NotifyButton(ev, idx, pressed);
- queue.AddEvent(ev);
+ MouseEvent ev;
+ for (auto &interface : mouse_interfaces)
+ if (interface->IsUsingHostPointer())
+ interface->NotifyButton(ev, idx, pressed);
+ queue.AddEvent(ev);
}
-void MOUSE_EventButton(const uint8_t idx,
- const bool pressed,
+void MOUSE_EventButton(const uint8_t idx, const bool pressed,
const MouseInterfaceId interface_id)
{
- auto interface = MouseInterface::Get(interface_id);
- if (interface && interface->IsUsingEvents()) {
- MouseEvent ev;
- interface->NotifyButton(ev, idx, pressed);
- queue.AddEvent(ev);
- }
+ auto interface = MouseInterface::Get(interface_id);
+ if (interface && interface->IsUsingEvents()) {
+ MouseEvent ev;
+ interface->NotifyButton(ev, idx, pressed);
+ queue.AddEvent(ev);
+ }
}
void MOUSE_EventWheel(const int16_t w_rel)
{
- MouseEvent ev;
- for (auto &interface : mouse_interfaces)
- if (interface->IsUsingHostPointer())
- interface->NotifyWheel(ev, w_rel);
- queue.AddEvent(ev);
+ MouseEvent ev;
+ for (auto &interface : mouse_interfaces)
+ if (interface->IsUsingHostPointer())
+ interface->NotifyWheel(ev, w_rel);
+ queue.AddEvent(ev);
}
-void MOUSE_EventWheel(const int16_t w_rel,
- const MouseInterfaceId interface_id)
+void MOUSE_EventWheel(const int16_t w_rel, const MouseInterfaceId interface_id)
{
- auto interface = MouseInterface::Get(interface_id);
- if (interface && interface->IsUsingEvents()) {
- MouseEvent ev;
- interface->NotifyWheel(ev, w_rel);
- queue.AddEvent(ev);
- }
+ auto interface = MouseInterface::Get(interface_id);
+ if (interface && interface->IsUsingEvents()) {
+ MouseEvent ev;
+ interface->NotifyWheel(ev, w_rel);
+ queue.AddEvent(ev);
+ }
}
// ***************************************************************************
// MOUSECTL.COM / GUI configurator interface
// ***************************************************************************
-static std::vector<MouseInterface *> get_relevant_interfaces(const std::vector<MouseInterfaceId> &list_ids)
+static std::vector<MouseInterface *> get_relevant_interfaces(
+ const std::vector<MouseInterfaceId> &list_ids)
{
- std::vector<MouseInterface *> list_tmp = {};
+ std::vector<MouseInterface *> list_tmp = {};
- if (list_ids.empty())
- // If command does not specify interfaces,
- // assume we are interested in all of them
- list_tmp = mouse_interfaces;
- else
- for (const auto &interface_id : list_ids) {
- auto interface = MouseInterface::Get(interface_id);
- if (interface)
- list_tmp.push_back(interface);
- }
+ if (list_ids.empty())
+ // If command does not specify interfaces,
+ // assume we are interested in all of them
+ list_tmp = mouse_interfaces;
+ else
+ for (const auto &interface_id : list_ids) {
+ auto interface = MouseInterface::Get(interface_id);
+ if (interface)
+ list_tmp.push_back(interface);
+ }
- // Filter out not emulated ones
- std::vector<MouseInterface *> list_out = {};
- for (const auto &interface : list_tmp)
- if (interface->IsEmulated())
- list_out.push_back(interface);
+ // 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;
+ return list_out;
}
MouseControlAPI::MouseControlAPI()
{
- manymouse.StartConfigAPI();
+ manymouse.StartConfigAPI();
}
MouseControlAPI::~MouseControlAPI()
{
- manymouse.StopConfigAPI();
- MOUSE_NotifyStateChanged();
+ manymouse.StopConfigAPI();
+ MOUSE_NotifyStateChanged();
}
bool MouseControlAPI::IsNoMouseMode()
{
- return mouse_config.no_mouse;
+ return mouse_config.no_mouse;
}
const std::vector<MouseInterfaceInfoEntry> &MouseControlAPI::GetInfoInterfaces() const
{
- return mouse_info.interfaces;
+ return mouse_info.interfaces;
}
const std::vector<MousePhysicalInfoEntry> &MouseControlAPI::GetInfoPhysical()
{
- manymouse.RescanIfSafe();
- return mouse_info.physical;
+ manymouse.RescanIfSafe();
+ return mouse_info.physical;
}
bool MouseControlAPI::CheckInterfaces(const MouseControlAPI::ListIDs &list_ids)
{
- const auto list = get_relevant_interfaces(list_ids);
-
- if (list_ids.empty() && list.empty())
- return false; // no emulated mouse interfaces
- if (list_ids.empty())
- return true; // OK, requested all emulated interfaces
- if (list_ids.size() != list.size())
- return false; // at least one requested interface is not emulated
-
- return true;
-}
-
-bool MouseControlAPI::PatternToRegex(const std::string &pattern,
- std::regex &regex)
-{
- // Convert DOS wildcard pattern to a regular expression
- std::stringstream pattern_regex;
- pattern_regex << std::hex;
- for (const auto character : pattern) {
- if (character < 0x20 || character > 0x7E) {
- return false;
- }
- if (character == '?')
- pattern_regex << ".";
- else if (character == '*')
- pattern_regex << ".*";
- else if ((character >= '0' && character <= '9') ||
- (character >= 'a' && character <= 'z') ||
- (character >= 'A' && character <= 'Z'))
- pattern_regex << character;
- else
- pattern_regex << "\\x" << static_cast<int>(character);
- }
-
- // Return a case-insensitive regular expression
- regex = std::regex(pattern_regex.str(), std::regex_constants::icase);
- return true;
+ const auto list = get_relevant_interfaces(list_ids);
+
+ if (list_ids.empty() && list.empty())
+ return false; // no emulated mouse interfaces
+ if (list_ids.empty())
+ return true; // OK, requested all emulated interfaces
+ if (list_ids.size() != list.size())
+ return false; // at least one requested interface is not emulated
+
+ return true;
+}
+
+bool MouseControlAPI::PatternToRegex(const std::string &pattern, std::regex &regex)
+{
+ // Convert DOS wildcard pattern to a regular expression
+ std::stringstream pattern_regex;
+ pattern_regex << std::hex;
+ for (const auto character : pattern) {
+ if (character < 0x20 || character > 0x7E) {
+ return false;
+ }
+ if (character == '?')
+ pattern_regex << ".";
+ else if (character == '*')
+ pattern_regex << ".*";
+ else if ((character >= '0' && character <= '9') ||
+ (character >= 'a' && character <= 'z') ||
+ (character >= 'A' && character <= 'Z'))
+ pattern_regex << character;
+ else
+ pattern_regex << "\\x" << static_cast<int>(character);
+ }
+
+ // Return a case-insensitive regular expression
+ regex = std::regex(pattern_regex.str(), std::regex_constants::icase);
+ return true;
}
bool MouseControlAPI::ProbeForMapping(uint8_t &device_id)
{
- if (mouse_config.no_mouse)
- return false;
+ if (mouse_config.no_mouse)
+ return false;
- manymouse.RescanIfSafe();
- return manymouse.ProbeForMapping(device_id);
+ manymouse.RescanIfSafe();
+ return manymouse.ProbeForMapping(device_id);
}
-bool MouseControlAPI::Map(const MouseInterfaceId interface_id,
- const uint8_t device_idx)
+bool MouseControlAPI::Map(const MouseInterfaceId interface_id, const uint8_t device_idx)
{
- if (mouse_config.no_mouse)
- return false;
+ if (mouse_config.no_mouse)
+ return false;
- auto mouse_interface = MouseInterface::Get(interface_id);
- if (!mouse_interface)
- return false;
+ auto mouse_interface = MouseInterface::Get(interface_id);
+ if (!mouse_interface)
+ return false;
- return mouse_interface->ConfigMap(device_idx);
+ return mouse_interface->ConfigMap(device_idx);
}
-bool MouseControlAPI::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;
+ if (mouse_config.no_mouse)
+ return false;
- manymouse.RescanIfSafe();
- const auto idx = manymouse.GetIdx(regex);
- if (idx >= mouse_info.physical.size())
- return false;
+ manymouse.RescanIfSafe();
+ const auto idx = manymouse.GetIdx(regex);
+ if (idx >= mouse_info.physical.size())
+ return false;
- return Map(interface_id, idx);
+ return Map(interface_id, idx);
}
bool MouseControlAPI::UnMap(const MouseControlAPI::ListIDs &list_ids)
{
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigUnMap();
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigUnMap();
- return !list.empty();
+ return !list.empty();
}
-bool MouseControlAPI::OnOff(const MouseControlAPI::ListIDs &list_ids,
- const bool enable)
+bool MouseControlAPI::OnOff(const MouseControlAPI::ListIDs &list_ids, const bool enable)
{
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigOnOff(enable);
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigOnOff(enable);
- return !list.empty();
+ return !list.empty();
}
bool MouseControlAPI::Reset(const MouseControlAPI::ListIDs &list_ids)
{
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigReset();
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigReset();
- return !list.empty();
+ return !list.empty();
}
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 ||
- sensitivity_y > mouse_predefined.sensitivity_user_max ||
- sensitivity_y < -mouse_predefined.sensitivity_user_max)
- return false;
+ if (sensitivity_x > mouse_predefined.sensitivity_user_max ||
+ sensitivity_x < -mouse_predefined.sensitivity_user_max ||
+ sensitivity_y > mouse_predefined.sensitivity_user_max ||
+ sensitivity_y < -mouse_predefined.sensitivity_user_max)
+ return false;
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigSetSensitivity(sensitivity_x, sensitivity_y);
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigSetSensitivity(sensitivity_x, sensitivity_y);
- return !list.empty();
+ return !list.empty();
}
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;
+ if (sensitivity_x > mouse_predefined.sensitivity_user_max ||
+ sensitivity_x < -mouse_predefined.sensitivity_user_max)
+ return false;
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigSetSensitivityX(sensitivity_x);
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigSetSensitivityX(sensitivity_x);
- return !list.empty();
+ return !list.empty();
}
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;
+ if (sensitivity_y > mouse_predefined.sensitivity_user_max ||
+ sensitivity_y < -mouse_predefined.sensitivity_user_max)
+ return false;
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigSetSensitivityY(sensitivity_y);
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigSetSensitivityY(sensitivity_y);
- return !list.empty();
+ return !list.empty();
}
bool MouseControlAPI::ResetSensitivity(const MouseControlAPI::ListIDs &list_ids)
{
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigResetSensitivity();
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigResetSensitivity();
- return !list.empty();
+ return !list.empty();
}
bool MouseControlAPI::ResetSensitivityX(const MouseControlAPI::ListIDs &list_ids)
{
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigResetSensitivityX();
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigResetSensitivityX();
- return !list.empty();
+ return !list.empty();
}
bool MouseControlAPI::ResetSensitivityY(const MouseControlAPI::ListIDs &list_ids)
{
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigResetSensitivityY();
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigResetSensitivityY();
- return !list.empty();
+ return !list.empty();
}
const std::vector<uint16_t> &MouseControlAPI::GetValidMinRateList()
{
- return MouseConfig::GetValidMinRateList();
+ return MouseConfig::GetValidMinRateList();
}
const std::string &MouseControlAPI::GetValidMinRateStr()
{
- static std::string out_str = "";
+ static std::string out_str = "";
- if (out_str.empty()) {
- const auto &valid_list = GetValidMinRateList();
+ if (out_str.empty()) {
+ const auto &valid_list = GetValidMinRateList();
- bool first = true;
- for (const auto &rate : valid_list) {
- if (first)
- first = false;
- else
- out_str += std::string(", ");
- out_str += std::to_string(rate);
- }
- }
+ bool first = true;
+ for (const auto &rate : valid_list) {
+ if (first)
+ first = false;
+ else
+ out_str += std::string(", ");
+ out_str += std::to_string(rate);
+ }
+ }
- return out_str;
+ return out_str;
}
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
+ const auto &valid_list = GetValidMinRateList();
+ if (std::find(valid_list.begin(), valid_list.end(), value_hz) ==
+ valid_list.end())
+ return false; // invalid value
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigSetMinRate(value_hz);
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigSetMinRate(value_hz);
- return !list.empty();
+ return !list.empty();
}
bool MouseControlAPI::ResetMinRate(const MouseControlAPI::ListIDs &list_ids)
{
- auto list = get_relevant_interfaces(list_ids);
- for (auto &interface : list)
- interface->ConfigResetMinRate();
+ auto list = get_relevant_interfaces(list_ids);
+ for (auto &interface : list)
+ interface->ConfigResetMinRate();
- return !list.empty();
+ return !list.empty();
}
// ***************************************************************************
@@ -584,81 +574,79 @@ bool MouseControlAPI::ResetMinRate(const MouseControlAPI::ListIDs &list_ids)
void MOUSE_SetConfigSeamless(const bool seamless)
{
- // Called during SDL initialization
- mouse_config.seamless = seamless;
- MOUSE_NotifyStateChanged();
+ // Called during SDL initialization
+ mouse_config.seamless = seamless;
+ MOUSE_NotifyStateChanged();
- // Just in case it is also called later
- for (auto &interface : mouse_interfaces)
- interface->UpdateConfig();
+ // Just in case it is also called later
+ for (auto &interface : mouse_interfaces)
+ interface->UpdateConfig();
- // Start mouse emulation if ready
- mouse_shared.ready_config_sdl = true;
- MOUSE_Startup();
+ // Start mouse emulation if ready
+ mouse_shared.ready_config_sdl = true;
+ MOUSE_Startup();
}
void MOUSE_SetConfigNoMouse()
{
- // NOTE: if it is decided to not allow enabling/disabling
- // this during runtime, add button click releases for all
- // the mouse buttons
- mouse_config.no_mouse = true;
+ // NOTE: if it is decided to not allow enabling/disabling
+ // this during runtime, add button click releases for all
+ // the mouse buttons
+ mouse_config.no_mouse = true;
- // Start mouse emulation if ready
- mouse_shared.ready_config_sdl = true;
- MOUSE_Startup();
+ // Start mouse emulation if ready
+ mouse_shared.ready_config_sdl = true;
+ MOUSE_Startup();
}
void MOUSE_Startup()
{
- if (mouse_shared.started ||
- !mouse_shared.ready_startup_sequence ||
- !mouse_shared.ready_config_mouse ||
- !mouse_shared.ready_config_sdl)
- return;
-
- // Callback for ps2 irq
- auto call_int74 = CALLBACK_Allocate();
- CALLBACK_Setup(call_int74, &int74_handler, CB_IRQ12, "int 74");
- // pseudocode for CB_IRQ12:
- // sti
- // push ds
- // push es
- // pushad
- // callback int74_handler
- // ps2 or user callback if requested
- // otherwise jumps to CB_IRQ12_RET
- // push ax
- // mov al, 0x20
- // out 0xa0, al
- // out 0x20, al
- // pop ax
- // cld
- // retf
-
- int74_ret_callback = CALLBACK_Allocate();
- CALLBACK_Setup(int74_ret_callback, &int74_ret_handler, CB_IRQ12_RET, "int 74 ret");
- // pseudocode for CB_IRQ12_RET:
- // cli
- // mov al, 0x20
- // out 0xa0, al
- // out 0x20, al
- // callback int74_ret_handler
- // popad
- // pop es
- // pop ds
- // iret
-
- // (MOUSE_IRQ > 7) ? (0x70 + MOUSE_IRQ - 8) : (0x8 + MOUSE_IRQ);
- RealSetVec(0x74, CALLBACK_RealPointer(call_int74));
-
- MouseInterface::InitAllInstances();
- mouse_shared.started = true;
+ if (mouse_shared.started || !mouse_shared.ready_startup_sequence ||
+ !mouse_shared.ready_config_mouse || !mouse_shared.ready_config_sdl)
+ return;
+
+ // Callback for ps2 irq
+ auto call_int74 = CALLBACK_Allocate();
+ CALLBACK_Setup(call_int74, &int74_handler, CB_IRQ12, "int 74");
+ // pseudocode for CB_IRQ12:
+ // sti
+ // push ds
+ // push es
+ // pushad
+ // callback int74_handler
+ // ps2 or user callback if requested
+ // otherwise jumps to CB_IRQ12_RET
+ // push ax
+ // mov al, 0x20
+ // out 0xa0, al
+ // out 0x20, al
+ // pop ax
+ // cld
+ // retf
+
+ int74_ret_callback = CALLBACK_Allocate();
+ CALLBACK_Setup(int74_ret_callback, &int74_ret_handler, CB_IRQ12_RET, "int 74 ret");
+ // pseudocode for CB_IRQ12_RET:
+ // cli
+ // mov al, 0x20
+ // out 0xa0, al
+ // out 0x20, al
+ // callback int74_ret_handler
+ // popad
+ // pop es
+ // pop ds
+ // iret
+
+ // (MOUSE_IRQ > 7) ? (0x70 + MOUSE_IRQ - 8) : (0x8 + MOUSE_IRQ);
+ RealSetVec(0x74, CALLBACK_RealPointer(call_int74));
+
+ MouseInterface::InitAllInstances();
+ mouse_shared.started = true;
}
void MOUSE_Init(Section * /*sec*/)
{
- // Start mouse emulation if ready
- mouse_shared.ready_startup_sequence = true;
- MOUSE_Startup();
+ // Start mouse emulation if ready
+ mouse_shared.ready_startup_sequence = true;
+ MOUSE_Startup();
}
diff --git a/src/hardware/mouse/mouse_common.cpp b/src/hardware/mouse/mouse_common.cpp
index fb1350dad..cad02c5e7 100644
--- a/src/hardware/mouse/mouse_common.cpp
+++ b/src/hardware/mouse/mouse_common.cpp
@@ -29,9 +29,9 @@ CHECK_NARROWING();
// Common variables
// ***************************************************************************
-MouseInfo mouse_info;
+MouseInfo mouse_info;
MouseShared mouse_shared;
-MouseVideo mouse_video;
+MouseVideo mouse_video;
// ***************************************************************************
// Common helper calculations
@@ -39,119 +39,120 @@ MouseVideo mouse_video;
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 scaling specification, desribed
- // for exampel here:
- // - https://wiki.osdev.org/Mouse_Input
-
- // Input: mouse speed
- // Output: acceleration coefficient (1.0f for speed >= 6.0f)
-
- // NOTE: If we don't have raw mouse input, stay with flat profile;
- // in such case the acceleration is already handled by the host OS,
- // adding our own could lead to hard to predict (most likely
- // undesirable) effects
-
- constexpr float a = 0.017153417f;
- constexpr float b = 0.382477002f;
- constexpr float lowest = 0.5f;
-
- // Normal PS/2 mouse 2:1 scaling algorithm is just a substitution:
- // 0 => 0, 1 => 1, 2 => 1, 3 => 3, 4 => 6, 5 => 9, other x => x * 2
- // and the same for negatives. But we want smooth cursor movement,
- // therefore we use approximation model (least square regression,
- // 3rd degree polynomial, on points -6, -5, ..., 0, ... , 5, 6,
- // here scaled to give f(6.0) = 6.0). Polynomial would be:
- //
- // f(x) = a*(x^3) + b*(x^1) = x*(a*(x^2) + b)
- //
- // This C++ function provides not the full polynomial, but rather
- // a coefficient (0.0f ... 1.0f) calculated from supplied speed,
- // by which the relative mouse measurement should be multiplied
-
- if (speed > -6.0f && speed < 6.0f)
- return std::max((a * speed * speed + b), lowest);
- else
- return 1.0f;
-
- // Please consider this algorithm as yet another nod to the past,
- // one more small touch of 20th century PC computing history :)
+ // 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 scaling specification, desribed
+ // for exampel here:
+ // - https://wiki.osdev.org/Mouse_Input
+
+ // Input: mouse speed
+ // Output: acceleration coefficient (1.0f for speed >= 6.0f)
+
+ // NOTE: If we don't have raw mouse input, stay with flat profile;
+ // in such case the acceleration is already handled by the host OS,
+ // adding our own could lead to hard to predict (most likely
+ // undesirable) effects
+
+ constexpr float a = 0.017153417f;
+ constexpr float b = 0.382477002f;
+ constexpr float lowest = 0.5f;
+
+ // Normal PS/2 mouse 2:1 scaling algorithm is just a substitution:
+ // 0 => 0, 1 => 1, 2 => 1, 3 => 3, 4 => 6, 5 => 9, other x => x * 2
+ // and the same for negatives. But we want smooth cursor movement,
+ // therefore we use approximation model (least square regression,
+ // 3rd degree polynomial, on points -6, -5, ..., 0, ... , 5, 6,
+ // here scaled to give f(6.0) = 6.0). Polynomial would be:
+ //
+ // f(x) = a*(x^3) + b*(x^1) = x*(a*(x^2) + b)
+ //
+ // This C++ function provides not the full polynomial, but rather
+ // a coefficient (0.0f ... 1.0f) calculated from supplied speed,
+ // by which the relative mouse measurement should be multiplied
+
+ if (speed > -6.0f && speed < 6.0f)
+ return std::max((a * speed * speed + b), lowest);
+ else
+ return 1.0f;
+
+ // Please consider this algorithm as yet another nod to the past,
+ // one more small touch of 20th century PC computing history :)
}
uint8_t MOUSE_GetDelayFromRateHz(const uint16_t rate_hz)
{
- assert(rate_hz);
- const auto tmp = std::lround(1000.0f / MOUSE_ClampRateHz(rate_hz));
- return static_cast<uint8_t>(tmp);
+ assert(rate_hz);
+ const auto tmp = std::lround(1000.0f / MOUSE_ClampRateHz(rate_hz));
+ return static_cast<uint8_t>(tmp);
}
float MOUSE_ClampRelativeMovement(const float rel)
{
- // Enforce sane upper limit of relative mouse movement
- return std::clamp(rel, -2048.0f, 2048.0f);
+ // Enforce sane upper limit of relative mouse movement
+ return std::clamp(rel, -2048.0f, 2048.0f);
}
uint16_t MOUSE_ClampRateHz(const uint16_t rate_hz)
{
- constexpr uint16_t rate_min = 10;
- constexpr uint16_t rate_max = 500;
+ constexpr uint16_t rate_min = 10;
+ constexpr uint16_t rate_max = 500;
- return std::clamp(rate_hz, rate_min, rate_max);
+ return std::clamp(rate_hz, rate_min, rate_max);
}
// ***************************************************************************
// Mouse speed calculation
// ***************************************************************************
-MouseSpeedCalculator::MouseSpeedCalculator(const float scaling) :
- ticks_start(PIC_Ticks),
- scaling(scaling * 1000.0f) // to convert from units/ms to units/s
-{
-}
+MouseSpeedCalculator::MouseSpeedCalculator(const float scaling)
+ : ticks_start(PIC_Ticks),
+ scaling(scaling * 1000.0f) // to convert from units/ms to units/s
+{}
float MouseSpeedCalculator::Get() const
{
- return speed;
+ return speed;
}
void MouseSpeedCalculator::Update(const float delta)
{
- // 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 (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;
- ticks_start = PIC_Ticks;
+ // 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 (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;
+ ticks_start = PIC_Ticks;
}
// ***************************************************************************
@@ -160,24 +161,24 @@ void MouseSpeedCalculator::Update(const float delta)
MouseButtons12 &MouseButtons12::operator=(const MouseButtons12 &other)
{
- data = other.data;
- return *this;
+ data = other.data;
+ return *this;
}
MouseButtons345 &MouseButtons345::operator=(const MouseButtons345 &other)
{
- data = other.data;
- return *this;
+ data = other.data;
+ return *this;
}
MouseButtonsAll &MouseButtonsAll::operator=(const MouseButtonsAll &other)
{
- data = other.data;
- return *this;
+ data = other.data;
+ return *this;
}
MouseButtons12S &MouseButtons12S::operator=(const MouseButtons12S &other)
{
- data = other.data;
- return *this;
+ data = other.data;
+ return *this;
}
diff --git a/src/hardware/mouse/mouse_common.h b/src/hardware/mouse/mouse_common.h
index ff9a7e0bb..a44779c84 100644
--- a/src/hardware/mouse/mouse_common.h
+++ b/src/hardware/mouse/mouse_common.h
@@ -29,44 +29,43 @@
class MouseShared {
public:
- bool active_bios = false; // true = BIOS has a registered callback
- bool active_dos = false; // true = DOS driver has a functioning callback
- bool active_vmm = false; // true = VMware-compatible driver is active
+ bool active_bios = false; // true = BIOS has a registered callback
+ bool active_dos = false; // true = DOS driver has a functioning callback
+ bool active_vmm = false; // true = VMware-compatible driver is active
- bool dos_cb_running = false; // true = DOS callback is running
+ bool dos_cb_running = false; // true = DOS callback is running
- // Readiness for initialization
- bool ready_startup_sequence = false;
- bool ready_config_mouse = false;
- bool ready_config_sdl = false;
+ // Readiness for initialization
+ bool ready_startup_sequence = false;
+ bool ready_config_mouse = false;
+ bool ready_config_sdl = false;
- bool started = false;
+ bool started = false;
};
class MouseVideo {
public:
- bool fullscreen = true;
+ bool fullscreen = true;
- uint16_t res_x = 640; // resolution to which guest image is scaled,
- uint16_t res_y = 400; // excluding black borders
+ uint16_t res_x = 640; // resolution to which guest image is scaled,
+ uint16_t res_y = 400; // excluding black borders
- uint16_t clip_x = 0; // clipping = size of black border (one side)
- uint16_t clip_y = 0;
+ uint16_t clip_x = 0; // clipping = size of black border (one side)
+ uint16_t clip_y = 0;
};
class MouseInfo {
public:
- std::vector<MouseInterfaceInfoEntry> interfaces = {};
- std::vector<MousePhysicalInfoEntry> physical = {};
+ std::vector<MouseInterfaceInfoEntry> interfaces = {};
+ std::vector<MousePhysicalInfoEntry> physical = {};
};
-extern MouseInfo mouse_info; // information which can be shared externally
+extern MouseInfo mouse_info; // information which can be shared externally
extern MouseShared mouse_shared; // shared internal information
-extern MouseVideo mouse_video; // video information - resolution, clipping, etc.
+extern MouseVideo mouse_video; // video information - resolution, clipping, etc.
extern bool mouse_is_captured;
-
// ***************************************************************************
// Common helper calculations
// ***************************************************************************
@@ -83,24 +82,22 @@ uint16_t MOUSE_ClampRateHz(const uint16_t rate_hz);
class MouseSpeedCalculator final {
public:
+ MouseSpeedCalculator(const float scaling);
- MouseSpeedCalculator(const float scaling);
-
- float Get() const;
- void Update(const float delta);
+ float Get() const;
+ void Update(const float delta);
private:
+ MouseSpeedCalculator() = delete;
+ MouseSpeedCalculator(const MouseSpeedCalculator &) = delete;
+ MouseSpeedCalculator &operator=(const MouseSpeedCalculator &) = delete;
- MouseSpeedCalculator() = delete;
- MouseSpeedCalculator(const MouseSpeedCalculator &) = delete;
- MouseSpeedCalculator &operator=(const MouseSpeedCalculator &) = delete;
+ uint32_t ticks_start = 0;
- uint32_t ticks_start = 0;
+ const float scaling;
- const float scaling;
-
- float distance = 0.0f;
- float speed = 0.0f;
+ float distance = 0.0f;
+ float speed = 0.0f;
};
// ***************************************************************************
@@ -111,61 +108,61 @@ private:
// (DOS driver) functions 0x03 / 0x05 / 0x06 and it's callback interface
union MouseButtons12 {
- // For storing left and right buttons only
- uint8_t data = 0;
+ // For storing left and right buttons only
+ uint8_t data = 0;
- bit_view<0, 1> left;
- bit_view<1, 1> right;
+ bit_view<0, 1> left;
+ bit_view<1, 1> right;
- MouseButtons12() : data(0) {}
- MouseButtons12(const uint8_t data) : data(data) {}
- MouseButtons12(const MouseButtons12 &other) : data(other.data) {}
- MouseButtons12 &operator=(const MouseButtons12 &other);
+ MouseButtons12() : data(0) {}
+ MouseButtons12(const uint8_t data) : data(data) {}
+ MouseButtons12(const MouseButtons12 &other) : data(other.data) {}
+ MouseButtons12 &operator=(const MouseButtons12 &other);
};
union MouseButtons345 {
- // For storing middle and extra buttons
- uint8_t data = 0;
+ // For storing middle and extra buttons
+ uint8_t data = 0;
- bit_view<2, 1> middle;
- bit_view<3, 1> extra_1;
- bit_view<4, 1> extra_2;
+ bit_view<2, 1> middle;
+ bit_view<3, 1> extra_1;
+ bit_view<4, 1> extra_2;
- MouseButtons345() : data(0) {}
- MouseButtons345(const uint8_t data) : data(data) {}
- MouseButtons345(const MouseButtons345 &other) : data(other.data) {}
- MouseButtons345 &operator=(const MouseButtons345 &other);
+ MouseButtons345() : data(0) {}
+ MouseButtons345(const uint8_t data) : data(data) {}
+ MouseButtons345(const MouseButtons345 &other) : data(other.data) {}
+ MouseButtons345 &operator=(const MouseButtons345 &other);
};
union MouseButtonsAll {
- // For storing all 5 mouse buttons
- uint8_t data = 0;
-
- bit_view<0, 1> left;
- bit_view<1, 1> right;
- bit_view<2, 1> middle;
- bit_view<3, 1> extra_1;
- bit_view<4, 1> extra_2;
-
- MouseButtonsAll() : data(0) {}
- MouseButtonsAll(const uint8_t data) : data(data) {}
- MouseButtonsAll(const MouseButtonsAll &other) : data(other.data) {}
- MouseButtonsAll &operator=(const MouseButtonsAll &other);
+ // For storing all 5 mouse buttons
+ uint8_t data = 0;
+
+ bit_view<0, 1> left;
+ bit_view<1, 1> right;
+ bit_view<2, 1> middle;
+ bit_view<3, 1> extra_1;
+ bit_view<4, 1> extra_2;
+
+ MouseButtonsAll() : data(0) {}
+ MouseButtonsAll(const uint8_t data) : data(data) {}
+ MouseButtonsAll(const MouseButtonsAll &other) : data(other.data) {}
+ MouseButtonsAll &operator=(const MouseButtonsAll &other);
};
union MouseButtons12S {
- // To be used where buttons 3/4/5 are squished
- // into a virtual middle button
- uint8_t data = 0;
-
- bit_view<0, 1> left;
- bit_view<1, 1> right;
- bit_view<2, 1> middle;
-
- MouseButtons12S() : data(0) {}
- MouseButtons12S(const uint8_t data) : data(data) {}
- MouseButtons12S(const MouseButtons12S &other) : data(other.data) {}
- MouseButtons12S &operator=(const MouseButtons12S &other);
+ // To be used where buttons 3/4/5 are squished
+ // into a virtual middle button
+ uint8_t data = 0;
+
+ bit_view<0, 1> left;
+ bit_view<1, 1> right;
+ bit_view<2, 1> middle;
+
+ MouseButtons12S() : data(0) {}
+ MouseButtons12S(const uint8_t data) : data(data) {}
+ MouseButtons12S(const MouseButtons12S &other) : data(other.data) {}
+ MouseButtons12S &operator=(const MouseButtons12S &other);
};
// ***************************************************************************
@@ -173,15 +170,14 @@ union MouseButtons12S {
// ***************************************************************************
struct MouseEvent {
- bool request_dos = false; // if DOS mouse driver needs an event
- bool request_ps2 = false; // if PS/2 mouse emulation needs an event
+ bool request_dos = false; // if DOS mouse driver needs an event
+ bool request_ps2 = false; // if PS/2 mouse emulation needs an event
- bool dos_moved = false;
- bool dos_button = false;
- bool dos_wheel = false;
+ bool dos_moved = false;
+ bool dos_button = false;
+ bool dos_wheel = false;
- MouseButtons12S dos_buttons = 0;
+ MouseButtons12S dos_buttons = 0;
};
-
#endif // DOSBOX_MOUSE_COMMON_H
diff --git a/src/hardware/mouse/mouse_config.cpp b/src/hardware/mouse/mouse_config.cpp
index 89cd4e3da..6f147beee 100644
--- a/src/hardware/mouse/mouse_config.cpp
+++ b/src/hardware/mouse/mouse_config.cpp
@@ -16,8 +16,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "mouse_common.h"
#include "mouse_config.h"
+#include "mouse_common.h"
#include "mouse_interfaces.h"
#include "checks.h"
@@ -31,7 +31,6 @@
CHECK_NARROWING();
-
// TODO - IntelliMouse Explorer emulation is currently deactivated - there is
// probably no way to test it. The IntelliMouse 3.0 software can use it, but
// it seems to require physical PS/2 mouse registers to work correctly,
@@ -39,307 +38,313 @@ CHECK_NARROWING();
// #define ENABLE_EXPLORER_MOUSE
-
-MouseConfig mouse_config;
+MouseConfig mouse_config;
MousePredefined mouse_predefined;
static const std::vector<std::string> list_models_ps2 = {
- "standard",
- "intellimouse",
+ "standard",
+ "intellimouse",
#ifdef ENABLE_EXPLORER_MOUSE
- "explorer",
+ "explorer",
#endif
};
static const std::vector<std::string> list_models_com = {
- "2button",
- "3button",
- "wheel",
- "msm",
- "2button+msm",
- "3button+msm",
- "wheel+msm",
+ "2button",
+ "3button",
+ "wheel",
+ "msm",
+ "2button+msm",
+ "3button+msm",
+ "wheel+msm",
};
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
-// 20", // PS/2 mouse
-// 30", // bus/InPort mouse
- 40, // PS/2 mouse, approx. limit for 1200 baud serial mouse
-// 50, // bus/InPort mouse
- 60, // PS/2 mouse, used by Microsoft Mouse Driver 8.20
- 80, // PS/2 mouse, approx. limit for 2400 baud serial mouse
- 100, // PS/2 mouse, bus/InPort mouse, used by CuteMouse 2.1b4
- 125, // USB mouse (basic, non-gaming), Bluetooth mouse
- 160, // approx. limit for 4800 baud serial mouse
- 200, // PS/2 mouse, bus/InPort mouse
- 250, // USB mouse (gaming)
- 330, // approx. limit for 9600 baud serial mouse
- 500, // USB mouse (gaming)
-
-// Todays gaming USB mice are capable of even higher sampling
-// rates (like 1000 Hz), but such values are way higher than
-// anything DOS games were designed for; most likely such rates
-// would only result in emulation slowdowns and compatibility
-// issues.
+ // Commented out values are probably not interesting
+ // for the end user as "boosted" sampling rate
+ // 10", // PS/2 mouse
+ // 20", // PS/2 mouse
+ // 30", // bus/InPort mouse
+ 40, // PS/2 mouse, approx. limit for 1200 baud serial mouse
+ // 50, // bus/InPort mouse
+ 60, // PS/2 mouse, used by Microsoft Mouse Driver 8.20
+ 80, // PS/2 mouse, approx. limit for 2400 baud serial mouse
+ 100, // PS/2 mouse, bus/InPort mouse, used by CuteMouse 2.1b4
+ 125, // USB mouse (basic, non-gaming), Bluetooth mouse
+ 160, // approx. limit for 4800 baud serial mouse
+ 200, // PS/2 mouse, bus/InPort mouse
+ 250, // USB mouse (gaming)
+ 330, // approx. limit for 9600 baud serial mouse
+ 500, // USB mouse (gaming)
+
+ // Todays gaming USB mice are capable of even higher sampling
+ // rates (like 1000 Hz), but such values are way higher than
+ // anything DOS games were designed for; most likely such rates
+ // would only result in emulation slowdowns and compatibility
+ // issues.
};
bool MouseConfig::ParseSerialModel(const std::string &model_str,
- MouseModelCOM &model,
- bool &auto_msm)
+ MouseModelCOM &model, bool &auto_msm)
{
- if (model_str == list_models_com[0]) {
- model = MouseModelCOM::Microsoft;
- auto_msm = false;
- return true;
- } else if (model_str == list_models_com[1]) {
- model = MouseModelCOM::Logitech;
- auto_msm = false;
- return true;
- } else if (model_str == list_models_com[2]) {
- model = MouseModelCOM::Wheel;
- auto_msm = false;
- return true;
- } else if (model_str == list_models_com[3]) {
- model = MouseModelCOM::MouseSystems;
- auto_msm = false;
- return true;
- } else if (model_str == list_models_com[4]) {
- model = MouseModelCOM::Microsoft;
- auto_msm = true;
- return true;
- } else if (model_str == list_models_com[5]) {
- model = MouseModelCOM::Logitech;
- auto_msm = true;
- return true;
- } else if (model_str == list_models_com[6]) {
- model = MouseModelCOM::Wheel;
- auto_msm = true;
- return true;
- }
-
- return false;
+ if (model_str == list_models_com[0]) {
+ model = MouseModelCOM::Microsoft;
+ auto_msm = false;
+ return true;
+ } else if (model_str == list_models_com[1]) {
+ model = MouseModelCOM::Logitech;
+ auto_msm = false;
+ return true;
+ } else if (model_str == list_models_com[2]) {
+ model = MouseModelCOM::Wheel;
+ auto_msm = false;
+ return true;
+ } else if (model_str == list_models_com[3]) {
+ model = MouseModelCOM::MouseSystems;
+ auto_msm = false;
+ return true;
+ } else if (model_str == list_models_com[4]) {
+ model = MouseModelCOM::Microsoft;
+ auto_msm = true;
+ return true;
+ } else if (model_str == list_models_com[5]) {
+ model = MouseModelCOM::Logitech;
+ auto_msm = true;
+ return true;
+ } else if (model_str == list_models_com[6]) {
+ model = MouseModelCOM::Wheel;
+ auto_msm = true;
+ return true;
+ }
+
+ return false;
}
const std::vector<uint16_t> &MouseConfig::GetValidMinRateList()
{
- return list_rates;
+ return list_rates;
}
static void config_read(Section *section)
{
- assert(section);
- const Section_prop *conf = dynamic_cast<Section_prop *>(section);
- assert(conf);
- if (!conf)
- return;
-
- // Settings changeable during runtime
-
- mouse_config.dos_immediate = conf->Get_bool("dos_mouse_immediate");
- mouse_config.raw_input = conf->Get_bool("mouse_raw_input");
- GFX_SetMouseRawInput(mouse_config.raw_input);
-
- // Settings below should be read only once
-
- if (mouse_shared.ready_config_mouse) {
- MOUSE_NotifyStateChanged();
- return;
- }
-
- // 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");
- 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
-
- mouse_config.dos_driver = conf->Get_bool("dos_mouse_driver");
-
- // PS/2 AUX port mouse configuration
-
- std::string prop_str = conf->Get_string("ps2_mouse_model");
- if (prop_str == list_models_ps2[0])
- mouse_config.model_ps2 = MouseModelPS2::Standard;
- if (prop_str == list_models_ps2[1])
- mouse_config.model_ps2 = MouseModelPS2::IntelliMouse;
+ assert(section);
+ const Section_prop *conf = dynamic_cast<Section_prop *>(section);
+ assert(conf);
+ if (!conf)
+ return;
+
+ // Settings changeable during runtime
+
+ mouse_config.dos_immediate = conf->Get_bool("dos_mouse_immediate");
+ mouse_config.raw_input = conf->Get_bool("mouse_raw_input");
+ GFX_SetMouseRawInput(mouse_config.raw_input);
+
+ // Settings below should be read only once
+
+ if (mouse_shared.ready_config_mouse) {
+ MOUSE_NotifyStateChanged();
+ return;
+ }
+
+ // 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);
+ 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");
+ 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
+
+ mouse_config.dos_driver = conf->Get_bool("dos_mouse_driver");
+
+ // PS/2 AUX port mouse configuration
+
+ std::string prop_str = conf->Get_string("ps2_mouse_model");
+ if (prop_str == list_models_ps2[0])
+ mouse_config.model_ps2 = MouseModelPS2::Standard;
+ if (prop_str == list_models_ps2[1])
+ mouse_config.model_ps2 = MouseModelPS2::IntelliMouse;
#ifdef ENABLE_EXPLORER_MOUSE
- if (prop_str == list_models_ps2[2])
- mouse_config.model_ps2 = MouseModelPS2::Explorer;
+ if (prop_str == list_models_ps2[2])
+ mouse_config.model_ps2 = MouseModelPS2::Explorer;
#endif
- // Serial (COM port) mice configuration
-
- auto set_model_com = [](const std::string &model_str,
- MouseModelCOM& model_var,
- bool &model_auto) {
- if (model_str == list_models_com[0] || model_str == list_models_com[4])
- model_var = MouseModelCOM::Microsoft;
- if (model_str == list_models_com[1] || model_str == list_models_com[5])
- model_var = MouseModelCOM::Logitech;
- if (model_str == list_models_com[2] || model_str == list_models_com[6])
- model_var = MouseModelCOM::Wheel;
- if (model_str == list_models_com[3])
- model_var = MouseModelCOM::MouseSystems;
-
- if (model_str == list_models_com[4] ||
- model_str == list_models_com[5] ||
- model_str == list_models_com[6])
- model_auto = true;
- else
- model_auto = false;
- };
-
- prop_str = conf->Get_string("com_mouse_model");
- set_model_com(prop_str,
- mouse_config.model_com,
- mouse_config.model_com_auto_msm);
-
- // Start mouse emulation if ready
- mouse_shared.ready_config_mouse = true;
- MOUSE_Startup();
+ // Serial (COM port) mice configuration
+
+ auto set_model_com = [](const std::string &model_str,
+ MouseModelCOM &model_var,
+ bool &model_auto) {
+ if (model_str == list_models_com[0] ||
+ model_str == list_models_com[4])
+ model_var = MouseModelCOM::Microsoft;
+ if (model_str == list_models_com[1] ||
+ model_str == list_models_com[5])
+ model_var = MouseModelCOM::Logitech;
+ if (model_str == list_models_com[2] ||
+ model_str == list_models_com[6])
+ model_var = MouseModelCOM::Wheel;
+ if (model_str == list_models_com[3])
+ model_var = MouseModelCOM::MouseSystems;
+
+ if (model_str == list_models_com[4] ||
+ model_str == list_models_com[5] ||
+ model_str == list_models_com[6])
+ model_auto = true;
+ else
+ model_auto = false;
+ };
+
+ prop_str = conf->Get_string("com_mouse_model");
+ set_model_com(prop_str, mouse_config.model_com, mouse_config.model_com_auto_msm);
+
+ // Start mouse emulation if ready
+ mouse_shared.ready_config_mouse = true;
+ MOUSE_Startup();
}
static void config_init(Section_prop &secprop)
{
- constexpr auto always = Property::Changeable::Always;
- constexpr auto only_at_start = Property::Changeable::OnlyAtStart;
-
- Prop_bool *prop_bool = 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.\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. 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("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"
- "settings. Works in fullscreen or when the mouse is captured in window mode.");
-
- // DOS driver configuration
-
- prop_bool = secprop.Add_bool("dos_mouse_driver", only_at_start, true);
- assert(prop_bool);
- prop_bool->Set_help("Enable built-in DOS mouse driver.\n"
- "Notes:\n"
- " Disable if you intend to use original MOUSE.COM driver in emulated DOS.\n"
- " When guest OS is booted, built-in driver gets disabled automatically.");
-
- prop_bool = secprop.Add_bool("dos_mouse_immediate", always, false);
- assert(prop_bool);
- prop_bool->Set_help("Updates mouse movement counters immediately, without waiting for interrupt.\n"
- "May improve gameplay, especially in fast paced games (arcade, FPS, etc.) - as\n"
- "for some games it effectively boosts the mouse sampling rate to 1000 Hz, without\n"
- "increasing interrupt overhead.\n"
- "Might cause compatibility issues. List of known incompatible games:\n"
- " - Ultima Underworld: The Stygian Abyss\n"
- " - Ultima Underworld II: Labyrinth of Worlds\n"
- "Please file a bug with the project if you find another game that fails when\n"
- "this is enabled, we will update this list.");
-
- // Physical mice configuration
-
- prop_str = secprop.Add_string("ps2_mouse_model", only_at_start, "intellimouse");
- assert(prop_str);
- prop_str->Set_values(list_models_ps2);
- prop_str->Set_help("PS/2 AUX port mouse model:\n"
- // TODO - Add option "none"
- " standard: 3 buttons, standard PS/2 mouse.\n"
- " intellimouse: 3 buttons + wheel, Microsoft IntelliMouse.\n"
+ constexpr auto always = Property::Changeable::Always;
+ constexpr auto only_at_start = Property::Changeable::OnlyAtStart;
+
+ Prop_bool *prop_bool = 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.\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. 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("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"
+ "settings. Works in fullscreen or when the mouse is captured in window mode.");
+
+ // DOS driver configuration
+
+ prop_bool = secprop.Add_bool("dos_mouse_driver", only_at_start, true);
+ assert(prop_bool);
+ prop_bool->Set_help(
+ "Enable built-in DOS mouse driver.\n"
+ "Notes:\n"
+ " Disable if you intend to use original MOUSE.COM driver in emulated DOS.\n"
+ " When guest OS is booted, built-in driver gets disabled automatically.");
+
+ prop_bool = secprop.Add_bool("dos_mouse_immediate", always, false);
+ assert(prop_bool);
+ prop_bool->Set_help(
+ "Updates mouse movement counters immediately, without waiting for interrupt.\n"
+ "May improve gameplay, especially in fast paced games (arcade, FPS, etc.) - as\n"
+ "for some games it effectively boosts the mouse sampling rate to 1000 Hz, without\n"
+ "increasing interrupt overhead.\n"
+ "Might cause compatibility issues. List of known incompatible games:\n"
+ " - Ultima Underworld: The Stygian Abyss\n"
+ " - Ultima Underworld II: Labyrinth of Worlds\n"
+ "Please file a bug with the project if you find another game that fails when\n"
+ "this is enabled, we will update this list.");
+
+ // Physical mice configuration
+
+ prop_str = secprop.Add_string("ps2_mouse_model", only_at_start, "intellimouse");
+ assert(prop_str);
+ prop_str->Set_values(list_models_ps2);
+ prop_str->Set_help(
+ "PS/2 AUX port mouse model:\n"
+ // TODO - Add option "none"
+ " standard: 3 buttons, standard PS/2 mouse.\n"
+ " intellimouse: 3 buttons + wheel, Microsoft IntelliMouse.\n"
#ifdef ENABLE_EXPLORER_MOUSE
- " explorer: 5 buttons + wheel, Microsoft IntelliMouse Explorer.\n"
+ " explorer: 5 buttons + wheel, Microsoft IntelliMouse Explorer.\n"
#endif
- "Default: intellimouse");
-
- prop_str = secprop.Add_string("com_mouse_model", only_at_start, "wheel+msm");
- assert(prop_str);
- prop_str->Set_values(list_models_com);
- prop_str->Set_help("COM (serial) port default mouse model:\n"
- " 2button: 2 buttons, Microsoft mouse.\n"
- " 3button: 3 buttons, Logitech mouse, mostly compatible with Microsoft mouse.\n"
- " wheel: 3 buttons + wheel, mostly compatible with Microsoft mouse.\n"
- " msm: 3 buttons, Mouse Systems mouse, NOT COMPATIBLE with Microsoft mouse.\n"
- " 2button+msm: Automatic choice between 2button and msm.\n"
- " 3button+msm: Automatic choice between 3button and msm.\n"
- " wheel+msm: Automatic choice between wheel and msm.\n"
- "Default: wheel+msm\n"
- "Notes:\n"
- " Go to [serial] section to enable/disable COM port mice.");
+ "Default: intellimouse");
+
+ prop_str = secprop.Add_string("com_mouse_model", only_at_start, "wheel+msm");
+ assert(prop_str);
+ prop_str->Set_values(list_models_com);
+ prop_str->Set_help(
+ "COM (serial) port default mouse model:\n"
+ " 2button: 2 buttons, Microsoft mouse.\n"
+ " 3button: 3 buttons, Logitech mouse, mostly compatible with Microsoft mouse.\n"
+ " wheel: 3 buttons + wheel, mostly compatible with Microsoft mouse.\n"
+ " msm: 3 buttons, Mouse Systems mouse, NOT COMPATIBLE with Microsoft mouse.\n"
+ " 2button+msm: Automatic choice between 2button and msm.\n"
+ " 3button+msm: Automatic choice between 3button and msm.\n"
+ " wheel+msm: Automatic choice between wheel and msm.\n"
+ "Default: wheel+msm\n"
+ "Notes:\n"
+ " Go to [serial] section to enable/disable COM port mice.");
}
void MOUSE_AddConfigSection(const config_ptr_t &conf)
{
- assert(conf);
- Section_prop *sec = conf->AddSection_prop("mouse", &config_read, true);
- assert(sec);
- config_init(*sec);
+ assert(conf);
+ Section_prop *sec = conf->AddSection_prop("mouse", &config_read, true);
+ assert(sec);
+ config_init(*sec);
}
diff --git a/src/hardware/mouse/mouse_config.h b/src/hardware/mouse/mouse_config.h
index 65570622c..35ca040b0 100644
--- a/src/hardware/mouse/mouse_config.h
+++ b/src/hardware/mouse/mouse_config.h
@@ -23,89 +23,87 @@
#include "mouse.h"
-
// ***************************************************************************
// Predefined calibration
// ***************************************************************************
struct MousePredefined {
- // Mouse equalization for consistent user experience - please adjust
- // values so that on full screen, with RAW mouse input, the mouse feel
- // is similar to Windows 3.11 for Workgroups with PS/2 mouse driver
- // and default settings
- const float sensitivity_dos = 0.6f;
- const float sensitivity_ps2 = 0.6f;
- const float sensitivity_vmm = 1.8f;
- const float sensitivity_com = 0.6f;
- // Constants to move 'intersection point' for the acceleration curve
- // Requires raw mouse input, otherwise there is no effect
- // Larger values = higher mouse acceleration
- 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;
+ // Mouse equalization for consistent user experience - please adjust
+ // values so that on full screen, with RAW mouse input, the mouse feel
+ // is similar to Windows 3.11 for Workgroups with PS/2 mouse driver
+ // and default settings
+ const float sensitivity_dos = 0.6f;
+ const float sensitivity_ps2 = 0.6f;
+ const float sensitivity_vmm = 1.8f;
+ const float sensitivity_com = 0.6f;
+ // Constants to move 'intersection point' for the acceleration curve
+ // Requires raw mouse input, otherwise there is no effect
+ // Larger values = higher mouse acceleration
+ 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;
-
// ***************************************************************************
// Configuration file content
// ***************************************************************************
enum class MouseModelPS2 : uint8_t {
- // Values must match PS/2 protocol IDs
- Standard = 0x00,
- IntelliMouse = 0x03,
- Explorer = 0x04,
+ // Values must match PS/2 protocol IDs
+ Standard = 0x00,
+ IntelliMouse = 0x03,
+ Explorer = 0x04,
};
enum class MouseModelCOM : uint8_t {
- NoMouse, // dummy value or no mouse
- Microsoft,
- Logitech,
- Wheel,
- MouseSystems
+ NoMouse, // dummy value or no mouse
+ Microsoft,
+ Logitech,
+ Wheel,
+ MouseSystems
};
enum class MouseModelBus : uint8_t {
- NoMouse,
- Bus,
- InPort,
+ NoMouse,
+ Bus,
+ InPort,
};
struct MouseConfig {
+ // From [sdl] section
- // From [sdl] section
+ bool no_mouse = false; // true = NoMouse selected in GUI
+ bool seamless = false; // true = seamless mouse integration
- bool no_mouse = false; // true = NoMouse selected in GUI
- bool seamless = false; // true = seamless mouse integration
+ // From [mouse] section
- // From [mouse] section
+ int8_t sensitivity_x = 50; // default sensitivity values
+ int8_t sensitivity_y = 50;
+ bool raw_input = false; // true = relative input is raw data
- int8_t sensitivity_x = 50; // default sensitivity values
- int8_t sensitivity_y = 50;
- bool raw_input = false; // true = relative input is raw data
+ bool dos_driver = false; // whether DOS virtual mouse driver should be
+ // enabled
+ bool dos_immediate = false;
- bool dos_driver = false; // whether DOS virtual mouse driver should be enabled
- bool dos_immediate = false;
+ MouseModelPS2 model_ps2 = MouseModelPS2::Standard;
- MouseModelPS2 model_ps2 = MouseModelPS2::Standard;
+ MouseModelCOM model_com = MouseModelCOM::Wheel;
+ bool model_com_auto_msm = true;
- MouseModelCOM model_com = MouseModelCOM::Wheel;
- bool model_com_auto_msm = true;
+ // Helper functions for external modules
- // Helper functions for external modules
-
- static const std::vector<uint16_t> &GetValidMinRateList();
- static bool ParseSerialModel(const std::string &model_str, MouseModelCOM &model, bool &auto_msm);
+ static const std::vector<uint16_t> &GetValidMinRateList();
+ static bool ParseSerialModel(const std::string &model_str,
+ MouseModelCOM &model, bool &auto_msm);
};
extern MouseConfig mouse_config;
-
#endif // DOSBOX_MOUSE_CONFIG_H
diff --git a/src/hardware/mouse/mouse_interfaces.cpp b/src/hardware/mouse/mouse_interfaces.cpp
index 1e4f4bbe3..379e2554b 100644
--- a/src/hardware/mouse/mouse_interfaces.cpp
+++ b/src/hardware/mouse/mouse_interfaces.cpp
@@ -16,10 +16,10 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include "mouse_interfaces.h"
#include "mouse.h"
#include "mouse_common.h"
#include "mouse_config.h"
-#include "mouse_interfaces.h"
#include "mouse_manymouse.h"
#include "mouse_queue.h"
@@ -27,223 +27,193 @@
CHECK_NARROWING();
-
std::vector<MouseInterface *> mouse_interfaces = {};
-
// ***************************************************************************
// Mouse interface information facade
// ***************************************************************************
-MouseInterfaceInfoEntry::MouseInterfaceInfoEntry(const MouseInterfaceId interface_id) :
- idx(static_cast<uint8_t>(interface_id))
-{
-}
+MouseInterfaceInfoEntry::MouseInterfaceInfoEntry(const MouseInterfaceId interface_id)
+ : idx(static_cast<uint8_t>(interface_id))
+{}
const MouseInterface &MouseInterfaceInfoEntry::Interface() const
{
- return *mouse_interfaces[idx];
+ return *mouse_interfaces[idx];
}
const MousePhysical &MouseInterfaceInfoEntry::MappedPhysical() const
{
- const auto idx = Interface().GetMappedDeviceIdx();
- return ManyMouseGlue::GetInstance().physical_devices[idx];
+ const auto idx = Interface().GetMappedDeviceIdx();
+ return ManyMouseGlue::GetInstance().physical_devices[idx];
}
bool MouseInterfaceInfoEntry::IsEmulated() const
{
- return Interface().IsEmulated();
+ return Interface().IsEmulated();
}
bool MouseInterfaceInfoEntry::IsMapped() const
{
- return Interface().IsMapped();
+ return Interface().IsMapped();
}
bool MouseInterfaceInfoEntry::IsMapped(const uint8_t device_idx) const
{
- return Interface().IsMapped(device_idx);
+ return Interface().IsMapped(device_idx);
}
bool MouseInterfaceInfoEntry::IsMappedDeviceDisconnected() const
{
- if (!IsMapped())
- return false;
+ if (!IsMapped())
+ return false;
- return MappedPhysical().IsDisconnected();
+ return MappedPhysical().IsDisconnected();
}
MouseInterfaceId MouseInterfaceInfoEntry::GetInterfaceId() const
{
- return Interface().GetInterfaceId();
+ return Interface().GetInterfaceId();
}
MouseMapStatus MouseInterfaceInfoEntry::GetMapStatus() const
{
- return Interface().GetMapStatus();
+ return Interface().GetMapStatus();
}
const std::string &MouseInterfaceInfoEntry::GetMappedDeviceName() const
{
- static const std::string empty = "";
- if (!IsMapped())
- return empty;
+ static const std::string empty = "";
+ if (!IsMapped())
+ return empty;
- return MappedPhysical().GetName();
+ return MappedPhysical().GetName();
}
int8_t MouseInterfaceInfoEntry::GetSensitivityX() const
{
- return Interface().GetSensitivityX();
+ return Interface().GetSensitivityX();
}
int8_t MouseInterfaceInfoEntry::GetSensitivityY() const
{
- return Interface().GetSensitivityY();
+ return Interface().GetSensitivityY();
}
uint16_t MouseInterfaceInfoEntry::GetMinRate() const
{
- return Interface().GetMinRate();
+ return Interface().GetMinRate();
}
uint16_t MouseInterfaceInfoEntry::GetRate() const
{
- return Interface().GetRate();
+ return Interface().GetRate();
}
// ***************************************************************************
// Physical mouse information facade
// ***************************************************************************
-MousePhysicalInfoEntry::MousePhysicalInfoEntry(const uint8_t idx) :
- idx(idx)
-{
-}
+MousePhysicalInfoEntry::MousePhysicalInfoEntry(const uint8_t idx) : idx(idx) {}
const MousePhysical &MousePhysicalInfoEntry::Physical() const
{
- return ManyMouseGlue::GetInstance().physical_devices[idx];
+ return ManyMouseGlue::GetInstance().physical_devices[idx];
}
bool MousePhysicalInfoEntry::IsMapped() const
{
- return Physical().IsMapped();
+ return Physical().IsMapped();
}
bool MousePhysicalInfoEntry::IsDeviceDisconnected() const
{
- return Physical().IsDisconnected();
+ return Physical().IsDisconnected();
}
const std::string &MousePhysicalInfoEntry::GetDeviceName() const
{
- return Physical().GetName();
+ return Physical().GetName();
}
// ***************************************************************************
// Concrete interfaces - declarations
// ***************************************************************************
-class InterfaceDos final : public MouseInterface
-{
+class InterfaceDos final : public MouseInterface {
public:
+ void NotifyMoved(MouseEvent &ev, const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs) override;
+ void NotifyButton(MouseEvent &ev, const uint8_t idx,
+ const bool pressed) override;
+ void NotifyWheel(MouseEvent &ev, const int16_t w_rel) override;
- void NotifyMoved(MouseEvent &ev,
- const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs) override;
- void NotifyButton(MouseEvent &ev,
- const uint8_t idx,
- const bool pressed) override;
- void NotifyWheel(MouseEvent &ev,
- const int16_t w_rel) override;
-
- void NotifyBooting() override;
+ void NotifyBooting() override;
private:
+ friend class MouseInterface;
- friend class MouseInterface;
-
- InterfaceDos();
- ~InterfaceDos() = default;
- InterfaceDos(const InterfaceDos &) = delete;
- InterfaceDos &operator=(const InterfaceDos &) = delete;
+ InterfaceDos();
+ ~InterfaceDos() = default;
+ InterfaceDos(const InterfaceDos &) = delete;
+ InterfaceDos &operator=(const InterfaceDos &) = delete;
- void Init() override;
+ void Init() override;
- void UpdateRawMapped() override;
- void UpdateMinRate() override;
- void UpdateRate() override;
+ void UpdateRawMapped() override;
+ void UpdateMinRate() override;
+ void UpdateRate() override;
};
-class InterfacePS2 final : public MouseInterface
-{
+class InterfacePS2 final : public MouseInterface {
public:
-
- void NotifyMoved(MouseEvent &ev,
- const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs) override;
- void NotifyButton(MouseEvent &ev,
- const uint8_t idx,
- const bool pressed) override;
- void NotifyWheel(MouseEvent &ev,
- const int16_t w_rel) override;
+ void NotifyMoved(MouseEvent &ev, const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs) override;
+ void NotifyButton(MouseEvent &ev, const uint8_t idx,
+ const bool pressed) override;
+ void NotifyWheel(MouseEvent &ev, const int16_t w_rel) override;
private:
+ friend class MouseInterface;
- friend class MouseInterface;
-
- InterfacePS2();
- ~InterfacePS2() = default;
- InterfacePS2(const InterfacePS2 &other) = delete;
- InterfacePS2 &operator=(const InterfacePS2 &other) = delete;
+ InterfacePS2();
+ ~InterfacePS2() = default;
+ InterfacePS2(const InterfacePS2 &other) = delete;
+ InterfacePS2 &operator=(const InterfacePS2 &other) = delete;
- void Init() override;
+ void Init() override;
- void UpdateRawMapped() override;
- void UpdateSensitivity() override;
- void UpdateRate() override;
+ void UpdateRawMapped() override;
+ void UpdateSensitivity() override;
+ void UpdateRate() override;
- float sensitivity_coeff_vmm_x = 1.0f; // cached sensitivity coefficient
- float sensitivity_coeff_vmm_y = 1.0f;
+ float sensitivity_coeff_vmm_x = 1.0f; // cached sensitivity coefficient
+ float sensitivity_coeff_vmm_y = 1.0f;
};
-class InterfaceCOM final : public MouseInterface
-{
+class InterfaceCOM final : public MouseInterface {
public:
+ void NotifyMoved(MouseEvent &ev, const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs) override;
+ void NotifyButton(MouseEvent &ev, const uint8_t idx,
+ const bool pressed) override;
+ void NotifyWheel(MouseEvent &ev, const int16_t w_rel) override;
- void NotifyMoved(MouseEvent &ev,
- const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs) override;
- void NotifyButton(MouseEvent &ev,
- const uint8_t idx,
- const bool pressed) override;
- void NotifyWheel(MouseEvent &ev,
- const int16_t w_rel) override;
+ void UpdateRate() override;
- void UpdateRate() override;
-
- void RegisterListener(CSerialMouse &listener_object) override;
- void UnRegisterListener() override;
+ void RegisterListener(CSerialMouse &listener_object) override;
+ void UnRegisterListener() override;
private:
+ friend class MouseInterface;
- friend class MouseInterface;
-
- InterfaceCOM(const uint8_t port_id);
- InterfaceCOM() = delete;
- ~InterfaceCOM() = default;
- InterfaceCOM(const InterfaceCOM &) = delete;
- InterfaceCOM &operator=(const InterfaceCOM &) = delete;
+ InterfaceCOM(const uint8_t port_id);
+ InterfaceCOM() = delete;
+ ~InterfaceCOM() = default;
+ InterfaceCOM(const InterfaceCOM &) = delete;
+ InterfaceCOM &operator=(const InterfaceCOM &) = delete;
- CSerialMouse *listener = nullptr;
+ CSerialMouse *listener = nullptr;
};
// ***************************************************************************
@@ -252,636 +222,605 @@ private:
void MouseInterface::InitAllInstances()
{
- if (!mouse_interfaces.empty())
- return; // already initialized
-
- const auto i_first = static_cast<uint8_t>(MouseInterfaceId::First);
- const auto i_last = static_cast<uint8_t>(MouseInterfaceId::Last);
- const auto i_com1 = static_cast<uint8_t>(MouseInterfaceId::COM1);
-
- for (uint8_t i = i_first; i <= i_last; i++)
- switch (static_cast<MouseInterfaceId>(i)) {
- case MouseInterfaceId::DOS:
- mouse_interfaces.emplace_back(new InterfaceDos());
- break;
- case MouseInterfaceId::PS2:
- mouse_interfaces.emplace_back(new InterfacePS2());
- break;
- case MouseInterfaceId::COM1:
- case MouseInterfaceId::COM2:
- case MouseInterfaceId::COM3:
- case MouseInterfaceId::COM4:
- mouse_interfaces.emplace_back(new InterfaceCOM(static_cast<uint8_t>(i - i_com1)));
- break;
- default:
- assert(false);
- break;
- }
-
- for (auto interface : mouse_interfaces)
- interface->Init();
+ if (!mouse_interfaces.empty())
+ return; // already initialized
+
+ const auto i_first = static_cast<uint8_t>(MouseInterfaceId::First);
+ const auto i_last = static_cast<uint8_t>(MouseInterfaceId::Last);
+ const auto i_com1 = static_cast<uint8_t>(MouseInterfaceId::COM1);
+
+ for (uint8_t i = i_first; i <= i_last; i++)
+ switch (static_cast<MouseInterfaceId>(i)) {
+ case MouseInterfaceId::DOS:
+ mouse_interfaces.emplace_back(new InterfaceDos());
+ break;
+ case MouseInterfaceId::PS2:
+ mouse_interfaces.emplace_back(new InterfacePS2());
+ break;
+ case MouseInterfaceId::COM1:
+ case MouseInterfaceId::COM2:
+ case MouseInterfaceId::COM3:
+ case MouseInterfaceId::COM4:
+ mouse_interfaces.emplace_back(new InterfaceCOM(
+ static_cast<uint8_t>(i - i_com1)));
+ break;
+ default: assert(false); break;
+ }
+
+ for (auto interface : mouse_interfaces)
+ interface->Init();
}
MouseInterface *MouseInterface::Get(const MouseInterfaceId interface_id)
{
- const auto idx = static_cast<size_t>(interface_id);
- if (idx < mouse_interfaces.size())
- return mouse_interfaces[idx];
+ const auto idx = static_cast<size_t>(interface_id);
+ if (idx < mouse_interfaces.size())
+ return mouse_interfaces[idx];
- assert(interface_id == MouseInterfaceId::None);
- return nullptr;
+ assert(interface_id == MouseInterfaceId::None);
+ return nullptr;
}
MouseInterface *MouseInterface::GetDOS()
{
- const auto idx = static_cast<uint8_t>(MouseInterfaceId::DOS);
- return MouseInterface::Get(static_cast<MouseInterfaceId>(idx));
+ const auto idx = static_cast<uint8_t>(MouseInterfaceId::DOS);
+ return MouseInterface::Get(static_cast<MouseInterfaceId>(idx));
}
MouseInterface *MouseInterface::GetPS2()
{
- const auto idx = static_cast<uint8_t>(MouseInterfaceId::PS2);
- return MouseInterface::Get(static_cast<MouseInterfaceId>(idx));
+ const auto idx = static_cast<uint8_t>(MouseInterfaceId::PS2);
+ return MouseInterface::Get(static_cast<MouseInterfaceId>(idx));
}
MouseInterface *MouseInterface::GetSerial(const uint8_t port_id)
{
- if (port_id < SERIAL_MAX_PORTS) {
- const auto idx = static_cast<uint8_t>(MouseInterfaceId::COM1) + port_id;
- return MouseInterface::Get(static_cast<MouseInterfaceId>(idx));
- }
+ if (port_id < SERIAL_MAX_PORTS) {
+ const auto idx = static_cast<uint8_t>(MouseInterfaceId::COM1) + port_id;
+ return MouseInterface::Get(static_cast<MouseInterfaceId>(idx));
+ }
- LOG_ERR("MOUSE: Ports above COM4 not supported");
- assert(false);
- return nullptr;
+ LOG_ERR("MOUSE: Ports above COM4 not supported");
+ assert(false);
+ return nullptr;
}
MouseInterface::MouseInterface(const MouseInterfaceId interface_id,
- const float sensitivity_predefined) :
- interface_id(interface_id),
- sensitivity_predefined(sensitivity_predefined)
+ const float sensitivity_predefined)
+ : interface_id(interface_id),
+ sensitivity_predefined(sensitivity_predefined)
{
- ConfigResetSensitivity();
- mouse_info.interfaces.emplace_back(MouseInterfaceInfoEntry(interface_id));
+ ConfigResetSensitivity();
+ mouse_info.interfaces.emplace_back(MouseInterfaceInfoEntry(interface_id));
}
-void MouseInterface::Init()
-{
-}
+void MouseInterface::Init() {}
uint8_t MouseInterface::GetInterfaceIdx() const
{
- return static_cast<uint8_t>(interface_id);
+ return static_cast<uint8_t>(interface_id);
}
bool MouseInterface::IsMapped() const
{
- return mapped_idx < mouse_info.physical.size();
+ return mapped_idx < mouse_info.physical.size();
}
bool MouseInterface::IsMapped(const uint8_t device_idx) const
{
- return mapped_idx == device_idx;
+ return mapped_idx == device_idx;
}
bool MouseInterface::IsEmulated() const
{
- return emulated;
+ return emulated;
}
bool MouseInterface::IsUsingEvents() const
{
- return IsEmulated() &&
- (map_status == MouseMapStatus::HostPointer ||
- map_status == MouseMapStatus::Mapped);
+ return IsEmulated() && (map_status == MouseMapStatus::HostPointer ||
+ map_status == MouseMapStatus::Mapped);
}
bool MouseInterface::IsUsingHostPointer() const
{
- return IsEmulated() && (map_status == MouseMapStatus::HostPointer);
+ return IsEmulated() && (map_status == MouseMapStatus::HostPointer);
}
uint16_t MouseInterface::GetMinRate() const
{
- return min_rate_hz;
+ return min_rate_hz;
}
MouseInterfaceId MouseInterface::GetInterfaceId() const
{
- return interface_id;
+ return interface_id;
}
MouseMapStatus MouseInterface::GetMapStatus() const
{
- return map_status;
+ return map_status;
}
uint8_t MouseInterface::GetMappedDeviceIdx() const
{
- return mapped_idx;
+ return mapped_idx;
}
int8_t MouseInterface::GetSensitivityX() const
{
- return sensitivity_user_x;
+ return sensitivity_user_x;
}
int8_t MouseInterface::GetSensitivityY() const
{
- return sensitivity_user_y;
+ return sensitivity_user_y;
}
uint16_t MouseInterface::GetRate() const
{
- return rate_hz;
+ return rate_hz;
}
void MouseInterface::NotifyInterfaceRate(const uint16_t value_hz)
{
- interface_rate_hz = value_hz;
- UpdateRate();
+ interface_rate_hz = value_hz;
+ UpdateRate();
}
-void MouseInterface::NotifyBooting()
-{
-}
+void MouseInterface::NotifyBooting() {}
void MouseInterface::NotifyDisconnect()
{
- SetMapStatus(MouseMapStatus::Disconnected, mapped_idx);
+ SetMapStatus(MouseMapStatus::Disconnected, mapped_idx);
}
-void MouseInterface::SetMapStatus(const MouseMapStatus status,
- const uint8_t device_idx)
+void MouseInterface::SetMapStatus(const MouseMapStatus status, const uint8_t device_idx)
{
- MouseMapStatus new_map_status = status;
- uint8_t new_mapped_idx = device_idx;
+ MouseMapStatus new_map_status = status;
+ uint8_t new_mapped_idx = device_idx;
- // Change 'mapped to host pointer' to just 'host pointer'
- if (new_map_status == MouseMapStatus::Mapped &&
- new_mapped_idx >= mouse_info.physical.size())
- new_map_status = MouseMapStatus::HostPointer;
+ // Change 'mapped to host pointer' to just 'host pointer'
+ if (new_map_status == MouseMapStatus::Mapped &&
+ new_mapped_idx >= mouse_info.physical.size())
+ new_map_status = MouseMapStatus::HostPointer;
- // if physical device is disconnected, change state from
- // 'mapped' to 'disconnected'
- if (new_map_status == MouseMapStatus::Mapped &&
- mouse_info.physical[new_mapped_idx].IsDeviceDisconnected())
- new_map_status = MouseMapStatus::Disconnected;
+ // if physical device is disconnected, change state from
+ // 'mapped' to 'disconnected'
+ if (new_map_status == MouseMapStatus::Mapped &&
+ mouse_info.physical[new_mapped_idx].IsDeviceDisconnected())
+ new_map_status = MouseMapStatus::Disconnected;
- // Perform necessary updates for mapping change
- if (map_status != new_map_status || mapped_idx != new_mapped_idx)
- ResetButtons();
- if (map_status != new_map_status)
- UpdateRawMapped();
- if (mapped_idx != new_mapped_idx)
- ManyMouseGlue::GetInstance().Map(new_mapped_idx, interface_id);
+ // Perform necessary updates for mapping change
+ if (map_status != new_map_status || mapped_idx != new_mapped_idx)
+ ResetButtons();
+ if (map_status != new_map_status)
+ UpdateRawMapped();
+ if (mapped_idx != new_mapped_idx)
+ ManyMouseGlue::GetInstance().Map(new_mapped_idx, interface_id);
- // Apply new mapping
- mapped_idx = new_mapped_idx;
- map_status = new_map_status;
+ // Apply new mapping
+ mapped_idx = new_mapped_idx;
+ map_status = new_map_status;
}
bool MouseInterface::ConfigMap(const uint8_t device_idx)
{
- if (!IsEmulated())
- return false;
+ if (!IsEmulated())
+ return false;
- SetMapStatus(MouseMapStatus::Mapped, device_idx);
- return true;
+ SetMapStatus(MouseMapStatus::Mapped, device_idx);
+ return true;
}
void MouseInterface::ConfigUnMap()
{
- SetMapStatus(MouseMapStatus::Mapped, idx_host_pointer);
+ SetMapStatus(MouseMapStatus::Mapped, idx_host_pointer);
}
void MouseInterface::ConfigOnOff(const bool enable)
{
- if (!IsEmulated())
- return;
+ if (!IsEmulated())
+ return;
- if (!enable)
- SetMapStatus(MouseMapStatus::Disabled);
- else if (map_status == MouseMapStatus::Disabled)
- SetMapStatus(MouseMapStatus::HostPointer);
+ if (!enable)
+ SetMapStatus(MouseMapStatus::Disabled);
+ else if (map_status == MouseMapStatus::Disabled)
+ SetMapStatus(MouseMapStatus::HostPointer);
}
void MouseInterface::ConfigReset()
{
- ConfigUnMap();
- ConfigOnOff(true);
- ConfigResetSensitivity();
- ConfigResetMinRate();
+ ConfigUnMap();
+ ConfigOnOff(true);
+ ConfigResetSensitivity();
+ ConfigResetMinRate();
}
-void MouseInterface::ConfigSetSensitivity(const int8_t value_x,
- const int8_t value_y)
+void MouseInterface::ConfigSetSensitivity(const int8_t value_x, const int8_t value_y)
{
- if (!IsEmulated())
- return;
+ if (!IsEmulated())
+ return;
- sensitivity_user_x = value_x;
- sensitivity_user_y = value_y;
- UpdateSensitivity();
+ sensitivity_user_x = value_x;
+ sensitivity_user_y = value_y;
+ UpdateSensitivity();
}
void MouseInterface::ConfigSetSensitivityX(const int8_t value)
{
- if (!IsEmulated())
- return;
+ if (!IsEmulated())
+ return;
- sensitivity_user_x = value;
- UpdateSensitivity();
+ sensitivity_user_x = value;
+ UpdateSensitivity();
}
void MouseInterface::ConfigSetSensitivityY(const int8_t value)
{
- if (!IsEmulated())
- return;
+ if (!IsEmulated())
+ return;
- sensitivity_user_y = value;
- UpdateSensitivity();
+ sensitivity_user_y = value;
+ UpdateSensitivity();
}
void MouseInterface::ConfigResetSensitivity()
{
- ConfigSetSensitivity(mouse_config.sensitivity_x,
- mouse_config.sensitivity_y);
+ ConfigSetSensitivity(mouse_config.sensitivity_x, mouse_config.sensitivity_y);
}
void MouseInterface::ConfigResetSensitivityX()
{
- ConfigSetSensitivityX(mouse_config.sensitivity_x);
+ ConfigSetSensitivityX(mouse_config.sensitivity_x);
}
void MouseInterface::ConfigResetSensitivityY()
{
- ConfigSetSensitivityY(mouse_config.sensitivity_y);
+ ConfigSetSensitivityY(mouse_config.sensitivity_y);
}
void MouseInterface::ConfigSetMinRate(const uint16_t value_hz)
{
- min_rate_hz = value_hz;
- UpdateMinRate();
+ min_rate_hz = value_hz;
+ UpdateMinRate();
}
void MouseInterface::ConfigResetMinRate()
{
- ConfigSetMinRate(0);
+ ConfigSetMinRate(0);
}
void MouseInterface::RegisterListener(CSerialMouse &)
{
- assert(false); // should never be called for unsupported interface
+ assert(false); // should never be called for unsupported interface
}
void MouseInterface::UnRegisterListener()
{
- assert(false); // should never be called for unsupported interface
+ assert(false); // should never be called for unsupported interface
}
void MouseInterface::UpdateConfig()
{
- UpdateRawMapped();
- UpdateSensitivity();
+ UpdateRawMapped();
+ UpdateSensitivity();
}
-void MouseInterface::UpdateRawMapped()
-{
-}
+void MouseInterface::UpdateRawMapped() {}
void MouseInterface::UpdateSensitivity()
{
- auto calculate = [this](const int8_t user_val)
- {
- // Mouse sensitivity formula is exponential - as it is probably
- // reasonable to expect user wanting to increase sensitivity
- // 1.5 times, but not 1.9 times - while the difference between
- // 5.0 and 5.4 times sensitivity increase is rather hard to
- // notice in a real life
+ auto calculate = [this](const int8_t user_val) {
+ // Mouse sensitivity formula is exponential - as it is probably
+ // reasonable to expect user wanting to increase sensitivity
+ // 1.5 times, but not 1.9 times - while the difference between
+ // 5.0 and 5.4 times sensitivity increase is rather hard to
+ // notice in a real life
- float power = 0.0f;
- float scaling = 0.0f;
+ float power = 0.0f;
+ float scaling = 0.0f;
- if (user_val > 0) {
- power = static_cast<float>(user_val - 50);
- scaling = sensitivity_predefined;
- } else if (user_val < 0) {
- power = static_cast<float>(-user_val - 50);
- scaling = -sensitivity_predefined;
- } else // user_cal == 0
- return 0.0f;
+ if (user_val > 0) {
+ power = static_cast<float>(user_val - 50);
+ scaling = sensitivity_predefined;
+ } else if (user_val < 0) {
+ power = static_cast<float>(-user_val - 50);
+ scaling = -sensitivity_predefined;
+ } else // user_cal == 0
+ return 0.0f;
- power /= mouse_predefined.sensitivity_double_steps;
- return scaling * std::pow(2.0f, power);
- };
+ power /= mouse_predefined.sensitivity_double_steps;
+ return scaling * std::pow(2.0f, power);
+ };
- sensitivity_coeff_x = calculate(sensitivity_user_x);
- sensitivity_coeff_y = calculate(sensitivity_user_y);
+ sensitivity_coeff_x = calculate(sensitivity_user_x);
+ sensitivity_coeff_y = calculate(sensitivity_user_y);
}
void MouseInterface::UpdateMinRate()
{
- UpdateRate();
+ UpdateRate();
}
void MouseInterface::UpdateRate()
{
- rate_hz = MOUSE_ClampRateHz(std::max(interface_rate_hz, min_rate_hz));
+ rate_hz = MOUSE_ClampRateHz(std::max(interface_rate_hz, min_rate_hz));
}
-void MouseInterface::UpdateButtons(const uint8_t idx,
- const bool pressed)
+void MouseInterface::UpdateButtons(const uint8_t idx, const bool pressed)
{
- old_buttons_12 = buttons_12;
- old_buttons_345 = buttons_345;
+ old_buttons_12 = buttons_12;
+ old_buttons_345 = buttons_345;
- switch (idx) {
- case 0: // left button
- buttons_12.left = pressed ? 1 : 0;
- break;
- case 1: // right button
- buttons_12.right = pressed ? 1 : 0;
- break;
- case 2: // middle button
- buttons_345.middle = pressed ? 1 : 0;
- break;
- case 3: // extra button #1
- buttons_345.extra_1 = pressed ? 1 : 0;
- break;
- case 4: // extra button #2
- buttons_345.extra_2 = pressed ? 1 : 0;
- break;
- default: // button not supported
- return;
- }
+ switch (idx) {
+ case 0: // left button
+ buttons_12.left = pressed ? 1 : 0;
+ break;
+ case 1: // right button
+ buttons_12.right = pressed ? 1 : 0;
+ break;
+ case 2: // middle button
+ buttons_345.middle = pressed ? 1 : 0;
+ break;
+ case 3: // extra button #1
+ buttons_345.extra_1 = pressed ? 1 : 0;
+ break;
+ case 4: // extra button #2
+ buttons_345.extra_2 = pressed ? 1 : 0;
+ break;
+ default: // button not supported
+ return;
+ }
}
void MouseInterface::ResetButtons()
{
- buttons_12 = 0;
- buttons_345 = 0;
+ buttons_12 = 0;
+ buttons_345 = 0;
}
bool MouseInterface::ChangedButtonsJoined() const
{
- return (old_buttons_12.data != buttons_12.data) ||
- (old_buttons_345.data != buttons_345.data);
+ return (old_buttons_12.data != buttons_12.data) ||
+ (old_buttons_345.data != buttons_345.data);
}
bool MouseInterface::ChangedButtonsSquished() const
{
- if (GCC_LIKELY(old_buttons_12.data != buttons_12.data))
- return true;
+ if (GCC_LIKELY(old_buttons_12.data != buttons_12.data))
+ return true;
- return (old_buttons_345.data == 0 && buttons_345.data != 0) ||
- (old_buttons_345.data != 0 && buttons_345.data == 0);
+ return (old_buttons_345.data == 0 && buttons_345.data != 0) ||
+ (old_buttons_345.data != 0 && buttons_345.data == 0);
}
MouseButtonsAll MouseInterface::GetButtonsJoined() const
{
- MouseButtonsAll buttons_all;
- buttons_all.data = buttons_12.data | buttons_345.data;
+ MouseButtonsAll buttons_all;
+ buttons_all.data = buttons_12.data | buttons_345.data;
- return buttons_all;
+ return buttons_all;
}
MouseButtons12S MouseInterface::GetButtonsSquished() const
{
- MouseButtons12S buttons_12S;
+ MouseButtons12S buttons_12S;
- // Squish buttons 3/4/5 into single virtual middle button
- buttons_12S.data = buttons_12.data;
- if (buttons_345.data)
- buttons_12S.middle = 1;
+ // Squish buttons 3/4/5 into single virtual middle button
+ buttons_12S.data = buttons_12.data;
+ if (buttons_345.data)
+ buttons_12S.middle = 1;
- return buttons_12S;
+ return buttons_12S;
}
// ***************************************************************************
// Concrete interfaces - implementation
// ***************************************************************************
-InterfaceDos::InterfaceDos() :
- MouseInterface(MouseInterfaceId::DOS, mouse_predefined.sensitivity_dos)
+InterfaceDos::InterfaceDos()
+ : MouseInterface(MouseInterfaceId::DOS, mouse_predefined.sensitivity_dos)
{
- UpdateSensitivity();
+ UpdateSensitivity();
}
void InterfaceDos::Init()
{
- if (mouse_config.dos_driver)
- MOUSEDOS_Init();
- else
- emulated = false;
- MOUSEDOS_NotifyMinRate(min_rate_hz);
+ if (mouse_config.dos_driver)
+ MOUSEDOS_Init();
+ else
+ emulated = false;
+ MOUSEDOS_NotifyMinRate(min_rate_hz);
}
-void InterfaceDos::NotifyMoved(MouseEvent &ev,
- const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs)
+void InterfaceDos::NotifyMoved(MouseEvent &ev, const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs)
{
- ev.dos_moved = MOUSEDOS_NotifyMoved(
- x_rel * sensitivity_coeff_x,
- y_rel * sensitivity_coeff_y,
- x_abs,
- y_abs);
- ev.request_dos = ev.dos_moved;
+ ev.dos_moved = MOUSEDOS_NotifyMoved(x_rel * sensitivity_coeff_x,
+ y_rel * sensitivity_coeff_y,
+ x_abs,
+ y_abs);
+ ev.request_dos = ev.dos_moved;
}
-void InterfaceDos::NotifyButton(MouseEvent &ev,
- const uint8_t idx,
- const bool pressed)
+void InterfaceDos::NotifyButton(MouseEvent &ev, const uint8_t idx, const bool pressed)
{
- UpdateButtons(idx, pressed);
- if (GCC_UNLIKELY(!ChangedButtonsSquished()))
- return;
+ UpdateButtons(idx, pressed);
+ if (GCC_UNLIKELY(!ChangedButtonsSquished()))
+ return;
- ev.dos_button = true;
- ev.dos_buttons = GetButtonsSquished();
- ev.request_dos = true;
+ ev.dos_button = true;
+ ev.dos_buttons = GetButtonsSquished();
+ ev.request_dos = true;
}
-void InterfaceDos::NotifyWheel(MouseEvent &ev,
- const int16_t w_rel)
+void InterfaceDos::NotifyWheel(MouseEvent &ev, const int16_t w_rel)
{
- ev.dos_wheel = MOUSEDOS_NotifyWheel(w_rel);
- ev.request_dos = ev.dos_wheel;
+ ev.dos_wheel = MOUSEDOS_NotifyWheel(w_rel);
+ ev.request_dos = ev.dos_wheel;
}
void InterfaceDos::NotifyBooting()
{
- // DOS virtual mouse driver gets unavailable
- // if guest OS is booted so do not waste time
- // emulating this interface
+ // DOS virtual mouse driver gets unavailable
+ // if guest OS is booted so do not waste time
+ // emulating this interface
- ConfigReset();
- emulated = false;
- ManyMouseGlue::GetInstance().ShutdownIfSafe();
+ ConfigReset();
+ emulated = false;
+ ManyMouseGlue::GetInstance().ShutdownIfSafe();
}
void InterfaceDos::UpdateRawMapped()
{
- MOUSEDOS_NotifyMapped(IsMapped());
- MOUSEDOS_NotifyRawInput(mouse_config.raw_input || IsMapped());
+ MOUSEDOS_NotifyMapped(IsMapped());
+ MOUSEDOS_NotifyRawInput(mouse_config.raw_input || IsMapped());
}
void InterfaceDos::UpdateMinRate()
{
- MOUSEDOS_NotifyMinRate(min_rate_hz);
+ MOUSEDOS_NotifyMinRate(min_rate_hz);
}
void InterfaceDos::UpdateRate()
{
- MouseInterface::UpdateRate();
- MouseQueue::GetInstance().SetRateDOS(rate_hz);
+ MouseInterface::UpdateRate();
+ MouseQueue::GetInstance().SetRateDOS(rate_hz);
}
-InterfacePS2::InterfacePS2() :
- MouseInterface(MouseInterfaceId::PS2, mouse_predefined.sensitivity_ps2)
+InterfacePS2::InterfacePS2()
+ : MouseInterface(MouseInterfaceId::PS2, mouse_predefined.sensitivity_ps2)
{
- UpdateSensitivity();
+ UpdateSensitivity();
}
void InterfacePS2::Init()
{
- MOUSEPS2_Init();
- MOUSEVMM_Init();
+ MOUSEPS2_Init();
+ MOUSEVMM_Init();
}
-void InterfacePS2::NotifyMoved(MouseEvent &ev,
- const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs)
+void InterfacePS2::NotifyMoved(MouseEvent &ev, const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs)
{
- const bool request_ps2 = MOUSEPS2_NotifyMoved(x_rel * sensitivity_coeff_x,
- y_rel * sensitivity_coeff_y);
- const bool request_vmm = MOUSEVMM_NotifyMoved(x_rel * sensitivity_coeff_vmm_x,
- y_rel * sensitivity_coeff_vmm_y,
- x_abs,
- y_abs);
+ const bool request_ps2 = MOUSEPS2_NotifyMoved(x_rel * sensitivity_coeff_x,
+ y_rel * sensitivity_coeff_y);
+ const bool request_vmm = MOUSEVMM_NotifyMoved(x_rel * sensitivity_coeff_vmm_x,
+ y_rel * sensitivity_coeff_vmm_y,
+ x_abs,
+ y_abs);
- ev.request_ps2 = request_ps2 || request_vmm;
+ ev.request_ps2 = request_ps2 || request_vmm;
}
-void InterfacePS2::NotifyButton(MouseEvent &ev,
- const uint8_t idx,
- const bool pressed)
+void InterfacePS2::NotifyButton(MouseEvent &ev, const uint8_t idx, const bool pressed)
{
- UpdateButtons(idx, pressed);
- if (GCC_UNLIKELY(!ChangedButtonsJoined()))
- return;
+ UpdateButtons(idx, pressed);
+ if (GCC_UNLIKELY(!ChangedButtonsJoined()))
+ return;
- const bool request_ps2 = MOUSEPS2_NotifyButton(GetButtonsSquished(),
- GetButtonsJoined());
- const bool request_vmm = MOUSEVMM_NotifyButton(GetButtonsSquished());
+ const bool request_ps2 = MOUSEPS2_NotifyButton(GetButtonsSquished(),
+ GetButtonsJoined());
+ const bool request_vmm = MOUSEVMM_NotifyButton(GetButtonsSquished());
- ev.request_ps2 = request_ps2 || request_vmm;
+ ev.request_ps2 = request_ps2 || request_vmm;
}
-void InterfacePS2::NotifyWheel(MouseEvent &ev,
- const int16_t w_rel)
+void InterfacePS2::NotifyWheel(MouseEvent &ev, const int16_t w_rel)
{
- const bool request_ps2 = MOUSEPS2_NotifyWheel(w_rel);
- const bool request_vmm = MOUSEVMM_NotifyWheel(w_rel);
+ const bool request_ps2 = MOUSEPS2_NotifyWheel(w_rel);
+ const bool request_vmm = MOUSEVMM_NotifyWheel(w_rel);
- ev.request_ps2 = request_ps2 || request_vmm;
+ ev.request_ps2 = request_ps2 || request_vmm;
}
void InterfacePS2::UpdateRawMapped()
{
- MOUSEVMM_NotifyMapped(IsMapped());
- MOUSEVMM_NotifyRawInput(mouse_config.raw_input || IsMapped());
+ MOUSEVMM_NotifyMapped(IsMapped());
+ MOUSEVMM_NotifyRawInput(mouse_config.raw_input || IsMapped());
}
void InterfacePS2::UpdateSensitivity()
{
- MouseInterface::UpdateSensitivity();
+ MouseInterface::UpdateSensitivity();
- const float tmp = mouse_predefined.sensitivity_vmm /
- mouse_predefined.sensitivity_ps2;
- sensitivity_coeff_vmm_x = sensitivity_coeff_x * tmp;
- sensitivity_coeff_vmm_y = sensitivity_coeff_y * tmp;
+ const float tmp = mouse_predefined.sensitivity_vmm /
+ mouse_predefined.sensitivity_ps2;
+ sensitivity_coeff_vmm_x = sensitivity_coeff_x * tmp;
+ sensitivity_coeff_vmm_y = sensitivity_coeff_y * tmp;
}
void InterfacePS2::UpdateRate()
{
- MouseInterface::UpdateRate();
- MouseQueue::GetInstance().SetRatePS2(rate_hz);
+ MouseInterface::UpdateRate();
+ MouseQueue::GetInstance().SetRatePS2(rate_hz);
}
-InterfaceCOM::InterfaceCOM(const uint8_t port_id) :
- MouseInterface(static_cast<MouseInterfaceId>(static_cast<uint8_t>(MouseInterfaceId::COM1) + port_id),
- mouse_predefined.sensitivity_com)
+InterfaceCOM::InterfaceCOM(const uint8_t port_id)
+ : MouseInterface(static_cast<MouseInterfaceId>(
+ static_cast<uint8_t>(MouseInterfaceId::COM1) + port_id),
+ mouse_predefined.sensitivity_com)
{
- UpdateSensitivity();
- // Wait for CSerialMouse to register itself
- emulated = false;
+ UpdateSensitivity();
+ // Wait for CSerialMouse to register itself
+ emulated = false;
}
-void InterfaceCOM::NotifyMoved(MouseEvent &,
- const float x_rel,
- const float y_rel,
- const uint16_t,
- const uint16_t)
+void InterfaceCOM::NotifyMoved(MouseEvent &, const float x_rel,
+ const float y_rel, const uint16_t, const uint16_t)
{
- assert(listener);
+ assert(listener);
- listener->NotifyMoved(x_rel * sensitivity_coeff_x,
- y_rel * sensitivity_coeff_y);
+ listener->NotifyMoved(x_rel * sensitivity_coeff_x,
+ y_rel * sensitivity_coeff_y);
}
-void InterfaceCOM::NotifyButton(MouseEvent &,
- const uint8_t idx,
- const bool pressed)
+void InterfaceCOM::NotifyButton(MouseEvent &, const uint8_t idx, const bool pressed)
{
- assert(listener);
+ assert(listener);
- UpdateButtons(idx, pressed);
- if (GCC_UNLIKELY(!ChangedButtonsSquished()))
- return;
+ UpdateButtons(idx, pressed);
+ if (GCC_UNLIKELY(!ChangedButtonsSquished()))
+ return;
- listener->NotifyButton(GetButtonsSquished().data, idx);
+ listener->NotifyButton(GetButtonsSquished().data, idx);
}
-void InterfaceCOM::NotifyWheel(MouseEvent &,
- const int16_t w_rel)
+void InterfaceCOM::NotifyWheel(MouseEvent &, const int16_t w_rel)
{
- assert(listener);
+ assert(listener);
- listener->NotifyWheel(w_rel);
+ listener->NotifyWheel(w_rel);
}
void InterfaceCOM::UpdateRate()
{
- MouseInterface::UpdateRate();
+ MouseInterface::UpdateRate();
- if (!listener)
- return;
+ if (!listener)
+ return;
- if (interface_rate_hz >= rate_hz || !interface_rate_hz)
- listener->BoostRate(0);
- else
- // Ask serial mouse emulation code to cheat on transmission
- // speed to simulate higher sampling rate
- listener->BoostRate(rate_hz);
+ if (interface_rate_hz >= rate_hz || !interface_rate_hz)
+ listener->BoostRate(0);
+ else
+ // Ask serial mouse emulation code to cheat on transmission
+ // speed to simulate higher sampling rate
+ listener->BoostRate(rate_hz);
}
void InterfaceCOM::RegisterListener(CSerialMouse &listener_object)
{
- listener = &listener_object;
- emulated = true;
+ listener = &listener_object;
+ emulated = true;
}
void InterfaceCOM::UnRegisterListener()
{
- // Serial mouse gets unavailable when listener object disconnects
+ // Serial mouse gets unavailable when listener object disconnects
- ConfigReset();
- listener = nullptr;
- emulated = false;
- ManyMouseGlue::GetInstance().ShutdownIfSafe();
+ ConfigReset();
+ listener = nullptr;
+ emulated = false;
+ ManyMouseGlue::GetInstance().ShutdownIfSafe();
}
diff --git a/src/hardware/mouse/mouse_interfaces.h b/src/hardware/mouse/mouse_interfaces.h
index 4eddf1bc4..a0c754960 100644
--- a/src/hardware/mouse/mouse_interfaces.h
+++ b/src/hardware/mouse/mouse_interfaces.h
@@ -45,16 +45,13 @@ void MOUSEDOS_NotifyMinRate(const uint16_t value_hz);
void MOUSEDOS_DrawCursor();
bool MOUSEDOS_HasCallback(const uint8_t mask);
-Bitu MOUSEDOS_DoCallback(const uint8_t mask,
- const MouseButtons12S buttons_12S);
+Bitu MOUSEDOS_DoCallback(const uint8_t mask, const MouseButtons12S buttons_12S);
// - needs relative movements
// - understands up to 3 buttons
-bool MOUSEDOS_NotifyMoved(const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs);
+bool MOUSEDOS_NotifyMoved(const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs);
bool MOUSEDOS_NotifyWheel(const int16_t w_rel);
uint8_t MOUSEDOS_UpdateMoved();
@@ -99,10 +96,8 @@ void MOUSEVMM_Deactivate();
// - needs absolute mouse position
// - understands up to 3 buttons
-bool MOUSEVMM_NotifyMoved(const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs);
+bool MOUSEVMM_NotifyMoved(const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs);
bool MOUSEVMM_NotifyButton(const MouseButtons12S buttons_12S);
bool MOUSEVMM_NotifyWheel(const int16_t w_rel);
@@ -120,120 +115,112 @@ bool MOUSEVMM_NotifyWheel(const int16_t w_rel);
// Base mouse interface
// ***************************************************************************
-class MouseInterface
-{
+class MouseInterface {
public:
-
- static void InitAllInstances();
- static MouseInterface *Get(const MouseInterfaceId interface_id);
- static MouseInterface *GetDOS();
- static MouseInterface *GetPS2();
- static MouseInterface *GetSerial(const uint8_t port_id);
-
- virtual void NotifyMoved(MouseEvent &ev,
- const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs) = 0;
- virtual void NotifyButton(MouseEvent &ev,
- const uint8_t idx,
- const bool pressed) = 0;
- virtual void NotifyWheel(MouseEvent &ev,
- const int16_t w_rel) = 0;
-
- void NotifyInterfaceRate(const uint16_t rate_hz);
- virtual void NotifyBooting();
- void NotifyDisconnect();
-
- bool IsMapped() const;
- bool IsMapped(const uint8_t device_idx) const;
- bool IsEmulated() const;
- bool IsUsingEvents() const;
- bool IsUsingHostPointer() const;
-
- MouseInterfaceId GetInterfaceId() const;
- MouseMapStatus GetMapStatus() const;
- uint8_t GetMappedDeviceIdx() const;
- int8_t GetSensitivityX() const;
- int8_t GetSensitivityY() const;
- uint16_t GetMinRate() const;
- uint16_t GetRate() const;
-
- bool ConfigMap(const uint8_t device_idx);
- void ConfigUnMap();
-
- void ConfigOnOff(const bool enable);
- void ConfigReset();
- void ConfigSetSensitivity(const int8_t value_x, const int8_t value_y);
- void ConfigSetSensitivityX(const int8_t value);
- void ConfigSetSensitivityY(const int8_t value);
- void ConfigResetSensitivity();
- void ConfigResetSensitivityX();
- void ConfigResetSensitivityY();
- void ConfigSetMinRate(const uint16_t value_hz);
- void ConfigResetMinRate();
-
- virtual void UpdateConfig();
- virtual void RegisterListener(CSerialMouse &listener_object);
- virtual void UnRegisterListener();
+ static void InitAllInstances();
+ static MouseInterface *Get(const MouseInterfaceId interface_id);
+ static MouseInterface *GetDOS();
+ static MouseInterface *GetPS2();
+ static MouseInterface *GetSerial(const uint8_t port_id);
+
+ virtual void NotifyMoved(MouseEvent &ev, const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs) = 0;
+ virtual void NotifyButton(MouseEvent &ev, const uint8_t idx,
+ const bool pressed) = 0;
+ virtual void NotifyWheel(MouseEvent &ev, const int16_t w_rel) = 0;
+
+ void NotifyInterfaceRate(const uint16_t rate_hz);
+ virtual void NotifyBooting();
+ void NotifyDisconnect();
+
+ bool IsMapped() const;
+ bool IsMapped(const uint8_t device_idx) const;
+ bool IsEmulated() const;
+ bool IsUsingEvents() const;
+ bool IsUsingHostPointer() const;
+
+ MouseInterfaceId GetInterfaceId() const;
+ MouseMapStatus GetMapStatus() const;
+ uint8_t GetMappedDeviceIdx() const;
+ int8_t GetSensitivityX() const;
+ int8_t GetSensitivityY() const;
+ uint16_t GetMinRate() const;
+ uint16_t GetRate() const;
+
+ bool ConfigMap(const uint8_t device_idx);
+ void ConfigUnMap();
+
+ void ConfigOnOff(const bool enable);
+ void ConfigReset();
+ void ConfigSetSensitivity(const int8_t value_x, const int8_t value_y);
+ void ConfigSetSensitivityX(const int8_t value);
+ void ConfigSetSensitivityY(const int8_t value);
+ void ConfigResetSensitivity();
+ void ConfigResetSensitivityX();
+ void ConfigResetSensitivityY();
+ void ConfigSetMinRate(const uint16_t value_hz);
+ void ConfigResetMinRate();
+
+ virtual void UpdateConfig();
+ virtual void RegisterListener(CSerialMouse &listener_object);
+ virtual void UnRegisterListener();
protected:
+ static constexpr uint8_t idx_host_pointer = UINT8_MAX;
- static constexpr uint8_t idx_host_pointer = UINT8_MAX;
-
- MouseInterface(const MouseInterfaceId interface_id,
- const float sensitivity_predefined);
- virtual ~MouseInterface() = default;
- virtual void Init();
+ MouseInterface(const MouseInterfaceId interface_id,
+ const float sensitivity_predefined);
+ virtual ~MouseInterface() = default;
+ virtual void Init();
- uint8_t GetInterfaceIdx() const;
+ uint8_t GetInterfaceIdx() const;
- void SetMapStatus(const MouseMapStatus status,
- const uint8_t device_idx = idx_host_pointer);
+ void SetMapStatus(const MouseMapStatus status,
+ const uint8_t device_idx = idx_host_pointer);
- virtual void UpdateRawMapped();
- virtual void UpdateSensitivity();
- virtual void UpdateMinRate();
- virtual void UpdateRate();
- void UpdateButtons(const uint8_t idx, const bool pressed);
- void ResetButtons();
+ virtual void UpdateRawMapped();
+ virtual void UpdateSensitivity();
+ virtual void UpdateMinRate();
+ virtual void UpdateRate();
+ void UpdateButtons(const uint8_t idx, const bool pressed);
+ void ResetButtons();
- bool ChangedButtonsJoined() const;
- bool ChangedButtonsSquished() const;
+ bool ChangedButtonsJoined() const;
+ bool ChangedButtonsSquished() const;
- MouseButtonsAll GetButtonsJoined() const;
- MouseButtons12S GetButtonsSquished() const;
+ MouseButtonsAll GetButtonsJoined() const;
+ MouseButtons12S GetButtonsSquished() const;
- bool emulated = true;
+ bool emulated = true;
- float sensitivity_coeff_x = 1.0f; // cached combined sensitivity coefficients
- float sensitivity_coeff_y = 1.0f; // to reduce amount of multiplications
+ float sensitivity_coeff_x = 1.0f; // cached combined sensitivity
+ // coefficients
+ float sensitivity_coeff_y = 1.0f; // to reduce amount of multiplications
- int8_t sensitivity_user_x = 0;
- int8_t sensitivity_user_y = 0;
+ int8_t sensitivity_user_x = 0;
+ int8_t sensitivity_user_y = 0;
- uint16_t rate_hz = 0;
- uint16_t min_rate_hz = 0;
- uint16_t interface_rate_hz = 0;
+ uint16_t rate_hz = 0;
+ uint16_t min_rate_hz = 0;
+ uint16_t interface_rate_hz = 0;
private:
+ MouseInterface() = delete;
+ MouseInterface(const MouseInterface &) = delete;
+ MouseInterface &operator=(const MouseInterface &) = delete;
- MouseInterface() = delete;
- MouseInterface(const MouseInterface &) = delete;
- MouseInterface &operator=(const MouseInterface &) = delete;
-
- const MouseInterfaceId interface_id = MouseInterfaceId::None;
+ const MouseInterfaceId interface_id = MouseInterfaceId::None;
- MouseMapStatus map_status = MouseMapStatus::HostPointer;
- uint8_t mapped_idx = idx_host_pointer; // index of mapped physical mouse
+ MouseMapStatus map_status = MouseMapStatus::HostPointer;
+ uint8_t mapped_idx = idx_host_pointer; // index of mapped physical mouse
- MouseButtons12 buttons_12 = 0; // host side buttons 1 (left), 2 (right)
- MouseButtons345 buttons_345 = 0; // host side buttons 3 (middle), 4, and 5
+ MouseButtons12 buttons_12 = 0; // host side buttons 1 (left), 2 (right)
+ MouseButtons345 buttons_345 = 0; // host side buttons 3 (middle), 4, and 5
- MouseButtons12 old_buttons_12 = 0; // pre-update values
- MouseButtons345 old_buttons_345 = 0;
+ MouseButtons12 old_buttons_12 = 0; // pre-update values
+ MouseButtons345 old_buttons_345 = 0;
- float sensitivity_predefined = 1.0f; // hardcoded for the given interface
+ float sensitivity_predefined = 1.0f; // hardcoded for the given interface
};
extern std::vector<MouseInterface *> mouse_interfaces;
diff --git a/src/hardware/mouse/mouse_manymouse.cpp b/src/hardware/mouse/mouse_manymouse.cpp
index e732a700b..1cacc84db 100644
--- a/src/hardware/mouse/mouse_manymouse.cpp
+++ b/src/hardware/mouse/mouse_manymouse.cpp
@@ -28,412 +28,412 @@
CHECK_NARROWING();
-
void manymouse_tick(uint32_t)
{
#if C_MANYMOUSE
- ManyMouseGlue::GetInstance().Tick();
+ ManyMouseGlue::GetInstance().Tick();
#endif // C_MANYMOUSE
}
-MousePhysical::MousePhysical(const std::string &name) :
- name(name)
-{
-}
+MousePhysical::MousePhysical(const std::string &name) : name(name) {}
bool MousePhysical::IsMapped() const
{
- return mapped_id != MouseInterfaceId::None;
+ return mapped_id != MouseInterfaceId::None;
}
bool MousePhysical::IsDisconnected() const
{
- return disconnected;
+ return disconnected;
}
MouseInterfaceId MousePhysical::GetMappedInterfaceId() const
{
- return mapped_id;
+ return mapped_id;
}
const std::string &MousePhysical::GetName() const
{
- return name;
+ return name;
}
ManyMouseGlue &ManyMouseGlue::GetInstance()
{
- static ManyMouseGlue *instance = nullptr;
- if (!instance)
- instance = new ManyMouseGlue();
- return *instance;
+ static ManyMouseGlue *instance = nullptr;
+ if (!instance)
+ instance = new ManyMouseGlue();
+ return *instance;
}
#if C_MANYMOUSE
void ManyMouseGlue::InitIfNeeded()
{
- if (initialized || malfunction)
- return;
-
- num_mice = ManyMouse_Init();
- if (num_mice < 0) {
- LOG_ERR("MOUSE: ManyMouse initialization failed");
- ManyMouse_Quit();
- malfunction = true;
- return;
- }
- initialized = true;
-
- if (num_mice >= max_mice) {
- num_mice = max_mice - 1;
- static bool logged = false;
- if (!logged) {
- logged = true;
- LOG_ERR("MOUSE: Up to %d simultaneously connected mice supported",
- max_mice);
- }
- }
-
- const auto new_driver_name = std::string(ManyMouse_DriverName());
- if (new_driver_name != driver_name) {
- driver_name = new_driver_name;
- LOG_INFO("MOUSE: ManyMouse driver '%s'", driver_name.c_str());
- }
-
- Rescan();
+ if (initialized || malfunction)
+ return;
+
+ num_mice = ManyMouse_Init();
+ if (num_mice < 0) {
+ LOG_ERR("MOUSE: ManyMouse initialization failed");
+ ManyMouse_Quit();
+ malfunction = true;
+ return;
+ }
+ initialized = true;
+
+ if (num_mice >= max_mice) {
+ num_mice = max_mice - 1;
+ static bool logged = false;
+ if (!logged) {
+ logged = true;
+ LOG_ERR("MOUSE: Up to %d simultaneously connected mice supported",
+ max_mice);
+ }
+ }
+
+ const auto new_driver_name = std::string(ManyMouse_DriverName());
+ if (new_driver_name != driver_name) {
+ driver_name = new_driver_name;
+ LOG_INFO("MOUSE: ManyMouse driver '%s'", driver_name.c_str());
+ }
+
+ Rescan();
}
void ManyMouseGlue::ShutdownIfSafe()
{
- if (is_mapping_in_effect || config_api_counter)
- return;
+ if (is_mapping_in_effect || config_api_counter)
+ return;
- ShutdownForced();
+ ShutdownForced();
}
void ManyMouseGlue::ShutdownForced()
{
- if (!initialized)
- return;
-
- PIC_RemoveEvents(manymouse_tick);
- ManyMouse_Quit();
- ClearPhysicalMice();
- num_mice = 0;
- initialized = false;
+ if (!initialized)
+ return;
+
+ PIC_RemoveEvents(manymouse_tick);
+ ManyMouse_Quit();
+ ClearPhysicalMice();
+ num_mice = 0;
+ initialized = false;
}
void ManyMouseGlue::StartConfigAPI()
{
- // Config API object is being created
- ++config_api_counter;
- assert(config_api_counter > 0);
+ // Config API object is being created
+ ++config_api_counter;
+ assert(config_api_counter > 0);
}
void ManyMouseGlue::StopConfigAPI()
{
- // Config API object is being destroyed
- assert(config_api_counter > 0);
- config_api_counter--;
- ShutdownIfSafe();
- if (!config_api_counter)
- rescan_blocked_config = false;
+ // Config API object is being destroyed
+ assert(config_api_counter > 0);
+ config_api_counter--;
+ ShutdownIfSafe();
+ if (!config_api_counter)
+ rescan_blocked_config = false;
}
void ManyMouseGlue::ClearPhysicalMice()
{
- mouse_info.physical.clear();
- physical_devices.clear();
- rel_x.clear();
- rel_y.clear();
+ mouse_info.physical.clear();
+ physical_devices.clear();
+ rel_x.clear();
+ rel_y.clear();
}
void ManyMouseGlue::Rescan()
{
- if (config_api_counter)
- // Do not allow another rescan until MouseConfigAPI
- // stops being used, it would be unsafe due to possible
- // changes of physical device list size/indices
- rescan_blocked_config = true;
-
- ClearPhysicalMice();
-
- for (uint8_t idx = 0; idx < num_mice; idx++) {
- const auto name_utf8 = ManyMouse_DeviceName(idx);
- 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] == character_nbsp)
- name[pos - 1] = character_space;
- // Remove non-ASCII and control characters
- if (name[pos - 1] < character_space ||
- name[pos - 1] >= character_nbsp)
- name.erase(pos - 1, 1);
- }
-
- // Try to rework into something useful names in the forms
- // 'FooBar Corp FooBar Corp Incredible Mouse'
- size_t pos = name.size() / 2 + 1;
- while (--pos > 2) {
- if (name[pos - 1] != ' ')
- continue;
- const std::string tmp = name.substr(0, pos);
- if (name.rfind(tmp + tmp, 0) == std::string::npos)
- continue;
- name = name.substr(pos);
- break;
- }
-
- // ManyMouse should limit device names to 64 characters,
- // but make sure name is indeed limited in length, and
- // strip trailing spaces
- name.resize(std::min(static_cast<size_t>(64), name.size()));
- while (!name.empty() && name.back() == ' ')
- name.pop_back();
-
- physical_devices.emplace_back(MousePhysical(name));
- mouse_info.physical.emplace_back(
- MousePhysicalInfoEntry(static_cast<uint8_t>(physical_devices.size() - 1)));
- }
+ if (config_api_counter)
+ // Do not allow another rescan until MouseConfigAPI
+ // stops being used, it would be unsafe due to possible
+ // changes of physical device list size/indices
+ rescan_blocked_config = true;
+
+ ClearPhysicalMice();
+
+ for (uint8_t idx = 0; idx < num_mice; idx++) {
+ const auto name_utf8 = ManyMouse_DeviceName(idx);
+ 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] == character_nbsp)
+ name[pos - 1] = character_space;
+ // Remove non-ASCII and control characters
+ if (name[pos - 1] < character_space ||
+ name[pos - 1] >= character_nbsp)
+ name.erase(pos - 1, 1);
+ }
+
+ // Try to rework into something useful names in the forms
+ // 'FooBar Corp FooBar Corp Incredible Mouse'
+ size_t pos = name.size() / 2 + 1;
+ while (--pos > 2) {
+ if (name[pos - 1] != ' ')
+ continue;
+ const std::string tmp = name.substr(0, pos);
+ if (name.rfind(tmp + tmp, 0) == std::string::npos)
+ continue;
+ name = name.substr(pos);
+ break;
+ }
+
+ // ManyMouse should limit device names to 64 characters,
+ // but make sure name is indeed limited in length, and
+ // strip trailing spaces
+ name.resize(std::min(static_cast<size_t>(64), name.size()));
+ while (!name.empty() && name.back() == ' ')
+ name.pop_back();
+
+ physical_devices.emplace_back(MousePhysical(name));
+ mouse_info.physical.emplace_back(MousePhysicalInfoEntry(
+ static_cast<uint8_t>(physical_devices.size() - 1)));
+ }
}
void ManyMouseGlue::RescanIfSafe()
{
- if (rescan_blocked_config)
- return;
+ if (rescan_blocked_config)
+ return;
- ShutdownIfSafe();
- InitIfNeeded();
+ ShutdownIfSafe();
+ InitIfNeeded();
}
bool ManyMouseGlue::ProbeForMapping(uint8_t &device_id)
{
- // Wait a little to speedup screen update
- const auto pic_ticks_start = PIC_Ticks;
- while (PIC_Ticks >= pic_ticks_start &&
- PIC_Ticks - pic_ticks_start < 50)
- CALLBACK_Idle();
-
- // Make sure the module is initialized,
- // but suppress default event handling
- InitIfNeeded();
- if (!initialized)
- return false;
- PIC_RemoveEvents(manymouse_tick);
-
- // Flush events, handle critical ones
- ManyMouseEvent event;
- while (ManyMouse_PollEvent(&event))
- HandleEvent(event, true); // handle critical events
-
- bool success = false;
- while (true) {
- // Poll mouse events, handle critical ones
- if (!ManyMouse_PollEvent(&event)) {
- CALLBACK_Idle();
- continue;
- }
- if (event.device >= max_mice)
- continue;
- HandleEvent(event, true);
-
- // Wait for mouse button press
- if (event.type != MANYMOUSE_EVENT_BUTTON || !event.value)
- continue;
- device_id = static_cast<uint8_t>(event.device);
-
- if (event.item >= 1)
- break; // user cancelled the interactive mouse mapping
-
- // Do not accept already mapped devices
- bool already_mapped = false;
- for (const auto &interface : mouse_interfaces)
- if (interface->IsMapped(device_id))
- already_mapped = true;
- if (already_mapped)
- continue;
-
- // Mouse probed successfully
- device_id = static_cast<uint8_t>(event.device);
- success = true;
- break;
- }
-
- if (is_mapping_in_effect && !mouse_config.no_mouse)
- PIC_AddEvent(manymouse_tick, tick_interval);
- return success;
+ // Wait a little to speedup screen update
+ const auto pic_ticks_start = PIC_Ticks;
+ while (PIC_Ticks >= pic_ticks_start && PIC_Ticks - pic_ticks_start < 50)
+ CALLBACK_Idle();
+
+ // Make sure the module is initialized,
+ // but suppress default event handling
+ InitIfNeeded();
+ if (!initialized)
+ return false;
+ PIC_RemoveEvents(manymouse_tick);
+
+ // Flush events, handle critical ones
+ ManyMouseEvent event;
+ while (ManyMouse_PollEvent(&event))
+ HandleEvent(event, true); // handle critical events
+
+ bool success = false;
+ while (true) {
+ // Poll mouse events, handle critical ones
+ if (!ManyMouse_PollEvent(&event)) {
+ CALLBACK_Idle();
+ continue;
+ }
+ if (event.device >= max_mice)
+ continue;
+ HandleEvent(event, true);
+
+ // Wait for mouse button press
+ if (event.type != MANYMOUSE_EVENT_BUTTON || !event.value)
+ continue;
+ device_id = static_cast<uint8_t>(event.device);
+
+ if (event.item >= 1)
+ break; // user cancelled the interactive mouse mapping
+
+ // Do not accept already mapped devices
+ bool already_mapped = false;
+ for (const auto &interface : mouse_interfaces)
+ if (interface->IsMapped(device_id))
+ already_mapped = true;
+ if (already_mapped)
+ continue;
+
+ // Mouse probed successfully
+ device_id = static_cast<uint8_t>(event.device);
+ success = true;
+ break;
+ }
+
+ if (is_mapping_in_effect && !mouse_config.no_mouse)
+ PIC_AddEvent(manymouse_tick, tick_interval);
+ return success;
}
uint8_t ManyMouseGlue::GetIdx(const std::regex &regex)
{
- // Try to match the mouse name which is not mapped yet
+ // Try to match the mouse name which is not mapped yet
- for (size_t i = 0; i < physical_devices.size(); i++) {
- const auto &physical_device = physical_devices[i];
+ for (size_t i = 0; i < physical_devices.size(); i++) {
+ const auto &physical_device = physical_devices[i];
- if (physical_device.IsDisconnected() ||
- !std::regex_match(physical_device.GetName(), regex))
- // mouse disconnected or name does not match
- continue;
+ if (physical_device.IsDisconnected() ||
+ !std::regex_match(physical_device.GetName(), regex))
+ // mouse disconnected or name does not match
+ continue;
- if (physical_device.GetMappedInterfaceId() == MouseInterfaceId::None)
- // name matches, mouse not mapped yet - use it!
- return static_cast<uint8_t>(i);
- }
+ if (physical_device.GetMappedInterfaceId() == MouseInterfaceId::None)
+ // name matches, mouse not mapped yet - use it!
+ return static_cast<uint8_t>(i);
+ }
- return max_mice; // return value which will be considered out of range
+ return max_mice; // return value which will be considered out of range
}
-void ManyMouseGlue::Map(const uint8_t physical_idx,
- const MouseInterfaceId interface_id)
+void ManyMouseGlue::Map(const uint8_t physical_idx, const MouseInterfaceId interface_id)
{
- assert(interface_id != MouseInterfaceId::None);
+ assert(interface_id != MouseInterfaceId::None);
- if (physical_idx >= physical_devices.size()) {
- UnMap(interface_id);
- return;
- }
+ if (physical_idx >= physical_devices.size()) {
+ UnMap(interface_id);
+ return;
+ }
- auto &physical_device = physical_devices[physical_idx];
- if (interface_id == physical_device.GetMappedInterfaceId())
- return; // nothing to update
- physical_device.mapped_id = interface_id;
+ auto &physical_device = physical_devices[physical_idx];
+ if (interface_id == physical_device.GetMappedInterfaceId())
+ return; // nothing to update
+ physical_device.mapped_id = interface_id;
- MapFinalize();
+ MapFinalize();
}
void ManyMouseGlue::UnMap(const MouseInterfaceId interface_id)
{
- for (auto &physical_device : physical_devices) {
- if (interface_id != physical_device.GetMappedInterfaceId())
- continue; // not a device to unmap
- physical_device.mapped_id = MouseInterfaceId::None;
- break;
- }
-
- MapFinalize();
+ for (auto &physical_device : physical_devices) {
+ if (interface_id != physical_device.GetMappedInterfaceId())
+ continue; // not a device to unmap
+ physical_device.mapped_id = MouseInterfaceId::None;
+ break;
+ }
+
+ MapFinalize();
}
void ManyMouseGlue::MapFinalize()
{
- PIC_RemoveEvents(manymouse_tick);
- is_mapping_in_effect = false;
- for (const auto &entry : mouse_info.physical) {
- if (entry.IsMapped())
- continue;
-
- is_mapping_in_effect = true;
- if (!mouse_config.no_mouse)
- PIC_AddEvent(manymouse_tick, tick_interval);
- break;
- }
+ PIC_RemoveEvents(manymouse_tick);
+ is_mapping_in_effect = false;
+ for (const auto &entry : mouse_info.physical) {
+ if (entry.IsMapped())
+ continue;
+
+ is_mapping_in_effect = true;
+ if (!mouse_config.no_mouse)
+ PIC_AddEvent(manymouse_tick, tick_interval);
+ break;
+ }
}
bool ManyMouseGlue::IsMappingInEffect() const
{
- return is_mapping_in_effect;
+ return is_mapping_in_effect;
}
-void ManyMouseGlue::HandleEvent(const ManyMouseEvent &event,
- const bool critical_only)
+void ManyMouseGlue::HandleEvent(const ManyMouseEvent &event, const bool critical_only)
{
- if (GCC_UNLIKELY(event.device >= mouse_info.physical.size()))
- return; // device ID out of supported range
- if (GCC_UNLIKELY(mouse_config.no_mouse &&
- event.type != MANYMOUSE_EVENT_DISCONNECT))
- return; // mouse control disabled in GUI
-
- const auto device_idx = static_cast<uint8_t>(event.device);
- const auto interface_id = physical_devices[device_idx].GetMappedInterfaceId();
- const bool no_interface = (interface_id == MouseInterfaceId::None);
-
- switch (event.type) {
-
- case MANYMOUSE_EVENT_ABSMOTION:
- // LOG_INFO("MANYMOUSE #%u ABSMOTION axis %d, %d", event.device, event.item, event.value);
- break;
-
- case MANYMOUSE_EVENT_RELMOTION:
- // LOG_INFO("MANYMOUSE #%u RELMOTION axis %d, %d", event.device, event.item, event.value);
- 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);
- rel_y.resize(static_cast<size_t>(device_idx + 1), 0);
- }
-
- if (event.item)
- rel_y[event.device] += event.value; // event.item 1
- else
- rel_x[event.device] += event.value; // event.item 0
- break;
-
- case MANYMOUSE_EVENT_BUTTON:
- // LOG_INFO("MANYMOUSE #%u BUTTON %u %s", event.device, event.item, event.value ? "press" : "release");
- if (no_interface || (critical_only && !event.value) || (event.item >= max_buttons))
- // TODO: Consider supporting extra mouse buttons
- // in the future. On Linux event items 3-7 are for
- // scroll wheel(s), 8 is for SDL button X1, 9 is
- // for X2, etc. - but I don't know yet if this
- // is consistent across various platforms
- break;
- MOUSE_EventButton(static_cast<uint8_t>(event.item), event.value, interface_id);
- break;
-
- case MANYMOUSE_EVENT_SCROLL:
- // 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(clamp_to_int16(-event.value), interface_id);
- break;
-
- case MANYMOUSE_EVENT_DISCONNECT:
- // LOG_INFO("MANYMOUSE #%u DISCONNECT", event.device);
- physical_devices[event.device].disconnected = true;
- for (uint8_t button = 0; button < max_buttons; button++)
- MOUSE_EventButton(button, false, interface_id);
- MOUSE_NotifyDisconnect(interface_id);
- break;
-
- default:
- // LOG_INFO("MANYMOUSE #%u (other event)", event.device);
- break;
- }
+ if (GCC_UNLIKELY(event.device >= mouse_info.physical.size()))
+ return; // device ID out of supported range
+ if (GCC_UNLIKELY(mouse_config.no_mouse &&
+ event.type != MANYMOUSE_EVENT_DISCONNECT))
+ return; // mouse control disabled in GUI
+
+ const auto device_idx = static_cast<uint8_t>(event.device);
+ const auto interface_id = physical_devices[device_idx].GetMappedInterfaceId();
+ const bool no_interface = (interface_id == MouseInterfaceId::None);
+
+ switch (event.type) {
+ case MANYMOUSE_EVENT_ABSMOTION:
+ // LOG_INFO("MANYMOUSE #%u ABSMOTION axis %d, %d", event.device,
+ // event.item, event.value);
+ break;
+
+ case MANYMOUSE_EVENT_RELMOTION:
+ // LOG_INFO("MANYMOUSE #%u RELMOTION axis %d, %d", event.device,
+ // event.item, event.value);
+ 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);
+ rel_y.resize(static_cast<size_t>(device_idx + 1), 0);
+ }
+
+ if (event.item)
+ rel_y[event.device] += event.value; // event.item 1
+ else
+ rel_x[event.device] += event.value; // event.item 0
+ break;
+
+ case MANYMOUSE_EVENT_BUTTON:
+ // LOG_INFO("MANYMOUSE #%u BUTTON %u %s", event.device,
+ // event.item, event.value ? "press" : "release");
+ if (no_interface || (critical_only && !event.value) ||
+ (event.item >= max_buttons))
+ // TODO: Consider supporting extra mouse buttons
+ // in the future. On Linux event items 3-7 are for
+ // scroll wheel(s), 8 is for SDL button X1, 9 is
+ // for X2, etc. - but I don't know yet if this
+ // is consistent across various platforms
+ break;
+ MOUSE_EventButton(static_cast<uint8_t>(event.item),
+ event.value,
+ interface_id);
+ break;
+
+ case MANYMOUSE_EVENT_SCROLL:
+ // 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(clamp_to_int16(-event.value), interface_id);
+ break;
+
+ case MANYMOUSE_EVENT_DISCONNECT:
+ // LOG_INFO("MANYMOUSE #%u DISCONNECT", event.device);
+ physical_devices[event.device].disconnected = true;
+ for (uint8_t button = 0; button < max_buttons; button++)
+ MOUSE_EventButton(button, false, interface_id);
+ MOUSE_NotifyDisconnect(interface_id);
+ break;
+
+ default:
+ // LOG_INFO("MANYMOUSE #%u (other event)", event.device);
+ break;
+ }
}
void ManyMouseGlue::Tick()
{
- assert(!mouse_config.no_mouse);
-
- // Handle all the events from the queue
- ManyMouseEvent event;
- while (ManyMouse_PollEvent(&event))
- HandleEvent(event);
-
- // Report accumulated mouse movements
- for (uint8_t idx = 0; idx < rel_x.size(); idx++) {
- if (rel_x[idx] == 0 && rel_y[idx] == 0)
- continue;
-
- const auto interface_id = physical_devices[idx].GetMappedInterfaceId();
- MOUSE_EventMoved(static_cast<float>(rel_x[idx]),
- static_cast<float>(rel_y[idx]),
- interface_id);
- rel_x[idx] = 0;
- rel_y[idx] = 0;
- }
-
- if (is_mapping_in_effect)
- PIC_AddEvent(manymouse_tick, tick_interval);
+ assert(!mouse_config.no_mouse);
+
+ // Handle all the events from the queue
+ ManyMouseEvent event;
+ while (ManyMouse_PollEvent(&event))
+ HandleEvent(event);
+
+ // Report accumulated mouse movements
+ for (uint8_t idx = 0; idx < rel_x.size(); idx++) {
+ if (rel_x[idx] == 0 && rel_y[idx] == 0)
+ continue;
+
+ const auto interface_id = physical_devices[idx].GetMappedInterfaceId();
+ MOUSE_EventMoved(static_cast<float>(rel_x[idx]),
+ static_cast<float>(rel_y[idx]),
+ interface_id);
+ rel_x[idx] = 0;
+ rel_y[idx] = 0;
+ }
+
+ if (is_mapping_in_effect)
+ PIC_AddEvent(manymouse_tick, tick_interval);
}
#else
@@ -442,42 +442,34 @@ void ManyMouseGlue::Tick()
void ManyMouseGlue::RescanIfSafe()
{
- static bool already_warned = false;
- if (!already_warned) {
- LOG_ERR("MOUSE: This build has no ManyMouse support");
- already_warned = true;
- }
+ static bool already_warned = false;
+ if (!already_warned) {
+ LOG_ERR("MOUSE: This build has no ManyMouse support");
+ already_warned = true;
+ }
}
-void ManyMouseGlue::ShutdownIfSafe()
-{
-}
+void ManyMouseGlue::ShutdownIfSafe() {}
-void ManyMouseGlue::StartConfigAPI()
-{
-}
+void ManyMouseGlue::StartConfigAPI() {}
-void ManyMouseGlue::StopConfigAPI()
-{
-}
+void ManyMouseGlue::StopConfigAPI() {}
bool ManyMouseGlue::ProbeForMapping(uint8_t &)
{
- return false;
+ return false;
}
uint8_t ManyMouseGlue::GetIdx(const std::regex &)
{
- return UINT8_MAX;
+ return UINT8_MAX;
}
-void ManyMouseGlue::Map(const uint8_t, const MouseInterfaceId)
-{
-}
+void ManyMouseGlue::Map(const uint8_t, const MouseInterfaceId) {}
bool ManyMouseGlue::IsMappingInEffect() const
{
- return false;
+ return false;
}
#endif // C_MANYMOUSE
diff --git a/src/hardware/mouse/mouse_manymouse.h b/src/hardware/mouse/mouse_manymouse.h
index 4853982c3..034aee515 100644
--- a/src/hardware/mouse/mouse_manymouse.h
+++ b/src/hardware/mouse/mouse_manymouse.h
@@ -26,93 +26,89 @@
#include <vector>
#if C_MANYMOUSE
-#include "../../libs/manymouse/manymouse.h"
+# include "../../libs/manymouse/manymouse.h"
#endif // C_MANYMOUSE
-class MousePhysical
-{
+class MousePhysical {
public:
- MousePhysical(const std::string &name);
+ MousePhysical(const std::string &name);
- bool IsMapped() const;
- bool IsDisconnected() const;
+ bool IsMapped() const;
+ bool IsDisconnected() const;
- MouseInterfaceId GetMappedInterfaceId() const;
- const std::string &GetName() const;
+ MouseInterfaceId GetMappedInterfaceId() const;
+ const std::string &GetName() const;
private:
+ friend class ManyMouseGlue;
- friend class ManyMouseGlue;
-
- const std::string name = "";
- MouseInterfaceId mapped_id = MouseInterfaceId::None;
- bool disconnected = false;
+ const std::string name = "";
+ MouseInterfaceId mapped_id = MouseInterfaceId::None;
+ bool disconnected = false;
};
class ManyMouseGlue final {
public:
+ static ManyMouseGlue &GetInstance();
- static ManyMouseGlue &GetInstance();
-
- void RescanIfSafe();
- void ShutdownIfSafe();
- void StartConfigAPI();
- void StopConfigAPI();
+ void RescanIfSafe();
+ void ShutdownIfSafe();
+ void StartConfigAPI();
+ void StopConfigAPI();
- bool ProbeForMapping(uint8_t &device_id);
- uint8_t GetIdx(const std::regex &regex);
+ bool ProbeForMapping(uint8_t &device_id);
+ uint8_t GetIdx(const std::regex &regex);
- void Map(const uint8_t physical_idx,
- const MouseInterfaceId interface_id);
+ void Map(const uint8_t physical_idx, const MouseInterfaceId interface_id);
- bool IsMappingInEffect() const;
+ bool IsMappingInEffect() const;
private:
+ friend class MouseInterfaceInfoEntry;
+ friend class MousePhysicalInfoEntry;
- friend class MouseInterfaceInfoEntry;
- friend class MousePhysicalInfoEntry;
-
- ManyMouseGlue() = default;
- ~ManyMouseGlue() = delete;
- ManyMouseGlue(const ManyMouseGlue &) = delete;
- ManyMouseGlue &operator=(const ManyMouseGlue &) = delete;
+ ManyMouseGlue() = default;
+ ~ManyMouseGlue() = delete;
+ ManyMouseGlue(const ManyMouseGlue &) = delete;
+ ManyMouseGlue &operator=(const ManyMouseGlue &) = delete;
- void Tick();
- friend void manymouse_tick(uint32_t);
+ void Tick();
+ friend void manymouse_tick(uint32_t);
#if C_MANYMOUSE
- void InitIfNeeded();
- void ShutdownForced();
- void ClearPhysicalMice();
- void Rescan();
+ void InitIfNeeded();
+ void ShutdownForced();
+ void ClearPhysicalMice();
+ void Rescan();
- void UnMap(const MouseInterfaceId interface_id);
- void MapFinalize();
+ void UnMap(const MouseInterfaceId interface_id);
+ void MapFinalize();
- void HandleEvent(const ManyMouseEvent &event,
- const bool critical_only = false);
+ void HandleEvent(const ManyMouseEvent &event,
+ const bool critical_only = false);
- bool initialized = false;
- bool malfunction = false; // once set to false, will stay false forever
- bool is_mapping_in_effect = false;
- bool rescan_blocked_config = false; // true = rescan blocked due to config API usage
- uint32_t config_api_counter = 0;
+ bool initialized = false;
+ bool malfunction = false; // once set to false, will stay false forever
+ bool is_mapping_in_effect = false;
+ bool rescan_blocked_config = false; // true = rescan blocked due to
+ // config API usage
+ uint32_t config_api_counter = 0;
- int num_mice = 0;
+ int num_mice = 0;
- std::string driver_name = "";
+ std::string driver_name = "";
- std::vector<int> rel_x = {}; // not yet reported accumulated movements
- std::vector<int> rel_y = {};
+ std::vector<int> rel_x = {}; // not yet reported accumulated movements
+ std::vector<int> rel_y = {};
- static constexpr uint8_t max_buttons = 3;
- static constexpr uint8_t max_mice = UINT8_MAX;
- static constexpr double tick_interval = 5.0;
+ static constexpr uint8_t max_buttons = 3;
+ static constexpr uint8_t max_mice = UINT8_MAX;
+ static constexpr double tick_interval = 5.0;
#endif // C_MANYMOUSE
- std::vector<MousePhysical> physical_devices = {};
+ std::vector<MousePhysical> physical_devices = {};
};
#endif // DOSBOX_MOUSE_MANYMOUSE_H
diff --git a/src/hardware/mouse/mouse_queue.cpp b/src/hardware/mouse/mouse_queue.cpp
index 095013fe4..a9d173a37 100644
--- a/src/hardware/mouse/mouse_queue.cpp
+++ b/src/hardware/mouse/mouse_queue.cpp
@@ -27,7 +27,6 @@
CHECK_NARROWING();
-
// ***************************************************************************
// Debug code, normally not enabled
// ***************************************************************************
@@ -35,23 +34,23 @@ CHECK_NARROWING();
// #define DEBUG_QUEUE_ENABLE
#ifndef DEBUG_QUEUE_ENABLE
-# define DEBUG_QUEUE(...) ;
+# define DEBUG_QUEUE(...) ;
#else
// TODO: after migrating to C++20, allow to skip the 2nd argument by using
// '__VA_OPT__(,) __VA_ARGS__' instead of ', __VA_ARGS__'
-# define DEBUG_QUEUE(fmt, ...) \
- LOG_INFO("(queue) %04d: " fmt, DEBUG_GetDiffTicks(), __VA_ARGS__);
+# define DEBUG_QUEUE(fmt, ...) \
+ LOG_INFO("(queue) %04d: " fmt, DEBUG_GetDiffTicks(), __VA_ARGS__);
static uint32_t DEBUG_GetDiffTicks()
{
- static uint32_t previous_ticks = 0;
- uint32_t diff_ticks = 0;
+ static uint32_t previous_ticks = 0;
+ uint32_t diff_ticks = 0;
- if (previous_ticks)
- diff_ticks = PIC_Ticks - previous_ticks;
+ if (previous_ticks)
+ diff_ticks = PIC_Ticks - previous_ticks;
- previous_ticks = PIC_Ticks;
- return diff_ticks;
+ previous_ticks = PIC_Ticks;
+ return diff_ticks;
}
#endif
@@ -62,251 +61,254 @@ static uint32_t DEBUG_GetDiffTicks()
void mouse_queue_tick(uint32_t)
{
- MouseQueue::GetInstance().Tick();
+ MouseQueue::GetInstance().Tick();
}
MouseQueue &MouseQueue::GetInstance()
{
- static MouseQueue *instance = nullptr;
- if (!instance)
- instance = new MouseQueue();
- return *instance;
+ static MouseQueue *instance = nullptr;
+ if (!instance)
+ instance = new MouseQueue();
+ return *instance;
}
void MouseQueue::SetRateDOS(const uint16_t rate_hz)
{
- // Convert rate in Hz to delay in milliseconds
- start_delay.dos_ms = MOUSE_GetDelayFromRateHz(rate_hz);
+ // Convert rate in Hz to delay in milliseconds
+ start_delay.dos_ms = MOUSE_GetDelayFromRateHz(rate_hz);
}
void MouseQueue::SetRatePS2(const uint16_t rate_hz)
{
- // Convert rate in Hz to delay in milliseconds
- start_delay.ps2_ms = MOUSE_GetDelayFromRateHz(rate_hz);
+ // Convert rate in Hz to delay in milliseconds
+ start_delay.ps2_ms = MOUSE_GetDelayFromRateHz(rate_hz);
}
void MouseQueue::AddEvent(MouseEvent &ev)
{
- DEBUG_QUEUE("AddEvent: %s %s",
- ev.request_dos ? "DOS" : "---"
- ev.request_ps2 ? "PS2" : "---");
-
- // Prevent unnecessary processing
- AggregateDosEvents(ev);
- if (!ev.request_dos && !ev.request_ps2)
- return; // event not relevant any more
-
- bool restart_timer = false;
- if (ev.request_dos) {
- if (!HasEventDos() && timer_in_progress && !delay.dos_ms) {
- DEBUG_QUEUE("AddEvent: restart timer for %s", "DOS");
- // We do not want the timer to start only then PS/2
- // event gets processed - for minimum latency it is
- // better to restart the timer
- restart_timer = true;
- }
-
- if (ev.dos_moved) {
- // Mouse has moved
- pending_dos_moved = true;
- } else if (ev.dos_wheel) {
- // Wheel has moved
- pending_dos_wheel = true;
- } else {
- // Button press/release
- pending_dos_button = true;
- pending_dos_buttons_state = ev.dos_buttons;
- }
- }
-
- if (ev.request_ps2) {
- if (!HasEventPS2() && timer_in_progress && !delay.ps2_ms) {
- DEBUG_QUEUE("AddEvent: restart timer for %s", "PS2");
- // We do not want the timer to start only when other event
- // gets processed - for minimum latency it is better to
- // restart the timer
- restart_timer = true;
- }
-
- // Events for PS/2 interface (or virtual machine compatible
- // drivers) do not carry any information - they are only
- // notifications that new data is available
- pending_ps2 |= ev.request_ps2;
- }
-
- if (restart_timer) {
- timer_in_progress = false;
- PIC_RemoveEvents(mouse_queue_tick);
- UpdateDelayCounters();
- StartTimerIfNeeded();
- } else if (!timer_in_progress) {
- DEBUG_QUEUE("ActivateIRQ, in %s", __FUNCTION__);
- // If no timer in progress, handle the event now
- PIC_ActivateIRQ(12);
- }
+ DEBUG_QUEUE("AddEvent: %s %s",
+ ev.request_dos ? "DOS"
+ : "---" ev.request_ps2 ? "PS2"
+ : "---");
+
+ // Prevent unnecessary processing
+ AggregateDosEvents(ev);
+ if (!ev.request_dos && !ev.request_ps2)
+ return; // event not relevant any more
+
+ bool restart_timer = false;
+ if (ev.request_dos) {
+ if (!HasEventDos() && timer_in_progress && !delay.dos_ms) {
+ DEBUG_QUEUE("AddEvent: restart timer for %s", "DOS");
+ // We do not want the timer to start only then PS/2
+ // event gets processed - for minimum latency it is
+ // better to restart the timer
+ restart_timer = true;
+ }
+
+ if (ev.dos_moved) {
+ // Mouse has moved
+ pending_dos_moved = true;
+ } else if (ev.dos_wheel) {
+ // Wheel has moved
+ pending_dos_wheel = true;
+ } else {
+ // Button press/release
+ pending_dos_button = true;
+ pending_dos_buttons_state = ev.dos_buttons;
+ }
+ }
+
+ if (ev.request_ps2) {
+ if (!HasEventPS2() && timer_in_progress && !delay.ps2_ms) {
+ DEBUG_QUEUE("AddEvent: restart timer for %s", "PS2");
+ // We do not want the timer to start only when other
+ // event gets processed - for minimum latency it is
+ // better to restart the timer
+ restart_timer = true;
+ }
+
+ // Events for PS/2 interface (or virtual machine compatible
+ // drivers) do not carry any information - they are only
+ // notifications that new data is available
+ pending_ps2 |= ev.request_ps2;
+ }
+
+ if (restart_timer) {
+ timer_in_progress = false;
+ PIC_RemoveEvents(mouse_queue_tick);
+ UpdateDelayCounters();
+ StartTimerIfNeeded();
+ } else if (!timer_in_progress) {
+ DEBUG_QUEUE("ActivateIRQ, in %s", __FUNCTION__);
+ // If no timer in progress, handle the event now
+ PIC_ActivateIRQ(12);
+ }
}
void MouseQueue::AggregateDosEvents(MouseEvent &ev)
{
- // We do not need duplicate move / wheel events
- if (pending_dos_moved)
- ev.dos_moved = false;
- if (pending_dos_wheel)
- ev.dos_wheel = false;
-
- // Same for mouse buttons - but in such case always update button data
- if (pending_dos_button && ev.dos_button) {
- ev.dos_button = false;
- pending_dos_buttons_state = ev.dos_buttons;
- }
-
- // Check if we still need this event
- if (!ev.dos_moved && !ev.dos_wheel && !ev.dos_button)
- ev.request_dos = false;
+ // We do not need duplicate move / wheel events
+ if (pending_dos_moved)
+ ev.dos_moved = false;
+ if (pending_dos_wheel)
+ ev.dos_wheel = false;
+
+ // Same for mouse buttons - but in such case always update button data
+ if (pending_dos_button && ev.dos_button) {
+ ev.dos_button = false;
+ pending_dos_buttons_state = ev.dos_buttons;
+ }
+
+ // Check if we still need this event
+ if (!ev.dos_moved && !ev.dos_wheel && !ev.dos_button)
+ ev.request_dos = false;
}
void MouseQueue::FetchEvent(MouseEvent &ev)
{
- // First try (prioritized) DOS events
- if (HasReadyEventDos()) {
- DEBUG_QUEUE("FetchEvent %s", "DOS");
- // Mark event as DOS one
- ev.request_dos = true;
- ev.dos_moved = pending_dos_moved;
- ev.dos_button = pending_dos_button;
- ev.dos_wheel = pending_dos_wheel;
- ev.dos_buttons = pending_dos_buttons_state;
- // Set delay before next DOS events
- delay.dos_ms = start_delay.dos_ms;
- // Clear event information
- pending_dos_moved = false;
- pending_dos_button = false;
- pending_dos_wheel = false;
- return;
- }
-
- // Now try PS/2 event
- if (HasReadyEventPS2()) {
- DEBUG_QUEUE("FetchEvent %s", "PS2");
- // Set delay before next PS/2 events
- delay.ps2_ms = start_delay.ps2_ms;
- // PS/2 events are really dummy - merely a notification
- // that something has happened and driver has to react
- ev.request_ps2 = true;
- pending_ps2 = false;
- return;
- }
-
- // Nothing to provide to interrupt handler,
- // event will stay empty
+ // First try (prioritized) DOS events
+ if (HasReadyEventDos()) {
+ DEBUG_QUEUE("FetchEvent %s", "DOS");
+ // Mark event as DOS one
+ ev.request_dos = true;
+ ev.dos_moved = pending_dos_moved;
+ ev.dos_button = pending_dos_button;
+ ev.dos_wheel = pending_dos_wheel;
+ ev.dos_buttons = pending_dos_buttons_state;
+ // Set delay before next DOS events
+ delay.dos_ms = start_delay.dos_ms;
+ // Clear event information
+ pending_dos_moved = false;
+ pending_dos_button = false;
+ pending_dos_wheel = false;
+ return;
+ }
+
+ // Now try PS/2 event
+ if (HasReadyEventPS2()) {
+ DEBUG_QUEUE("FetchEvent %s", "PS2");
+ // Set delay before next PS/2 events
+ delay.ps2_ms = start_delay.ps2_ms;
+ // PS/2 events are really dummy - merely a notification
+ // that something has happened and driver has to react
+ ev.request_ps2 = true;
+ pending_ps2 = false;
+ return;
+ }
+
+ // Nothing to provide to interrupt handler,
+ // event will stay empty
}
void MouseQueue::ClearEventsDOS()
{
- // Clear DOS relevant part of the queue
- pending_dos_moved = false;
- pending_dos_button = false;
- pending_dos_wheel = false;
- delay.dos_ms = 0;
-
- // If timer is not needed, stop it
- if (!HasEventAny()) {
- timer_in_progress = false;
- PIC_RemoveEvents(mouse_queue_tick);
- }
+ // Clear DOS relevant part of the queue
+ pending_dos_moved = false;
+ pending_dos_button = false;
+ pending_dos_wheel = false;
+ delay.dos_ms = 0;
+
+ // If timer is not needed, stop it
+ if (!HasEventAny()) {
+ timer_in_progress = false;
+ PIC_RemoveEvents(mouse_queue_tick);
+ }
}
void MouseQueue::StartTimerIfNeeded()
{
- // Do nothing if timer is already in progress
- if (timer_in_progress)
- return;
-
- bool timer_needed = false;
- uint8_t delay_ms = UINT8_MAX; // dummy delay, will never be used
-
- if (HasEventPS2() || delay.ps2_ms) {
- timer_needed = true;
- delay_ms = std::min(delay_ms, delay.ps2_ms);
- }
- if (HasEventDos() || delay.dos_ms) {
- timer_needed = true;
- delay_ms = std::min(delay_ms, delay.dos_ms);
- }
-
- // If queue is empty and all expired, we need no timer
- if (!timer_needed)
- return;
-
- // Enforce some non-zero delay between events; needed
- // for example if DOS interrupt handler is busy
- delay_ms = std::max(delay_ms, static_cast<uint8_t>(1));
-
- // Start the timer
- DEBUG_QUEUE("StartTimer, %d", delay_ms);
- pic_ticks_start = PIC_Ticks;
- timer_in_progress = true;
- PIC_AddEvent(mouse_queue_tick, static_cast<double>(delay_ms));
+ // Do nothing if timer is already in progress
+ if (timer_in_progress)
+ return;
+
+ bool timer_needed = false;
+ uint8_t delay_ms = UINT8_MAX; // dummy delay, will never be used
+
+ if (HasEventPS2() || delay.ps2_ms) {
+ timer_needed = true;
+ delay_ms = std::min(delay_ms, delay.ps2_ms);
+ }
+ if (HasEventDos() || delay.dos_ms) {
+ timer_needed = true;
+ delay_ms = std::min(delay_ms, delay.dos_ms);
+ }
+
+ // If queue is empty and all expired, we need no timer
+ if (!timer_needed)
+ return;
+
+ // Enforce some non-zero delay between events; needed
+ // for example if DOS interrupt handler is busy
+ delay_ms = std::max(delay_ms, static_cast<uint8_t>(1));
+
+ // Start the timer
+ DEBUG_QUEUE("StartTimer, %d", delay_ms);
+ pic_ticks_start = PIC_Ticks;
+ timer_in_progress = true;
+ PIC_AddEvent(mouse_queue_tick, static_cast<double>(delay_ms));
}
void MouseQueue::UpdateDelayCounters()
{
- const uint32_t tmp = (PIC_Ticks > pic_ticks_start) ? (PIC_Ticks - pic_ticks_start) : 1;
- uint8_t elapsed = static_cast<uint8_t>(
+ const uint32_t tmp = (PIC_Ticks > pic_ticks_start)
+ ? (PIC_Ticks - pic_ticks_start)
+ : 1;
+ uint8_t elapsed = static_cast<uint8_t>(
std::min(tmp, static_cast<uint32_t>(UINT8_MAX)));
- if (!pic_ticks_start)
- elapsed = 1;
+ if (!pic_ticks_start)
+ elapsed = 1;
- auto calc_new_delay = [](const uint8_t delay, const uint8_t elapsed) {
- return static_cast<uint8_t>((delay > elapsed) ? (delay - elapsed)
- : 0);
- };
+ auto calc_new_delay = [](const uint8_t delay, const uint8_t elapsed) {
+ return static_cast<uint8_t>((delay > elapsed) ? (delay - elapsed)
+ : 0);
+ };
- delay.dos_ms = calc_new_delay(delay.dos_ms, elapsed);
- delay.ps2_ms = calc_new_delay(delay.ps2_ms, elapsed);
+ delay.dos_ms = calc_new_delay(delay.dos_ms, elapsed);
+ delay.ps2_ms = calc_new_delay(delay.ps2_ms, elapsed);
- pic_ticks_start = 0;
+ pic_ticks_start = 0;
}
void MouseQueue::Tick()
{
- DEBUG_QUEUE("%s", "Tick");
-
- timer_in_progress = false;
- UpdateDelayCounters();
-
- // If we have anything to pass to guest side via INT74, activate
- // interrupt; otherwise start the timer again
- if (HasReadyEventDos() || HasReadyEventPS2()) {
- DEBUG_QUEUE("ActivateIRQ, in %s", __FUNCTION__);
- PIC_ActivateIRQ(12);
- } else
- StartTimerIfNeeded();
+ DEBUG_QUEUE("%s", "Tick");
+
+ timer_in_progress = false;
+ UpdateDelayCounters();
+
+ // If we have anything to pass to guest side via INT74, activate
+ // interrupt; otherwise start the timer again
+ if (HasReadyEventDos() || HasReadyEventPS2()) {
+ DEBUG_QUEUE("ActivateIRQ, in %s", __FUNCTION__);
+ PIC_ActivateIRQ(12);
+ } else
+ StartTimerIfNeeded();
}
bool MouseQueue::HasEventDos() const
{
- return pending_dos_moved || pending_dos_button || pending_dos_wheel;
+ return pending_dos_moved || pending_dos_button || pending_dos_wheel;
}
bool MouseQueue::HasEventPS2() const
{
- return pending_ps2;
+ return pending_ps2;
}
bool MouseQueue::HasEventAny() const
{
- return HasEventDos() || HasEventPS2();
+ return HasEventDos() || HasEventPS2();
}
bool MouseQueue::HasReadyEventDos() const
{
- return HasEventDos() && !delay.dos_ms &&
- // do not launch DOS callback if it's busy
- !mouse_shared.dos_cb_running;
+ return HasEventDos() && !delay.dos_ms &&
+ // do not launch DOS callback if it's busy
+ !mouse_shared.dos_cb_running;
}
bool MouseQueue::HasReadyEventPS2() const
{
- return HasEventPS2() && !delay.ps2_ms;
+ return HasEventPS2() && !delay.ps2_ms;
}
diff --git a/src/hardware/mouse/mouse_queue.h b/src/hardware/mouse/mouse_queue.h
index 7268cc4d1..e5cfe3c2c 100644
--- a/src/hardware/mouse/mouse_queue.h
+++ b/src/hardware/mouse/mouse_queue.h
@@ -21,64 +21,61 @@
#include "mouse_common.h"
-
class MouseQueue final {
public:
+ static MouseQueue &GetInstance();
- static MouseQueue &GetInstance();
-
- void SetRateDOS(const uint16_t rate_hz); // for DOS mouse driver
- void SetRatePS2(const uint16_t rate_hz); // for PS/2 AUX port mice
+ void SetRateDOS(const uint16_t rate_hz); // for DOS mouse driver
+ void SetRatePS2(const uint16_t rate_hz); // for PS/2 AUX port mice
- void AddEvent(MouseEvent &ev);
- void FetchEvent(MouseEvent &ev);
- void ClearEventsDOS();
- void StartTimerIfNeeded();
+ void AddEvent(MouseEvent &ev);
+ void FetchEvent(MouseEvent &ev);
+ void ClearEventsDOS();
+ void StartTimerIfNeeded();
private:
-
- MouseQueue() = default;
- ~MouseQueue() = delete;
- MouseQueue(const MouseQueue &) = delete;
- MouseQueue &operator=(const MouseQueue &) = delete;
-
- void Tick();
- friend void mouse_queue_tick(uint32_t);
-
- void AggregateDosEvents(MouseEvent &ev);
- void UpdateDelayCounters();
- uint8_t ClampStartDelay(float value_ms) const;
-
- struct { // initial value of delay counters, in milliseconds
- uint8_t dos_ms = 5;
- uint8_t ps2_ms = 5;
- } start_delay = {};
-
- // Time in milliseconds which has to elapse before event can take place
- struct {
- uint8_t dos_ms = 0;
- uint8_t ps2_ms = 0;
- } delay = {};
-
- // Pending events, waiting to be passed to guest system
- bool pending_dos_moved = false;
- bool pending_dos_button = false;
- bool pending_dos_wheel = false;
- bool pending_ps2 = false;
-
- MouseButtons12S pending_dos_buttons_state = 0;
-
- bool timer_in_progress = false;
- uint32_t pic_ticks_start = 0; // PIC_Ticks value when timer starts
-
- // Helpers to check if there are events in the queue
- bool HasEventDos() const;
- bool HasEventPS2() const;
- bool HasEventAny() const;
-
- // Helpers to check if there are events ready to be handled
- bool HasReadyEventDos() const;
- bool HasReadyEventPS2() const;
+ MouseQueue() = default;
+ ~MouseQueue() = delete;
+ MouseQueue(const MouseQueue &) = delete;
+ MouseQueue &operator=(const MouseQueue &) = delete;
+
+ void Tick();
+ friend void mouse_queue_tick(uint32_t);
+
+ void AggregateDosEvents(MouseEvent &ev);
+ void UpdateDelayCounters();
+ uint8_t ClampStartDelay(float value_ms) const;
+
+ struct { // initial value of delay counters, in milliseconds
+ uint8_t dos_ms = 5;
+ uint8_t ps2_ms = 5;
+ } start_delay = {};
+
+ // Time in milliseconds which has to elapse before event can take place
+ struct {
+ uint8_t dos_ms = 0;
+ uint8_t ps2_ms = 0;
+ } delay = {};
+
+ // Pending events, waiting to be passed to guest system
+ bool pending_dos_moved = false;
+ bool pending_dos_button = false;
+ bool pending_dos_wheel = false;
+ bool pending_ps2 = false;
+
+ MouseButtons12S pending_dos_buttons_state = 0;
+
+ bool timer_in_progress = false;
+ uint32_t pic_ticks_start = 0; // PIC_Ticks value when timer starts
+
+ // Helpers to check if there are events in the queue
+ bool HasEventDos() const;
+ bool HasEventPS2() const;
+ bool HasEventAny() const;
+
+ // Helpers to check if there are events ready to be handled
+ bool HasReadyEventDos() const;
+ bool HasReadyEventPS2() const;
};
#endif // DOSBOX_MOUSE_QUEUE_H
diff --git a/src/hardware/mouse/mouseif_dos_driver.cpp b/src/hardware/mouse/mouseif_dos_driver.cpp
index fea52df11..08e5111d6 100644
--- a/src/hardware/mouse/mouseif_dos_driver.cpp
+++ b/src/hardware/mouse/mouseif_dos_driver.cpp
@@ -49,8 +49,8 @@ CHECK_NARROWING();
// - https://www.stanislavs.org/helppc/int_33.html
// - http://www2.ift.ulaval.ca/~marchand/ift17583/dosints.pdf
-static constexpr uint8_t cursor_size_x = 16;
-static constexpr uint8_t cursor_size_y = 16;
+static constexpr uint8_t cursor_size_x = 16;
+static constexpr uint8_t cursor_size_y = 16;
static constexpr uint16_t cursor_size_xy = cursor_size_x * cursor_size_y;
static constexpr uint8_t num_buttons = 3;
@@ -59,27 +59,27 @@ enum class MouseCursor : uint8_t { Software = 0, Hardware = 1, Text = 2 };
// This enum has to be compatible with mask in DOS driver function 0x0c
enum class MouseEventId : uint8_t {
- NotDosEvent = 0,
- MouseHasMoved = 1 << 0,
- PressedLeft = 1 << 1,
- ReleasedLeft = 1 << 2,
- PressedRight = 1 << 3,
- ReleasedRight = 1 << 4,
- PressedMiddle = 1 << 5,
- ReleasedMiddle = 1 << 6,
- WheelHasMoved = 1 << 0,
+ NotDosEvent = 0,
+ MouseHasMoved = 1 << 0,
+ PressedLeft = 1 << 1,
+ ReleasedLeft = 1 << 2,
+ PressedRight = 1 << 3,
+ ReleasedRight = 1 << 4,
+ PressedMiddle = 1 << 5,
+ ReleasedMiddle = 1 << 6,
+ WheelHasMoved = 1 << 0,
};
// These values represent 'hardware' state, not driver state
static MouseButtons12S buttons = 0;
-static float pos_x = 0.0f;
-static float pos_y = 0.0f;
-static int8_t counter_w = 0; // wheel counter
-static bool is_mapped = false; // true = physical mouse is mapped to this interface
-static bool raw_input = true; // true = no host mouse acceleration pre-applied
+static float pos_x = 0.0f;
+static float pos_y = 0.0f;
+static int8_t counter_w = 0; // wheel counter
+static bool is_mapped = false; // true = physical mouse is mapped to this interface
+static bool raw_input = true; // true = no host mouse acceleration pre-applied
-static bool rate_is_set = false; // true = rate was set by DOS application
+static bool rate_is_set = false; // true = rate was set by DOS application
static uint16_t rate_hz = 0;
static uint16_t min_rate_hz = 0;
@@ -87,121 +87,122 @@ static uint16_t min_rate_hz = 0;
// but not necessary visible to the application
static struct {
- // Mouse movement
- float x_rel = 0.0f;
- float y_rel = 0.0f;
- uint16_t x_abs = 0;
- uint16_t y_abs = 0;
-
- // Wheel movement
- int16_t w_rel = 0;
-
- void Reset() {
- x_rel = 0.0f;
- y_rel = 0.0f;
- w_rel = 0;
- }
+ // Mouse movement
+ float x_rel = 0.0f;
+ float y_rel = 0.0f;
+ uint16_t x_abs = 0;
+ uint16_t y_abs = 0;
+
+ // Wheel movement
+ int16_t w_rel = 0;
+
+ void Reset()
+ {
+ x_rel = 0.0f;
+ y_rel = 0.0f;
+ w_rel = 0;
+ }
} pending;
// 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)
constexpr float acceleration_multiplier = 6.0f;
-static MouseSpeedCalculator speed_mickeys(acceleration_multiplier *
- mouse_predefined.acceleration_dos);
+static MouseSpeedCalculator speed_mickeys(
+ acceleration_multiplier *mouse_predefined.acceleration_dos);
static struct { // DOS driver state
- // Structure containing (only!) data which should be
- // saved/restored during task switching
-
- // DANGER, WILL ROBINSON!
- //
- // This whole structure can be read or written from the guest side
- // via virtual DOS driver, functions 0x15 / 0x16 / 0x17.
- // Do not put here any array indices, pointers, or anything that
- // can crash the emulator if filled-in incorrectly, or that can
- // be used by malicious code to escape from emulation!
-
- bool enabled = false; // TODO: make use of this
- bool wheel_api = false; // CuteMouse compatible wheel extension
-
- uint16_t times_pressed[num_buttons] = {0};
- uint16_t times_released[num_buttons] = {0};
- uint16_t last_released_x[num_buttons] = {0};
- uint16_t last_released_y[num_buttons] = {0};
- uint16_t last_pressed_x[num_buttons] = {0};
- uint16_t last_pressed_y[num_buttons] = {0};
- uint16_t last_wheel_moved_x = 0;
- uint16_t last_wheel_moved_y = 0;
-
- int16_t mickey_counter_x = 0;
- int16_t mickey_counter_y = 0;
-
- float mickey_delta_x = 0.0f;
- float mickey_delta_y = 0.0f;
-
- float mickeys_per_pixel_x = 0.0f;
- float mickeys_per_pixel_y = 0.0f;
-
- uint16_t double_speed_threshold = 0; // in mickeys/s
-
- uint16_t granularity_x = 0; // mask
- uint16_t granularity_y = 0;
-
- int16_t update_region_x[2] = {0};
- int16_t update_region_y[2] = {0};
-
- uint16_t language = 0; // language for driver messages, unused
- uint8_t mode = 0;
-
- // sensitivity
- uint8_t sensitivity_x = 0;
- uint8_t sensitivity_y = 0;
- // TODO: find out what it is for (acceleration?), for now
- // just set it to default value on startup
- uint8_t unknown_01 = 50;
-
- float sensitivity_coeff_x = 0;
- float sensitivity_coeff_y = 0;
-
- // mouse position allowed range
- int16_t minpos_x = 0;
- int16_t maxpos_x = 0;
- int16_t minpos_y = 0;
- int16_t maxpos_y = 0;
-
- // mouse cursor
- uint8_t page = 0; // cursor display page number
- bool inhibit_draw = false;
- uint16_t hidden = 0;
- uint16_t oldhidden = 0;
- int16_t clipx = 0;
- int16_t clipy = 0;
- int16_t hot_x = 0; // cursor hot spot, horizontal
- int16_t hot_y = 0; // cursor hot spot, vertical
-
- struct {
- bool enabled = false;
- uint16_t pos_x = 0;
- uint16_t pos_y = 0;
- uint8_t data[cursor_size_xy] = {0};
-
- } background = {};
-
- MouseCursor cursor_type = MouseCursor::Software;
-
- // cursor shape definition
- uint16_t text_and_mask = 0;
- uint16_t text_xor_mask = 0;
- bool user_screen_mask = false;
- bool user_cursor_mask = false;
- uint16_t user_def_screen_mask[cursor_size_x] = {0};
- uint16_t user_def_cursor_mask[cursor_size_y] = {0};
-
- // user callback
- uint16_t user_callback_mask = 0;
- uint16_t user_callback_segment = 0;
- uint16_t user_callback_offset = 0;
+ // Structure containing (only!) data which should be
+ // saved/restored during task switching
+
+ // DANGER, WILL ROBINSON!
+ //
+ // This whole structure can be read or written from the guest side
+ // via virtual DOS driver, functions 0x15 / 0x16 / 0x17.
+ // Do not put here any array indices, pointers, or anything that
+ // can crash the emulator if filled-in incorrectly, or that can
+ // be used by malicious code to escape from emulation!
+
+ bool enabled = false; // TODO: make use of this
+ bool wheel_api = false; // CuteMouse compatible wheel extension
+
+ uint16_t times_pressed[num_buttons] = {0};
+ uint16_t times_released[num_buttons] = {0};
+ uint16_t last_released_x[num_buttons] = {0};
+ uint16_t last_released_y[num_buttons] = {0};
+ uint16_t last_pressed_x[num_buttons] = {0};
+ uint16_t last_pressed_y[num_buttons] = {0};
+ uint16_t last_wheel_moved_x = 0;
+ uint16_t last_wheel_moved_y = 0;
+
+ int16_t mickey_counter_x = 0;
+ int16_t mickey_counter_y = 0;
+
+ float mickey_delta_x = 0.0f;
+ float mickey_delta_y = 0.0f;
+
+ float mickeys_per_pixel_x = 0.0f;
+ float mickeys_per_pixel_y = 0.0f;
+
+ uint16_t double_speed_threshold = 0; // in mickeys/s
+
+ uint16_t granularity_x = 0; // mask
+ uint16_t granularity_y = 0;
+
+ int16_t update_region_x[2] = {0};
+ int16_t update_region_y[2] = {0};
+
+ uint16_t language = 0; // language for driver messages, unused
+ uint8_t mode = 0;
+
+ // sensitivity
+ uint8_t sensitivity_x = 0;
+ uint8_t sensitivity_y = 0;
+ // TODO: find out what it is for (acceleration?), for now
+ // just set it to default value on startup
+ uint8_t unknown_01 = 50;
+
+ float sensitivity_coeff_x = 0;
+ float sensitivity_coeff_y = 0;
+
+ // mouse position allowed range
+ int16_t minpos_x = 0;
+ int16_t maxpos_x = 0;
+ int16_t minpos_y = 0;
+ int16_t maxpos_y = 0;
+
+ // mouse cursor
+ uint8_t page = 0; // cursor display page number
+ bool inhibit_draw = false;
+ uint16_t hidden = 0;
+ uint16_t oldhidden = 0;
+ int16_t clipx = 0;
+ int16_t clipy = 0;
+ int16_t hot_x = 0; // cursor hot spot, horizontal
+ int16_t hot_y = 0; // cursor hot spot, vertical
+
+ struct {
+ bool enabled = false;
+ uint16_t pos_x = 0;
+ uint16_t pos_y = 0;
+ uint8_t data[cursor_size_xy] = {0};
+
+ } background = {};
+
+ MouseCursor cursor_type = MouseCursor::Software;
+
+ // cursor shape definition
+ uint16_t text_and_mask = 0;
+ uint16_t text_xor_mask = 0;
+ bool user_screen_mask = false;
+ bool user_cursor_mask = false;
+ uint16_t user_def_screen_mask[cursor_size_x] = {0};
+ uint16_t user_def_cursor_mask[cursor_size_y] = {0};
+
+ // user callback
+ uint16_t user_callback_mask = 0;
+ uint16_t user_callback_segment = 0;
+ uint16_t user_callback_offset = 0;
} state;
@@ -213,39 +214,39 @@ static RealPt user_callback;
static uint8_t signed_to_reg8(const int8_t x)
{
- if (x >= 0)
- return static_cast<uint8_t>(x);
- else
- // -1 for 0xff, -2 for 0xfe, etc.
- return static_cast<uint8_t>(0x100 + x);
+ if (x >= 0)
+ return static_cast<uint8_t>(x);
+ else
+ // -1 for 0xff, -2 for 0xfe, etc.
+ return static_cast<uint8_t>(0x100 + x);
}
static uint16_t signed_to_reg16(const int16_t x)
{
- if (x >= 0)
- return static_cast<uint16_t>(x);
- else
- // -1 for 0xffff, -2 for 0xfffe, etc.
- return static_cast<uint16_t>(0x10000 + x);
+ if (x >= 0)
+ return static_cast<uint16_t>(x);
+ else
+ // -1 for 0xffff, -2 for 0xfffe, etc.
+ return static_cast<uint16_t>(0x10000 + x);
}
static int16_t reg_to_signed16(const uint16_t x)
{
- if (bit::is(x, b15))
- // 0xffff for -1, 0xfffe for -2, etc.
- return static_cast<int16_t>(x - 0x10000);
- else
- return static_cast<int16_t>(x);
+ if (bit::is(x, b15))
+ // 0xffff for -1, 0xfffe for -2, etc.
+ return static_cast<int16_t>(x - 0x10000);
+ else
+ return static_cast<int16_t>(x);
}
static uint16_t get_pos_x()
{
- return static_cast<uint16_t>(std::lround(pos_x)) & state.granularity_x;
+ return static_cast<uint16_t>(std::lround(pos_x)) & state.granularity_x;
}
static uint16_t get_pos_y()
{
- return static_cast<uint16_t>(std::lround(pos_y)) & state.granularity_y;
+ return static_cast<uint16_t>(std::lround(pos_y)) & state.granularity_y;
}
// ***************************************************************************
@@ -256,13 +257,13 @@ static constexpr uint16_t default_text_and_mask = 0x77FF;
static constexpr uint16_t default_text_xor_mask = 0x7700;
static uint16_t default_screen_mask[cursor_size_y] = {
- 0x3FFF, 0x1FFF, 0x0FFF, 0x07FF, 0x03FF, 0x01FF, 0x00FF, 0x007F,
- 0x003F, 0x001F, 0x01FF, 0x00FF, 0x30FF, 0xF87F, 0xF87F, 0xFCFF
+ 0x3FFF, 0x1FFF, 0x0FFF, 0x07FF, 0x03FF, 0x01FF, 0x00FF, 0x007F,
+ 0x003F, 0x001F, 0x01FF, 0x00FF, 0x30FF, 0xF87F, 0xF87F, 0xFCFF
};
static uint16_t default_cursor_mask[cursor_size_y] = {
- 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7C00, 0x7E00, 0x7F00,
- 0x7F80, 0x7C00, 0x6C00, 0x4600, 0x0600, 0x0300, 0x0300, 0x0000
+ 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7C00, 0x7E00, 0x7F00,
+ 0x7F80, 0x7C00, 0x6C00, 0x4600, 0x0600, 0x0300, 0x0300, 0x0000
};
// ***************************************************************************
@@ -276,41 +277,41 @@ extern void ReadCharAttr(uint16_t col, uint16_t row, uint8_t page, uint16_t *res
static void restore_cursor_background_text()
{
- if (state.hidden || state.inhibit_draw)
- return;
-
- if (state.background.enabled) {
- WriteChar(state.background.pos_x,
- state.background.pos_y,
- real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_PAGE),
- state.background.data[0],
- state.background.data[1],
- true);
- state.background.enabled = false;
- }
+ if (state.hidden || state.inhibit_draw)
+ return;
+
+ if (state.background.enabled) {
+ WriteChar(state.background.pos_x,
+ state.background.pos_y,
+ real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_PAGE),
+ state.background.data[0],
+ state.background.data[1],
+ true);
+ state.background.enabled = false;
+ }
}
static void draw_cursor_text()
{
- // Restore Background
- restore_cursor_background_text();
-
- // Check if cursor in update region
- auto x = get_pos_x();
- auto y = get_pos_y();
- if ((y <= state.update_region_y[1]) && (y >= state.update_region_y[0]) &&
- (x <= state.update_region_x[1]) && (x >= state.update_region_x[0])) {
- return;
- }
-
- // Save Background
- state.background.pos_x = static_cast<uint16_t>(x / 8);
- state.background.pos_y = static_cast<uint16_t>(y / 8);
- if (state.mode < 2)
- state.background.pos_x = state.background.pos_x / 2;
-
- // use current page (CV program)
- uint8_t page = real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_PAGE);
+ // Restore Background
+ restore_cursor_background_text();
+
+ // Check if cursor in update region
+ auto x = get_pos_x();
+ auto y = get_pos_y();
+ if ((y <= state.update_region_y[1]) && (y >= state.update_region_y[0]) &&
+ (x <= state.update_region_x[1]) && (x >= state.update_region_x[0])) {
+ return;
+ }
+
+ // Save Background
+ state.background.pos_x = static_cast<uint16_t>(x / 8);
+ state.background.pos_y = static_cast<uint16_t>(y / 8);
+ if (state.mode < 2)
+ state.background.pos_x = state.background.pos_x / 2;
+
+ // use current page (CV program)
+ uint8_t page = real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_PAGE);
if (state.cursor_type == MouseCursor::Software) {
uint16_t result = 0;
@@ -333,20 +334,22 @@ static void draw_cursor_text()
read_high_byte(result),
true);
} else {
- uint16_t address = static_cast<uint16_t>(page *
- real_readw(BIOSMEM_SEG, BIOSMEM_PAGE_SIZE));
- address = static_cast<uint16_t>(address +
- (state.background.pos_y * real_readw(BIOSMEM_SEG, BIOSMEM_NB_COLS) +
- state.background.pos_x) * 2);
- address /= 2;
- uint16_t cr = real_readw(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
- IO_Write(cr, 0xe);
- IO_Write(static_cast<io_port_t>(cr + 1),
- static_cast<uint8_t>((address >> 8) & 0xff));
- IO_Write(cr, 0xf);
- IO_Write(static_cast<io_port_t>(cr + 1),
- static_cast<uint8_t>(address & 0xff));
- }
+ uint16_t address = static_cast<uint16_t>(
+ page * real_readw(BIOSMEM_SEG, BIOSMEM_PAGE_SIZE));
+ address = static_cast<uint16_t>(
+ address + (state.background.pos_y *
+ real_readw(BIOSMEM_SEG, BIOSMEM_NB_COLS) +
+ state.background.pos_x) *
+ 2);
+ address /= 2;
+ uint16_t cr = real_readw(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
+ IO_Write(cr, 0xe);
+ IO_Write(static_cast<io_port_t>(cr + 1),
+ static_cast<uint8_t>((address >> 8) & 0xff));
+ IO_Write(cr, 0xf);
+ IO_Write(static_cast<io_port_t>(cr + 1),
+ static_cast<uint8_t>(address & 0xff));
+ }
}
// ***************************************************************************
@@ -354,218 +357,221 @@ static void draw_cursor_text()
// ***************************************************************************
static struct {
-
- uint8_t sequ_address = 0;
- uint8_t sequ_data = 0;
- uint8_t grdc_address[9] = {0};
+ uint8_t sequ_address = 0;
+ uint8_t sequ_data = 0;
+ uint8_t grdc_address[9] = {0};
} vga_regs;
static void save_vga_registers()
{
- if (IS_VGA_ARCH) {
- for (uint8_t i = 0; i < 9; i++) {
- IO_Write(VGAREG_GRDC_ADDRESS, i);
- vga_regs.grdc_address[i] = IO_Read(VGAREG_GRDC_DATA);
- }
- // Setup some default values in GFX regs that should work
- IO_Write(VGAREG_GRDC_ADDRESS, 3);
- IO_Write(VGAREG_GRDC_DATA, 0); // disable rotate and operation
- IO_Write(VGAREG_GRDC_ADDRESS, 5);
- IO_Write(VGAREG_GRDC_DATA, vga_regs.grdc_address[5] & 0xf0); // Force read/write mode 0
-
- // Set Map to all planes. Celtic Tales
- vga_regs.sequ_address = IO_Read(VGAREG_SEQU_ADDRESS);
- IO_Write(VGAREG_SEQU_ADDRESS, 2);
- vga_regs.sequ_data = IO_Read(VGAREG_SEQU_DATA);
- IO_Write(VGAREG_SEQU_DATA, 0xF);
- } else if (machine == MCH_EGA) {
- // Set Map to all planes.
- IO_Write(VGAREG_SEQU_ADDRESS, 2);
- IO_Write(VGAREG_SEQU_DATA, 0xF);
- }
+ if (IS_VGA_ARCH) {
+ for (uint8_t i = 0; i < 9; i++) {
+ IO_Write(VGAREG_GRDC_ADDRESS, i);
+ vga_regs.grdc_address[i] = IO_Read(VGAREG_GRDC_DATA);
+ }
+ // Setup some default values in GFX regs that should work
+ IO_Write(VGAREG_GRDC_ADDRESS, 3);
+ IO_Write(VGAREG_GRDC_DATA, 0); // disable rotate and operation
+ IO_Write(VGAREG_GRDC_ADDRESS, 5);
+ IO_Write(VGAREG_GRDC_DATA,
+ vga_regs.grdc_address[5] & 0xf0); // Force read/write
+ // mode 0
+
+ // Set Map to all planes. Celtic Tales
+ vga_regs.sequ_address = IO_Read(VGAREG_SEQU_ADDRESS);
+ IO_Write(VGAREG_SEQU_ADDRESS, 2);
+ vga_regs.sequ_data = IO_Read(VGAREG_SEQU_DATA);
+ IO_Write(VGAREG_SEQU_DATA, 0xF);
+ } else if (machine == MCH_EGA) {
+ // Set Map to all planes.
+ IO_Write(VGAREG_SEQU_ADDRESS, 2);
+ IO_Write(VGAREG_SEQU_DATA, 0xF);
+ }
}
static void restore_vga_registers()
{
- if (IS_VGA_ARCH) {
- for (uint8_t i = 0; i < 9; i++) {
- IO_Write(VGAREG_GRDC_ADDRESS, i);
- IO_Write(VGAREG_GRDC_DATA, vga_regs.grdc_address[i]);
- }
-
- IO_Write(VGAREG_SEQU_ADDRESS, 2);
- IO_Write(VGAREG_SEQU_DATA, vga_regs.sequ_data);
- IO_Write(VGAREG_SEQU_ADDRESS, vga_regs.sequ_address);
- }
+ if (IS_VGA_ARCH) {
+ for (uint8_t i = 0; i < 9; i++) {
+ IO_Write(VGAREG_GRDC_ADDRESS, i);
+ IO_Write(VGAREG_GRDC_DATA, vga_regs.grdc_address[i]);
+ }
+
+ IO_Write(VGAREG_SEQU_ADDRESS, 2);
+ IO_Write(VGAREG_SEQU_DATA, vga_regs.sequ_data);
+ IO_Write(VGAREG_SEQU_ADDRESS, vga_regs.sequ_address);
+ }
}
static void clip_cursor_area(int16_t &x1, int16_t &x2, int16_t &y1, int16_t &y2,
uint16_t &addx1, uint16_t &addx2, uint16_t &addy)
{
- addx1 = 0;
- addx2 = 0;
- addy = 0;
- // Clip up
- if (y1 < 0) {
- addy = static_cast<uint16_t>(addy - y1);
- y1 = 0;
- }
- // Clip down
- if (y2 > state.clipy) {
- y2 = state.clipy;
- };
- // Clip left
- if (x1 < 0) {
- addx1 = static_cast<uint16_t>(addx1 - x1);
- x1 = 0;
- };
- // Clip right
- if (x2 > state.clipx) {
- addx2 = static_cast<uint16_t>(x2 - state.clipx);
- x2 = state.clipx;
- };
+ addx1 = 0;
+ addx2 = 0;
+ addy = 0;
+ // Clip up
+ if (y1 < 0) {
+ addy = static_cast<uint16_t>(addy - y1);
+ y1 = 0;
+ }
+ // Clip down
+ if (y2 > state.clipy) {
+ y2 = state.clipy;
+ };
+ // Clip left
+ if (x1 < 0) {
+ addx1 = static_cast<uint16_t>(addx1 - x1);
+ x1 = 0;
+ };
+ // Clip right
+ if (x2 > state.clipx) {
+ addx2 = static_cast<uint16_t>(x2 - state.clipx);
+ x2 = state.clipx;
+ };
}
static void restore_cursor_background()
{
- if (state.hidden || state.inhibit_draw || !state.background.enabled)
- return;
-
- save_vga_registers();
-
- // Restore background
- uint16_t addx1, addx2, addy;
- uint16_t data_pos = 0;
- int16_t x1 = static_cast<int16_t>(state.background.pos_x);
- int16_t y1 = static_cast<int16_t>(state.background.pos_y);
- int16_t x2 = static_cast<int16_t>(x1 + cursor_size_x - 1);
- int16_t y2 = static_cast<int16_t>(y1 + cursor_size_y - 1);
-
- clip_cursor_area(x1, x2, y1, y2, addx1, addx2, addy);
-
- data_pos = static_cast<uint16_t>(addy * cursor_size_x);
- for (int16_t y = y1; y <= y2; y++) {
- data_pos = static_cast<uint16_t>(data_pos + addx1);
- for (int16_t x = x1; x <= x2; x++) {
- INT10_PutPixel(static_cast<uint16_t>(x),
- static_cast<uint16_t>(y),
- state.page,
- state.background.data[data_pos++]);
- };
- data_pos = static_cast<uint16_t>(data_pos + addx2);
- };
- state.background.enabled = false;
-
- restore_vga_registers();
+ if (state.hidden || state.inhibit_draw || !state.background.enabled)
+ return;
+
+ save_vga_registers();
+
+ // Restore background
+ uint16_t addx1, addx2, addy;
+ uint16_t data_pos = 0;
+ int16_t x1 = static_cast<int16_t>(state.background.pos_x);
+ int16_t y1 = static_cast<int16_t>(state.background.pos_y);
+ int16_t x2 = static_cast<int16_t>(x1 + cursor_size_x - 1);
+ int16_t y2 = static_cast<int16_t>(y1 + cursor_size_y - 1);
+
+ clip_cursor_area(x1, x2, y1, y2, addx1, addx2, addy);
+
+ data_pos = static_cast<uint16_t>(addy * cursor_size_x);
+ for (int16_t y = y1; y <= y2; y++) {
+ data_pos = static_cast<uint16_t>(data_pos + addx1);
+ for (int16_t x = x1; x <= x2; x++) {
+ INT10_PutPixel(static_cast<uint16_t>(x),
+ static_cast<uint16_t>(y),
+ state.page,
+ state.background.data[data_pos++]);
+ };
+ data_pos = static_cast<uint16_t>(data_pos + addx2);
+ };
+ state.background.enabled = false;
+
+ restore_vga_registers();
}
void MOUSEDOS_DrawCursor()
{
- if (state.hidden || state.inhibit_draw)
- return;
- INT10_SetCurMode();
- // In Textmode ?
- if (CurMode->type == M_TEXT) {
- draw_cursor_text();
- return;
- }
-
- // Check video page. Seems to be ignored for text mode.
- // hence the text mode handled above this
- // >>> removed because BIOS page is not actual page in some cases, e.g.
- // QQP games
- // if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE) != state.page)
- // return;
-
- // Check if cursor in update region
- /* if ((get_pos_x() >= state.update_region_x[0]) && (get_pos_y() <=
- state.update_region_x[1]) && (get_pos_y() >= state.update_region_y[0])
- && (GETPOS_Y <= state.update_region_y[1])) { if
- (CurMode->type==M_TEXT16) restore_cursor_background_text(); else
- restore_cursor_background();
- --mouse.shown;
- return;
- }
- */ /*Not sure yet what to do update region should be set to ??? */
-
- // Get Clipping ranges
-
- state.clipx = static_cast<int16_t>((Bits)CurMode->swidth - 1); // Get from BIOS?
- state.clipy = static_cast<int16_t>((Bits)CurMode->sheight - 1);
-
- // might be vidmode == 0x13?2:1
- int16_t xratio = 640;
- if (CurMode->swidth > 0)
- xratio = static_cast<int16_t>(xratio / CurMode->swidth);
- if (xratio == 0)
- xratio = 1;
-
- restore_cursor_background();
-
- save_vga_registers();
-
- // Save Background
- uint16_t addx1, addx2, addy;
- uint16_t data_pos = 0;
- int16_t x1 = static_cast<int16_t>(get_pos_x() / xratio - state.hot_x);
- int16_t y1 = static_cast<int16_t>(get_pos_y() - state.hot_y);
- int16_t x2 = static_cast<int16_t>(x1 + cursor_size_x - 1);
- int16_t y2 = static_cast<int16_t>(y1 + cursor_size_y - 1);
-
- clip_cursor_area(x1, x2, y1, y2, addx1, addx2, addy);
-
- data_pos = static_cast<uint16_t>(addy * cursor_size_x);
- for (int16_t y = y1; y <= y2; y++) {
- data_pos = static_cast<uint16_t>(data_pos + addx1);
- for (int16_t x = x1; x <= x2; x++) {
- INT10_GetPixel(static_cast<uint16_t>(x),
- static_cast<uint16_t>(y),
- state.page,
- &state.background.data[data_pos++]);
- };
- data_pos = static_cast<uint16_t>(data_pos + addx2);
- };
- state.background.enabled = true;
- state.background.pos_x = static_cast<uint16_t>(get_pos_x() / xratio - state.hot_x);
- state.background.pos_y = static_cast<uint16_t>(get_pos_y() - state.hot_y);
-
- // Draw Mousecursor
- data_pos = static_cast<uint16_t>(addy * cursor_size_x);
- const auto screen_mask = state.user_screen_mask ? state.user_def_screen_mask
- : default_screen_mask;
- const auto cursor_mask = state.user_cursor_mask ? state.user_def_cursor_mask
- : default_cursor_mask;
- for (int16_t y = y1; y <= y2; y++) {
- uint16_t sc_mask = screen_mask[addy + y - y1];
- uint16_t cu_mask = cursor_mask[addy + y - y1];
- if (addx1 > 0) {
- sc_mask = static_cast<uint16_t>(sc_mask << addx1);
- cu_mask = static_cast<uint16_t>(cu_mask << addx1);
- data_pos = static_cast<uint16_t>(data_pos + addx1);
- };
- for (int16_t x = x1; x <= x2; x++) {
- constexpr auto highest_bit = (1 << (cursor_size_x - 1));
- uint8_t pixel = 0;
- // ScreenMask
- if (sc_mask & highest_bit)
- pixel = state.background.data[data_pos];
- // CursorMask
- if (cu_mask & highest_bit)
- pixel = pixel ^ 0x0f;
- sc_mask = static_cast<uint16_t>(sc_mask << 1);
- cu_mask = static_cast<uint16_t>(cu_mask << 1);
- // Set Pixel
- INT10_PutPixel(static_cast<uint16_t>(x),
- static_cast<uint16_t>(y),
- state.page,
- pixel);
- ++data_pos;
- };
- data_pos = static_cast<uint16_t>(addx2 + data_pos);
- };
-
- restore_vga_registers();
+ if (state.hidden || state.inhibit_draw)
+ return;
+ INT10_SetCurMode();
+ // In Textmode ?
+ if (CurMode->type == M_TEXT) {
+ draw_cursor_text();
+ return;
+ }
+
+ // Check video page. Seems to be ignored for text mode.
+ // hence the text mode handled above this
+ // >>> removed because BIOS page is not actual page in some cases, e.g.
+ // QQP games
+ // if (real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE) != state.page)
+ // return;
+
+ // Check if cursor in update region
+ /* if ((get_pos_x() >= state.update_region_x[0]) && (get_pos_y() <=
+ state.update_region_x[1]) && (get_pos_y() >= state.update_region_y[0])
+ && (GETPOS_Y <= state.update_region_y[1])) { if
+ (CurMode->type==M_TEXT16) restore_cursor_background_text(); else
+ restore_cursor_background();
+ --mouse.shown;
+ return;
+ }
+ */ /*Not sure yet what to do update region should be set to ??? */
+
+ // Get Clipping ranges
+
+ state.clipx = static_cast<int16_t>((Bits)CurMode->swidth - 1); // Get from
+ // BIOS?
+ state.clipy = static_cast<int16_t>((Bits)CurMode->sheight - 1);
+
+ // might be vidmode == 0x13?2:1
+ int16_t xratio = 640;
+ if (CurMode->swidth > 0)
+ xratio = static_cast<int16_t>(xratio / CurMode->swidth);
+ if (xratio == 0)
+ xratio = 1;
+
+ restore_cursor_background();
+
+ save_vga_registers();
+
+ // Save Background
+ uint16_t addx1, addx2, addy;
+ uint16_t data_pos = 0;
+ int16_t x1 = static_cast<int16_t>(get_pos_x() / xratio - state.hot_x);
+ int16_t y1 = static_cast<int16_t>(get_pos_y() - state.hot_y);
+ int16_t x2 = static_cast<int16_t>(x1 + cursor_size_x - 1);
+ int16_t y2 = static_cast<int16_t>(y1 + cursor_size_y - 1);
+
+ clip_cursor_area(x1, x2, y1, y2, addx1, addx2, addy);
+
+ data_pos = static_cast<uint16_t>(addy * cursor_size_x);
+ for (int16_t y = y1; y <= y2; y++) {
+ data_pos = static_cast<uint16_t>(data_pos + addx1);
+ for (int16_t x = x1; x <= x2; x++) {
+ INT10_GetPixel(static_cast<uint16_t>(x),
+ static_cast<uint16_t>(y),
+ state.page,
+ &state.background.data[data_pos++]);
+ };
+ data_pos = static_cast<uint16_t>(data_pos + addx2);
+ };
+ state.background.enabled = true;
+ state.background.pos_x = static_cast<uint16_t>(get_pos_x() / xratio -
+ state.hot_x);
+ state.background.pos_y = static_cast<uint16_t>(get_pos_y() - state.hot_y);
+
+ // Draw Mousecursor
+ data_pos = static_cast<uint16_t>(addy * cursor_size_x);
+ const auto screen_mask = state.user_screen_mask ? state.user_def_screen_mask
+ : default_screen_mask;
+ const auto cursor_mask = state.user_cursor_mask ? state.user_def_cursor_mask
+ : default_cursor_mask;
+ for (int16_t y = y1; y <= y2; y++) {
+ uint16_t sc_mask = screen_mask[addy + y - y1];
+ uint16_t cu_mask = cursor_mask[addy + y - y1];
+ if (addx1 > 0) {
+ sc_mask = static_cast<uint16_t>(sc_mask << addx1);
+ cu_mask = static_cast<uint16_t>(cu_mask << addx1);
+ data_pos = static_cast<uint16_t>(data_pos + addx1);
+ };
+ for (int16_t x = x1; x <= x2; x++) {
+ constexpr auto highest_bit = (1 << (cursor_size_x - 1));
+ uint8_t pixel = 0;
+ // ScreenMask
+ if (sc_mask & highest_bit)
+ pixel = state.background.data[data_pos];
+ // CursorMask
+ if (cu_mask & highest_bit)
+ pixel = pixel ^ 0x0f;
+ sc_mask = static_cast<uint16_t>(sc_mask << 1);
+ cu_mask = static_cast<uint16_t>(cu_mask << 1);
+ // Set Pixel
+ INT10_PutPixel(static_cast<uint16_t>(x),
+ static_cast<uint16_t>(y),
+ state.page,
+ pixel);
+ ++data_pos;
+ };
+ data_pos = static_cast<uint16_t>(addx2 + data_pos);
+ };
+
+ restore_vga_registers();
}
// ***************************************************************************
@@ -574,1109 +580,1148 @@ void MOUSEDOS_DrawCursor()
static void update_driver_active()
{
- mouse_shared.active_dos = (state.user_callback_mask != 0);
- MOUSE_NotifyStateChanged();
+ mouse_shared.active_dos = (state.user_callback_mask != 0);
+ MOUSE_NotifyStateChanged();
}
static uint8_t get_reset_wheel_8bit()
{
- if (!state.wheel_api)
- return 0;
+ if (!state.wheel_api)
+ return 0;
- const auto tmp = counter_w;
- counter_w = 0; // reading always clears the counter
+ const auto tmp = counter_w;
+ counter_w = 0; // reading always clears the counter
- // 0xff for -1, 0xfe for -2, etc.
- return signed_to_reg8(tmp);
+ // 0xff for -1, 0xfe for -2, etc.
+ return signed_to_reg8(tmp);
}
static uint16_t get_reset_wheel_16bit()
{
- if (!state.wheel_api)
- return 0;
+ if (!state.wheel_api)
+ return 0;
- const int16_t tmp = counter_w;
- counter_w = 0; // reading always clears the counter
+ const int16_t tmp = counter_w;
+ counter_w = 0; // reading always clears the counter
- return signed_to_reg16(tmp);
+ return signed_to_reg16(tmp);
}
static void set_mickey_pixel_rate(const int16_t ratio_x, const int16_t ratio_y)
{
- // According to https://www.stanislavs.org/helppc/int_33-f.html
- // the values should be non-negative (highest bit not set)
-
- if ((ratio_x > 0) && (ratio_y > 0)) {
- // ratio = number of mickeys per 8 pixels
- constexpr auto pixels = 8.0f;
- state.mickeys_per_pixel_x = static_cast<float>(ratio_x) / pixels;
- state.mickeys_per_pixel_y = static_cast<float>(ratio_y) / pixels;
- }
+ // According to https://www.stanislavs.org/helppc/int_33-f.html
+ // the values should be non-negative (highest bit not set)
+
+ if ((ratio_x > 0) && (ratio_y > 0)) {
+ // ratio = number of mickeys per 8 pixels
+ constexpr auto pixels = 8.0f;
+ state.mickeys_per_pixel_x = static_cast<float>(ratio_x) / pixels;
+ state.mickeys_per_pixel_y = static_cast<float>(ratio_y) / pixels;
+ }
}
static void set_double_speed_threshold(const uint16_t threshold)
{
- if (threshold)
- state.double_speed_threshold = threshold;
- else
- state.double_speed_threshold = 64; // default value
+ if (threshold)
+ state.double_speed_threshold = threshold;
+ else
+ state.double_speed_threshold = 64; // default value
}
static void set_sensitivity(const uint16_t sensitivity_x,
- const uint16_t sensitivity_y,
- const uint16_t unknown)
+ const uint16_t sensitivity_y, const uint16_t unknown)
{
- const auto tmp_x = std::min(static_cast<uint16_t>(100), sensitivity_x);
- const auto tmp_y = std::min(static_cast<uint16_t>(100), sensitivity_y);
- const auto tmp_u = std::min(static_cast<uint16_t>(100), unknown);
+ const auto tmp_x = std::min(static_cast<uint16_t>(100), sensitivity_x);
+ const auto tmp_y = std::min(static_cast<uint16_t>(100), sensitivity_y);
+ const auto tmp_u = std::min(static_cast<uint16_t>(100), unknown);
- state.sensitivity_x = static_cast<uint8_t>(tmp_x);
- state.sensitivity_y = static_cast<uint8_t>(tmp_y);
- state.unknown_01 = static_cast<uint8_t>(tmp_u);
+ state.sensitivity_x = static_cast<uint8_t>(tmp_x);
+ state.sensitivity_y = static_cast<uint8_t>(tmp_y);
+ state.unknown_01 = static_cast<uint8_t>(tmp_u);
- // It is unclear how the original mouse driver handles sensitivity,
- // but one can observe that setting value 0 stops the mouse movement
- // completely, 50 is the default, and 100 seems to more or less
- // dobule it. Linear sensitivity should be good enough.
+ // It is unclear how the original mouse driver handles sensitivity,
+ // but one can observe that setting value 0 stops the mouse movement
+ // completely, 50 is the default, and 100 seems to more or less
+ // dobule it. Linear sensitivity should be good enough.
- state.sensitivity_coeff_x = state.sensitivity_x / 50.0f;
- state.sensitivity_coeff_y = state.sensitivity_y / 50.0f;
+ state.sensitivity_coeff_x = state.sensitivity_x / 50.0f;
+ state.sensitivity_coeff_y = state.sensitivity_y / 50.0f;
}
static void notify_interface_rate()
{
- // Real mouse drivers set the PS/2 mouse sampling rate
- // to the following rates:
- // - A4 Pointing Device 8.04A 100 Hz
- // - CuteMouse 2.1b4 100 Hz
- // - Genius Dynamic Mouse 9.20 60 Hz
- // - Microsoft Mouse 8.20 60 Hz
- // - Mouse Systems 8.00 100 Hz
- // and the most common serial mice were 1200 bauds, which gives
- // approx. 40 Hz sampling rate limit due to COM port bandwidth.
-
- // Original DOSBox uses 200 Hz for callbacks, but the internal
- // states (buttons, mickey counters) are updated in realtime.
- // This is too much (at least Ultima Underworld I and II do not
- // like this).
-
- // Set default value to 200 Hz (which is the maximum setting for
- // PS/2 mice - and hopefully this is safe (if it's not, user can
- // always adjust it in configuration file or with MOUSECTL.COM).
-
- constexpr uint16_t rate_default_hz = 200;
-
- if (rate_is_set)
- // Rate was set by guest application - use this value. The minimum
- // will be enforced by MouseInterface nevertheless
- MouseInterface::GetDOS()->NotifyInterfaceRate(rate_hz);
- else if (min_rate_hz)
- // If user set the minimum mouse rate - follow it
- MouseInterface::GetDOS()->NotifyInterfaceRate(min_rate_hz);
- else
- // No user setting in effect - use default value
- MouseInterface::GetDOS()->NotifyInterfaceRate(rate_default_hz);
+ // Real mouse drivers set the PS/2 mouse sampling rate
+ // to the following rates:
+ // - A4 Pointing Device 8.04A 100 Hz
+ // - CuteMouse 2.1b4 100 Hz
+ // - Genius Dynamic Mouse 9.20 60 Hz
+ // - Microsoft Mouse 8.20 60 Hz
+ // - Mouse Systems 8.00 100 Hz
+ // and the most common serial mice were 1200 bauds, which gives
+ // approx. 40 Hz sampling rate limit due to COM port bandwidth.
+
+ // Original DOSBox uses 200 Hz for callbacks, but the internal
+ // states (buttons, mickey counters) are updated in realtime.
+ // This is too much (at least Ultima Underworld I and II do not
+ // like this).
+
+ // Set default value to 200 Hz (which is the maximum setting for
+ // PS/2 mice - and hopefully this is safe (if it's not, user can
+ // always adjust it in configuration file or with MOUSECTL.COM).
+
+ constexpr uint16_t rate_default_hz = 200;
+
+ if (rate_is_set)
+ // Rate was set by guest application - use this value. The
+ // minimum will be enforced by MouseInterface nevertheless
+ MouseInterface::GetDOS()->NotifyInterfaceRate(rate_hz);
+ else if (min_rate_hz)
+ // If user set the minimum mouse rate - follow it
+ MouseInterface::GetDOS()->NotifyInterfaceRate(min_rate_hz);
+ else
+ // No user setting in effect - use default value
+ MouseInterface::GetDOS()->NotifyInterfaceRate(rate_default_hz);
}
static void set_interrupt_rate(const uint16_t rate_id)
{
- uint16_t val_hz;
-
- switch (rate_id) {
- case 0: val_hz = 0; break; // no events, TODO: this should be simulated
- case 1: val_hz = 30; break;
- case 2: val_hz = 50; break;
- case 3: val_hz = 100; break;
- default: val_hz = 200; break; // above 4 is not suported, set max
- }
-
- if (val_hz) {
- rate_is_set = true;
- rate_hz = val_hz;
- notify_interface_rate();
- }
+ uint16_t val_hz;
+
+ switch (rate_id) {
+ case 0: val_hz = 0; break; // no events, TODO: this should be simulated
+ case 1: val_hz = 30; break;
+ case 2: val_hz = 50; break;
+ case 3: val_hz = 100; break;
+ default: val_hz = 200; break; // above 4 is not suported, set max
+ }
+
+ if (val_hz) {
+ rate_is_set = true;
+ rate_hz = val_hz;
+ notify_interface_rate();
+ }
}
static void reset_hardware()
{
- // Resetting the wheel API status in reset() might seem to be a more
- // logical approach, but this is clearly not what CuteMouse does;
- // if this is done in reset(), the DN2 is unable to use mouse wheel
- state.wheel_api = false;
- counter_w = 0;
+ // Resetting the wheel API status in reset() might seem to be a more
+ // logical approach, but this is clearly not what CuteMouse does;
+ // if this is done in reset(), the DN2 is unable to use mouse wheel
+ state.wheel_api = false;
+ counter_w = 0;
- PIC_SetIRQMask(12, false); // lower IRQ line
+ PIC_SetIRQMask(12, false); // lower IRQ line
- // Reset mouse refresh rate
- rate_is_set = false;
- notify_interface_rate();
+ // Reset mouse refresh rate
+ rate_is_set = false;
+ notify_interface_rate();
}
void MOUSEDOS_NotifyMinRate(const uint16_t value_hz)
{
- min_rate_hz = value_hz;
+ min_rate_hz = value_hz;
- // If rate was set by a DOS application, don't change it
- if (rate_is_set)
- return;
+ // If rate was set by a DOS application, don't change it
+ if (rate_is_set)
+ return;
- notify_interface_rate();
+ notify_interface_rate();
}
void MOUSEDOS_BeforeNewVideoMode()
{
- if (CurMode->type != M_TEXT)
- restore_cursor_background();
- else
- restore_cursor_background_text();
-
- state.hidden = 1;
- state.oldhidden = 1;
- state.background.enabled = false;
+ if (CurMode->type != M_TEXT)
+ restore_cursor_background();
+ else
+ restore_cursor_background_text();
+
+ state.hidden = 1;
+ state.oldhidden = 1;
+ state.background.enabled = false;
}
// TODO: Does way to much. Many things should be moved to mouse reset one day
void MOUSEDOS_AfterNewVideoMode(const bool setmode)
{
- state.inhibit_draw = false;
- // Get the correct resolution from the current video mode
- uint8_t mode = mem_readb(BIOS_VIDEO_MODE);
- if (setmode && mode == state.mode)
- LOG(LOG_MOUSE, LOG_NORMAL)("New video mode is the same as the old");
- state.granularity_x = 0xffff;
- state.granularity_y = 0xffff;
- switch (mode) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x07: {
- state.granularity_x = (mode < 2) ? 0xfff0 : 0xfff8;
- state.granularity_y = 0xfff8;
- Bitu rows = IS_EGAVGA_ARCH ? real_readb(BIOSMEM_SEG, BIOSMEM_NB_ROWS) : 24;
- if ((rows == 0) || (rows > 250))
- rows = 24;
- state.maxpos_y = static_cast<int16_t>(8 * (rows + 1) - 1);
- break;
- }
- case 0x04:
- case 0x05:
- case 0x06:
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0d:
- case 0x0e:
- case 0x13: // 320x200 VGA
- if (mode == 0x0d || mode == 0x13)
- state.granularity_x = 0xfffe;
- state.maxpos_y = 199;
- break;
- case 0x0f:
- case 0x10: state.maxpos_y = 349; break;
- case 0x11:
- case 0x12: state.maxpos_y = 479; break;
- default:
- LOG(LOG_MOUSE, LOG_ERROR)("Unhandled videomode %X on reset", mode);
- state.inhibit_draw = true;
- return;
- }
-
- state.mode = mode;
- state.maxpos_x = 639;
- state.minpos_x = 0;
- state.minpos_y = 0;
- state.hot_x = 0;
- state.hot_y = 0;
- state.user_screen_mask = false;
- state.user_cursor_mask = false;
- state.text_and_mask = default_text_and_mask;
- state.text_xor_mask = default_text_xor_mask;
- state.page = 0;
- state.update_region_y[1] = -1; // offscreen
- state.cursor_type = MouseCursor::Software;
- state.enabled = true;
-
- MOUSE_NotifyResetDOS();
+ state.inhibit_draw = false;
+ // Get the correct resolution from the current video mode
+ uint8_t mode = mem_readb(BIOS_VIDEO_MODE);
+ if (setmode && mode == state.mode)
+ LOG(LOG_MOUSE, LOG_NORMAL)
+ ("New video mode is the same as the old");
+ state.granularity_x = 0xffff;
+ state.granularity_y = 0xffff;
+ switch (mode) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x07: {
+ state.granularity_x = (mode < 2) ? 0xfff0 : 0xfff8;
+ state.granularity_y = 0xfff8;
+ Bitu rows = IS_EGAVGA_ARCH
+ ? real_readb(BIOSMEM_SEG, BIOSMEM_NB_ROWS)
+ : 24;
+ if ((rows == 0) || (rows > 250))
+ rows = 24;
+ state.maxpos_y = static_cast<int16_t>(8 * (rows + 1) - 1);
+ break;
+ }
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ case 0x0e:
+ case 0x13: // 320x200 VGA
+ if (mode == 0x0d || mode == 0x13)
+ state.granularity_x = 0xfffe;
+ state.maxpos_y = 199;
+ break;
+ case 0x0f:
+ case 0x10: state.maxpos_y = 349; break;
+ case 0x11:
+ case 0x12: state.maxpos_y = 479; break;
+ default:
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Unhandled videomode %X on reset", mode);
+ state.inhibit_draw = true;
+ return;
+ }
+
+ state.mode = mode;
+ state.maxpos_x = 639;
+ state.minpos_x = 0;
+ state.minpos_y = 0;
+ state.hot_x = 0;
+ state.hot_y = 0;
+ state.user_screen_mask = false;
+ state.user_cursor_mask = false;
+ state.text_and_mask = default_text_and_mask;
+ state.text_xor_mask = default_text_xor_mask;
+ state.page = 0;
+ state.update_region_y[1] = -1; // offscreen
+ state.cursor_type = MouseCursor::Software;
+ state.enabled = true;
+
+ MOUSE_NotifyResetDOS();
}
static void reset()
{
- // Although these do not belong to the driver state,
- // reset them too to avoid any possible problems
- counter_w = 0;
- pending.Reset();
+ // Although these do not belong to the driver state,
+ // reset them too to avoid any possible problems
+ counter_w = 0;
+ pending.Reset();
- MOUSEDOS_BeforeNewVideoMode();
- MOUSEDOS_AfterNewVideoMode(false);
+ MOUSEDOS_BeforeNewVideoMode();
+ MOUSEDOS_AfterNewVideoMode(false);
- set_mickey_pixel_rate(8, 16);
- set_double_speed_threshold(0); // set default value
+ set_mickey_pixel_rate(8, 16);
+ set_double_speed_threshold(0); // set default value
- state.enabled = true;
+ state.enabled = true;
- pos_x = static_cast<float>((state.maxpos_x + 1) / 2);
- pos_y = static_cast<float>((state.maxpos_y + 1) / 2);
+ pos_x = static_cast<float>((state.maxpos_x + 1) / 2);
+ pos_y = static_cast<float>((state.maxpos_y + 1) / 2);
- state.mickey_counter_x = 0;
- state.mickey_counter_y = 0;
- state.mickey_delta_x = 0.0f;
- state.mickey_delta_y = 0.0f;
+ state.mickey_counter_x = 0;
+ state.mickey_counter_y = 0;
+ state.mickey_delta_x = 0.0f;
+ state.mickey_delta_y = 0.0f;
- state.last_wheel_moved_x = 0;
- state.last_wheel_moved_y = 0;
+ state.last_wheel_moved_x = 0;
+ state.last_wheel_moved_y = 0;
- for (uint16_t idx = 0; idx < num_buttons; idx++) {
- state.times_pressed[idx] = 0;
- state.times_released[idx] = 0;
- state.last_pressed_x[idx] = 0;
- state.last_pressed_y[idx] = 0;
- state.last_released_x[idx] = 0;
- state.last_released_y[idx] = 0;
- }
+ for (uint16_t idx = 0; idx < num_buttons; idx++) {
+ state.times_pressed[idx] = 0;
+ state.times_released[idx] = 0;
+ state.last_pressed_x[idx] = 0;
+ state.last_pressed_y[idx] = 0;
+ state.last_released_x[idx] = 0;
+ state.last_released_y[idx] = 0;
+ }
- state.user_callback_mask = 0;
- mouse_shared.dos_cb_running = false;
+ state.user_callback_mask = 0;
+ mouse_shared.dos_cb_running = false;
- update_driver_active();
- MOUSE_NotifyResetDOS();
+ update_driver_active();
+ MOUSE_NotifyResetDOS();
}
static void limit_coordinates()
{
- auto limit = [](float &pos, const int16_t minpos, const int16_t maxpos) {
- const float min = static_cast<float>(minpos);
- const float max = static_cast<float>(maxpos);
+ auto limit = [](float &pos, const int16_t minpos, const int16_t maxpos) {
+ const float min = static_cast<float>(minpos);
+ const float max = static_cast<float>(maxpos);
- pos = std::clamp(pos, min, max);
- };
+ pos = std::clamp(pos, min, max);
+ };
- limit(pos_x, state.minpos_x, state.maxpos_x);
- limit(pos_y, state.minpos_y, state.maxpos_y);
+ limit(pos_x, state.minpos_x, state.maxpos_x);
+ limit(pos_y, state.minpos_y, state.maxpos_y);
}
static void update_mickeys_on_move(const float x_rel, const float y_rel)
{
- auto update = [](int16_t &counter, float &delta, const float rel) {
- delta += rel;
-
- // Check if movement is significant enough
- const auto d = static_cast<int16_t>(std::lround(delta));
- if (d == 0)
- return;
-
- // Consume part of delta to increase/decrease the counter
- delta -= d;
- int32_t counter_big = counter + d;
-
- // Handle counter wrap around int16_t limits
- if (counter_big > INT16_MAX)
- counter_big -= UINT16_MAX + 1;
- else if (counter_big < INT16_MIN)
- counter_big += UINT16_MAX + 1;
-
- counter = static_cast<int16_t>(counter_big);
- };
-
- const float x_mov = x_rel * state.mickeys_per_pixel_x;
- const float y_mov = y_rel * state.mickeys_per_pixel_y;
-
- // Update mickey counters and mickey speed measurement
- update(state.mickey_counter_x, state.mickey_delta_x, x_mov);
- update(state.mickey_counter_y, state.mickey_delta_y, y_mov);
- speed_mickeys.Update(std::sqrt(x_mov * x_mov + y_mov * y_mov));
+ auto update = [](int16_t &counter, float &delta, const float rel) {
+ delta += rel;
+
+ // Check if movement is significant enough
+ const auto d = static_cast<int16_t>(std::lround(delta));
+ if (d == 0)
+ return;
+
+ // Consume part of delta to increase/decrease the counter
+ delta -= d;
+ int32_t counter_big = counter + d;
+
+ // Handle counter wrap around int16_t limits
+ if (counter_big > INT16_MAX)
+ counter_big -= UINT16_MAX + 1;
+ else if (counter_big < INT16_MIN)
+ counter_big += UINT16_MAX + 1;
+
+ counter = static_cast<int16_t>(counter_big);
+ };
+
+ const float x_mov = x_rel * state.mickeys_per_pixel_x;
+ const float y_mov = y_rel * state.mickeys_per_pixel_y;
+
+ // Update mickey counters and mickey speed measurement
+ update(state.mickey_counter_x, state.mickey_delta_x, x_mov);
+ update(state.mickey_counter_y, state.mickey_delta_y, y_mov);
+ speed_mickeys.Update(std::sqrt(x_mov * x_mov + y_mov * y_mov));
}
static void move_cursor_captured(const float x_rel, const float y_rel)
{
- // Update mickey counters
- update_mickeys_on_move(x_rel, y_rel);
+ // Update mickey counters
+ update_mickeys_on_move(x_rel, y_rel);
- // Apply mouse movement according to our acceleration model
- pos_x += x_rel;
- pos_y += y_rel;
+ // Apply mouse movement according to our acceleration model
+ pos_x += x_rel;
+ pos_y += y_rel;
}
static void move_cursor_seamless(const float x_rel, const float y_rel,
const uint16_t x_abs, const uint16_t y_abs)
{
- // Update mickey counters
- update_mickeys_on_move(x_rel, y_rel);
-
- auto calculate = [](const uint16_t absolute,
- const uint16_t res,
- const uint16_t clip) {
- assert(res > 1u);
- return (static_cast<float>(absolute) - clip) /
- static_cast<float>(res - 1);
- };
-
- // Apply mouse movement to mimic host OS
- float x = calculate(x_abs, mouse_video.res_x, mouse_video.clip_x);
- float y = calculate(y_abs, mouse_video.res_y, mouse_video.clip_y);
-
- // TODO: this is probably overcomplicated, especially
- // the usage of relative movement - to be investigated
- if (CurMode->type == M_TEXT) {
- pos_x = x * 8;
- pos_x *= real_readw(BIOSMEM_SEG, BIOSMEM_NB_COLS);
- pos_y = y * 8;
- pos_y *= IS_EGAVGA_ARCH
- ? static_cast<float>(real_readb(BIOSMEM_SEG, BIOSMEM_NB_ROWS) + 1)
- : 25.0f;
- } else if ((state.maxpos_x < 2048) || (state.maxpos_y < 2048) ||
- (state.maxpos_x != state.maxpos_y)) {
- if ((state.maxpos_x > 0) && (state.maxpos_y > 0)) {
- pos_x = x * state.maxpos_x;
- pos_y = y * state.maxpos_y;
- } else {
- pos_x += x_rel;
- pos_y += y_rel;
- }
- } else {
- // Fake relative movement through absolute coordinates
- pos_x += x_rel;
- pos_y += y_rel;
- }
+ // Update mickey counters
+ update_mickeys_on_move(x_rel, y_rel);
+
+ auto calculate = [](const uint16_t absolute,
+ const uint16_t res,
+ const uint16_t clip) {
+ assert(res > 1u);
+ return (static_cast<float>(absolute) - clip) /
+ static_cast<float>(res - 1);
+ };
+
+ // Apply mouse movement to mimic host OS
+ float x = calculate(x_abs, mouse_video.res_x, mouse_video.clip_x);
+ float y = calculate(y_abs, mouse_video.res_y, mouse_video.clip_y);
+
+ // TODO: this is probably overcomplicated, especially
+ // the usage of relative movement - to be investigated
+ if (CurMode->type == M_TEXT) {
+ pos_x = x * 8;
+ pos_x *= real_readw(BIOSMEM_SEG, BIOSMEM_NB_COLS);
+ pos_y = y * 8;
+ pos_y *= IS_EGAVGA_ARCH
+ ? static_cast<float>(
+ real_readb(BIOSMEM_SEG, BIOSMEM_NB_ROWS) + 1)
+ : 25.0f;
+ } else if ((state.maxpos_x < 2048) || (state.maxpos_y < 2048) ||
+ (state.maxpos_x != state.maxpos_y)) {
+ if ((state.maxpos_x > 0) && (state.maxpos_y > 0)) {
+ pos_x = x * state.maxpos_x;
+ pos_y = y * state.maxpos_y;
+ } else {
+ pos_x += x_rel;
+ pos_y += y_rel;
+ }
+ } else {
+ // Fake relative movement through absolute coordinates
+ pos_x += x_rel;
+ pos_y += y_rel;
+ }
}
static bool is_captured()
{
- // If DOS driver uses a mapped physical mouse, always consider it captured,
- // as we have no absolute mouse position from the host OS
+ // If DOS driver uses a mapped physical mouse, always consider it
+ // captured, as we have no absolute mouse position from the host OS
- return mouse_is_captured || is_mapped;
+ return mouse_is_captured || is_mapped;
}
static uint8_t move_cursor()
{
- const auto old_pos_x = get_pos_x();
- const auto old_pos_y = get_pos_y();
-
- const auto old_mickey_x = static_cast<int16_t>(state.mickey_counter_x);
- const auto old_mickey_y = static_cast<int16_t>(state.mickey_counter_y);
-
- if (is_captured()) {
-
- // For raw mouse input use our built-in pointer acceleration model
- const float acceleration_coeff = raw_input ?
- MOUSE_GetBallisticsCoeff(speed_mickeys.Get() / state.double_speed_threshold) * 2.0f:
- 2.0f;
-
- const float tmp_x = pending.x_rel * acceleration_coeff * state.sensitivity_coeff_x;
- const float tmp_y = pending.y_rel * acceleration_coeff * state.sensitivity_coeff_y;
-
- move_cursor_captured(MOUSE_ClampRelativeMovement(tmp_x),
- MOUSE_ClampRelativeMovement(tmp_y));
-
- } else
- move_cursor_seamless(pending.x_rel, pending.y_rel,
- pending.x_abs, pending.y_abs);
-
- // Pending relative movement is now consummed
- pending.x_rel = 0.0f;
- pending.y_rel = 0.0f;
-
- // Make sure cursor stays in the range defined by application
- limit_coordinates();
-
- // Filter out unneeded events (like sub-pixel mouse movements,
- // which won't change guest side mouse state)
- const bool abs_changed = (old_pos_x != get_pos_x()) ||
- (old_pos_y != get_pos_y());
- const bool rel_changed = (old_mickey_x != state.mickey_counter_x) ||
- (old_mickey_y != state.mickey_counter_y);
-
- if (abs_changed || rel_changed)
- return static_cast<uint8_t>(MouseEventId::MouseHasMoved);
- else
- return 0;
+ const auto old_pos_x = get_pos_x();
+ const auto old_pos_y = get_pos_y();
+
+ const auto old_mickey_x = static_cast<int16_t>(state.mickey_counter_x);
+ const auto old_mickey_y = static_cast<int16_t>(state.mickey_counter_y);
+
+ if (is_captured()) {
+ // For raw mouse input use our built-in pointer acceleration model
+ const float acceleration_coeff =
+ raw_input ? MOUSE_GetBallisticsCoeff(
+ speed_mickeys.Get() /
+ state.double_speed_threshold) *
+ 2.0f
+ : 2.0f;
+
+ const float tmp_x = pending.x_rel * acceleration_coeff *
+ state.sensitivity_coeff_x;
+ const float tmp_y = pending.y_rel * acceleration_coeff *
+ state.sensitivity_coeff_y;
+
+ move_cursor_captured(MOUSE_ClampRelativeMovement(tmp_x),
+ MOUSE_ClampRelativeMovement(tmp_y));
+
+ } else
+ move_cursor_seamless(pending.x_rel,
+ pending.y_rel,
+ pending.x_abs,
+ pending.y_abs);
+
+ // Pending relative movement is now consummed
+ pending.x_rel = 0.0f;
+ pending.y_rel = 0.0f;
+
+ // Make sure cursor stays in the range defined by application
+ limit_coordinates();
+
+ // Filter out unneeded events (like sub-pixel mouse movements,
+ // which won't change guest side mouse state)
+ const bool abs_changed = (old_pos_x != get_pos_x()) ||
+ (old_pos_y != get_pos_y());
+ const bool rel_changed = (old_mickey_x != state.mickey_counter_x) ||
+ (old_mickey_y != state.mickey_counter_y);
+
+ if (abs_changed || rel_changed)
+ return static_cast<uint8_t>(MouseEventId::MouseHasMoved);
+ else
+ return 0;
}
uint8_t MOUSEDOS_UpdateMoved()
{
- if (mouse_config.dos_immediate)
- return static_cast<uint8_t>(MouseEventId::MouseHasMoved);
- else
- return move_cursor();
+ if (mouse_config.dos_immediate)
+ return static_cast<uint8_t>(MouseEventId::MouseHasMoved);
+ else
+ return move_cursor();
}
uint8_t MOUSEDOS_UpdateButtons(const MouseButtons12S new_buttons_12S)
{
- if (buttons.data == new_buttons_12S.data)
- return 0;
-
- auto mark_pressed = [](const uint8_t idx) {
- state.last_pressed_x[idx] = get_pos_x();
- state.last_pressed_y[idx] = get_pos_y();
- ++state.times_pressed[idx];
- };
-
- auto mark_released = [](const uint8_t idx) {
- state.last_released_x[idx] = get_pos_x();
- state.last_released_y[idx] = get_pos_y();
- ++state.times_released[idx];
- };
-
- uint8_t mask = 0;
- if (new_buttons_12S.left && !buttons.left) {
- mark_pressed(0);
- mask |= static_cast<uint8_t>(MouseEventId::PressedLeft);
- } else if (!new_buttons_12S.left && buttons.left) {
- mark_released(0);
- mask |= static_cast<uint8_t>(MouseEventId::ReleasedLeft);
- }
-
- if (new_buttons_12S.right && !buttons.right) {
- mark_pressed(1);
- mask |= static_cast<uint8_t>(MouseEventId::PressedRight);
- } else if (!new_buttons_12S.right && buttons.right) {
- mark_released(1);
- mask |= static_cast<uint8_t>(MouseEventId::ReleasedRight);
- }
-
- if (new_buttons_12S.middle && !buttons.middle) {
- mark_pressed(2);
- mask |= static_cast<uint8_t>(MouseEventId::PressedMiddle);
- } else if (!new_buttons_12S.middle && buttons.middle) {
- mark_released(2);
- mask |= static_cast<uint8_t>(MouseEventId::ReleasedMiddle);
- }
-
- buttons = new_buttons_12S;
- return mask;
+ if (buttons.data == new_buttons_12S.data)
+ return 0;
+
+ auto mark_pressed = [](const uint8_t idx) {
+ state.last_pressed_x[idx] = get_pos_x();
+ state.last_pressed_y[idx] = get_pos_y();
+ ++state.times_pressed[idx];
+ };
+
+ auto mark_released = [](const uint8_t idx) {
+ state.last_released_x[idx] = get_pos_x();
+ state.last_released_y[idx] = get_pos_y();
+ ++state.times_released[idx];
+ };
+
+ uint8_t mask = 0;
+ if (new_buttons_12S.left && !buttons.left) {
+ mark_pressed(0);
+ mask |= static_cast<uint8_t>(MouseEventId::PressedLeft);
+ } else if (!new_buttons_12S.left && buttons.left) {
+ mark_released(0);
+ mask |= static_cast<uint8_t>(MouseEventId::ReleasedLeft);
+ }
+
+ if (new_buttons_12S.right && !buttons.right) {
+ mark_pressed(1);
+ mask |= static_cast<uint8_t>(MouseEventId::PressedRight);
+ } else if (!new_buttons_12S.right && buttons.right) {
+ mark_released(1);
+ mask |= static_cast<uint8_t>(MouseEventId::ReleasedRight);
+ }
+
+ if (new_buttons_12S.middle && !buttons.middle) {
+ mark_pressed(2);
+ mask |= static_cast<uint8_t>(MouseEventId::PressedMiddle);
+ } else if (!new_buttons_12S.middle && buttons.middle) {
+ mark_released(2);
+ mask |= static_cast<uint8_t>(MouseEventId::ReleasedMiddle);
+ }
+
+ buttons = new_buttons_12S;
+ return mask;
}
static uint8_t move_wheel()
{
- counter_w = clamp_to_int8(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;
+ // Pending wheel scroll is now consummed
+ pending.w_rel = 0;
- state.last_wheel_moved_x = get_pos_x();
- state.last_wheel_moved_y = get_pos_y();
+ state.last_wheel_moved_x = get_pos_x();
+ state.last_wheel_moved_y = get_pos_y();
- if (counter_w != 0)
- return static_cast<uint8_t>(MouseEventId::WheelHasMoved);
- else
- return 0;
+ if (counter_w != 0)
+ return static_cast<uint8_t>(MouseEventId::WheelHasMoved);
+ else
+ return 0;
}
uint8_t MOUSEDOS_UpdateWheel()
{
- if (mouse_config.dos_immediate)
- return static_cast<uint8_t>(MouseEventId::WheelHasMoved);
- else
- return move_wheel();
+ if (mouse_config.dos_immediate)
+ return static_cast<uint8_t>(MouseEventId::WheelHasMoved);
+ else
+ return move_wheel();
}
-bool MOUSEDOS_NotifyMoved(const float x_rel,
- const float y_rel,
- const uint16_t x_abs,
- const uint16_t y_abs)
+bool MOUSEDOS_NotifyMoved(const float x_rel, const float y_rel,
+ const uint16_t x_abs, const uint16_t y_abs)
{
- // Check if an event is needed
- bool event_needed = false;
- if (is_captured()) {
- // Uses relative mouse movements - processing is too complicated
- // to easily predict whether the event can be safely omitted
- event_needed = true;
- // TODO: it actually can be done - but it will require some refactoring
- } else {
- // Uses absolute mouse position (seamless mode), relative movements
- // can wait to be reported - they are completely unreliable anyway
- if (pending.x_abs != x_abs || pending.y_abs != y_abs)
- event_needed = true;
- }
-
- // Update values to be consummed when the event arrives
- pending.x_rel = MOUSE_ClampRelativeMovement(pending.x_rel + x_rel);
- pending.y_rel = MOUSE_ClampRelativeMovement(pending.y_rel + y_rel);
- pending.x_abs = x_abs;
- pending.y_abs = y_abs;
-
- // NOTES:
- //
- // It might be tempting to optimize the flow here, by skipping
- // the whole event-queue-callback flow if there is no callback
- // registered, no graphic cursor to draw, etc. Don't do this - there
- // is at least one game (Master of Orion II), which performs INT 0x33
- // calls with 0x0f parameter (changing the callback settings)
- // constantly (don't ask me, why) - doing too much optimization
- // can cause the game to skip mouse events.
-
- if (!event_needed)
- return 0;
-
- if (mouse_config.dos_immediate)
- return (move_cursor() != 0);
- else
- return true;
+ // Check if an event is needed
+ bool event_needed = false;
+ if (is_captured()) {
+ // Uses relative mouse movements - processing is too complicated
+ // to easily predict whether the event can be safely omitted
+ event_needed = true;
+ // TODO: it actually can be done - but it will require some
+ // refactoring
+ } else {
+ // Uses absolute mouse position (seamless mode), relative
+ // movements can wait to be reported - they are completely
+ // unreliable anyway
+ if (pending.x_abs != x_abs || pending.y_abs != y_abs)
+ event_needed = true;
+ }
+
+ // Update values to be consummed when the event arrives
+ pending.x_rel = MOUSE_ClampRelativeMovement(pending.x_rel + x_rel);
+ pending.y_rel = MOUSE_ClampRelativeMovement(pending.y_rel + y_rel);
+ pending.x_abs = x_abs;
+ pending.y_abs = y_abs;
+
+ // NOTES:
+ //
+ // It might be tempting to optimize the flow here, by skipping
+ // the whole event-queue-callback flow if there is no callback
+ // registered, no graphic cursor to draw, etc. Don't do this - there
+ // is at least one game (Master of Orion II), which performs INT 0x33
+ // calls with 0x0f parameter (changing the callback settings)
+ // constantly (don't ask me, why) - doing too much optimization
+ // can cause the game to skip mouse events.
+
+ if (!event_needed)
+ return 0;
+
+ if (mouse_config.dos_immediate)
+ return (move_cursor() != 0);
+ else
+ return true;
}
bool MOUSEDOS_NotifyWheel(const int16_t w_rel)
{
- if (!state.wheel_api)
- return 0;
-
- // Although in some places it is possible for the guest code to get
- // 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 = clamp_to_int8(pending.w_rel + w_rel);
-
- if (pending.w_rel == 0)
- return 0;
-
- if (mouse_config.dos_immediate)
- return (move_wheel() != 0);
- else
- return true;
+ if (!state.wheel_api)
+ return 0;
+
+ // Although in some places it is possible for the guest code to get
+ // 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 = clamp_to_int8(pending.w_rel + w_rel);
+
+ if (pending.w_rel == 0)
+ return 0;
+
+ if (mouse_config.dos_immediate)
+ return (move_wheel() != 0);
+ else
+ return true;
}
static Bitu int33_handler()
{
- switch (reg_ax) {
- case 0x00: // MS MOUSE - reset driver and read status
- reset_hardware();
- [[fallthrough]];
- case 0x21: // MS MOUSE v6.0+ - software reset
- reg_ax = 0xffff; // mouse driver installed
- reg_bx = 3; // for 2 buttons return 0xffff
- reset();
- break;
- case 0x01: // MS MOUSE v1.0+ - show mouse cursor
- if (state.hidden)
- --state.hidden;
- state.update_region_y[1] = -1; // offscreen
- MOUSEDOS_DrawCursor();
- break;
- case 0x02: // MS MOUSE v1.0+ - hide mouse cursor
- if (CurMode->type != M_TEXT)
- restore_cursor_background();
- else
- restore_cursor_background_text();
- ++state.hidden;
- break;
- case 0x03: // MS MOUSE v1.0+ / WheelAPI v1.0+ - get position and button status
- reg_bl = buttons.data;
- reg_bh = get_reset_wheel_8bit(); // CuteMouse clears wheel counter too
- reg_cx = get_pos_x();
- reg_dx = get_pos_y();
- break;
- case 0x04: // MS MOUSE v1.0+ - position mouse cursor
- {
- // If position isn't different from current position, don't
- // change it. (position is rounded so numbers get lost when the
- // rounded number is set) (arena/simulation Wolf)
- if (reg_to_signed16(reg_cx) != get_pos_x())
- pos_x = static_cast<float>(reg_cx);
- if (reg_to_signed16(reg_dx) != get_pos_y())
- pos_y = static_cast<float>(reg_dx);
- limit_coordinates();
- MOUSEDOS_DrawCursor();
- break;
- }
- case 0x05: // MS MOUSE v1.0+ / WheelAPI v1.0+ - get button press / wheel data
- {
- const uint16_t idx = reg_bx; // button index
- if (idx == 0xffff && state.wheel_api) {
- // 'magic' index for checking wheel instead of button
- reg_bx = get_reset_wheel_16bit();
- reg_cx = state.last_wheel_moved_x;
- reg_dx = state.last_wheel_moved_y;
- } else if (idx < num_buttons) {
- reg_ax = buttons.data;
- reg_bx = state.times_pressed[idx];
- reg_cx = state.last_pressed_x[idx];
- reg_dx = state.last_pressed_y[idx];
- state.times_pressed[idx] = 0;
- } else {
- // unsupported - try to do something same
- reg_ax = buttons.data;
- reg_bx = 0;
- reg_cx = 0;
- reg_dx = 0;
- }
- break;
- }
- case 0x06: // MS MOUSE v1.0+ / WheelAPI v1.0+ - get button release data /
- // mouse wheel data
- {
- const uint16_t idx = reg_bx; // button index
- if (idx == 0xffff && state.wheel_api) {
- // 'magic' index for checking wheel instead of button
- reg_bx = get_reset_wheel_16bit();
- reg_cx = state.last_wheel_moved_x;
- reg_dx = state.last_wheel_moved_y;
- } else if (idx < num_buttons) {
- reg_ax = buttons.data;
- reg_bx = state.times_released[idx];
- reg_cx = state.last_released_x[idx];
- reg_dx = state.last_released_y[idx];
-
- state.times_released[idx] = 0;
- } else {
- // unsupported - try to do something same
- reg_ax = buttons.data;
- reg_bx = 0;
- reg_cx = 0;
- reg_dx = 0;
- }
- break;
- }
- case 0x07: // MS MOUSE v1.0+ - define horizontal cursor range
- // Lemmings set 1-640 and wants that. Iron Seed set 0-640. but
- // doesn't like 640. Iron Seed works if newvideo mode with mode
- // 13 sets 0-639. Larry 6 actually wants newvideo mode with mode
- // 13 to set it to 0-319.
- state.minpos_x = std::min(reg_to_signed16(reg_cx),
- reg_to_signed16(reg_dx));
- state.maxpos_x = std::max(reg_to_signed16(reg_cx),
- reg_to_signed16(reg_dx));
- // Battle Chess wants this
- pos_x = std::clamp(pos_x,
- static_cast<float>(state.minpos_x),
- static_cast<float>(state.maxpos_x));
- // Or alternatively this:
- // pos_x = (state.maxpos_x - state.minpos_x + 1) / 2;
- LOG(LOG_MOUSE, LOG_NORMAL)("Define Hortizontal range min:%d max:%d",
- state.minpos_x, state.maxpos_x);
- break;
- case 0x08: // MS MOUSE v1.0+ - define vertical cursor range
- // not sure what to take instead of the CurMode (see case 0x07
- // as well) especially the cases where sheight= 400 and we set
- // it with the mouse_reset to 200 disabled it at the moment.
- // Seems to break syndicate who want 400 in mode 13
- state.minpos_y = std::min(reg_to_signed16(reg_cx),
- reg_to_signed16(reg_dx));
- state.maxpos_y = std::max(reg_to_signed16(reg_cx),
- reg_to_signed16(reg_dx));
- // Battle Chess wants this
- pos_y = std::clamp(pos_y,
- static_cast<float>(state.minpos_y),
- static_cast<float>(state.maxpos_y));
- // Or alternatively this:
- // pos_y = (state.maxpos_y - state.minpos_y + 1) / 2;
- LOG(LOG_MOUSE, LOG_NORMAL)("Define Vertical range min:%d max:%d",
- state.minpos_y, state.maxpos_y);
- break;
- case 0x09: // MS MOUSE v3.0+ - define GFX cursor
- {
- auto clamp_hot = [](const uint16_t reg, const int cursor_size) {
- return std::clamp(reg_to_signed16(reg),
- static_cast<int16_t>(-cursor_size),
- static_cast<int16_t>(cursor_size));
- };
-
- PhysPt src = SegPhys(es) + reg_dx;
- MEM_BlockRead(src, state.user_def_screen_mask, cursor_size_y * 2);
- src += cursor_size_y * 2;
- MEM_BlockRead(src, state.user_def_cursor_mask, cursor_size_y * 2);
- state.user_screen_mask = true;
- state.user_cursor_mask = true;
- state.hot_x = clamp_hot(reg_bx, cursor_size_x);
- state.hot_y = clamp_hot(reg_cx, cursor_size_y);
- state.cursor_type = MouseCursor::Text;
- MOUSEDOS_DrawCursor();
- break;
- }
- case 0x0a: // MS MOUSE v3.0+ - define text cursor
- // TODO: shouldn't we use MouseCursor::Text, not
- // MouseCursor::Software?
- state.cursor_type = (reg_bx ? MouseCursor::Hardware
- : MouseCursor::Software);
- state.text_and_mask = reg_cx;
- state.text_xor_mask = reg_dx;
- if (reg_bx) {
- INT10_SetCursorShape(reg_cl, reg_dl);
- LOG(LOG_MOUSE, LOG_NORMAL)("Hardware Text cursor selected");
- }
- MOUSEDOS_DrawCursor();
- break;
- case 0x27: // MS MOUSE v7.01+ - get screen/cursor masks and mickey counts
- reg_ax = state.text_and_mask;
- reg_bx = state.text_xor_mask;
- [[fallthrough]];
- case 0x0b: // MS MOUSE v1.0+ - read motion data
- reg_cx = signed_to_reg16(state.mickey_counter_x);
- reg_dx = signed_to_reg16(state.mickey_counter_y);
- state.mickey_counter_x = 0;
- state.mickey_counter_y = 0;
- break;
- case 0x0c: // MS MOUSE v1.0+ - define user callback parameters
- state.user_callback_mask = reg_cx;
- state.user_callback_segment = SegValue(es);
- state.user_callback_offset = reg_dx;
- update_driver_active();
- break;
- case 0x0d: // MS MOUSE v1.0+ - light pen emulation on
- case 0x0e: // MS MOUSE v1.0+ - light pen emulation off
- // Both buttons down = pen pressed, otherwise pen considered
- // off-screen
- // TODO: maybe implement light pen using SDL touch events?
- LOG(LOG_MOUSE, LOG_ERROR)("Mouse light pen emulation not implemented");
- break;
- case 0x0f: // MS MOUSE v1.0+ - define mickey/pixel rate
- set_mickey_pixel_rate(reg_to_signed16(reg_cx), reg_to_signed16(reg_dx));
- break;
- case 0x10: // MS MOUSE v1.0+ - define screen region for updating
- state.update_region_x[0] = reg_to_signed16(reg_cx);
- state.update_region_y[0] = reg_to_signed16(reg_dx);
- state.update_region_x[1] = reg_to_signed16(reg_si);
- state.update_region_y[1] = reg_to_signed16(reg_di);
- MOUSEDOS_DrawCursor();
- break;
- case 0x11: // WheelAPI v1.0+ - get mouse capabilities
- reg_ax = 0x574d; // Identifier for detection purposes
- reg_bx = 0; // Reserved capabilities flags
- reg_cx = 1; // Wheel is supported
- state.wheel_api = true; // This call enables WheelAPI extensions
- counter_w = 0;
- // Previous implementation provided Genius Mouse 9.06 function
- // to get number of buttons
- // (https://sourceforge.net/p/dosbox/patches/32/), it was
- // returning 0xffff in reg_ax and number of buttons in reg_bx; I
- // suppose the WheelAPI extensions are more useful
- break;
- case 0x12: // MS MOUSE - set large graphics cursor block
- LOG(LOG_MOUSE, LOG_ERROR)("Large graphics cursor block not implemented");
- break;
- case 0x13: // MS MOUSE v5.0+ - set double-speed threshold
- set_double_speed_threshold(reg_bx);
- break;
- case 0x14: // MS MOUSE v3.0+ - exchange event-handler
- {
- const auto old_segment = state.user_callback_segment;
- const auto old_offset = state.user_callback_offset;
- const auto old_mask = state.user_callback_mask;
- // Set new values
- state.user_callback_mask = reg_cx;
- state.user_callback_segment = SegValue(es);
- state.user_callback_offset = reg_dx;
- update_driver_active();
- // Return old values
- reg_cx = old_mask;
- reg_dx = old_offset;
- SegSet16(es, old_segment);
- break;
- }
- case 0x15: // MS MOUSE v6.0+ - get driver storage space requirements
- reg_bx = sizeof(state);
- break;
- case 0x16: // MS MOUSE v6.0+ - save driver state
- LOG(LOG_MOUSE, LOG_WARN)("Saving driver state...");
- MEM_BlockWrite(SegPhys(es) + reg_dx, &state, sizeof(state));
- break;
- case 0x17: // MS MOUSE v6.0+ - load driver state
- LOG(LOG_MOUSE, LOG_WARN)("Loading driver state...");
- MEM_BlockRead(SegPhys(es) + reg_dx, &state, sizeof(state));
- pending.Reset();
- update_driver_active();
- set_sensitivity(state.sensitivity_x,
- state.sensitivity_y,
- state.unknown_01);
- // TODO: we should probably also fake an event for mouse
- // movement, redraw cursor, etc.
- break;
- case 0x18: // MS MOUSE v6.0+ - set alternate mouse user handler
- case 0x19: // MS MOUSE v6.0+ - set alternate mouse user handler
- LOG(LOG_MOUSE, LOG_ERROR)("Alternate mouse user handler not implemented");
- break;
- case 0x1a: // MS MOUSE v6.0+ - set mouse sensitivity
- // NOTE: Ralf Brown Interrupt List (and some other sources) claim,
- // that this should duplicate functions 0x0f and 0x13 - this is
- // not true at least for Mouse Systems driver v8.00 and
- // IBM/Microsoft driver v8.20
- set_sensitivity(reg_bx, reg_cx, reg_dx);
- break;
- case 0x1b: // MS MOUSE v6.0+ - get mouse sensitivity
- reg_bx = state.sensitivity_x;
- reg_cx = state.sensitivity_y;
- reg_dx = state.unknown_01;
- break;
- case 0x1c: // MS MOUSE v6.0+ - set interrupt rate
- set_interrupt_rate(reg_bx);
- break;
- case 0x1d: // MS MOUSE v6.0+ - set display page number
- state.page = reg_bl;
- break;
- case 0x1e: // MS MOUSE v6.0+ - get display page number
- reg_bx = state.page;
- break;
- case 0x1f: // MS MOUSE v6.0+ - disable mouse driver
- // ES:BX old mouse driver Zero at the moment TODO
- reg_bx = 0;
- SegSet16(es, 0);
- state.enabled = false;
- state.oldhidden = state.hidden;
- state.hidden = 1;
- // According to Ralf Brown Interrupt List it returns 0x20 if
- // success, but CuteMouse source code claims the code for
- // success if 0x1f. Both agree that 0xffff means failure.
- // Since reg_ax is 0x1f here, no need to change anything.
- break;
- case 0x20: // MS MOUSE v6.0+ - enable mouse driver
- state.enabled = true;
- state.hidden = state.oldhidden;
- break;
- case 0x22: // MS MOUSE v6.0+ - set language for messages
- // 00h = English, 01h = French, 02h = Dutch, 03h = German, 04h =
- // Swedish 05h = Finnish, 06h = Spanish, 07h = Portugese, 08h =
- // Italian
- state.language = reg_bx;
- break;
- case 0x23: // MS MOUSE v6.0+ - get language for messages
- reg_bx = state.language;
- break;
- case 0x24: // MS MOUSE v6.26+ - get Software version, mouse type, and IRQ number
- reg_bx = 0x805; // version 8.05 woohoo
- reg_ch = 0x04; // PS/2 type
- reg_cl = 0; // PS/2 mouse; for others it would be an IRQ number
- break;
- case 0x25: // MS MOUSE v6.26+ - get general driver information
- // TODO: According to PC sourcebook reference
- // Returns:
- // AH = status
- // bit 7 driver type: 1=sys 0=com
- // bit 6: 0=non-integrated 1=integrated mouse driver
- // bits 4-5: cursor type 00=software text cursor
- // 01=hardware text cursor 1X=graphics cursor bits 0-3:
- // Function 28 mouse interrupt rate
- // AL = Number of MDDS (?)
- // BX = fCursor lock
- // CX = FinMouse code
- // DX = fMouse busy
- LOG(LOG_MOUSE, LOG_ERROR)("General driver information not implemented");
- break;
- case 0x26: // MS MOUSE v6.26+ - get maximum virtual coordinates
- reg_bx = (state.enabled ? 0x0000 : 0xffff);
- reg_cx = signed_to_reg16(state.maxpos_x);
- reg_dx = signed_to_reg16(state.maxpos_y);
- break;
- case 0x28: // MS MOUSE v7.0+ - set video mode
- // TODO: According to PC sourcebook
- // Entry:
- // CX = Requested video mode
- // DX = Font size, 0 for default
- // Returns:
- // DX = 0 on success, nonzero (requested video mode) if not
- LOG(LOG_MOUSE, LOG_ERROR)("Set video mode not implemented");
- break;
- case 0x29: // MS MOUSE v7.0+ - enumerate video modes
- // TODO: According to PC sourcebook
- // Entry:
- // CX = 0 for first, != 0 for next
- // Exit:
- // BX:DX = named string far ptr
- // CX = video mode number
- LOG(LOG_MOUSE, LOG_ERROR)("Enumerate video modes not implemented");
- break;
- case 0x2a: // MS MOUSE v7.01+ - get cursor hot spot
- // Microsoft uses a negative byte counter
- // for cursor visibility
- reg_al = static_cast<uint8_t>(-state.hidden);
- reg_bx = signed_to_reg16(state.hot_x);
- reg_cx = signed_to_reg16(state.hot_y);
- reg_dx = 0x04; // PS/2 mouse type
- break;
- case 0x2b: // MS MOUSE v7.0+ - load acceleration profiles
- case 0x2c: // MS MOUSE v7.0+ - get acceleration profiles
- case 0x2d: // MS MOUSE v7.0+ - select acceleration profile
- case 0x2e: // MS MOUSE v8.10+ - set acceleration profile names
- case 0x33: // MS MOUSE v7.05+ - get/switch accelleration profile
- LOG(LOG_MOUSE, LOG_ERROR)("Custom acceleration profiles not implemented");
- break;
- case 0x2f: // MS MOUSE v7.02+ - mouse hardware reset
- LOG(LOG_MOUSE, LOG_ERROR)("INT 33 AX=2F mouse hardware reset not implemented");
- break;
- case 0x30: // MS MOUSE v7.04+ - get/set BallPoint information
- LOG(LOG_MOUSE, LOG_ERROR)("Get/set BallPoint information not implemented");
- break;
- case 0x31: // MS MOUSE v7.05+ - get current min/max virtual coordinates
- reg_ax = signed_to_reg16(state.minpos_x);
- reg_bx = signed_to_reg16(state.minpos_y);
- reg_cx = signed_to_reg16(state.maxpos_x);
- reg_dx = signed_to_reg16(state.maxpos_y);
- break;
- case 0x32: // MS MOUSE v7.05+ - get active advanced functions
- LOG(LOG_MOUSE, LOG_ERROR)("Get active advanced functions not implemented");
- break;
- case 0x34: // MS MOUSE v8.0+ - get initialization file
- LOG(LOG_MOUSE, LOG_ERROR)("Get initialization file not implemented");
- break;
- case 0x35: // MS MOUSE v8.10+ - LCD screen large pointer support
- LOG(LOG_MOUSE, LOG_ERROR)("LCD screen large pointer support not implemented");
- break;
- case 0x4d: // MS MOUSE - return pointer to copyright string
- LOG(LOG_MOUSE, LOG_ERROR)("Return pointer to copyright string not implemented");
- break;
- case 0x6d: // MS MOUSE - get version string
- LOG(LOG_MOUSE, LOG_ERROR)("Get version string not implemented");
- break;
- case 0x70: // Mouse Systems - installation check
- case 0x72: // Mouse Systems 7.01+, Genius Mouse 9.06+ - unknown
- case 0x73: // Mouse Systems 7.01+ - get button assignments
- LOG(LOG_MOUSE, LOG_ERROR)("Mouse Sytems mouse extensions not implemented");
- break;
- case 0x53C1: // Logitech CyberMan
- LOG(LOG_MOUSE, LOG_NORMAL)("Mouse function 53C1 for Logitech CyberMan called. Ignored by regular mouse driver.");
- break;
- default:
- LOG(LOG_MOUSE, LOG_ERROR)("Mouse function %04X not implemented", reg_ax);
- break;
- }
- return CBRET_NONE;
+ switch (reg_ax) {
+ case 0x00: // MS MOUSE - reset driver and read status
+ reset_hardware();
+ [[fallthrough]];
+ case 0x21: // MS MOUSE v6.0+ - software reset
+ reg_ax = 0xffff; // mouse driver installed
+ reg_bx = 3; // for 2 buttons return 0xffff
+ reset();
+ break;
+ case 0x01: // MS MOUSE v1.0+ - show mouse cursor
+ if (state.hidden)
+ --state.hidden;
+ state.update_region_y[1] = -1; // offscreen
+ MOUSEDOS_DrawCursor();
+ break;
+ case 0x02: // MS MOUSE v1.0+ - hide mouse cursor
+ if (CurMode->type != M_TEXT)
+ restore_cursor_background();
+ else
+ restore_cursor_background_text();
+ ++state.hidden;
+ break;
+ case 0x03: // MS MOUSE v1.0+ / WheelAPI v1.0+ - get position and button
+ // status
+ reg_bl = buttons.data;
+ reg_bh = get_reset_wheel_8bit(); // CuteMouse clears wheel
+ // counter too
+ reg_cx = get_pos_x();
+ reg_dx = get_pos_y();
+ break;
+ case 0x04: // MS MOUSE v1.0+ - position mouse cursor
+ {
+ // If position isn't different from current position, don't
+ // change it. (position is rounded so numbers get lost when the
+ // rounded number is set) (arena/simulation Wolf)
+ if (reg_to_signed16(reg_cx) != get_pos_x())
+ pos_x = static_cast<float>(reg_cx);
+ if (reg_to_signed16(reg_dx) != get_pos_y())
+ pos_y = static_cast<float>(reg_dx);
+ limit_coordinates();
+ MOUSEDOS_DrawCursor();
+ break;
+ }
+ case 0x05: // MS MOUSE v1.0+ / WheelAPI v1.0+ - get button press / wheel
+ // data
+ {
+ const uint16_t idx = reg_bx; // button index
+ if (idx == 0xffff && state.wheel_api) {
+ // 'magic' index for checking wheel instead of button
+ reg_bx = get_reset_wheel_16bit();
+ reg_cx = state.last_wheel_moved_x;
+ reg_dx = state.last_wheel_moved_y;
+ } else if (idx < num_buttons) {
+ reg_ax = buttons.data;
+ reg_bx = state.times_pressed[idx];
+ reg_cx = state.last_pressed_x[idx];
+ reg_dx = state.last_pressed_y[idx];
+ state.times_pressed[idx] = 0;
+ } else {
+ // unsupported - try to do something same
+ reg_ax = buttons.data;
+ reg_bx = 0;
+ reg_cx = 0;
+ reg_dx = 0;
+ }
+ break;
+ }
+ case 0x06: // MS MOUSE v1.0+ / WheelAPI v1.0+ - get button release data
+ // / mouse wheel data
+ {
+ const uint16_t idx = reg_bx; // button index
+ if (idx == 0xffff && state.wheel_api) {
+ // 'magic' index for checking wheel instead of button
+ reg_bx = get_reset_wheel_16bit();
+ reg_cx = state.last_wheel_moved_x;
+ reg_dx = state.last_wheel_moved_y;
+ } else if (idx < num_buttons) {
+ reg_ax = buttons.data;
+ reg_bx = state.times_released[idx];
+ reg_cx = state.last_released_x[idx];
+ reg_dx = state.last_released_y[idx];
+
+ state.times_released[idx] = 0;
+ } else {
+ // unsupported - try to do something same
+ reg_ax = buttons.data;
+ reg_bx = 0;
+ reg_cx = 0;
+ reg_dx = 0;
+ }
+ break;
+ }
+ case 0x07: // MS MOUSE v1.0+ - define horizontal cursor range
+ // Lemmings set 1-640 and wants that. Iron Seed set 0-640. but
+ // doesn't like 640. Iron Seed works if newvideo mode with mode
+ // 13 sets 0-639. Larry 6 actually wants newvideo mode with mode
+ // 13 to set it to 0-319.
+ state.minpos_x = std::min(reg_to_signed16(reg_cx), reg_to_signed16(reg_dx));
+ state.maxpos_x = std::max(reg_to_signed16(reg_cx), reg_to_signed16(reg_dx));
+ // Battle Chess wants this
+ pos_x = std::clamp(pos_x,
+ static_cast<float>(state.minpos_x),
+ static_cast<float>(state.maxpos_x));
+ // Or alternatively this:
+ // pos_x = (state.maxpos_x - state.minpos_x + 1) / 2;
+ LOG(LOG_MOUSE, LOG_NORMAL)
+ ("Define Hortizontal range min:%d max:%d", state.minpos_x, state.maxpos_x);
+ break;
+ case 0x08: // MS MOUSE v1.0+ - define vertical cursor range
+ // not sure what to take instead of the CurMode (see case 0x07
+ // as well) especially the cases where sheight= 400 and we set
+ // it with the mouse_reset to 200 disabled it at the moment.
+ // Seems to break syndicate who want 400 in mode 13
+ state.minpos_y = std::min(reg_to_signed16(reg_cx),
+ reg_to_signed16(reg_dx));
+ state.maxpos_y = std::max(reg_to_signed16(reg_cx),
+ reg_to_signed16(reg_dx));
+ // Battle Chess wants this
+ pos_y = std::clamp(pos_y,
+ static_cast<float>(state.minpos_y),
+ static_cast<float>(state.maxpos_y));
+ // Or alternatively this:
+ // pos_y = (state.maxpos_y - state.minpos_y + 1) / 2;
+ LOG(LOG_MOUSE, LOG_NORMAL)
+ ("Define Vertical range min:%d max:%d", state.minpos_y, state.maxpos_y);
+ break;
+ case 0x09: // MS MOUSE v3.0+ - define GFX cursor
+ {
+ auto clamp_hot = [](const uint16_t reg, const int cursor_size) {
+ return std::clamp(reg_to_signed16(reg),
+ static_cast<int16_t>(-cursor_size),
+ static_cast<int16_t>(cursor_size));
+ };
+
+ PhysPt src = SegPhys(es) + reg_dx;
+ MEM_BlockRead(src, state.user_def_screen_mask, cursor_size_y * 2);
+ src += cursor_size_y * 2;
+ MEM_BlockRead(src, state.user_def_cursor_mask, cursor_size_y * 2);
+ state.user_screen_mask = true;
+ state.user_cursor_mask = true;
+ state.hot_x = clamp_hot(reg_bx, cursor_size_x);
+ state.hot_y = clamp_hot(reg_cx, cursor_size_y);
+ state.cursor_type = MouseCursor::Text;
+ MOUSEDOS_DrawCursor();
+ break;
+ }
+ case 0x0a: // MS MOUSE v3.0+ - define text cursor
+ // TODO: shouldn't we use MouseCursor::Text, not
+ // MouseCursor::Software?
+ state.cursor_type = (reg_bx ? MouseCursor::Hardware
+ : MouseCursor::Software);
+ state.text_and_mask = reg_cx;
+ state.text_xor_mask = reg_dx;
+ if (reg_bx) {
+ INT10_SetCursorShape(reg_cl, reg_dl);
+ LOG(LOG_MOUSE, LOG_NORMAL)
+ ("Hardware Text cursor selected");
+ }
+ MOUSEDOS_DrawCursor();
+ break;
+ case 0x27: // MS MOUSE v7.01+ - get screen/cursor masks and mickey counts
+ reg_ax = state.text_and_mask;
+ reg_bx = state.text_xor_mask;
+ [[fallthrough]];
+ case 0x0b: // MS MOUSE v1.0+ - read motion data
+ reg_cx = signed_to_reg16(state.mickey_counter_x);
+ reg_dx = signed_to_reg16(state.mickey_counter_y);
+ state.mickey_counter_x = 0;
+ state.mickey_counter_y = 0;
+ break;
+ case 0x0c: // MS MOUSE v1.0+ - define user callback parameters
+ state.user_callback_mask = reg_cx;
+ state.user_callback_segment = SegValue(es);
+ state.user_callback_offset = reg_dx;
+ update_driver_active();
+ break;
+ case 0x0d: // MS MOUSE v1.0+ - light pen emulation on
+ case 0x0e: // MS MOUSE v1.0+ - light pen emulation off
+ // Both buttons down = pen pressed, otherwise pen considered
+ // off-screen
+ // TODO: maybe implement light pen using SDL touch events?
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Mouse light pen emulation not implemented");
+ break;
+ case 0x0f: // MS MOUSE v1.0+ - define mickey/pixel rate
+ set_mickey_pixel_rate(reg_to_signed16(reg_cx),
+ reg_to_signed16(reg_dx));
+ break;
+ case 0x10: // MS MOUSE v1.0+ - define screen region for updating
+ state.update_region_x[0] = reg_to_signed16(reg_cx);
+ state.update_region_y[0] = reg_to_signed16(reg_dx);
+ state.update_region_x[1] = reg_to_signed16(reg_si);
+ state.update_region_y[1] = reg_to_signed16(reg_di);
+ MOUSEDOS_DrawCursor();
+ break;
+ case 0x11: // WheelAPI v1.0+ - get mouse capabilities
+ reg_ax = 0x574d; // Identifier for detection purposes
+ reg_bx = 0; // Reserved capabilities flags
+ reg_cx = 1; // Wheel is supported
+ state.wheel_api = true; // This call enables WheelAPI extensions
+ counter_w = 0;
+ // Previous implementation provided Genius Mouse 9.06 function
+ // to get number of buttons
+ // (https://sourceforge.net/p/dosbox/patches/32/), it was
+ // returning 0xffff in reg_ax and number of buttons in reg_bx; I
+ // suppose the WheelAPI extensions are more useful
+ break;
+ case 0x12: // MS MOUSE - set large graphics cursor block
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Large graphics cursor block not implemented");
+ break;
+ case 0x13: // MS MOUSE v5.0+ - set double-speed threshold
+ set_double_speed_threshold(reg_bx);
+ break;
+ case 0x14: // MS MOUSE v3.0+ - exchange event-handler
+ {
+ const auto old_segment = state.user_callback_segment;
+ const auto old_offset = state.user_callback_offset;
+ const auto old_mask = state.user_callback_mask;
+ // Set new values
+ state.user_callback_mask = reg_cx;
+ state.user_callback_segment = SegValue(es);
+ state.user_callback_offset = reg_dx;
+ update_driver_active();
+ // Return old values
+ reg_cx = old_mask;
+ reg_dx = old_offset;
+ SegSet16(es, old_segment);
+ break;
+ }
+ case 0x15: // MS MOUSE v6.0+ - get driver storage space requirements
+ reg_bx = sizeof(state);
+ break;
+ case 0x16: // MS MOUSE v6.0+ - save driver state
+ LOG(LOG_MOUSE, LOG_WARN)("Saving driver state...");
+ MEM_BlockWrite(SegPhys(es) + reg_dx, &state, sizeof(state));
+ break;
+ case 0x17: // MS MOUSE v6.0+ - load driver state
+ LOG(LOG_MOUSE, LOG_WARN)("Loading driver state...");
+ MEM_BlockRead(SegPhys(es) + reg_dx, &state, sizeof(state));
+ pending.Reset();
+ update_driver_active();
+ set_sensitivity(state.sensitivity_x,
+ state.sensitivity_y,
+ state.unknown_01);
+ // TODO: we should probably also fake an event for mouse
+ // movement, redraw cursor, etc.
+ break;
+ case 0x18: // MS MOUSE v6.0+ - set alternate mouse user handler
+ case 0x19: // MS MOUSE v6.0+ - set alternate mouse user handler
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Alternate mouse user handler not implemented");
+ break;
+ case 0x1a: // MS MOUSE v6.0+ - set mouse sensitivity
+ // NOTE: Ralf Brown Interrupt List (and some other sources)
+ // claim, that this should duplicate functions 0x0f and 0x13 -
+ // this is not true at least for Mouse Systems driver v8.00 and
+ // IBM/Microsoft driver v8.20
+ set_sensitivity(reg_bx, reg_cx, reg_dx);
+ break;
+ case 0x1b: // MS MOUSE v6.0+ - get mouse sensitivity
+ reg_bx = state.sensitivity_x;
+ reg_cx = state.sensitivity_y;
+ reg_dx = state.unknown_01;
+ break;
+ case 0x1c: // MS MOUSE v6.0+ - set interrupt rate
+ set_interrupt_rate(reg_bx);
+ break;
+ case 0x1d: // MS MOUSE v6.0+ - set display page number
+ state.page = reg_bl;
+ break;
+ case 0x1e: // MS MOUSE v6.0+ - get display page number
+ reg_bx = state.page;
+ break;
+ case 0x1f: // MS MOUSE v6.0+ - disable mouse driver
+ // ES:BX old mouse driver Zero at the moment TODO
+ reg_bx = 0;
+ SegSet16(es, 0);
+ state.enabled = false;
+ state.oldhidden = state.hidden;
+ state.hidden = 1;
+ // According to Ralf Brown Interrupt List it returns 0x20 if
+ // success, but CuteMouse source code claims the code for
+ // success if 0x1f. Both agree that 0xffff means failure.
+ // Since reg_ax is 0x1f here, no need to change anything.
+ break;
+ case 0x20: // MS MOUSE v6.0+ - enable mouse driver
+ state.enabled = true;
+ state.hidden = state.oldhidden;
+ break;
+ case 0x22: // MS MOUSE v6.0+ - set language for messages
+ // 00h = English, 01h = French, 02h = Dutch, 03h = German, 04h =
+ // Swedish 05h = Finnish, 06h = Spanish, 07h = Portugese, 08h =
+ // Italian
+ state.language = reg_bx;
+ break;
+ case 0x23: // MS MOUSE v6.0+ - get language for messages
+ reg_bx = state.language;
+ break;
+ case 0x24: // MS MOUSE v6.26+ - get Software version, mouse type, and
+ // IRQ number
+ reg_bx = 0x805; // version 8.05 woohoo
+ reg_ch = 0x04; // PS/2 type
+ reg_cl = 0; // PS/2 mouse; for others it would be an IRQ number
+ break;
+ case 0x25: // MS MOUSE v6.26+ - get general driver information
+ // TODO: According to PC sourcebook reference
+ // Returns:
+ // AH = status
+ // bit 7 driver type: 1=sys 0=com
+ // bit 6: 0=non-integrated 1=integrated mouse driver
+ // bits 4-5: cursor type 00=software text cursor
+ // 01=hardware text cursor 1X=graphics cursor bits 0-3:
+ // Function 28 mouse interrupt rate
+ // AL = Number of MDDS (?)
+ // BX = fCursor lock
+ // CX = FinMouse code
+ // DX = fMouse busy
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("General driver information not implemented");
+ break;
+ case 0x26: // MS MOUSE v6.26+ - get maximum virtual coordinates
+ reg_bx = (state.enabled ? 0x0000 : 0xffff);
+ reg_cx = signed_to_reg16(state.maxpos_x);
+ reg_dx = signed_to_reg16(state.maxpos_y);
+ break;
+ case 0x28: // MS MOUSE v7.0+ - set video mode
+ // TODO: According to PC sourcebook
+ // Entry:
+ // CX = Requested video mode
+ // DX = Font size, 0 for default
+ // Returns:
+ // DX = 0 on success, nonzero (requested video mode) if not
+ LOG(LOG_MOUSE, LOG_ERROR)("Set video mode not implemented");
+ break;
+ case 0x29: // MS MOUSE v7.0+ - enumerate video modes
+ // TODO: According to PC sourcebook
+ // Entry:
+ // CX = 0 for first, != 0 for next
+ // Exit:
+ // BX:DX = named string far ptr
+ // CX = video mode number
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Enumerate video modes not implemented");
+ break;
+ case 0x2a: // MS MOUSE v7.01+ - get cursor hot spot
+ // Microsoft uses a negative byte counter
+ // for cursor visibility
+ reg_al = static_cast<uint8_t>(-state.hidden);
+ reg_bx = signed_to_reg16(state.hot_x);
+ reg_cx = signed_to_reg16(state.hot_y);
+ reg_dx = 0x04; // PS/2 mouse type
+ break;
+ case 0x2b: // MS MOUSE v7.0+ - load acceleration profiles
+ case 0x2c: // MS MOUSE v7.0+ - get acceleration profiles
+ case 0x2d: // MS MOUSE v7.0+ - select acceleration profile
+ case 0x2e: // MS MOUSE v8.10+ - set acceleration profile names
+ case 0x33: // MS MOUSE v7.05+ - get/switch accelleration profile
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Custom acceleration profiles not implemented");
+ break;
+ case 0x2f: // MS MOUSE v7.02+ - mouse hardware reset
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("INT 33 AX=2F mouse hardware reset not implemented");
+ break;
+ case 0x30: // MS MOUSE v7.04+ - get/set BallPoint information
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Get/set BallPoint information not implemented");
+ break;
+ case 0x31: // MS MOUSE v7.05+ - get current min/max virtual coordinates
+ reg_ax = signed_to_reg16(state.minpos_x);
+ reg_bx = signed_to_reg16(state.minpos_y);
+ reg_cx = signed_to_reg16(state.maxpos_x);
+ reg_dx = signed_to_reg16(state.maxpos_y);
+ break;
+ case 0x32: // MS MOUSE v7.05+ - get active advanced functions
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Get active advanced functions not implemented");
+ break;
+ case 0x34: // MS MOUSE v8.0+ - get initialization file
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Get initialization file not implemented");
+ break;
+ case 0x35: // MS MOUSE v8.10+ - LCD screen large pointer support
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("LCD screen large pointer support not implemented");
+ break;
+ case 0x4d: // MS MOUSE - return pointer to copyright string
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Return pointer to copyright string not implemented");
+ break;
+ case 0x6d: // MS MOUSE - get version string
+ LOG(LOG_MOUSE, LOG_ERROR)("Get version string not implemented");
+ break;
+ case 0x70: // Mouse Systems - installation check
+ case 0x72: // Mouse Systems 7.01+, Genius Mouse 9.06+ - unknown
+ case 0x73: // Mouse Systems 7.01+ - get button assignments
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Mouse Sytems mouse extensions not implemented");
+ break;
+ case 0x53C1: // Logitech CyberMan
+ LOG(LOG_MOUSE, LOG_NORMAL)
+ ("Mouse function 53C1 for Logitech CyberMan called. Ignored by regular mouse driver.");
+ break;
+ default:
+ LOG(LOG_MOUSE, LOG_ERROR)
+ ("Mouse function %04X not implemented", reg_ax);
+ break;
+ }
+ return CBRET_NONE;
}
static Bitu mouse_bd_handler()
{
- // the stack contains offsets to register values
- uint16_t raxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x0a));
- uint16_t rbxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x08));
- uint16_t rcxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x06));
- uint16_t rdxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x04));
-
- // read out the actual values, registers ARE overwritten
- const uint16_t rax = real_readw(SegValue(ds), raxpt);
- reg_ax = rax;
- reg_bx = real_readw(SegValue(ds), rbxpt);
- reg_cx = real_readw(SegValue(ds), rcxpt);
- reg_dx = real_readw(SegValue(ds), rdxpt);
-
- // some functions are treated in a special way (additional registers)
- switch (rax) {
- case 0x09: // Define GFX Cursor
- case 0x16: // Save driver state
- case 0x17: // load driver state
- SegSet16(es, SegValue(ds));
- break;
- case 0x0c: // Define interrupt subroutine parameters
- case 0x14: // Exchange event-handler
- if (reg_bx != 0)
- SegSet16(es, reg_bx);
- else
- SegSet16(es, SegValue(ds));
- break;
- case 0x10: // Define screen region for updating
- reg_cx = real_readw(SegValue(ds), rdxpt);
- reg_dx = real_readw(SegValue(ds), static_cast<uint16_t>(rdxpt + 2));
- reg_si = real_readw(SegValue(ds), static_cast<uint16_t>(rdxpt + 4));
- reg_di = real_readw(SegValue(ds), static_cast<uint16_t>(rdxpt + 6));
- break;
- default: break;
- }
-
- int33_handler();
-
- // save back the registers, too
- real_writew(SegValue(ds), raxpt, reg_ax);
- real_writew(SegValue(ds), rbxpt, reg_bx);
- real_writew(SegValue(ds), rcxpt, reg_cx);
- real_writew(SegValue(ds), rdxpt, reg_dx);
- switch (rax) {
- case 0x1f: // Disable Mousedriver
- real_writew(SegValue(ds), rbxpt, SegValue(es));
- break;
- case 0x14: // Exchange event-handler
- real_writew(SegValue(ds), rcxpt, SegValue(es));
- break;
- default: break;
- }
-
- return CBRET_NONE;
+ // the stack contains offsets to register values
+ uint16_t raxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x0a));
+ uint16_t rbxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x08));
+ uint16_t rcxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x06));
+ uint16_t rdxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x04));
+
+ // read out the actual values, registers ARE overwritten
+ const uint16_t rax = real_readw(SegValue(ds), raxpt);
+ reg_ax = rax;
+ reg_bx = real_readw(SegValue(ds), rbxpt);
+ reg_cx = real_readw(SegValue(ds), rcxpt);
+ reg_dx = real_readw(SegValue(ds), rdxpt);
+
+ // some functions are treated in a special way (additional registers)
+ switch (rax) {
+ case 0x09: // Define GFX Cursor
+ case 0x16: // Save driver state
+ case 0x17: // load driver state
+ SegSet16(es, SegValue(ds));
+ break;
+ case 0x0c: // Define interrupt subroutine parameters
+ case 0x14: // Exchange event-handler
+ if (reg_bx != 0)
+ SegSet16(es, reg_bx);
+ else
+ SegSet16(es, SegValue(ds));
+ break;
+ case 0x10: // Define screen region for updating
+ reg_cx = real_readw(SegValue(ds), rdxpt);
+ reg_dx = real_readw(SegValue(ds), static_cast<uint16_t>(rdxpt + 2));
+ reg_si = real_readw(SegValue(ds), static_cast<uint16_t>(rdxpt + 4));
+ reg_di = real_readw(SegValue(ds), static_cast<uint16_t>(rdxpt + 6));
+ break;
+ default: break;
+ }
+
+ int33_handler();
+
+ // save back the registers, too
+ real_writew(SegValue(ds), raxpt, reg_ax);
+ real_writew(SegValue(ds), rbxpt, reg_bx);
+ real_writew(SegValue(ds), rcxpt, reg_cx);
+ real_writew(SegValue(ds), rdxpt, reg_dx);
+ switch (rax) {
+ case 0x1f: // Disable Mousedriver
+ real_writew(SegValue(ds), rbxpt, SegValue(es));
+ break;
+ case 0x14: // Exchange event-handler
+ real_writew(SegValue(ds), rcxpt, SegValue(es));
+ break;
+ default: break;
+ }
+
+ return CBRET_NONE;
}
static Bitu user_callback_handler()
{
- mouse_shared.dos_cb_running = false;
- return CBRET_NONE;
+ mouse_shared.dos_cb_running = false;
+ return CBRET_NONE;
}
bool MOUSEDOS_HasCallback(const uint8_t mask)
{
- return state.user_callback_mask & mask;
+ return state.user_callback_mask & mask;
}
-Bitu MOUSEDOS_DoCallback(const uint8_t mask,
- const MouseButtons12S buttons_12S)
+Bitu MOUSEDOS_DoCallback(const uint8_t mask, const MouseButtons12S buttons_12S)
{
- mouse_shared.dos_cb_running = true;
- const bool mouse_moved = mask & static_cast<uint8_t>(MouseEventId::MouseHasMoved);
- const bool wheel_moved = mask & static_cast<uint8_t>(MouseEventId::WheelHasMoved);
-
- // Extension for Windows mouse driver by javispedro:
- // - https://git.javispedro.com/cgit/vbados.git/about/
- // which allows seamless mouse integration. It is also included in DOSBox-X and Dosemu2:
- // - https://github.com/joncampbell123/dosbox-x/pull/3424
- // - https://github.com/dosemu2/dosemu2/issues/1552#issuecomment-1100777880
- // - https://github.com/dosemu2/dosemu2/commit/cd9d2dbc8e3d58dc7cbc92f172c0d447881526be
- // - https://github.com/joncampbell123/dosbox-x/commit/aec29ce28eb4b520f21ead5b2debf370183b9f28
- reg_ah = (!is_captured() && mouse_moved) ? 1 : 0;
-
- reg_al = mask;
- reg_bl = buttons_12S.data;
- reg_bh = wheel_moved ? get_reset_wheel_8bit() : 0;
- reg_cx = get_pos_x();
- reg_dx = get_pos_y();
- reg_si = signed_to_reg16(state.mickey_counter_x);
- reg_di = signed_to_reg16(state.mickey_counter_y);
-
- CPU_Push16(RealSeg(user_callback));
- CPU_Push16(RealOff(user_callback));
- CPU_Push16(state.user_callback_segment);
- CPU_Push16(state.user_callback_offset);
-
- return CBRET_NONE;
+ mouse_shared.dos_cb_running = true;
+ const bool mouse_moved = mask &
+ static_cast<uint8_t>(MouseEventId::MouseHasMoved);
+ const bool wheel_moved = mask &
+ static_cast<uint8_t>(MouseEventId::WheelHasMoved);
+
+ // Extension for Windows mouse driver by javispedro:
+ // - https://git.javispedro.com/cgit/vbados.git/about/
+ // which allows seamless mouse integration. It is also included in
+ // DOSBox-X and Dosemu2:
+ // - https://github.com/joncampbell123/dosbox-x/pull/3424
+ // -
+ // https://github.com/dosemu2/dosemu2/issues/1552#issuecomment-1100777880
+ // -
+ // https://github.com/dosemu2/dosemu2/commit/cd9d2dbc8e3d58dc7cbc92f172c0d447881526be
+ // -
+ // https://github.com/joncampbell123/dosbox-x/commit/aec29ce28eb4b520f21ead5b2debf370183b9f28
+ reg_ah = (!is_captured() && mouse_moved) ? 1 : 0;
+
+ reg_al = mask;
+ reg_bl = buttons_12S.data;
+ reg_bh = wheel_moved ? get_reset_wheel_8bit() : 0;
+ reg_cx = get_pos_x();
+ reg_dx = get_pos_y();
+ reg_si = signed_to_reg16(state.mickey_counter_x);
+ reg_di = signed_to_reg16(state.mickey_counter_y);
+
+ CPU_Push16(RealSeg(user_callback));
+ CPU_Push16(RealOff(user_callback));
+ CPU_Push16(state.user_callback_segment);
+ CPU_Push16(state.user_callback_offset);
+
+ return CBRET_NONE;
}
void MOUSEDOS_NotifyMapped(const bool enabled)
{
- is_mapped = enabled;
+ is_mapped = enabled;
}
void MOUSEDOS_NotifyRawInput(const bool enabled)
{
- raw_input = enabled;
+ raw_input = enabled;
}
void MOUSEDOS_Init()
{
- // Callback for mouse interrupt 0x33
- auto call_int33 = CALLBACK_Allocate();
- // RealPt int33_location = RealMake(CB_SEG + 1,(call_int33 * CB_SIZE) - 0x10);
- RealPt int33_location = RealMake(static_cast<uint16_t>(DOS_GetMemory(0x1) - 1), 0x10);
- CALLBACK_Setup(call_int33, &int33_handler, CB_MOUSE,
- Real2Phys(int33_location), "Mouse");
- // Wasteland needs low(seg(int33))!=0 and low(ofs(int33))!=0
- real_writed(0, 0x33 << 2, int33_location);
-
- auto call_mouse_bd = CALLBACK_Allocate();
- CALLBACK_Setup(call_mouse_bd,
- &mouse_bd_handler,
- CB_RETF8,
- PhysMake(RealSeg(int33_location),
- static_cast<uint16_t>(RealOff(int33_location) + 2)),
- "MouseBD");
- // pseudocode for CB_MOUSE (including the special backdoor entry point):
- // jump near i33hd
- // callback mouse_bd_handler
- // retf 8
- // label i33hd:
- // callback int33_handler
- // iret
-
- // Callback for mouse user routine return
- auto call_user = CALLBACK_Allocate();
- CALLBACK_Setup(call_user, &user_callback_handler, CB_RETF_CLI, "mouse user ret");
- user_callback = CALLBACK_RealPointer(call_user);
-
- state.user_callback_segment = 0x6362; // magic value
- state.hidden = 1; // hide cursor on startup
- state.mode = UINT8_MAX; // non-existing mode
-
- set_sensitivity(50, 50, 50);
- reset_hardware();
- reset();
+ // Callback for mouse interrupt 0x33
+ auto call_int33 = CALLBACK_Allocate();
+ // RealPt int33_location = RealMake(CB_SEG + 1,(call_int33 * CB_SIZE) -
+ // 0x10);
+ RealPt int33_location = RealMake(static_cast<uint16_t>(DOS_GetMemory(0x1) - 1),
+ 0x10);
+ CALLBACK_Setup(call_int33,
+ &int33_handler,
+ CB_MOUSE,
+ Real2Phys(int33_location),
+ "Mouse");
+ // Wasteland needs low(seg(int33))!=0 and low(ofs(int33))!=0
+ real_writed(0, 0x33 << 2, int33_location);
+
+ auto call_mouse_bd = CALLBACK_Allocate();
+ CALLBACK_Setup(call_mouse_bd,
+ &mouse_bd_handler,
+ CB_RETF8,
+ PhysMake(RealSeg(int33_location),
+ static_cast<uint16_t>(RealOff(int33_location) + 2)),
+ "MouseBD");
+ // pseudocode for CB_MOUSE (including the special backdoor entry point):
+ // jump near i33hd
+ // callback mouse_bd_handler
+ // retf 8
+ // label i33hd:
+ // callback int33_handler
+ // iret
+
+ // Callback for mouse user routine return
+ auto call_user = CALLBACK_Allocate();
+ CALLBACK_Setup(call_user, &user_callback_handler, CB_RETF_CLI, "mouse user ret");
+ user_callback = CALLBACK_RealPointer(call_user);
+
+ state.user_callback_segment = 0x6362; // magic value
+ state.hidden = 1; // hide cursor on startup
+ state.mode = UINT8_MAX; // non-existing mode
+
+ set_sensitivity(50, 50, 50);
+ reset_hardware();
+ reset();
}
diff --git a/src/hardware/mouse/mouseif_ps2_bios.cpp b/src/hardware/mouse/mouseif_ps2_bios.cpp
index 210ecfaf1..3ea8c9869 100644
--- a/src/hardware/mouse/mouseif_ps2_bios.cpp
+++ b/src/hardware/mouse/mouseif_ps2_bios.cpp
@@ -55,7 +55,7 @@ static float delta_x = 0.0f; // accumulated mouse movement since last reported
static float delta_y = 0.0f;
static int8_t counter_w = 0; // mouse wheel counter
-static MouseModelPS2 protocol = MouseModelPS2::Standard;
+static MouseModelPS2 protocol = MouseModelPS2::Standard;
static uint8_t unlock_idx_im = 0; // sequence index for unlocking extended protocol
static uint8_t unlock_idx_xp = 0;
@@ -75,277 +75,277 @@ static float counts_rate = 0.0f; // 1.0 is 4 counts per mm
void MOUSEPS2_UpdateButtonSquish()
{
- // - if VMware compatible driver is enabled, never try to report
- // mouse buttons 4 and 5, that would be asking for trouble
- // - for PS/2 modes other than IntelliMouse Explorer there is
- // no standard way to report buttons 4 and 5
-
- const bool squish = mouse_shared.active_vmm || (protocol != MouseModelPS2::Explorer);
- buttons.data = squish ? buttons_12S.data : buttons_all.data;
+ // - if VMware compatible driver is enabled, never try to report
+ // mouse buttons 4 and 5, that would be asking for trouble
+ // - for PS/2 modes other than IntelliMouse Explorer there is
+ // no standard way to report buttons 4 and 5
+
+ const bool squish = mouse_shared.active_vmm ||
+ (protocol != MouseModelPS2::Explorer);
+ buttons.data = squish ? buttons_12S.data : buttons_all.data;
}
static void terminate_unlick_sequence()
{
- unlock_idx_im = 0;
- unlock_idx_xp = 0;
+ unlock_idx_im = 0;
+ unlock_idx_xp = 0;
}
static void set_protocol(const MouseModelPS2 new_protocol)
{
- terminate_unlick_sequence();
-
- static bool first_time = true;
- if (first_time || protocol != new_protocol) {
- first_time = false;
- protocol = new_protocol;
- const char *protocol_name = nullptr;
- switch (protocol) {
- case MouseModelPS2::Standard:
- protocol_name = "Standard, 3 buttons";
- break;
- case MouseModelPS2::IntelliMouse:
- protocol_name = "IntelliMouse, wheel, 3 buttons";
- break;
- case MouseModelPS2::Explorer:
- protocol_name = "IntelliMouse Explorer, wheel, 5 buttons";
- break;
- default: break;
- }
-
- LOG_MSG("MOUSE (PS/2): %s", protocol_name);
-
- packet[0] = 0;
- packet[1] = 0;
- packet[2] = 0;
- packet[3] = 0;
-
- MOUSEPS2_UpdateButtonSquish();
- }
+ terminate_unlick_sequence();
+
+ static bool first_time = true;
+ if (first_time || protocol != new_protocol) {
+ first_time = false;
+ protocol = new_protocol;
+ const char *protocol_name = nullptr;
+ switch (protocol) {
+ case MouseModelPS2::Standard:
+ protocol_name = "Standard, 3 buttons";
+ break;
+ case MouseModelPS2::IntelliMouse:
+ protocol_name = "IntelliMouse, wheel, 3 buttons";
+ break;
+ case MouseModelPS2::Explorer:
+ protocol_name = "IntelliMouse Explorer, wheel, 5 buttons";
+ break;
+ default: break;
+ }
+
+ LOG_MSG("MOUSE (PS/2): %s", protocol_name);
+
+ packet[0] = 0;
+ packet[1] = 0;
+ packet[2] = 0;
+ packet[3] = 0;
+
+ MOUSEPS2_UpdateButtonSquish();
+ }
}
static uint8_t get_reset_wheel_4bit()
{
- const int8_t tmp = std::clamp(counter_w,
- static_cast<int8_t>(-0x08),
- static_cast<int8_t>(0x07));
- counter_w = 0; // reading always clears the counter
+ const int8_t tmp = std::clamp(counter_w,
+ static_cast<int8_t>(-0x08),
+ static_cast<int8_t>(0x07));
+ counter_w = 0; // reading always clears the counter
- // 0x0f for -1, 0x0e for -2, etc.
- return static_cast<uint8_t>((tmp >= 0) ? tmp : 0x10 + tmp);
+ // 0x0f for -1, 0x0e for -2, etc.
+ return static_cast<uint8_t>((tmp >= 0) ? tmp : 0x10 + tmp);
}
static uint8_t get_reset_wheel_8bit()
{
- const auto tmp = counter_w;
- counter_w = 0; // reading always clears thecounter
+ const auto tmp = counter_w;
+ counter_w = 0; // reading always clears thecounter
- // 0xff for -1, 0xfe for -2, etc.
- return static_cast<uint8_t>((tmp >= 0) ? tmp : 0x100 + tmp);
+ // 0xff for -1, 0xfe for -2, etc.
+ return static_cast<uint8_t>((tmp >= 0) ? tmp : 0x100 + tmp);
}
static int16_t get_scaled_movement(const int16_t d)
{
- if (!scaling_21)
- return d;
-
- switch (d) {
- case -5: return -9;
- case -4: return -6;
- case -3: return -3;
- case -2: return -1;
- case -1: return -1;
- case 1: return 1;
- case 2: return 1;
- case 3: return 3;
- case 4: return 6;
- case 5: return 9;
- default: return static_cast<int16_t>(2 * d);
- }
+ if (!scaling_21)
+ return d;
+
+ switch (d) {
+ case -5: return -9;
+ case -4: return -6;
+ case -3: return -3;
+ case -2: return -1;
+ case -1: return -1;
+ case 1: return 1;
+ case 2: return 1;
+ case 3: return 3;
+ case 4: return 6;
+ case 5: return 9;
+ default: return static_cast<int16_t>(2 * d);
+ }
}
static void reset_counters()
{
- delta_x = 0.0f;
- delta_y = 0.0f;
- counter_w = 0;
+ delta_x = 0.0f;
+ delta_y = 0.0f;
+ counter_w = 0;
}
void MOUSEPS2_UpdatePacket()
{
- union {
- uint8_t data = 0x08;
-
- bit_view<0, 1> left;
- bit_view<1, 1> right;
- bit_view<2, 1> middle;
- bit_view<4, 1> sign_x;
- bit_view<5, 1> sign_y;
- bit_view<6, 1> overflow_x;
- bit_view<7, 1> overflow_y;
- } mdat;
-
- mdat.left = buttons.left;
- mdat.right = buttons.right;
- mdat.middle = buttons.middle;
-
- auto dx = static_cast<int16_t>(std::round(delta_x));
- auto dy = static_cast<int16_t>(std::round(delta_y));
-
- delta_x -= dx;
- delta_y -= dy;
-
- dx = get_scaled_movement(dx);
- dy = get_scaled_movement(static_cast<int16_t>(-dy));
-
- if (protocol == MouseModelPS2::Explorer) {
- // There is no overflow for 5-button mouse protocol, see
- // HT82M30A datasheet
- dx = std::clamp(dx,
- static_cast<int16_t>(-UINT8_MAX),
- static_cast<int16_t>(UINT8_MAX));
- dy = std::clamp(dy,
- static_cast<int16_t>(-UINT8_MAX),
- static_cast<int16_t>(UINT8_MAX));
- } else {
- if ((dx > 0xff) || (dx < -0xff))
- mdat.overflow_x = 1;
- if ((dy > 0xff) || (dy < -0xff))
- mdat.overflow_y = 1;
- }
-
- dx %= 0x100;
- if (dx < 0) {
- dx = static_cast<int16_t>(dx + 0x100);
- mdat.sign_x = 1;
- }
-
- dy %= 0x100;
- if (dy < 0) {
- dy = static_cast<int16_t>(dy + 0x100);
- mdat.sign_y = 1;
- }
-
- packet[0] = mdat.data;
- packet[1] = static_cast<uint8_t>(dx);
- packet[2] = static_cast<uint8_t>(dy);
-
- if (protocol == MouseModelPS2::IntelliMouse)
- packet[3] = get_reset_wheel_8bit();
- else if (protocol == MouseModelPS2::Explorer) {
- packet[3] = get_reset_wheel_4bit();
- if (buttons.extra_1)
- bit::set(packet[3], b4);
- if (buttons.extra_2)
- bit::set(packet[3], b5);
- }
- else
- packet[3] = 0;
+ union {
+ uint8_t data = 0x08;
+
+ bit_view<0, 1> left;
+ bit_view<1, 1> right;
+ bit_view<2, 1> middle;
+ bit_view<4, 1> sign_x;
+ bit_view<5, 1> sign_y;
+ bit_view<6, 1> overflow_x;
+ bit_view<7, 1> overflow_y;
+ } mdat;
+
+ mdat.left = buttons.left;
+ mdat.right = buttons.right;
+ mdat.middle = buttons.middle;
+
+ auto dx = static_cast<int16_t>(std::round(delta_x));
+ auto dy = static_cast<int16_t>(std::round(delta_y));
+
+ delta_x -= dx;
+ delta_y -= dy;
+
+ dx = get_scaled_movement(dx);
+ dy = get_scaled_movement(static_cast<int16_t>(-dy));
+
+ if (protocol == MouseModelPS2::Explorer) {
+ // There is no overflow for 5-button mouse protocol, see
+ // HT82M30A datasheet
+ dx = std::clamp(dx,
+ static_cast<int16_t>(-UINT8_MAX),
+ static_cast<int16_t>(UINT8_MAX));
+ dy = std::clamp(dy,
+ static_cast<int16_t>(-UINT8_MAX),
+ static_cast<int16_t>(UINT8_MAX));
+ } else {
+ if ((dx > 0xff) || (dx < -0xff))
+ mdat.overflow_x = 1;
+ if ((dy > 0xff) || (dy < -0xff))
+ mdat.overflow_y = 1;
+ }
+
+ dx %= 0x100;
+ if (dx < 0) {
+ dx = static_cast<int16_t>(dx + 0x100);
+ mdat.sign_x = 1;
+ }
+
+ dy %= 0x100;
+ if (dy < 0) {
+ dy = static_cast<int16_t>(dy + 0x100);
+ mdat.sign_y = 1;
+ }
+
+ packet[0] = mdat.data;
+ packet[1] = static_cast<uint8_t>(dx);
+ packet[2] = static_cast<uint8_t>(dy);
+
+ if (protocol == MouseModelPS2::IntelliMouse)
+ packet[3] = get_reset_wheel_8bit();
+ else if (protocol == MouseModelPS2::Explorer) {
+ packet[3] = get_reset_wheel_4bit();
+ if (buttons.extra_1)
+ bit::set(packet[3], b4);
+ if (buttons.extra_2)
+ bit::set(packet[3], b5);
+ } else
+ packet[3] = 0;
}
static void cmd_set_resolution(const uint8_t new_counts_mm)
{
- terminate_unlick_sequence();
+ terminate_unlick_sequence();
- if (new_counts_mm != 1 && new_counts_mm != 2 && new_counts_mm != 4 &&
- new_counts_mm != 8)
- // Invalid parameter, set default
- counts_mm = 4;
- else
- counts_mm = new_counts_mm;
+ if (new_counts_mm != 1 && new_counts_mm != 2 && new_counts_mm != 4 &&
+ new_counts_mm != 8)
+ // Invalid parameter, set default
+ counts_mm = 4;
+ else
+ counts_mm = new_counts_mm;
- counts_rate = counts_mm / 4.0f;
+ counts_rate = counts_mm / 4.0f;
}
static void cmd_set_sample_rate(const uint8_t new_rate_hz)
{
- reset_counters();
-
- if (new_rate_hz != 10 && new_rate_hz != 20 && new_rate_hz != 40 &&
- new_rate_hz != 60 && new_rate_hz != 80 && new_rate_hz != 100 &&
- new_rate_hz != 200) {
- // Invalid parameter, set default
- terminate_unlick_sequence();
- rate_hz = 100;
- } else
- rate_hz = new_rate_hz;
-
- // Update event queue settings and interface information
- MouseInterface::GetPS2()->NotifyInterfaceRate(rate_hz);
-
- // Handle extended mouse protocol unlock sequences
- auto unlock = [](const std::vector<uint8_t> &sequence,
- uint8_t &idx,
- const MouseModelPS2 potential_protocol) {
- if (sequence[idx] != rate_hz)
- idx = 0;
- else if (sequence.size() == ++idx) {
- set_protocol(potential_protocol);
- }
- };
-
- static const std::vector<uint8_t> seq_im = {200, 100, 80};
- static const std::vector<uint8_t> seq_xp = {200, 200, 80};
-
- if (mouse_config.model_ps2 == MouseModelPS2::IntelliMouse)
- unlock(seq_im, unlock_idx_im, MouseModelPS2::IntelliMouse);
- else if (mouse_config.model_ps2 == MouseModelPS2::Explorer) {
- unlock(seq_im, unlock_idx_im, MouseModelPS2::IntelliMouse);
- unlock(seq_xp, unlock_idx_xp, MouseModelPS2::Explorer);
- }
+ reset_counters();
+
+ if (new_rate_hz != 10 && new_rate_hz != 20 && new_rate_hz != 40 &&
+ new_rate_hz != 60 && new_rate_hz != 80 && new_rate_hz != 100 &&
+ new_rate_hz != 200) {
+ // Invalid parameter, set default
+ terminate_unlick_sequence();
+ rate_hz = 100;
+ } else
+ rate_hz = new_rate_hz;
+
+ // Update event queue settings and interface information
+ MouseInterface::GetPS2()->NotifyInterfaceRate(rate_hz);
+
+ // Handle extended mouse protocol unlock sequences
+ auto unlock = [](const std::vector<uint8_t> &sequence,
+ uint8_t &idx,
+ const MouseModelPS2 potential_protocol) {
+ if (sequence[idx] != rate_hz)
+ idx = 0;
+ else if (sequence.size() == ++idx) {
+ set_protocol(potential_protocol);
+ }
+ };
+
+ static const std::vector<uint8_t> seq_im = {200, 100, 80};
+ static const std::vector<uint8_t> seq_xp = {200, 200, 80};
+
+ if (mouse_config.model_ps2 == MouseModelPS2::IntelliMouse)
+ unlock(seq_im, unlock_idx_im, MouseModelPS2::IntelliMouse);
+ else if (mouse_config.model_ps2 == MouseModelPS2::Explorer) {
+ unlock(seq_im, unlock_idx_im, MouseModelPS2::IntelliMouse);
+ unlock(seq_xp, unlock_idx_xp, MouseModelPS2::Explorer);
+ }
}
static void cmd_set_defaults()
{
- cmd_set_resolution(4);
- cmd_set_sample_rate(100);
+ cmd_set_resolution(4);
+ cmd_set_sample_rate(100);
- MOUSEPS2_UpdateButtonSquish();
+ MOUSEPS2_UpdateButtonSquish();
}
static void cmd_reset()
{
- cmd_set_defaults();
- set_protocol(MouseModelPS2::Standard);
- reset_counters();
+ cmd_set_defaults();
+ set_protocol(MouseModelPS2::Standard);
+ reset_counters();
}
static void cmd_set_scaling_21(const bool enable)
{
- terminate_unlick_sequence();
+ terminate_unlick_sequence();
- scaling_21 = enable;
+ scaling_21 = enable;
}
bool MOUSEPS2_NotifyMoved(const float x_rel, const float y_rel)
{
- delta_x = MOUSE_ClampRelativeMovement(delta_x + x_rel);
- delta_y = MOUSE_ClampRelativeMovement(delta_y + y_rel);
+ delta_x = MOUSE_ClampRelativeMovement(delta_x + x_rel);
+ delta_y = MOUSE_ClampRelativeMovement(delta_y + y_rel);
- return (std::fabs(delta_x) >= 0.5f) || (std::fabs(delta_y) >= 0.5f);
+ return (std::fabs(delta_x) >= 0.5f) || (std::fabs(delta_y) >= 0.5f);
}
bool MOUSEPS2_NotifyButton(const MouseButtons12S new_buttons_12S,
const MouseButtonsAll new_buttons_all)
{
- const auto buttons_old = buttons;
+ const auto buttons_old = buttons;
- buttons_12S = new_buttons_12S;
- buttons_all = new_buttons_all;
- MOUSEPS2_UpdateButtonSquish();
+ buttons_12S = new_buttons_12S;
+ buttons_all = new_buttons_all;
+ MOUSEPS2_UpdateButtonSquish();
- return (buttons_old.data != buttons.data);
+ return (buttons_old.data != buttons.data);
}
bool MOUSEPS2_NotifyWheel(const int16_t w_rel)
{
- if (protocol != MouseModelPS2::IntelliMouse &&
- protocol != MouseModelPS2::Explorer)
- return false;
+ if (protocol != MouseModelPS2::IntelliMouse &&
+ protocol != MouseModelPS2::Explorer)
+ return false;
- auto old_counter_w = counter_w;
- counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + w_rel));
+ auto old_counter_w = counter_w;
+ counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + w_rel));
- return (old_counter_w != counter_w);
+ return (old_counter_w != counter_w);
}
// ***************************************************************************
@@ -369,157 +369,157 @@ static RealPt ps2_callback = 0;
void MOUSEBIOS_Reset()
{
- cmd_reset();
- PIC_SetIRQMask(12, false); // lower IRQ line
- MOUSEVMM_Deactivate(); // VBADOS seems to expect this
+ cmd_reset();
+ PIC_SetIRQMask(12, false); // lower IRQ line
+ MOUSEVMM_Deactivate(); // VBADOS seems to expect this
}
void MOUSEBIOS_SetCallback(const uint16_t pseg, const uint16_t pofs)
{
- if ((pseg == 0) && (pofs == 0)) {
- callback_init = false;
- } else {
- callback_init = true;
- callback_seg = pseg;
- callback_ofs = pofs;
- }
+ if ((pseg == 0) && (pofs == 0)) {
+ callback_init = false;
+ } else {
+ callback_init = true;
+ callback_seg = pseg;
+ callback_ofs = pofs;
+ }
}
bool MOUSEBIOS_SetPacketSize(const uint8_t packet_size)
{
- if (packet_size == 3)
- packet_4bytes = false;
- else if (packet_size == 4)
- packet_4bytes = true;
- else
- return false; // unsupported packet size
-
- return true;
+ if (packet_size == 3)
+ packet_4bytes = false;
+ else if (packet_size == 4)
+ packet_4bytes = true;
+ else
+ return false; // unsupported packet size
+
+ return true;
}
bool MOUSEBIOS_SetSampleRate(const uint8_t rate_id)
{
- switch (rate_id) {
- case 0: cmd_set_sample_rate(10); break;
- case 1: cmd_set_sample_rate(20); break;
- case 2: cmd_set_sample_rate(40); break;
- case 3: cmd_set_sample_rate(60); break;
- case 4: cmd_set_sample_rate(80); break;
- case 5: cmd_set_sample_rate(100); break;
- case 6: cmd_set_sample_rate(200); break;
- default: return false;
- }
-
- return true;
+ switch (rate_id) {
+ case 0: cmd_set_sample_rate(10); break;
+ case 1: cmd_set_sample_rate(20); break;
+ case 2: cmd_set_sample_rate(40); break;
+ case 3: cmd_set_sample_rate(60); break;
+ case 4: cmd_set_sample_rate(80); break;
+ case 5: cmd_set_sample_rate(100); break;
+ case 6: cmd_set_sample_rate(200); break;
+ default: return false;
+ }
+
+ return true;
}
bool MOUSEBIOS_SetResolution(const uint8_t res_id)
{
- switch (res_id) {
- case 0: cmd_set_resolution(1); break;
- case 1: cmd_set_resolution(2); break;
- case 2: cmd_set_resolution(4); break;
- case 3: cmd_set_resolution(8); break;
- default: return false;
- }
-
- return true;
+ switch (res_id) {
+ case 0: cmd_set_resolution(1); break;
+ case 1: cmd_set_resolution(2); break;
+ case 2: cmd_set_resolution(4); break;
+ case 3: cmd_set_resolution(8); break;
+ default: return false;
+ }
+
+ return true;
}
void MOUSEBIOS_SetScaling21(const bool enable)
{
- cmd_set_scaling_21(enable);
+ cmd_set_scaling_21(enable);
}
bool MOUSEBIOS_SetState(const bool use)
{
- if (use && !callback_init) {
- mouse_shared.active_bios = false;
- MOUSE_NotifyStateChanged();
- return false;
- } else {
- mouse_shared.active_bios = use;
- MOUSE_NotifyStateChanged();
- return true;
- }
+ if (use && !callback_init) {
+ mouse_shared.active_bios = false;
+ MOUSE_NotifyStateChanged();
+ return false;
+ } else {
+ mouse_shared.active_bios = use;
+ MOUSE_NotifyStateChanged();
+ return true;
+ }
}
uint8_t MOUSEBIOS_GetResolution()
{
- return counts_mm;
+ return counts_mm;
}
uint8_t MOUSEBIOS_GetSampleRate()
{
- return rate_hz;
+ return rate_hz;
}
uint8_t MOUSEBIOS_GetStatus()
{
- union {
- uint8_t data = 0;
-
- bit_view<0, 1> left;
- bit_view<1, 1> right;
- bit_view<2, 1> middle;
- // bit 3 - reserved
- bit_view<4, 1> scaling_21;
- bit_view<5, 1> reporting;
- bit_view<6, 1> mode_remote;
- // bit 7 - reserved
- } ret;
-
- ret.left = buttons.left;
- ret.right = buttons.right;
- ret.middle = buttons.middle;
-
- ret.scaling_21 = scaling_21;
- ret.reporting = 1;
-
- return ret.data;
+ union {
+ uint8_t data = 0;
+
+ bit_view<0, 1> left;
+ bit_view<1, 1> right;
+ bit_view<2, 1> middle;
+ // bit 3 - reserved
+ bit_view<4, 1> scaling_21;
+ bit_view<5, 1> reporting;
+ bit_view<6, 1> mode_remote;
+ // bit 7 - reserved
+ } ret;
+
+ ret.left = buttons.left;
+ ret.right = buttons.right;
+ ret.middle = buttons.middle;
+
+ ret.scaling_21 = scaling_21;
+ ret.reporting = 1;
+
+ return ret.data;
}
uint8_t MOUSEBIOS_GetProtocol()
{
- return static_cast<uint8_t>(protocol);
+ return static_cast<uint8_t>(protocol);
}
static Bitu callback_ret()
{
- CPU_Pop16();
- CPU_Pop16();
- CPU_Pop16();
- CPU_Pop16(); // remove 4 words
- return CBRET_NONE;
+ CPU_Pop16();
+ CPU_Pop16();
+ CPU_Pop16();
+ CPU_Pop16(); // remove 4 words
+ return CBRET_NONE;
}
Bitu MOUSEBIOS_DoCallback()
{
- if (!packet_4bytes) {
- CPU_Push16(packet[0]);
- CPU_Push16(packet[1]);
- CPU_Push16(packet[2]);
- } else {
- CPU_Push16(static_cast<uint16_t>((packet[0] + packet[1] * 0x100)));
- CPU_Push16(packet[2]);
- CPU_Push16(packet[3]);
- }
- CPU_Push16((uint16_t)0);
-
- CPU_Push16(RealSeg(ps2_callback));
- CPU_Push16(RealOff(ps2_callback));
- SegSet16(cs, callback_seg);
- reg_ip = callback_ofs;
-
- return CBRET_NONE;
+ if (!packet_4bytes) {
+ CPU_Push16(packet[0]);
+ CPU_Push16(packet[1]);
+ CPU_Push16(packet[2]);
+ } else {
+ CPU_Push16(static_cast<uint16_t>((packet[0] + packet[1] * 0x100)));
+ CPU_Push16(packet[2]);
+ CPU_Push16(packet[3]);
+ }
+ CPU_Push16((uint16_t)0);
+
+ CPU_Push16(RealSeg(ps2_callback));
+ CPU_Push16(RealOff(ps2_callback));
+ SegSet16(cs, callback_seg);
+ reg_ip = callback_ofs;
+
+ return CBRET_NONE;
}
void MOUSEPS2_Init()
{
- // Callback for ps2 user callback handling
- auto call_ps2 = CALLBACK_Allocate();
- CALLBACK_Setup(call_ps2, &callback_ret, CB_RETF, "ps2 bios callback");
- ps2_callback = CALLBACK_RealPointer(call_ps2);
+ // Callback for ps2 user callback handling
+ auto call_ps2 = CALLBACK_Allocate();
+ CALLBACK_Setup(call_ps2, &callback_ret, CB_RETF, "ps2 bios callback");
+ ps2_callback = CALLBACK_RealPointer(call_ps2);
- MOUSEBIOS_Reset();
+ MOUSEBIOS_Reset();
}
diff --git a/src/hardware/mouse/mouseif_virtual_machines.cpp b/src/hardware/mouse/mouseif_virtual_machines.cpp
index 32f4a5fca..b2133bab6 100644
--- a/src/hardware/mouse/mouseif_virtual_machines.cpp
+++ b/src/hardware/mouse/mouseif_virtual_machines.cpp
@@ -43,41 +43,41 @@ CHECK_NARROWING();
// - https://git.javispedro.com/cgit/vbmouse.git (planned support)
enum class VMwareCmd : uint16_t {
- GetVersion = 10,
- AbsPointerData = 39,
- AbsPointerStatus = 40,
- AbsPointerCommand = 41,
+ GetVersion = 10,
+ AbsPointerData = 39,
+ AbsPointerStatus = 40,
+ AbsPointerCommand = 41,
};
enum class VMwareAbsPointer : uint32_t {
- Enable = 0x45414552,
- Relative = 0xF5,
- Absolute = 0x53424152,
+ Enable = 0x45414552,
+ Relative = 0xF5,
+ Absolute = 0x53424152,
};
union VMwareButtons {
- uint8_t data = 0;
- bit_view<5, 1> left;
- bit_view<4, 1> right;
- bit_view<3, 1> middle;
+ uint8_t data = 0;
+ bit_view<5, 1> left;
+ bit_view<4, 1> right;
+ bit_view<3, 1> middle;
};
static constexpr io_port_t VMWARE_PORT = 0x5658u; // communication port
// static constexpr io_port_t VMWARE_PORTHB = 0x5659u; // communication port,
- // high bandwidth
+// high bandwidth
static constexpr uint32_t VMWARE_MAGIC = 0x564D5868u; // magic number for all
// VMware calls
static constexpr uint32_t ABS_UPDATED = 4; // tells that new pointer
// position is available
static constexpr uint32_t ABS_NOT_UPDATED = 0;
-static bool raw_input = true; // true = no host mouse acceleration pre-applied
-static bool is_mapped = false; // true = physical mouse is mapped to this interface
-static bool updated = false; // true = mouse state update waits to be picked up
-static VMwareButtons buttons; // state of mouse buttons, in VMware format
-static uint16_t scaled_x = 0x7fff; // absolute position scaled from 0 to 0xffff
-static uint16_t scaled_y = 0x7fff; // 0x7fff is a center position
-static int8_t counter_w = 0; // wheel movement counter
+static bool raw_input = true; // true = no host mouse acceleration pre-applied
+static bool is_mapped = false; // true = physical mouse is mapped to this interface
+static bool updated = false; // true = mouse state update waits to be picked up
+static VMwareButtons buttons; // state of mouse buttons, in VMware format
+static uint16_t scaled_x = 0x7fff; // absolute position scaled from 0 to 0xffff
+static uint16_t scaled_y = 0x7fff; // 0x7fff is a center position
+static int8_t counter_w = 0; // wheel movement counter
static float pos_x = 0.0f;
static float pos_y = 0.0f;
@@ -85,8 +85,7 @@ 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)
constexpr float acceleration_multiplier = 0.02f;
-static MouseSpeedCalculator speed_xy(acceleration_multiplier *
- mouse_predefined.acceleration_vmm);
+static MouseSpeedCalculator speed_xy(acceleration_multiplier *mouse_predefined.acceleration_vmm);
// ***************************************************************************
// VMware interface implementation
@@ -94,201 +93,203 @@ static MouseSpeedCalculator speed_xy(acceleration_multiplier *
static void MOUSEVMM_Activate()
{
- if (!mouse_shared.active_vmm) {
- mouse_shared.active_vmm = true;
- LOG_MSG("MOUSE (PS/2): VMware protocol enabled");
- if (mouse_is_captured) {
- // If mouse is captured, prepare sane start settings
- // (center of the screen, will trigger mouse move event)
- pos_x = mouse_video.res_x / 2.0f;
- pos_y = mouse_video.res_y / 2.0f;
- scaled_x = 0;
- scaled_y = 0;
- }
- MOUSEPS2_UpdateButtonSquish();
- MOUSE_NotifyStateChanged();
- }
- buttons.data = 0;
- counter_w = 0;
+ if (!mouse_shared.active_vmm) {
+ mouse_shared.active_vmm = true;
+ LOG_MSG("MOUSE (PS/2): VMware protocol enabled");
+ if (mouse_is_captured) {
+ // If mouse is captured, prepare sane start settings
+ // (center of the screen, will trigger mouse move event)
+ pos_x = mouse_video.res_x / 2.0f;
+ pos_y = mouse_video.res_y / 2.0f;
+ scaled_x = 0;
+ scaled_y = 0;
+ }
+ MOUSEPS2_UpdateButtonSquish();
+ MOUSE_NotifyStateChanged();
+ }
+ buttons.data = 0;
+ counter_w = 0;
}
void MOUSEVMM_Deactivate()
{
- if (mouse_shared.active_vmm) {
- mouse_shared.active_vmm = false;
- LOG_MSG("MOUSE (PS/2): VMware protocol disabled");
- MOUSEPS2_UpdateButtonSquish();
- MOUSE_NotifyStateChanged();
- }
- buttons.data = 0;
- counter_w = 0;
+ if (mouse_shared.active_vmm) {
+ mouse_shared.active_vmm = false;
+ LOG_MSG("MOUSE (PS/2): VMware protocol disabled");
+ MOUSEPS2_UpdateButtonSquish();
+ MOUSE_NotifyStateChanged();
+ }
+ buttons.data = 0;
+ counter_w = 0;
}
void MOUSEVMM_NotifyMapped(const bool enabled)
{
- is_mapped = enabled;
+ is_mapped = enabled;
}
void MOUSEVMM_NotifyRawInput(const bool enabled)
{
- raw_input = enabled;
+ raw_input = enabled;
}
static void cmd_get_version()
{
- reg_eax = 0; // protocol version
- reg_ebx = VMWARE_MAGIC;
+ reg_eax = 0; // protocol version
+ reg_ebx = VMWARE_MAGIC;
}
static void cmd_abs_pointer_data()
{
- reg_eax = buttons.data;
- reg_ebx = scaled_x;
- reg_ecx = scaled_y;
- reg_edx = static_cast<uint32_t>((counter_w >= 0) ? counter_w : 0x100 + counter_w);
+ reg_eax = buttons.data;
+ reg_ebx = scaled_x;
+ reg_ecx = scaled_y;
+ reg_edx = static_cast<uint32_t>((counter_w >= 0) ? counter_w
+ : 0x100 + counter_w);
- counter_w = 0;
+ counter_w = 0;
}
static void cmd_abs_pointer_status()
{
- reg_eax = updated ? ABS_UPDATED : ABS_NOT_UPDATED;
- updated = false;
+ reg_eax = updated ? ABS_UPDATED : ABS_NOT_UPDATED;
+ updated = false;
}
static void cmd_abs_pointer_command()
{
- switch (static_cast<VMwareAbsPointer>(reg_ebx)) {
- case VMwareAbsPointer::Enable: break; // can be safely ignored
- case VMwareAbsPointer::Relative: MOUSEVMM_Deactivate(); break;
- case VMwareAbsPointer::Absolute: MOUSEVMM_Activate(); break;
- default:
- LOG_WARNING("MOUSE (PS/2): unimplemented VMware subcommand 0x%08x",
- reg_ebx);
- break;
- }
+ switch (static_cast<VMwareAbsPointer>(reg_ebx)) {
+ case VMwareAbsPointer::Enable: break; // can be safely ignored
+ case VMwareAbsPointer::Relative: MOUSEVMM_Deactivate(); break;
+ case VMwareAbsPointer::Absolute: MOUSEVMM_Activate(); break;
+ default:
+ LOG_WARNING("MOUSE (PS/2): unimplemented VMware subcommand 0x%08x",
+ reg_ebx);
+ break;
+ }
}
static uint32_t port_read_vmware(const io_port_t, const io_width_t)
{
- if (reg_eax != VMWARE_MAGIC)
- return 0;
-
- switch (static_cast<VMwareCmd>(reg_cx)) {
- case VMwareCmd::GetVersion: cmd_get_version(); break;
- case VMwareCmd::AbsPointerData: cmd_abs_pointer_data(); break;
- case VMwareCmd::AbsPointerStatus: cmd_abs_pointer_status(); break;
- case VMwareCmd::AbsPointerCommand: cmd_abs_pointer_command(); break;
- default:
- LOG_WARNING("MOUSE (PS/2): unimplemented VMware command 0x%08x",
- reg_ecx);
- break;
- }
-
- return reg_eax;
+ if (reg_eax != VMWARE_MAGIC)
+ return 0;
+
+ switch (static_cast<VMwareCmd>(reg_cx)) {
+ case VMwareCmd::GetVersion: cmd_get_version(); break;
+ case VMwareCmd::AbsPointerData: cmd_abs_pointer_data(); break;
+ case VMwareCmd::AbsPointerStatus: cmd_abs_pointer_status(); break;
+ case VMwareCmd::AbsPointerCommand: cmd_abs_pointer_command(); break;
+ default:
+ LOG_WARNING("MOUSE (PS/2): unimplemented VMware command 0x%08x",
+ reg_ecx);
+ break;
+ }
+
+ return reg_eax;
}
bool MOUSEVMM_NotifyMoved(const float x_rel, const float y_rel,
const uint16_t x_abs, const uint16_t y_abs)
{
- if (!mouse_shared.active_vmm)
- return false;
-
- speed_xy.Update(std::sqrt(x_rel * x_rel + y_rel * y_rel));
-
- const auto old_scaled_x = scaled_x;
- const auto old_scaled_y = scaled_y;
-
- auto calculate = [](float &position,
- const float relative,
- const uint16_t absolute,
- const uint16_t resolution,
- const uint16_t clip) {
- assert(resolution > 1u);
-
- if (mouse_is_captured || is_mapped) {
- // Mouse is captured, there is no need for pointer
- // integration with host OS - we can use relative
- // movement with configured sensitivity and (for
- // raw mouse input) our built-in pointer acceleration
- // model
-
- if (raw_input) {
- const auto coeff = MOUSE_GetBallisticsCoeff(speed_xy.Get());
- position += MOUSE_ClampRelativeMovement(relative * coeff);
- }
- else
- position += MOUSE_ClampRelativeMovement(relative);
- } else
- // Cursor position controlled by the host OS
- position = static_cast<float>(std::max(absolute - clip, 0));
-
- position = std::clamp(position, 0.0f, static_cast<float>(resolution));
-
- const auto scale = static_cast<float>(UINT16_MAX) /
- static_cast<float>(resolution - 1);
- const auto tmp = std::min(static_cast<uint32_t>(UINT16_MAX),
- static_cast<uint32_t>(
- std::lround(position * scale)));
-
- return static_cast<uint16_t>(tmp);
- };
-
- scaled_x = calculate(pos_x, x_rel, x_abs, mouse_video.res_x, mouse_video.clip_x);
- scaled_y = calculate(pos_y, y_rel, y_abs, mouse_video.res_y, mouse_video.clip_y);
-
- // Filter out unneeded events (like sub-pixel mouse movements,
- // which won't change guest side mouse state)
- if (GCC_UNLIKELY(old_scaled_x == scaled_x && old_scaled_y == scaled_y))
- return false;
-
- updated = true;
- return true;
+ if (!mouse_shared.active_vmm)
+ return false;
+
+ speed_xy.Update(std::sqrt(x_rel * x_rel + y_rel * y_rel));
+
+ const auto old_scaled_x = scaled_x;
+ const auto old_scaled_y = scaled_y;
+
+ auto calculate = [](float &position,
+ const float relative,
+ const uint16_t absolute,
+ const uint16_t resolution,
+ const uint16_t clip) {
+ assert(resolution > 1u);
+
+ if (mouse_is_captured || is_mapped) {
+ // Mouse is captured, there is no need for pointer
+ // integration with host OS - we can use relative
+ // movement with configured sensitivity and (for
+ // raw mouse input) our built-in pointer acceleration
+ // model
+
+ if (raw_input) {
+ const auto coeff = MOUSE_GetBallisticsCoeff(
+ speed_xy.Get());
+ position += MOUSE_ClampRelativeMovement(
+ relative * coeff);
+ } else
+ position += MOUSE_ClampRelativeMovement(relative);
+ } else
+ // Cursor position controlled by the host OS
+ position = static_cast<float>(std::max(absolute - clip, 0));
+
+ position = std::clamp(position, 0.0f, static_cast<float>(resolution));
+
+ const auto scale = static_cast<float>(UINT16_MAX) /
+ static_cast<float>(resolution - 1);
+ const auto tmp = std::min(static_cast<uint32_t>(UINT16_MAX),
+ static_cast<uint32_t>(
+ std::lround(position * scale)));
+
+ return static_cast<uint16_t>(tmp);
+ };
+
+ scaled_x = calculate(pos_x, x_rel, x_abs, mouse_video.res_x, mouse_video.clip_x);
+ scaled_y = calculate(pos_y, y_rel, y_abs, mouse_video.res_y, mouse_video.clip_y);
+
+ // Filter out unneeded events (like sub-pixel mouse movements,
+ // which won't change guest side mouse state)
+ if (GCC_UNLIKELY(old_scaled_x == scaled_x && old_scaled_y == scaled_y))
+ return false;
+
+ updated = true;
+ return true;
}
bool MOUSEVMM_NotifyButton(const MouseButtons12S buttons_12S)
{
- if (!mouse_shared.active_vmm)
- return false;
+ if (!mouse_shared.active_vmm)
+ return false;
- const auto old_buttons = buttons;
- buttons.data = 0;
+ const auto old_buttons = buttons;
+ buttons.data = 0;
- // Direct assignment of .data is not possible, as bit layout is different
- buttons.left = static_cast<bool>(buttons_12S.left);
- buttons.right = static_cast<bool>(buttons_12S.right);
- buttons.middle = static_cast<bool>(buttons_12S.middle);
+ // Direct assignment of .data is not possible, as bit layout is different
+ buttons.left = static_cast<bool>(buttons_12S.left);
+ buttons.right = static_cast<bool>(buttons_12S.right);
+ buttons.middle = static_cast<bool>(buttons_12S.middle);
- if (GCC_UNLIKELY(old_buttons.data == buttons.data))
- return false;
+ if (GCC_UNLIKELY(old_buttons.data == buttons.data))
+ return false;
- updated = true;
- return true;
+ updated = true;
+ return true;
}
bool MOUSEVMM_NotifyWheel(const int16_t w_rel)
{
- if (!mouse_shared.active_vmm)
- return false;
+ if (!mouse_shared.active_vmm)
+ return false;
- const auto old_counter_w = counter_w;
- counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + w_rel));
+ const auto old_counter_w = counter_w;
+ counter_w = clamp_to_int8(static_cast<int32_t>(counter_w + w_rel));
- if (GCC_UNLIKELY(old_counter_w == counter_w))
- return false;
+ if (GCC_UNLIKELY(old_counter_w == counter_w))
+ return false;
- updated = true;
- return true;
+ updated = true;
+ return true;
}
void MOUSEVMM_NewScreenParams(const uint16_t x_abs, const uint16_t y_abs)
{
- // Report a fake mouse movement
- if (MOUSEVMM_NotifyMoved(0.0f, 0.0f, x_abs, y_abs) && mouse_shared.active_vmm)
- MOUSE_NotifyFakePS2();
+ // Report a fake mouse movement
+ if (MOUSEVMM_NotifyMoved(0.0f, 0.0f, x_abs, y_abs) && mouse_shared.active_vmm)
+ MOUSE_NotifyFakePS2();
}
void MOUSEVMM_Init()
{
- IO_RegisterReadHandler(VMWARE_PORT, port_read_vmware, io_width_t::dword);
+ IO_RegisterReadHandler(VMWARE_PORT, port_read_vmware, io_width_t::dword);
}
diff --git a/src/hardware/serialport/serialmouse.cpp b/src/hardware/serialport/serialmouse.cpp
index 7063da017..745f740a1 100644
--- a/src/hardware/serialport/serialmouse.cpp
+++ b/src/hardware/serialport/serialmouse.cpp
@@ -34,545 +34,545 @@
CHECK_NARROWING();
-
// Port clock divider for 1200 baud transmission
static constexpr uint16_t divider_1200_baud = 96;
// 1200 baud serial mice is limited to about 40 Hz sampling rate
// due to serial port transmission constraints
static constexpr uint16_t rate_1200_baud = 40;
-
CSerialMouse::CSerialMouse(const uint8_t id, CommandLine *cmd)
: CSerial(id, cmd),
port_id(id),
port_num(static_cast<uint16_t>(id + 1))
{
- auto interface = MouseInterface::GetSerial(port_id);
- if (!interface)
- return;
+ auto interface = MouseInterface::GetSerial(port_id);
+ if (!interface)
+ return;
- // Get the parameters from the configuration file
+ // Get the parameters from the configuration file
- param_model = mouse_config.model_com;
- param_auto_msm = mouse_config.model_com_auto_msm;
+ param_model = mouse_config.model_com;
+ param_auto_msm = mouse_config.model_com_auto_msm;
- // Handle deprecated parameters
+ // Handle deprecated parameters
- HandleDeprecatedOptions(cmd);
+ HandleDeprecatedOptions(cmd);
- // Override with parameters from command line or [serial] section
+ // Override with parameters from command line or [serial] section
- std::string model_string;
- if (cmd->FindStringBegin("model:", model_string, false) &&
- !MouseConfig::ParseSerialModel(model_string, param_model, param_auto_msm)) {
- LOG_ERR("MOUSE (COM%d): Invalid model '%s'",
- port_num,
- model_string.c_str());
- }
+ std::string model_string;
+ if (cmd->FindStringBegin("model:", model_string, false) &&
+ !MouseConfig::ParseSerialModel(model_string, param_model, param_auto_msm)) {
+ LOG_ERR("MOUSE (COM%d): Invalid model '%s'",
+ port_num,
+ model_string.c_str());
+ }
- CSerial::Init_Registers();
- setRI(false);
- setDSR(false);
- setCD(false);
- setCTS(false);
+ CSerial::Init_Registers();
+ setRI(false);
+ setDSR(false);
+ setCD(false);
+ setCTS(false);
- interface->RegisterListener(*this);
- interface->NotifyInterfaceRate(rate_1200_baud);
- InstallationSuccessful = true;
+ interface->RegisterListener(*this);
+ interface->NotifyInterfaceRate(rate_1200_baud);
+ InstallationSuccessful = true;
}
CSerialMouse::~CSerialMouse()
{
- auto interface = MouseInterface::GetSerial(port_id);
- if (interface)
- interface->UnRegisterListener();
+ auto interface = MouseInterface::GetSerial(port_id);
+ if (interface)
+ interface->UnRegisterListener();
- removeEvent(SERIAL_TX_EVENT); // clear events
- SetModel(MouseModelCOM::NoMouse);
+ removeEvent(SERIAL_TX_EVENT); // clear events
+ SetModel(MouseModelCOM::NoMouse);
}
void CSerialMouse::HandleDeprecatedOptions(CommandLine *cmd)
{
- std::string option;
- if (cmd->FindStringBegin("rate:", option, false))
- LOG_WARNING("MOUSE (COM%d): Deprecated option 'rate:' - ignored", port_num);
-
- const bool found_deprecated = cmd->FindStringBegin("type:", option, false);
-
- if (found_deprecated) {
- LOG_WARNING("MOUSE (COM%d): Deprecated option 'type:'", port_num);
-
- if (option == "2btn") {
- param_model = MouseModelCOM::Microsoft;
- param_auto_msm = false;
- } else if (option == "2btn+msm") {
- param_model = MouseModelCOM::Microsoft;
- param_auto_msm = true;
- } else if (option == "3btn") {
- param_model = MouseModelCOM::Logitech;
- param_auto_msm = false;
- } else if (option == "3btn+msm") {
- param_model = MouseModelCOM::Logitech;
- param_auto_msm = true;
- } else if (option == "wheel") {
- param_model = MouseModelCOM::Wheel;
- param_auto_msm = false;
- } else if (option == "wheel+msm") {
- param_model = MouseModelCOM::Wheel;
- param_auto_msm = true;
- } else if (option == "msm") {
- param_model = MouseModelCOM::MouseSystems;
- param_auto_msm = false;
- } else {
- LOG_ERR("MOUSE (COM%d): Invalid type '%s'",
- port_num,
- option.c_str());
- return;
- }
- }
+ std::string option;
+ if (cmd->FindStringBegin("rate:", option, false))
+ LOG_WARNING("MOUSE (COM%d): Deprecated option 'rate:' - ignored",
+ port_num);
+
+ const bool found_deprecated = cmd->FindStringBegin("type:", option, false);
+
+ if (found_deprecated) {
+ LOG_WARNING("MOUSE (COM%d): Deprecated option 'type:'", port_num);
+
+ if (option == "2btn") {
+ param_model = MouseModelCOM::Microsoft;
+ param_auto_msm = false;
+ } else if (option == "2btn+msm") {
+ param_model = MouseModelCOM::Microsoft;
+ param_auto_msm = true;
+ } else if (option == "3btn") {
+ param_model = MouseModelCOM::Logitech;
+ param_auto_msm = false;
+ } else if (option == "3btn+msm") {
+ param_model = MouseModelCOM::Logitech;
+ param_auto_msm = true;
+ } else if (option == "wheel") {
+ param_model = MouseModelCOM::Wheel;
+ param_auto_msm = false;
+ } else if (option == "wheel+msm") {
+ param_model = MouseModelCOM::Wheel;
+ param_auto_msm = true;
+ } else if (option == "msm") {
+ param_model = MouseModelCOM::MouseSystems;
+ param_auto_msm = false;
+ } else {
+ LOG_ERR("MOUSE (COM%d): Invalid type '%s'",
+ port_num,
+ option.c_str());
+ return;
+ }
+ }
}
void CSerialMouse::BoostRate(const uint16_t rate_hz)
{
- if (!rate_hz || model == MouseModelCOM::NoMouse) {
- rate_coeff = 1.0f;
- return;
- }
-
- // Estimate current sampling rate, as precisely as possible
- auto estimate = [](const uint16_t bauds,
- const uint8_t byte_len,
- const MouseModelCOM model) {
- // In addition to byte_len, the mouse has to send
- // 3 more bits per each byte: start, parity, stop
-
- if (model == MouseModelCOM::Microsoft ||
- model == MouseModelCOM::Logitech ||
- model == MouseModelCOM::Wheel)
- // Microsoft-style protocol
- // single movement needs exactly 3 bytes to be reported
- return bauds / (static_cast<float>(byte_len + 3) * 3.0f);
- else if (model == MouseModelCOM::MouseSystems)
- // Mouse Systems protocol
- // single movement needs per average 2.5 bytes to be reported
- return bauds / (static_cast<float>(byte_len + 3) * 2.5f);
-
- assert(false); // unimplemented
- return static_cast<float>(rate_1200_baud);
- };
-
- // Calculate coefficient to match requested rate
- rate_coeff = estimate(1200, port_byte_len, model) / rate_hz;
+ if (!rate_hz || model == MouseModelCOM::NoMouse) {
+ rate_coeff = 1.0f;
+ return;
+ }
+
+ // Estimate current sampling rate, as precisely as possible
+ auto estimate = [](const uint16_t bauds,
+ const uint8_t byte_len,
+ const MouseModelCOM model) {
+ // In addition to byte_len, the mouse has to send
+ // 3 more bits per each byte: start, parity, stop
+
+ if (model == MouseModelCOM::Microsoft ||
+ model == MouseModelCOM::Logitech || model == MouseModelCOM::Wheel)
+ // Microsoft-style protocol
+ // single movement needs exactly 3 bytes to be reported
+ return bauds / (static_cast<float>(byte_len + 3) * 3.0f);
+ else if (model == MouseModelCOM::MouseSystems)
+ // Mouse Systems protocol
+ // single movement needs per average 2.5 bytes to be
+ // reported
+ return bauds / (static_cast<float>(byte_len + 3) * 2.5f);
+
+ assert(false); // unimplemented
+ return static_cast<float>(rate_1200_baud);
+ };
+
+ // Calculate coefficient to match requested rate
+ rate_coeff = estimate(1200, port_byte_len, model) / rate_hz;
}
void CSerialMouse::SetModel(const MouseModelCOM new_model)
{
- if (model != new_model) {
- model = new_model;
- const char *name = nullptr;
- switch (model) {
- case MouseModelCOM::NoMouse: // just to print out log in the destructor
- name = "(none)";
- break;
- case MouseModelCOM::Microsoft:
- name = "Microsoft, 2 buttons";
- has_3rd_button = false;
- has_wheel = false;
- break;
- case MouseModelCOM::Logitech:
- name = "Logitech, 3 buttons";
- has_3rd_button = true;
- has_wheel = false;
- break;
- case MouseModelCOM::Wheel:
- name = "wheel, 3 buttons";
- has_3rd_button = true;
- has_wheel = true;
- break;
- case MouseModelCOM::MouseSystems:
- name = "Mouse Systems, 3 buttons";
- has_3rd_button = true;
- has_wheel = false;
- break;
- default:
- assert(false); // unimplemented
- break;
- }
-
- if (name)
- LOG_MSG("MOUSE (COM%d): %s", port_num, name);
- }
-
- // So far all emulated mice are 1200 bauds, but report anyway
- // to trigger rate_coeff recalculation
- MouseInterface::GetSerial(port_id)->NotifyInterfaceRate(rate_1200_baud);
+ if (model != new_model) {
+ model = new_model;
+ const char *name = nullptr;
+ switch (model) {
+ case MouseModelCOM::NoMouse: // just to print out log in the
+ // destructor
+ name = "(none)";
+ break;
+ case MouseModelCOM::Microsoft:
+ name = "Microsoft, 2 buttons";
+ has_3rd_button = false;
+ has_wheel = false;
+ break;
+ case MouseModelCOM::Logitech:
+ name = "Logitech, 3 buttons";
+ has_3rd_button = true;
+ has_wheel = false;
+ break;
+ case MouseModelCOM::Wheel:
+ name = "wheel, 3 buttons";
+ has_3rd_button = true;
+ has_wheel = true;
+ break;
+ case MouseModelCOM::MouseSystems:
+ name = "Mouse Systems, 3 buttons";
+ has_3rd_button = true;
+ has_wheel = false;
+ break;
+ default:
+ assert(false); // unimplemented
+ break;
+ }
+
+ if (name)
+ LOG_MSG("MOUSE (COM%d): %s", port_num, name);
+ }
+
+ // So far all emulated mice are 1200 bauds, but report anyway
+ // to trigger rate_coeff recalculation
+ MouseInterface::GetSerial(port_id)->NotifyInterfaceRate(rate_1200_baud);
}
void CSerialMouse::AbortPacket()
{
- packet_len = 0;
- xmit_idx = 0xff;
- need_xmit_part2 = false;
- got_another_move = false;
- got_another_button = false;
+ packet_len = 0;
+ xmit_idx = 0xff;
+ need_xmit_part2 = false;
+ got_another_move = false;
+ got_another_button = false;
}
void CSerialMouse::ClearCounters()
{
- counter_x = 0;
- counter_y = 0;
- counter_w = 0;
+ counter_x = 0;
+ counter_y = 0;
+ counter_w = 0;
}
void CSerialMouse::MouseReset()
{
- AbortPacket();
- ClearCounters();
- buttons = 0;
- send_ack = true;
+ AbortPacket();
+ ClearCounters();
+ buttons = 0;
+ send_ack = true;
- SetEventRX();
+ SetEventRX();
}
void CSerialMouse::NotifyMoved(const float x_rel, const float y_rel)
{
- delta_x = MOUSE_ClampRelativeMovement(delta_x + x_rel);
- delta_y = MOUSE_ClampRelativeMovement(delta_y + y_rel);
+ delta_x = MOUSE_ClampRelativeMovement(delta_x + x_rel);
+ delta_y = MOUSE_ClampRelativeMovement(delta_y + y_rel);
- const auto dx = static_cast<int16_t>(std::lround(delta_x));
- const auto dy = static_cast<int16_t>(std::lround(delta_y));
+ const auto dx = static_cast<int16_t>(std::lround(delta_x));
+ const auto dy = static_cast<int16_t>(std::lround(delta_y));
- if (dx == 0 && dy == 0)
- return; // movement not significant enough
+ if (dx == 0 && dy == 0)
+ return; // movement not significant enough
- counter_x = clamp_to_int8(counter_x + dx);
- counter_y = clamp_to_int8(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;
+ delta_x -= dx;
+ delta_y -= dy;
- // Initiate data transfer and form the packet to transmit. If another
- // packet is already transmitting now then wait for it to finish before
- // transmitting ours, and let the mouse motion accumulate in the meantime
+ // Initiate data transfer and form the packet to transmit. If another
+ // packet is already transmitting now then wait for it to finish before
+ // transmitting ours, and let the mouse motion accumulate in the meantime
- if (xmit_idx >= packet_len)
- StartPacketData();
- else
- got_another_move = true;
+ if (xmit_idx >= packet_len)
+ StartPacketData();
+ else
+ got_another_move = true;
}
void CSerialMouse::NotifyButton(const uint8_t new_buttons, const uint8_t idx)
{
- if (!has_3rd_button && idx > 1)
- return;
+ if (!has_3rd_button && idx > 1)
+ return;
- buttons = new_buttons;
+ buttons = new_buttons;
- if (xmit_idx >= packet_len)
- StartPacketData(idx > 1);
- else
- got_another_button = true;
+ if (xmit_idx >= packet_len)
+ StartPacketData(idx > 1);
+ else
+ got_another_button = true;
}
void CSerialMouse::NotifyWheel(const int16_t w_rel)
{
- if (!has_wheel)
- return;
+ if (!has_wheel)
+ return;
- counter_w = clamp_to_int8(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
- got_another_button = true;
+ if (xmit_idx >= packet_len)
+ StartPacketData(true);
+ else
+ got_another_button = true;
}
void CSerialMouse::StartPacketId() // send the mouse identifier
{
- if (model == MouseModelCOM::NoMouse)
- return;
- AbortPacket();
- ClearCounters();
-
- packet_len = 0;
- switch (model) {
- case MouseModelCOM::Microsoft: packet[packet_len++] = 'M'; break;
- case MouseModelCOM::Logitech:
- packet[packet_len++] = 'M';
- packet[packet_len++] = '3';
- break;
- case MouseModelCOM::Wheel:
- packet[packet_len++] = 'M';
- packet[packet_len++] = 'Z';
- packet[packet_len++] = '@'; // for some reason 86Box sends more
- // than just 'MZ'
- packet[packet_len++] = 0;
- packet[packet_len++] = 0;
- packet[packet_len++] = 0;
- break;
- case MouseModelCOM::MouseSystems:
- packet[packet_len++] = 'H';
- break;
- default:
- assert(false); // unimplemented
- break;
- }
-
- // send packet
- xmit_idx = 0;
- SetEventRX();
+ if (model == MouseModelCOM::NoMouse)
+ return;
+ AbortPacket();
+ ClearCounters();
+
+ packet_len = 0;
+ switch (model) {
+ case MouseModelCOM::Microsoft: packet[packet_len++] = 'M'; break;
+ case MouseModelCOM::Logitech:
+ packet[packet_len++] = 'M';
+ packet[packet_len++] = '3';
+ break;
+ case MouseModelCOM::Wheel:
+ packet[packet_len++] = 'M';
+ packet[packet_len++] = 'Z';
+ packet[packet_len++] = '@'; // for some reason 86Box sends more
+ // than just 'MZ'
+ packet[packet_len++] = 0;
+ packet[packet_len++] = 0;
+ packet[packet_len++] = 0;
+ break;
+ case MouseModelCOM::MouseSystems: packet[packet_len++] = 'H'; break;
+ default:
+ assert(false); // unimplemented
+ break;
+ }
+
+ // send packet
+ xmit_idx = 0;
+ SetEventRX();
}
void CSerialMouse::StartPacketData(const bool extended)
{
- if (model == MouseModelCOM::NoMouse)
- return;
-
- if (model == MouseModelCOM::Microsoft || model == MouseModelCOM::Logitech ||
- model == MouseModelCOM::Wheel) {
- // -- -- -- -- -- -- -- --
- // Byte 0: X 1 LB RB Y7 Y6 X7 X6
- // Byte 1: X 0 X5 X4 X3 X2 X1 X0
- // Byte 2: X 0 Y5 Y4 Y3 Y2 Y1 Y0
- // Byte 3: X 0 MB 00 W3 W2 W1 W0 - only sent if needed
-
- // Do NOT set bit 7. It confuses CTMOUSE.EXE (CuteMouse) serial
- // support. Leaving it clear is the only way to make mouse
- // movement possible. Microsoft Windows on the other hand
- // doesn't care if bit 7 is set.
-
- const auto dx = ClampCounter(counter_x);
- const auto dy = ClampCounter(counter_y);
- const auto bt = has_3rd_button ? (buttons & 7) : (buttons & 3);
-
- packet[0] = static_cast<uint8_t>(
- 0x40 | ((bt & 1) << 5) | ((bt & 2) << 3) |
- (((dy >> 6) & 3) << 2) | ((dx >> 6) & 3));
- packet[1] = static_cast<uint8_t>(0x00 | (dx & 0x3f));
- packet[2] = static_cast<uint8_t>(0x00 | (dy & 0x3f));
- if (extended) {
- uint8_t dw = std::clamp(counter_w,
- static_cast<int8_t>(-0x10),
- static_cast<int8_t>(0x0f)) & 0x0f;
- packet[3] = static_cast<uint8_t>(((bt & 4) ? 0x20 : 0) | dw);
- packet_len = 4;
- } else {
- packet_len = 3;
- }
- need_xmit_part2 = false;
-
- } else if (model == MouseModelCOM::MouseSystems) {
- // -- -- -- -- -- -- -- --
- // Byte 0: 1 0 0 0 0 LB MB RB
- // Byte 1: X7 X6 X5 X4 X3 X2 X1 X0
- // Byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
-
- const auto bt = has_3rd_button ? ((~buttons) & 7)
- : ((~buttons) & 3);
-
- packet[0] = static_cast<uint8_t>(0x80 | ((bt & 1) << 2) |
+ if (model == MouseModelCOM::NoMouse)
+ return;
+
+ if (model == MouseModelCOM::Microsoft ||
+ model == MouseModelCOM::Logitech || model == MouseModelCOM::Wheel) {
+ // -- -- -- -- -- -- -- --
+ // Byte 0: X 1 LB RB Y7 Y6 X7 X6
+ // Byte 1: X 0 X5 X4 X3 X2 X1 X0
+ // Byte 2: X 0 Y5 Y4 Y3 Y2 Y1 Y0
+ // Byte 3: X 0 MB 00 W3 W2 W1 W0 - only sent if needed
+
+ // Do NOT set bit 7. It confuses CTMOUSE.EXE (CuteMouse) serial
+ // support. Leaving it clear is the only way to make mouse
+ // movement possible. Microsoft Windows on the other hand
+ // doesn't care if bit 7 is set.
+
+ const auto dx = ClampCounter(counter_x);
+ const auto dy = ClampCounter(counter_y);
+ const auto bt = has_3rd_button ? (buttons & 7) : (buttons & 3);
+
+ packet[0] = static_cast<uint8_t>(
+ 0x40 | ((bt & 1) << 5) | ((bt & 2) << 3) |
+ (((dy >> 6) & 3) << 2) | ((dx >> 6) & 3));
+ packet[1] = static_cast<uint8_t>(0x00 | (dx & 0x3f));
+ packet[2] = static_cast<uint8_t>(0x00 | (dy & 0x3f));
+ if (extended) {
+ uint8_t dw = std::clamp(counter_w,
+ static_cast<int8_t>(-0x10),
+ static_cast<int8_t>(0x0f)) &
+ 0x0f;
+ packet[3] = static_cast<uint8_t>(((bt & 4) ? 0x20 : 0) | dw);
+ packet_len = 4;
+ } else {
+ packet_len = 3;
+ }
+ need_xmit_part2 = false;
+
+ } else if (model == MouseModelCOM::MouseSystems) {
+ // -- -- -- -- -- -- -- --
+ // Byte 0: 1 0 0 0 0 LB MB RB
+ // Byte 1: X7 X6 X5 X4 X3 X2 X1 X0
+ // Byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+
+ const auto bt = has_3rd_button ? ((~buttons) & 7)
+ : ((~buttons) & 3);
+
+ packet[0] = static_cast<uint8_t>(0x80 | ((bt & 1) << 2) |
((bt & 2) >> 1) | ((bt & 4) >> 1));
- packet[1] = ClampCounter(counter_x);
- packet[2] = ClampCounter(-counter_y);
- packet_len = 3;
- need_xmit_part2 = true; // next part contains mouse movement since
- // the start of the 1st part
-
- } else
- assert(false); // unimplemented
-
- ClearCounters();
-
- // send packet
- xmit_idx = 0;
- got_another_button = false;
- got_another_move = false;
- SetEventRX();
+ packet[1] = ClampCounter(counter_x);
+ packet[2] = ClampCounter(-counter_y);
+ packet_len = 3;
+ need_xmit_part2 = true; // next part contains mouse movement
+ // since the start of the 1st part
+
+ } else
+ assert(false); // unimplemented
+
+ ClearCounters();
+
+ // send packet
+ xmit_idx = 0;
+ got_another_button = false;
+ got_another_move = false;
+ SetEventRX();
}
void CSerialMouse::StartPacketPart2()
{
- // port settings are valid at this point
+ // port settings are valid at this point
- if (model == MouseModelCOM::MouseSystems) {
- // -- -- -- -- -- -- -- --
- // Byte 3: X7 X6 X5 X4 X3 X2 X1 X0
- // Byte 4: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+ if (model == MouseModelCOM::MouseSystems) {
+ // -- -- -- -- -- -- -- --
+ // Byte 3: X7 X6 X5 X4 X3 X2 X1 X0
+ // Byte 4: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
- packet[0] = ClampCounter(counter_x);
- packet[1] = ClampCounter(-counter_y);
+ packet[0] = ClampCounter(counter_x);
+ packet[1] = ClampCounter(-counter_y);
- packet_len = 2;
- need_xmit_part2 = false;
- } else
- assert(false); // unimplemented
+ packet_len = 2;
+ need_xmit_part2 = false;
+ } else
+ assert(false); // unimplemented
- ClearCounters();
+ ClearCounters();
- // send packet
- xmit_idx = 0;
- got_another_move = false;
- SetEventRX();
+ // send packet
+ xmit_idx = 0;
+ got_another_move = false;
+ SetEventRX();
}
void CSerialMouse::SetEventTX()
{
- setEvent(SERIAL_TX_EVENT, bytetime * rate_coeff);
+ setEvent(SERIAL_TX_EVENT, bytetime * rate_coeff);
}
void CSerialMouse::SetEventRX()
{
- setEvent(SERIAL_RX_EVENT, bytetime * rate_coeff);
+ setEvent(SERIAL_RX_EVENT, bytetime * rate_coeff);
}
void CSerialMouse::SetEventTHR()
{
- setEvent(SERIAL_THR_EVENT, bytetime / 10);
+ setEvent(SERIAL_THR_EVENT, bytetime / 10);
}
uint8_t CSerialMouse::ClampCounter(const int32_t counter) const
{
- const auto tmp = std::clamp(counter,
- static_cast<int32_t>(INT8_MIN),
- static_cast<int32_t>(INT8_MAX));
- return static_cast<uint8_t>(tmp);
+ const auto tmp = std::clamp(counter,
+ static_cast<int32_t>(INT8_MIN),
+ static_cast<int32_t>(INT8_MAX));
+ return static_cast<uint8_t>(tmp);
}
void CSerialMouse::handleUpperEvent(const uint16_t event_type)
{
- if (event_type == SERIAL_TX_EVENT) {
- ByteTransmitted(); // tx timeout
- } else if (event_type == SERIAL_THR_EVENT) {
- ByteTransmitting();
- SetEventTX();
- } else if (event_type == SERIAL_RX_EVENT) {
- // check for bytes to be sent to port
- if (CSerial::CanReceiveByte()) {
- if (send_ack) {
- send_ack = false;
- StartPacketId();
- } else if (xmit_idx < packet_len) {
- CSerial::receiveByte(packet[xmit_idx++]);
- if (xmit_idx >= packet_len && need_xmit_part2)
- StartPacketPart2();
- else if (xmit_idx >= packet_len &&
- (got_another_move || got_another_button))
- StartPacketData();
- else
- SetEventRX();
- }
- } else
- SetEventRX();
- }
+ if (event_type == SERIAL_TX_EVENT) {
+ ByteTransmitted(); // tx timeout
+ } else if (event_type == SERIAL_THR_EVENT) {
+ ByteTransmitting();
+ SetEventTX();
+ } else if (event_type == SERIAL_RX_EVENT) {
+ // check for bytes to be sent to port
+ if (CSerial::CanReceiveByte()) {
+ if (send_ack) {
+ send_ack = false;
+ StartPacketId();
+ } else if (xmit_idx < packet_len) {
+ CSerial::receiveByte(packet[xmit_idx++]);
+ if (xmit_idx >= packet_len && need_xmit_part2)
+ StartPacketPart2();
+ else if (xmit_idx >= packet_len &&
+ (got_another_move || got_another_button))
+ StartPacketData();
+ else
+ SetEventRX();
+ }
+ } else
+ SetEventRX();
+ }
}
void CSerialMouse::updatePortConfig(const uint16_t divider, const uint8_t lcr)
{
- AbortPacket();
-
- // We have to select between Microsoft-style protocol (this includes Logitech
- // and wheel mice) and Mouse Systems Mouse protocol, or decide the port
- // settings are not valid for any mouse
-
- port_byte_len = static_cast<uint8_t>((lcr & 0x3) + 5);
- const auto one_stop_bit = !(lcr & 0x4);
- const auto parity_id = static_cast<uint8_t>((lcr & 0x38) >> 3);
-
- // LOG_MSG("MOUSE (COM%d): lcr 0x%04x, divider %d, byte_len %d, stop %d, parity %d",
- // port_num, lcr, divider, port_byte_len, one_stop_bit, parity_id);
-
- if (divider != divider_1200_baud) {
- // We need 1200 bauds for a mouse; TODO:support faster serial mice,
- // see https://man7.org/linux/man-pages/man4/mouse.4.html
- SetModel(MouseModelCOM::NoMouse);
- return;
- }
-
- // Require 1 sop bit
- if (!one_stop_bit) {
- SetModel(MouseModelCOM::NoMouse);
- return;
- }
-
- // Require parity 'N'
- if (parity_id == 1 || parity_id == 3 || parity_id == 5 || parity_id == 7) {
- SetModel(MouseModelCOM::NoMouse);
- return;
- }
-
- // Check protocol compatibility with byte length
- bool ok_microsoft = (param_model != MouseModelCOM::MouseSystems);
- bool ok_mouse_systems = param_auto_msm || (param_model == MouseModelCOM::MouseSystems);
-
- // NOTE: It seems some software (at least The Settlers) tries to use
- // Microsoft-style protocol by setting port to 8 bits per byte;
- // we allow this if autodetection is not enabled, otherwise it is
- // impossible to guess which protocol the guest software expects
-
- if (port_byte_len != 7 && !(!param_auto_msm && port_byte_len == 8))
- ok_microsoft = false;
- if (port_byte_len != 8)
- ok_mouse_systems = false;
-
- // Set the mouse protocol
- if (ok_microsoft)
- SetModel(param_model);
- else if (ok_mouse_systems)
- SetModel(MouseModelCOM::MouseSystems);
- else
- SetModel(MouseModelCOM::NoMouse);
+ AbortPacket();
+
+ // We have to select between Microsoft-style protocol (this includes
+ // Logitech and wheel mice) and Mouse Systems Mouse protocol, or decide
+ // the port settings are not valid for any mouse
+
+ port_byte_len = static_cast<uint8_t>((lcr & 0x3) + 5);
+ const auto one_stop_bit = !(lcr & 0x4);
+ const auto parity_id = static_cast<uint8_t>((lcr & 0x38) >> 3);
+
+ // LOG_MSG("MOUSE (COM%d): lcr 0x%04x, divider %d, byte_len %d, stop %d,
+ // parity %d",
+ // port_num, lcr, divider, port_byte_len, one_stop_bit, parity_id);
+
+ if (divider != divider_1200_baud) {
+ // We need 1200 bauds for a mouse; TODO:support faster serial
+ // mice, see https://man7.org/linux/man-pages/man4/mouse.4.html
+ SetModel(MouseModelCOM::NoMouse);
+ return;
+ }
+
+ // Require 1 sop bit
+ if (!one_stop_bit) {
+ SetModel(MouseModelCOM::NoMouse);
+ return;
+ }
+
+ // Require parity 'N'
+ if (parity_id == 1 || parity_id == 3 || parity_id == 5 || parity_id == 7) {
+ SetModel(MouseModelCOM::NoMouse);
+ return;
+ }
+
+ // Check protocol compatibility with byte length
+ bool ok_microsoft = (param_model != MouseModelCOM::MouseSystems);
+ bool ok_mouse_systems = param_auto_msm ||
+ (param_model == MouseModelCOM::MouseSystems);
+
+ // NOTE: It seems some software (at least The Settlers) tries to use
+ // Microsoft-style protocol by setting port to 8 bits per byte;
+ // we allow this if autodetection is not enabled, otherwise it is
+ // impossible to guess which protocol the guest software expects
+
+ if (port_byte_len != 7 && !(!param_auto_msm && port_byte_len == 8))
+ ok_microsoft = false;
+ if (port_byte_len != 8)
+ ok_mouse_systems = false;
+
+ // Set the mouse protocol
+ if (ok_microsoft)
+ SetModel(param_model);
+ else if (ok_mouse_systems)
+ SetModel(MouseModelCOM::MouseSystems);
+ else
+ SetModel(MouseModelCOM::NoMouse);
}
void CSerialMouse::updateMSR() {}
void CSerialMouse::transmitByte(const uint8_t, const bool first)
{
- if (first)
- SetEventTHR();
- else
- SetEventTX();
+ if (first)
+ SetEventTHR();
+ else
+ SetEventTX();
}
void CSerialMouse::setBreak(const bool) {}
void CSerialMouse::setRTSDTR(const bool rts, const bool dtr)
{
- if (rts && dtr && !getRTS() && !getDTR()) {
-
- // The serial mouse driver turns on the mouse by bringing up
- // RTS and DTR. Not just for show, but to give the serial mouse
- // a power source to work from. Likewise, drivers "reset" the
- // mouse by bringing down the lines, then bringing them back
- // up. And most drivers turn off the mouse when not in use by
- // bringing them back down and leaving them that way.
- //
- // We're expected to transmit ASCII character 'M' when first
- // initialized, so that the driver knows we're a Microsoft
- // compatible serial mouse attached to a COM port.
-
- MouseReset();
- }
-
- setRTS(rts);
- setDTR(dtr);
+ if (rts && dtr && !getRTS() && !getDTR()) {
+ // The serial mouse driver turns on the mouse by bringing up
+ // RTS and DTR. Not just for show, but to give the serial mouse
+ // a power source to work from. Likewise, drivers "reset" the
+ // mouse by bringing down the lines, then bringing them back
+ // up. And most drivers turn off the mouse when not in use by
+ // bringing them back down and leaving them that way.
+ //
+ // We're expected to transmit ASCII character 'M' when first
+ // initialized, so that the driver knows we're a Microsoft
+ // compatible serial mouse attached to a COM port.
+
+ MouseReset();
+ }
+
+ setRTS(rts);
+ setDTR(dtr);
}
void CSerialMouse::setRTS(const bool val)
{
- if (val && !getRTS() && getDTR()) {
- MouseReset();
- }
+ if (val && !getRTS() && getDTR()) {
+ MouseReset();
+ }
- setCTS(val);
+ setCTS(val);
}
void CSerialMouse::setDTR(const bool val)
{
- if (val && !getDTR() && getRTS()) {
- MouseReset();
- }
+ if (val && !getDTR() && getRTS()) {
+ MouseReset();
+ }
- setDSR(val);
- setRI(val);
- setCD(val);
+ setDSR(val);
+ setRI(val);
+ setCD(val);
}
diff --git a/src/hardware/serialport/serialmouse.h b/src/hardware/serialport/serialmouse.h
index 8bb29beb5..8c9337446 100644
--- a/src/hardware/serialport/serialmouse.h
+++ b/src/hardware/serialport/serialmouse.h
@@ -24,76 +24,74 @@
#include "../mouse/mouse_config.h"
-
class CSerialMouse : public CSerial {
public:
- CSerialMouse(const uint8_t id, CommandLine *cmd);
- virtual ~CSerialMouse();
+ CSerialMouse(const uint8_t id, CommandLine *cmd);
+ virtual ~CSerialMouse();
- void NotifyMoved(const float x_rel, const float y_rel);
- void NotifyButton(const uint8_t new_buttons,
- const uint8_t idx); // changed button, staring from 0
- void NotifyWheel(const int16_t w_rel);
+ void NotifyMoved(const float x_rel, const float y_rel);
+ void NotifyButton(const uint8_t new_buttons,
+ const uint8_t idx); // changed button, staring from 0
+ void NotifyWheel(const int16_t w_rel);
- void BoostRate(const uint16_t rate_hz); // 0 = standard rate
+ void BoostRate(const uint16_t rate_hz); // 0 = standard rate
- void setRTSDTR(const bool rts, const bool dtr) override;
- void setRTS(const bool val) override;
- void setDTR(const bool val) override;
+ void setRTSDTR(const bool rts, const bool dtr) override;
+ void setRTS(const bool val) override;
+ void setDTR(const bool val) override;
- void updatePortConfig(const uint16_t divider, const uint8_t lcr) override;
- void updateMSR() override;
- void transmitByte(const uint8_t val, const bool first) override;
- void setBreak(const bool value) override;
- void handleUpperEvent(const uint16_t event_type) override;
+ void updatePortConfig(const uint16_t divider, const uint8_t lcr) override;
+ void updateMSR() override;
+ void transmitByte(const uint8_t val, const bool first) override;
+ void setBreak(const bool value) override;
+ void handleUpperEvent(const uint16_t event_type) override;
private:
-
- void HandleDeprecatedOptions(CommandLine *cmd);
- void SetModel(const MouseModelCOM new_type);
- void AbortPacket();
- void ClearCounters();
- void MouseReset();
- void StartPacketId();
- void StartPacketData(const bool extended = false);
- void StartPacketPart2();
- void SetEventTX();
- void SetEventRX();
- void SetEventTHR();
- uint8_t ClampCounter(const int32_t counter) const;
-
- const uint8_t port_id = 0;
- const uint16_t port_num = 0; // for logging purposes
-
- // Mouse model as specified in the parameter
- MouseModelCOM param_model = MouseModelCOM::NoMouse;
- // If true = autoswitch between param_model and Mouse Systems mouse
- bool param_auto_msm = false;
-
- MouseModelCOM model = MouseModelCOM::NoMouse; // currently emulated model
-
- uint8_t port_byte_len = 0; // how many bits the port transmits in a byte
-
- bool has_3rd_button = false;
- bool has_wheel = false;
- float rate_coeff = 1.0f; // coefficient for boosted sampling rate
- 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 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;
- int8_t counter_x = 0; // position counters, as visible on guest size
- int8_t counter_y = 0;
- int8_t counter_w = 0;
+ void HandleDeprecatedOptions(CommandLine *cmd);
+ void SetModel(const MouseModelCOM new_type);
+ void AbortPacket();
+ void ClearCounters();
+ void MouseReset();
+ void StartPacketId();
+ void StartPacketData(const bool extended = false);
+ void StartPacketPart2();
+ void SetEventTX();
+ void SetEventRX();
+ void SetEventTHR();
+ uint8_t ClampCounter(const int32_t counter) const;
+
+ const uint8_t port_id = 0;
+ const uint16_t port_num = 0; // for logging purposes
+
+ // Mouse model as specified in the parameter
+ MouseModelCOM param_model = MouseModelCOM::NoMouse;
+ // If true = autoswitch between param_model and Mouse Systems mouse
+ bool param_auto_msm = false;
+
+ MouseModelCOM model = MouseModelCOM::NoMouse; // currently emulated model
+
+ uint8_t port_byte_len = 0; // how many bits the port transmits in a byte
+
+ bool has_3rd_button = false;
+ bool has_wheel = false;
+ float rate_coeff = 1.0f; // coefficient for boosted sampling rate
+ 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 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;
+ int8_t counter_x = 0; // position counters, as visible on guest size
+ int8_t counter_y = 0;
+ int8_t counter_w = 0;
};
#endif // DOSBOX_SERIALMOUSE_H