diff options
author | FeralChild64 <unknown> | 2022-10-16 20:44:33 +0300 |
---|---|---|
committer | kcgen <1557255+kcgen@users.noreply.github.com> | 2022-10-22 21:15:34 +0300 |
commit | 04401fc0270091cde34672ba097c2cb40af14fbc (patch) | |
tree | ae66bc74df49da1366b29806b3e0dc32f4345cc9 | |
parent | 175b256ddb43dac52dc7da3cf8c42eb392438c41 (diff) |
Handle code review remarks
-rw-r--r-- | include/mouse.h | 26 | ||||
-rw-r--r-- | src/dos/program_mousectl.cpp | 904 | ||||
-rw-r--r-- | src/dos/program_mousectl.h | 72 | ||||
-rw-r--r-- | src/hardware/mouse/mouse.cpp | 54 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_common.cpp | 4 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_config.cpp | 199 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_config.h | 30 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_interfaces.cpp | 148 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_interfaces.h | 31 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_manymouse.cpp | 88 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_manymouse.h | 8 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_queue.cpp | 20 | ||||
-rw-r--r-- | src/hardware/mouse/mouse_queue.h | 4 | ||||
-rw-r--r-- | src/hardware/mouse/mouseif_dos_driver.cpp | 48 | ||||
-rw-r--r-- | src/hardware/mouse/mouseif_ps2_bios.cpp | 125 | ||||
-rw-r--r-- | src/hardware/serialport/serialmouse.cpp | 12 | ||||
-rw-r--r-- | src/ints/bios.cpp | 8 |
17 files changed, 913 insertions, 868 deletions
diff --git a/include/mouse.h b/include/mouse.h index 12b3b5e51..98ef12871 100644 --- a/include/mouse.h +++ b/include/mouse.h @@ -98,7 +98,8 @@ bool MOUSE_IsUsingSeamlessSetting(); // if user selected seamless mode is in eff // BIOS mouse interface for PS/2 mouse // *************************************************************************** -bool MOUSEBIOS_SetState(const bool use); +bool MOUSEBIOS_Enable(); +bool MOUSEBIOS_Disable(); void MOUSEBIOS_SetCallback(const uint16_t pseg, const uint16_t pofs); void MOUSEBIOS_Reset(); bool MOUSEBIOS_SetPacketSize(const uint8_t packet_size); @@ -134,16 +135,16 @@ public: MouseInterfaceId GetInterfaceId() const; MouseMapStatus GetMapStatus() const; const std::string &GetMappedDeviceName() const; - int8_t GetSensitivityX() const; // -99 to +99 - int8_t GetSensitivityY() const; // -99 to +99 - uint16_t GetMinRate() const; // 10-500, 0 for none - uint16_t GetRate() const; // current rate, 10-500, 0 for N/A + int16_t GetSensitivityX() const; // -999 to +999 + int16_t GetSensitivityY() const; // -999 to +999 + uint16_t GetMinRate() const; // 10-500, 0 for none + uint16_t GetRate() const; // current rate, 10-500, 0 for N/A private: friend class MouseInterface; MouseInterfaceInfoEntry(const MouseInterfaceId interface_id); - const uint8_t idx; + const uint8_t interface_idx; const MouseInterface &Interface() const; const MousePhysical &MappedPhysical() const; }; @@ -192,11 +193,12 @@ public: bool OnOff(const ListIDs &list_ids, const bool enable); bool Reset(const ListIDs &list_ids); - // Valid sensitivity values are from -99 to +99 - bool SetSensitivity(const ListIDs &list_ids, const int8_t sensitivity_x, - const int8_t sensitivity_y); - bool SetSensitivityX(const ListIDs &list_ids, const int8_t sensitivity_x); - bool SetSensitivityY(const ListIDs &list_ids, const int8_t sensitivity_y); + // Valid sensitivity values are from -999 to +999 + bool SetSensitivity(const ListIDs &list_ids, + const int16_t sensitivity_x, + const int16_t sensitivity_y); + bool SetSensitivityX(const ListIDs &list_ids, const int16_t sensitivity_x); + bool SetSensitivityY(const ListIDs &list_ids, const int16_t sensitivity_y); bool ResetSensitivity(const ListIDs &list_ids); bool ResetSensitivityX(const ListIDs &list_ids); @@ -204,6 +206,8 @@ public: static const std::vector<uint16_t> &GetValidMinRateList(); static const std::string &GetValidMinRateStr(); + static std::string GetInterfaceNameStr(const MouseInterfaceId interface_id); + bool SetMinRate(const MouseControlAPI::ListIDs &list_ids, const uint16_t value_hz); bool ResetMinRate(const MouseControlAPI::ListIDs &list_ids); diff --git a/src/dos/program_mousectl.cpp b/src/dos/program_mousectl.cpp index 656b27c4c..64709fe55 100644 --- a/src/dos/program_mousectl.cpp +++ b/src/dos/program_mousectl.cpp @@ -29,510 +29,566 @@ CHECK_NARROWING(); - void MOUSECTL::Run() { - if (HelpRequested()) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_HELP_LONG")); - return; - } + if (HelpRequested()) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_HELP_LONG")); + return; + } - ParseAndRun(); - // TODO: once exit codes are supported, set it according to result + ParseAndRun(); + // TODO: once exit codes are supported, set it according to result } bool MOUSECTL::ParseAndRun() { - // Put all the parameters into vector - std::vector<std::string> params; - cmd->FillVector(params); - - // Extract the list of interfaces from the vector - list_ids.clear(); - if (!ParseInterfaces(params) || !CheckInterfaces()) - return false; - - auto param_equal = [¶ms](const size_t idx, const char *string) - { - if (idx >= params.size()) - return false; - return iequals(params[idx], string); - }; - - // CmdShow - if (list_ids.size() == 0 && params.size() == 0) - return CmdShow(false); - if (list_ids.size() == 0 && params.size() == 1) - if (param_equal(0, "-all")) - return CmdShow(true); - - // CmdMap - by supplied host mouse name - if (list_ids.size() == 1 && params.size() == 2) - if (param_equal(0, "-map")) - return CmdMap(list_ids[0], params[1]); - - // CmdMap - interactive - if (list_ids.size() >= 1 && params.size() == 1) - if (param_equal(0, "-map")) - return CmdMap(); - - // CmdUnmap / CmdOnOff / CmdReset / CmdSensitivity / CmdMinRate - if (params.size() == 1) { - if (param_equal(0, "-unmap")) - return CmdUnMap(); - if (param_equal(0, "-on")) - return CmdOnOff(true); - if (param_equal(0, "-off")) - return CmdOnOff(false); - if (param_equal(0, "-reset")) - return CmdReset(); - if (param_equal(0, "-s")) - return CmdSensitivity(); - if (param_equal(0, "-sx")) - return CmdSensitivityX(); - if (param_equal(0, "-sy")) - return CmdSensitivityY(); - if (param_equal(0, "-r")) - return CmdMinRate(); - } - - // CmdSensitivity / CmdMinRate with a non-default value - if (params.size() == 2) { - if (param_equal(0, "-r")) - return CmdMinRate(params[1]); - - const auto value = std::atoi(params[1].c_str()); - if (value < -99 || value > 99) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_SENSITIVITY")); - return false; - } - if (param_equal(0, "-s")) - return CmdSensitivity(static_cast<int8_t>(value)); - if (param_equal(0, "-sx")) - return CmdSensitivityX(static_cast<int8_t>(value)); - if (param_equal(0, "-sy")) - return CmdSensitivityY(static_cast<int8_t>(value)); - } - - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX")); - return false; + // Put all the parameters into vector + std::vector<std::string> params; + cmd->FillVector(params); + + // Extract the list of interfaces from the vector + list_ids.clear(); + if (!ParseInterfaces(params) || !CheckInterfaces()) + return false; + + auto param_equal = [¶ms](const size_t idx, const char *string) { + if (idx >= params.size()) + return false; + return iequals(params[idx], string); + }; + + // CmdShow + if (list_ids.size() == 0 && params.empty()) + return CmdShow(false); + if (list_ids.size() == 0 && params.size() == 1) + if (param_equal(0, "-all")) + return CmdShow(true); + + // CmdMap - by supplied host mouse name + if (list_ids.size() == 1 && params.size() == 2) + if (param_equal(0, "-map")) + return CmdMap(list_ids[0], params[1]); + + // CmdMap - interactive + if (!list_ids.empty() && params.size() == 1) + if (param_equal(0, "-map")) + return CmdMap(); + + // CmdUnmap / CmdOnOff / CmdReset / CmdSensitivity / CmdMinRate + if (params.size() == 1) { + if (param_equal(0, "-unmap")) + return CmdUnMap(); + if (param_equal(0, "-on")) + return CmdOnOff(true); + if (param_equal(0, "-off")) + return CmdOnOff(false); + if (param_equal(0, "-reset")) + return CmdReset(); + if (param_equal(0, "-s")) + return CmdSensitivity(); + if (param_equal(0, "-sx")) + return CmdSensitivityX(); + if (param_equal(0, "-sy")) + return CmdSensitivityY(); + if (param_equal(0, "-r")) + return CmdMinRate(); + } + + // CmdSensitivity / CmdMinRate with a non-default value + if (params.size() == 2) { + if (param_equal(0, "-r")) + return CmdMinRate(params[1]); + + if (param_equal(0, "-s")) + return CmdSensitivity(params[1], params[1]); + if (param_equal(0, "-sx")) + return CmdSensitivityX(params[1]); + if (param_equal(0, "-sy")) + return CmdSensitivityY(params[1]); + } + if (params.size() == 3) { + if (param_equal(0, "-s")) + return CmdSensitivity(params[1], params[2]); + } + + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX")); + return false; } -bool MOUSECTL::ParseInterfaces(std::vector<std::string> ¶ms) +bool MOUSECTL::ParseSensitivity(const std::string ¶m, int16_t &value) { - auto add_if_is_interface = [&](const std::string ¶m) { - for (const auto id : { - MouseInterfaceId::DOS, - MouseInterfaceId::PS2, - MouseInterfaceId::COM1, - MouseInterfaceId::COM2, - MouseInterfaceId::COM3, - MouseInterfaceId::COM4, - }) { - if (iequals(param, GetInterfaceStr(id))) { - list_ids.push_back(id); - return true; - } - } - if (iequals(param, "PS2")) { // syntax sugar, easier to type than 'PS/2' - list_ids.push_back(MouseInterfaceId::PS2); - return true; - } - return false; - }; - while (!params.empty() && add_if_is_interface(params.front())) - params.erase(params.begin()); // pop - - // Check that all interfaces are unique - std::set<MouseInterfaceId> tmp(list_ids.begin(), list_ids.end()); - if (list_ids.size() != tmp.size()) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_DUPLICATED")); - return false; - } - - return true; + value = 0; + + int tmp = 0; + if (!ParseIntParam(param, tmp)) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_SENSITIVITY")); + return false; + } + + // Maximum allowed user sensitivity value + constexpr int16_t sensitivity_user_max = 999; + if (tmp < -sensitivity_user_max || tmp > sensitivity_user_max) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_SENSITIVITY")); + return false; + } + + value = static_cast<int16_t>(tmp); + return true; } -bool MOUSECTL::CheckInterfaces() +bool MOUSECTL::ParseIntParam(const std::string ¶m, int &value) { - if (MouseControlAPI::CheckInterfaces(list_ids)) - return true; - - if (list_ids.empty()) - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_INTERFACES")); - else - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MISSING_INTERFACES")); + try { + value = std::stoi(param); + } catch (...) { + value = 0; + return false; + } + + return true; +} - return false; +bool MOUSECTL::ParseInterfaces(std::vector<std::string> ¶ms) +{ + auto add_if_is_interface = [&](const std::string ¶m) { + for (const auto id : { + MouseInterfaceId::DOS, + MouseInterfaceId::PS2, + MouseInterfaceId::COM1, + MouseInterfaceId::COM2, + MouseInterfaceId::COM3, + MouseInterfaceId::COM4, + }) { + if (iequals(param, MouseControlAPI::GetInterfaceNameStr(id))) { + list_ids.push_back(id); + return true; + } + } + if (iequals(param, "PS2")) { // syntax sugar, easier to type + // than 'PS/2' + list_ids.push_back(MouseInterfaceId::PS2); + return true; + } + return false; + }; + while (!params.empty() && add_if_is_interface(params.front())) + params.erase(params.begin()); // pop + + // Check that all interfaces are unique + const std::set<MouseInterfaceId> tmp(list_ids.begin(), list_ids.end()); + if (list_ids.size() != tmp.size()) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_DUPLICATED")); + return false; + } + + return true; } -const char *MOUSECTL::GetInterfaceStr(const MouseInterfaceId interface_id) const +bool MOUSECTL::CheckInterfaces() { - switch (interface_id) { - case MouseInterfaceId::DOS: return "DOS"; - case MouseInterfaceId::PS2: return "PS/2"; - case MouseInterfaceId::COM1: return "COM1"; - case MouseInterfaceId::COM2: return "COM2"; - case MouseInterfaceId::COM3: return "COM3"; - case MouseInterfaceId::COM4: return "COM4"; - case MouseInterfaceId::None: return ""; - default: - assert(false); // missing implementation - return nullptr; - } + if (MouseControlAPI::CheckInterfaces(list_ids)) + return true; + + if (list_ids.empty()) + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_INTERFACES")); + else + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MISSING_INTERFACES")); + + return false; } -const char *MOUSECTL::GetMapStatusStr(const MouseMapStatus map_status) const +const char *MOUSECTL::GetMapStatusStr(const MouseMapStatus map_status) { - switch (map_status) { - case MouseMapStatus::HostPointer: - return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_HOST"); - case MouseMapStatus::Mapped: - return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_MAPPED"); - case MouseMapStatus::Disconnected: - return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISCONNECTED"); - case MouseMapStatus::Disabled: - return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISABLED"); - default: - assert(false); // missing implementation - return nullptr; - } + switch (map_status) { + case MouseMapStatus::HostPointer: + return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_HOST"); + case MouseMapStatus::Mapped: + return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_MAPPED"); + case MouseMapStatus::Disconnected: + return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISCONNECTED"); + case MouseMapStatus::Disabled: + return MSG_Get("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISABLED"); + default: + assert(false); // missing implementation + return nullptr; + } } bool MOUSECTL::CmdShow(const bool show_all) { - MouseControlAPI mouse_config_api; - const auto info_interfaces = mouse_config_api.GetInfoInterfaces(); - - bool show_mapped = false; - bool hint_rate_com = false; - bool hint_rate_min = false; - - // Display emulated interface list - WriteOut("\n"); - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HEADER1")); - WriteOut("\n"); - for (const auto &entry : info_interfaces) { - if (!entry.IsEmulated()) - continue; - const auto interface_id = entry.GetInterfaceId(); - const auto rate_hz = entry.GetRate(); - const bool rate_enforced = entry.GetMinRate(); - - if (rate_enforced) - hint_rate_min = true; - - if (interface_id == MouseInterfaceId::COM1 || - interface_id == MouseInterfaceId::COM2 || - interface_id == MouseInterfaceId::COM3 || - interface_id == MouseInterfaceId::COM4) - hint_rate_com = true; - - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_LAYOUT1"), - GetInterfaceStr(interface_id), - entry.GetSensitivityX(), - entry.GetSensitivityY(), - rate_enforced ? "*" : "", - rate_hz ? std::to_string(rate_hz).c_str() : "-", - convert_ansi_markup(GetMapStatusStr(entry.GetMapStatus())).c_str()); - WriteOut("\n"); - - if (entry.GetMapStatus() == MouseMapStatus::Mapped) - show_mapped = true; - } - WriteOut("\n"); - - const bool hint = hint_rate_com || hint_rate_min; - if (hint) - { - if (hint_rate_com) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_COM")); - WriteOut("\n"); - } - if (hint_rate_min) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_MIN")); - WriteOut("\n"); - } - WriteOut("\n"); - } - - if (!show_all && !show_mapped) - return true; - - const auto info_physical = mouse_config_api.GetInfoPhysical(); - if (info_physical.empty()) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_PHYSICAL_MICE")); - WriteOut("\n\n"); - return true; - } - - if (hint) - WriteOut("\n"); - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HEADER2")); - WriteOut("\n"); - - // Display physical mice mapped to some interface - for (const auto &entry : info_interfaces) { - if (!entry.IsMapped() || entry.IsMappedDeviceDisconnected()) - continue; - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2"), - GetInterfaceStr(entry.GetInterfaceId()), - entry.GetMappedDeviceName().c_str()); - WriteOut("\n"); - } - - if (!show_all) - return true; - - // Display physical mice not mapped to any interface - for (const auto &entry : info_physical) { - if (entry.IsMapped() || entry.IsDeviceDisconnected()) - continue; - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2_UNMAPPED"), - entry.GetDeviceName().c_str()); - WriteOut("\n"); - } - WriteOut("\n"); - - return true; + MouseControlAPI mouse_config_api; + const auto info_interfaces = mouse_config_api.GetInfoInterfaces(); + + bool show_mapped = false; + bool hint_rate_com = false; + bool hint_rate_min = false; + + // Display emulated interface list + WriteOut("\n"); + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HEADER1")); + WriteOut("\n"); + for (const auto &entry : info_interfaces) { + if (!entry.IsEmulated()) + continue; + const auto interface_id = entry.GetInterfaceId(); + const auto rate_hz = entry.GetRate(); + const bool rate_enforced = entry.GetMinRate(); + + if (rate_enforced) + hint_rate_min = true; + + if (interface_id == MouseInterfaceId::COM1 || + interface_id == MouseInterfaceId::COM2 || + interface_id == MouseInterfaceId::COM3 || + interface_id == MouseInterfaceId::COM4) + hint_rate_com = true; + + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_LAYOUT1"), + MouseControlAPI::GetInterfaceNameStr(interface_id).c_str(), + entry.GetSensitivityX(), + entry.GetSensitivityY(), + rate_enforced ? "*" : "", + rate_hz ? std::to_string(rate_hz).c_str() : "-", + convert_ansi_markup(GetMapStatusStr(entry.GetMapStatus())) + .c_str()); + WriteOut("\n"); + + if (entry.GetMapStatus() == MouseMapStatus::Mapped) + show_mapped = true; + } + WriteOut("\n"); + + const bool hint = hint_rate_com || hint_rate_min; + if (hint) { + if (hint_rate_com) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_COM")); + WriteOut("\n"); + } + if (hint_rate_min) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_MIN")); + WriteOut("\n"); + } + WriteOut("\n"); + } + + if (!show_all && !show_mapped) + return true; + + const auto info_physical = mouse_config_api.GetInfoPhysical(); + if (info_physical.empty()) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_PHYSICAL_MICE")); + WriteOut("\n\n"); + return true; + } + + if (hint) + WriteOut("\n"); + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_HEADER2")); + WriteOut("\n"); + + // Display physical mice mapped to some interface + bool needs_newline = false; + for (const auto &entry : info_interfaces) { + if (!entry.IsMapped() || entry.IsMappedDeviceDisconnected()) + continue; + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2"), + MouseControlAPI::GetInterfaceNameStr(entry.GetInterfaceId()) + .c_str(), + entry.GetMappedDeviceName().c_str()); + WriteOut("\n"); + needs_newline = true; + } + + if (!show_all) { + if (needs_newline) + WriteOut("\n"); + return true; + } + + // Display physical mice not mapped to any interface + for (const auto &entry : info_physical) { + if (entry.IsMapped() || entry.IsDeviceDisconnected()) + continue; + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2_UNMAPPED"), + entry.GetDeviceName().c_str()); + WriteOut("\n"); + } + WriteOut("\n"); + + return true; } void MOUSECTL::FinalizeMapping() { - WriteOut("\n"); - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAP_HINT")); - WriteOut("\n\n"); + WriteOut("\n"); + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAP_HINT")); + WriteOut("\n\n"); - GFX_MouseCaptureAfterMapping(); + GFX_MouseCaptureAfterMapping(); } bool MOUSECTL::CmdMap(const MouseInterfaceId interface_id, const std::string &pattern) { - std::regex regex; - if (!MouseControlAPI::PatternToRegex(pattern, regex)) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_PATTERN")); - return false; - } - - if (MouseControlAPI::IsNoMouseMode()) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE")); - return false; - } - - MouseControlAPI mouse_config_api; - if (!mouse_config_api.Map(interface_id, regex)) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_MATCH")); - return false; - } - - FinalizeMapping(); - return true; + std::regex regex; + if (!MouseControlAPI::PatternToRegex(pattern, regex)) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_PATTERN")); + return false; + } + + if (MouseControlAPI::IsNoMouseMode()) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE")); + return false; + } + + MouseControlAPI mouse_config_api; + if (!mouse_config_api.Map(interface_id, regex)) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_MATCH")); + return false; + } + + FinalizeMapping(); + return true; } bool MOUSECTL::CmdMap() { - assert(list_ids.size() >= 1); - - if (MouseControlAPI::IsNoMouseMode()) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE")); - return false; - } - - MouseControlAPI mouse_config_api; - const auto info_physical = mouse_config_api.GetInfoPhysical(); - - if (info_physical.empty()) { - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_PHYSICAL_MICE")); - WriteOut("\n\n"); - return false; - } - - // Clear the current mapping before starting interactive mapper - std::vector<MouseInterfaceId> empty; - mouse_config_api.UnMap(empty); - - WriteOut("\n"); - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAP_ADVICE")); - WriteOut("\n\n"); - - for (const auto &interface_id : list_ids) { - WriteOut(convert_ansi_markup("[color=cyan]%-4s[reset] ?").c_str(), - GetInterfaceStr(interface_id)); - - uint8_t device_id = 0; - if (!mouse_config_api.ProbeForMapping(device_id)) { - mouse_config_api.UnMap(empty); - WriteOut("\b"); - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAP_CANCEL")); - WriteOut("\n\n"); - return false; - } - - WriteOut("\b"); - WriteOut(info_physical[device_id].GetDeviceName().c_str()); - WriteOut("\n"); - mouse_config_api.Map(interface_id, device_id); - } - - FinalizeMapping(); - return true; + assert(!list_ids.empty()); + + if (MouseControlAPI::IsNoMouseMode()) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE")); + return false; + } + + MouseControlAPI mouse_config_api; + const auto info_physical = mouse_config_api.GetInfoPhysical(); + + if (info_physical.empty()) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_NO_PHYSICAL_MICE")); + WriteOut("\n\n"); + return false; + } + + // Clear the current mapping before starting interactive mapper + std::vector<MouseInterfaceId> empty; + mouse_config_api.UnMap(empty); + + WriteOut("\n"); + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAP_ADVICE")); + WriteOut("\n\n"); + + for (const auto &interface_id : list_ids) { + WriteOut(convert_ansi_markup("[color=cyan]%-4s[reset] ?").c_str(), + MouseControlAPI::GetInterfaceNameStr(interface_id).c_str()); + + uint8_t device_id = 0; + if (!mouse_config_api.ProbeForMapping(device_id)) { + mouse_config_api.UnMap(empty); + WriteOut("\b"); + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_MAP_CANCEL")); + WriteOut("\n\n"); + return false; + } + + WriteOut("\b"); + WriteOut(info_physical[device_id].GetDeviceName().c_str()); + WriteOut("\n"); + mouse_config_api.Map(interface_id, device_id); + } + + FinalizeMapping(); + return true; } bool MOUSECTL::CmdUnMap() { - MouseControlAPI mouse_config_api; - mouse_config_api.UnMap(list_ids); - return true; + MouseControlAPI mouse_config_api; + mouse_config_api.UnMap(list_ids); + return true; } bool MOUSECTL::CmdOnOff(const bool enable) { - MouseControlAPI mouse_config_api; - mouse_config_api.OnOff(list_ids, enable); - return true; + MouseControlAPI mouse_config_api; + mouse_config_api.OnOff(list_ids, enable); + return true; } bool MOUSECTL::CmdReset() { - MouseControlAPI mouse_config_api; - mouse_config_api.Reset(list_ids); - return true; + MouseControlAPI mouse_config_api; + mouse_config_api.Reset(list_ids); + return true; } -bool MOUSECTL::CmdSensitivity(const int8_t value) +bool MOUSECTL::CmdSensitivity(const std::string ¶m_x, const std::string ¶m_y) { - MouseControlAPI mouse_config_api; - mouse_config_api.SetSensitivity(list_ids, value, value); - return true; + int16_t value_x = 0; + int16_t value_y = 0; + if (!ParseSensitivity(param_x, value_x) || !ParseSensitivity(param_y, value_y)) + return false; + + MouseControlAPI mouse_config_api; + mouse_config_api.SetSensitivity(list_ids, value_x, value_y); + return true; } -bool MOUSECTL::CmdSensitivityX(const int8_t value) +bool MOUSECTL::CmdSensitivityX(const std::string ¶m) { - MouseControlAPI mouse_config_api; - mouse_config_api.SetSensitivityX(list_ids, value); - return true; + int16_t value = 0; + if (!ParseSensitivity(param, value)) + return false; + + MouseControlAPI mouse_config_api; + mouse_config_api.SetSensitivityX(list_ids, value); + return true; } -bool MOUSECTL::CmdSensitivityY(const int8_t value) +bool MOUSECTL::CmdSensitivityY(const std::string ¶m) { - MouseControlAPI mouse_config_api; - mouse_config_api.SetSensitivityY(list_ids, value); - return true; + int16_t value = 0; + if (!ParseSensitivity(param, value)) + return false; + + MouseControlAPI mouse_config_api; + mouse_config_api.SetSensitivityY(list_ids, value); + return true; } bool MOUSECTL::CmdSensitivity() { - MouseControlAPI mouse_config_api; - mouse_config_api.ResetSensitivity(list_ids); - return true; + MouseControlAPI mouse_config_api; + mouse_config_api.ResetSensitivity(list_ids); + return true; } bool MOUSECTL::CmdSensitivityX() { - MouseControlAPI mouse_config_api; - mouse_config_api.ResetSensitivityX(list_ids); - return true; + MouseControlAPI mouse_config_api; + mouse_config_api.ResetSensitivityX(list_ids); + return true; } bool MOUSECTL::CmdSensitivityY() { - MouseControlAPI mouse_config_api; - mouse_config_api.ResetSensitivityY(list_ids); - return true; + MouseControlAPI mouse_config_api; + mouse_config_api.ResetSensitivityY(list_ids); + return true; } bool MOUSECTL::CmdMinRate(const std::string ¶m) { - const auto &valid_list = MouseControlAPI::GetValidMinRateList(); - const auto &valid_str = MouseControlAPI::GetValidMinRateStr(); - - const auto tmp = std::atoi(param.c_str()); - if (tmp < 0 || tmp > UINT16_MAX) { - // Parameter way out of range - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_MIN_RATE"), valid_str.c_str()); - return false; - } - - uint16_t value_hz = static_cast<uint16_t>(tmp); - if (std::find(valid_list.begin(), valid_list.end(), value_hz) == valid_list.end()) { - // Parameter not in the list of allowed values - WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_MIN_RATE"), valid_str.c_str()); - return false; - } - - MouseControlAPI mouse_config_api; - mouse_config_api.SetMinRate(list_ids, value_hz); - return true; + const auto &valid_list = MouseControlAPI::GetValidMinRateList(); + const auto &valid_str = MouseControlAPI::GetValidMinRateStr(); + + int tmp = 0; + if (!ParseIntParam(param, tmp)) { + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_MIN_RATE"), + valid_str.c_str()); + return false; + } + + if (tmp < 0 || tmp > UINT16_MAX) { + // Parameter way out of range + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_MIN_RATE"), + valid_str.c_str()); + return false; + } + + const auto value_hz = static_cast<uint16_t>(tmp); + if (!contains(valid_list, value_hz)) { + // Parameter not in the list of allowed values + WriteOut(MSG_Get("SHELL_CMD_MOUSECTL_SYNTAX_MIN_RATE"), + valid_str.c_str()); + return false; + } + + MouseControlAPI mouse_config_api; + mouse_config_api.SetMinRate(list_ids, value_hz); + return true; } bool MOUSECTL::CmdMinRate() { - MouseControlAPI mouse_config_api; - mouse_config_api.ResetMinRate(list_ids); - return true; + MouseControlAPI mouse_config_api; + mouse_config_api.ResetMinRate(list_ids); + return true; } void MOUSECTL::AddMessages() { - MSG_Add("SHELL_CMD_MOUSECTL_HELP_LONG", - "Manages physical and logical mice.\n" - "\n" - "Usage:\n" - " [color=green]mousectl[reset] [-all]\n" - " [color=green]mousectl[reset] [color=white]INTERFACE[reset] -map name\n" - " [color=green]mousectl[reset] [color=white]INTERFACE[reset] [[color=white]INTERFACE[reset] ...] -map\n" - " [color=green]mousectl[reset] [[color=white]INTERFACE[reset] ...] -unmap | -on | -off | -reset\n" - " [color=green]mousectl[reset] [[color=white]INTERFACE[reset] ...] -s | -sx | -sy [sensitivity]\n" - " [color=green]mousectl[reset] [[color=white]INTERFACE[reset] ...] -r [min_rate]\n" - "\n" - "Where:\n" - " [color=white]INTERFACE[reset] one of [color=white]DOS[reset], [color=white]PS/2[reset], [color=white]COM1[reset], [color=white]COM2[reset], [color=white]COM3[reset], [color=white]COM4[reset]\n" - " -map -unmap maps/unmaps physical mouse, honors DOS wildcards in name\n" - " -s -sx -sy sets sensitivity / for x axis / for y axis, from -99 to +99\n" - " -r sets minimum mouse sampling rate\n" - " -on -off enables or disables mouse on the given interface\n" - " -reset restores all mouse settings from the configuration file\n" - "\n" - "Notes:\n" - " - if host mouse name is omitted, it is mapped in interactive mode\n" - " - if sensitivity or rate is omitted, it is reset to default value\n" - "\n" - "Examples:\n" - " [color=green]mousectl[reset] [color=white]DOS[reset] [color=white]COM1[reset] -map ; asks user to select mice for a two player game"); - - MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX", "Wrong command syntax."); - MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_PATTERN", "Wrong syntax, only ASCII characters allowed in pattern."); - MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_SENSITIVITY", "Wrong syntax, sensitivity needs to be in -99 to +99 range."); - MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_DUPLICATED", "Wrong syntax, duplicated mouse interfaces."); - MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_MIN_RATE", "Wrong syntax, sampling rate has to be one of:\n%s"); - - MSG_Add("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE", "Mapping not available in NoMouse mode."); - MSG_Add("SHELL_CMD_MOUSECTL_NO_INTERFACES", "No mouse interfaces available."); - MSG_Add("SHELL_CMD_MOUSECTL_MISSING_INTERFACES", "Mouse interface not available."); - MSG_Add("SHELL_CMD_MOUSECTL_NO_PHYSICAL_MICE", "No physical mice detected."); - MSG_Add("SHELL_CMD_MOUSECTL_NO_MATCH", "No available mouse matching the pattern found."); - - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HEADER1", "[color=white]Interface Sensitivity Rate (Hz) Status[reset]"); - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_LAYOUT1", "[color=cyan]%-4s[reset] X:%+.2d Y:%+.2d %1s %3s %s"); - - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HEADER2", "[color=white]Interface Mouse Name[reset]"); - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2", "[color=cyan]%-4s[reset] %s"); - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2_UNMAPPED", "not mapped %s"); - - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_HOST", "uses system pointer"); - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_MAPPED", "mapped physical mouse"); - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISCONNECTED", "[color=red]mapped mouse disconnected[reset]"); - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISABLED", "disabled"); - - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_COM", "Sampling rates for mice on [color=cyan]COM[reset] interfaces are estimations only."); - MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_MIN", "Sampling rates with minimum value set are marked with '*'."); - - MSG_Add("SHELL_CMD_MOUSECTL_MAP_ADVICE", - "Click [color=white]left[reset] mouse button to map the physical mouse to the interface. Clicking\n" - "any other button cancels the mapping and assigns system pointer to all the\n" - "mouse interfaces."); - MSG_Add("SHELL_CMD_MOUSECTL_MAP_CANCEL", "(mapping cancelled)"); - MSG_Add("SHELL_CMD_MOUSECTL_MAP_HINT", - "Mouse captured. Seamless mouse integration is always disabled while mapping is\n" - "in effect and mapped mice always receive raw input events."); + MSG_Add("SHELL_CMD_MOUSECTL_HELP_LONG", + "Manages physical and logical mice.\n" + "\n" + "Usage:\n" + " [color=green]mousectl[reset] [-all]\n" + " [color=green]mousectl[reset] [color=white]INTERFACE[reset] -map [color=cyan]NAME[reset]\n" + " [color=green]mousectl[reset] [color=white]INTERFACE[reset] [[color=white]INTERFACE[reset] ...] -map\n" + " [color=green]mousectl[reset] [[color=white]INTERFACE[reset] ...] -unmap | -on | -off | -reset\n" + " [color=green]mousectl[reset] [[color=white]INTERFACE[reset] ...] -s | -sx | -sy [sensitivity]\n" + " [color=green]mousectl[reset] [[color=white]INTERFACE[reset] ...] -s sensitivity_x sensitivity_y\n" + " [color=green]mousectl[reset] [[color=white]INTERFACE[reset] ...] -r [min_rate]\n" + "\n" + "Where:\n" + " [color=white]INTERFACE[reset] one of [color=white]DOS[reset], [color=white]PS/2[reset], [color=white]COM1[reset], [color=white]COM2[reset], [color=white]COM3[reset], [color=white]COM4[reset]\n" + " -map -unmap maps/unmaps physical mouse, honors DOS wildcards in [color=cyan]NAME[reset]\n" + " -s -sx -sy sets sensitivity / for x axis / for y axis, from -999 to +999\n" + " -r sets minimum mouse sampling rate\n" + " -on -off enables or disables mouse on the given interface\n" + " -reset restores all mouse settings from the configuration file\n" + "\n" + "Notes:\n" + " - if sensitivity or rate is omitted, it is reset to default value\n" + "\n" + "Examples:\n" + " [color=green]mousectl[reset] [color=white]DOS[reset] [color=white]COM1[reset] -map ; asks user to select mice for a two player game"); + + MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX", "Wrong command syntax."); + MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_PATTERN", + "Wrong syntax, only ASCII characters allowed in pattern."); + MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_SENSITIVITY", + "Wrong syntax, sensitivity needs to be in -999 to +999 range."); + MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_DUPLICATED", + "Wrong syntax, duplicated mouse interfaces."); + MSG_Add("SHELL_CMD_MOUSECTL_SYNTAX_MIN_RATE", + "Wrong syntax, sampling rate has to be one of:\n%s"); + + MSG_Add("SHELL_CMD_MOUSECTL_MAPPING_NO_MOUSE", + "Mapping not available in NoMouse mode."); + MSG_Add("SHELL_CMD_MOUSECTL_NO_INTERFACES", "No mouse interfaces available."); + MSG_Add("SHELL_CMD_MOUSECTL_MISSING_INTERFACES", + "Mouse interface not available."); + MSG_Add("SHELL_CMD_MOUSECTL_NO_PHYSICAL_MICE", "No physical mice detected."); + MSG_Add("SHELL_CMD_MOUSECTL_NO_MATCH", + "No available mouse matching the pattern found."); + + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HEADER1", + "[color=white]Interface Sensitivity Rate (Hz) Status[reset]"); + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_LAYOUT1", + "[color=cyan]%-4s[reset] X:%+.3d Y:%+.3d %1s %3s %s"); + + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HEADER2", + "[color=white]Interface Mouse Name[reset]"); + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2", + "[color=cyan]%-4s[reset] %s"); + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_LAYOUT2_UNMAPPED", "not mapped %s"); + + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_HOST", "uses system pointer"); + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_MAPPED", "mapped physical mouse"); + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISCONNECTED", + "[color=red]mapped mouse disconnected[reset]"); + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_STATUS_DISABLED", "disabled"); + + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_COM", + "Sampling rates for mice on [color=cyan]COM[reset] interfaces are estimations only."); + MSG_Add("SHELL_CMD_MOUSECTL_TABLE_HINT_RATE_MIN", + "Sampling rates with minimum value set are marked with '*'."); + + MSG_Add("SHELL_CMD_MOUSECTL_MAP_ADVICE", + "Click [color=white]left[reset] mouse button to map the physical mouse to the interface. Clicking\n" + "any other button cancels the mapping and assigns system pointer to all the\n" + "mouse interfaces."); + MSG_Add("SHELL_CMD_MOUSECTL_MAP_CANCEL", "(mapping cancelled)"); + MSG_Add("SHELL_CMD_MOUSECTL_MAP_HINT", + "Mouse captured. Seamless mouse integration is always disabled while mapping is\n" + "in effect and mapped mice always receive raw input events."); } diff --git a/src/dos/program_mousectl.h b/src/dos/program_mousectl.h index 5aa8d543d..03fcab311 100644 --- a/src/dos/program_mousectl.h +++ b/src/dos/program_mousectl.h @@ -25,51 +25,49 @@ #include "mouse.h" - class MOUSECTL final : public Program { public: - MOUSECTL() - { - AddMessages(); - help_detail = {HELP_Filter::All, - HELP_Category::Dosbox, - HELP_CmdType::Program, - "MOUSECTL"}; - } - void Run(); + MOUSECTL() + { + AddMessages(); + help_detail = {HELP_Filter::All, + HELP_Category::Dosbox, + HELP_CmdType::Program, + "MOUSECTL"}; + } + void Run(); private: + bool ParseAndRun(); + bool ParseInterfaces(std::vector<std::string> ¶ms); + bool ParseSensitivity(const std::string ¶m, int16_t &value); + static bool ParseIntParam(const std::string ¶m, int &value); + bool CheckInterfaces(); + void FinalizeMapping(); - bool ParseAndRun(); - bool ParseInterfaces(std::vector<std::string> ¶ms); - bool CheckInterfaces(); - void FinalizeMapping(); - - const char *GetInterfaceStr(const MouseInterfaceId interface_id) const; - const char *GetMapStatusStr(const MouseMapStatus map_status) const; + static const char *GetMapStatusStr(const MouseMapStatus map_status); - // Methods below exectute specific commands requested by the user, - // they return 'true' if DOS error code should indicate success, - // and 'false' if we should report a failure - bool CmdShow(const bool show_all); - bool CmdMap(const MouseInterfaceId interface_id, - const std::string &pattern); - bool CmdMap(); - bool CmdUnMap(); - bool CmdOnOff(const bool enable); - bool CmdReset(); - bool CmdSensitivity(const int8_t value); - bool CmdSensitivityX(const int8_t value); - bool CmdSensitivityY(const int8_t value); - bool CmdSensitivity(); - bool CmdSensitivityX(); - bool CmdSensitivityY(); - bool CmdMinRate(const std::string ¶m); - bool CmdMinRate(); + // Methods below exectute specific commands requested by the user, + // they return 'true' if DOS error code should indicate success, + // and 'false' if we should report a failure + bool CmdShow(const bool show_all); + bool CmdMap(const MouseInterfaceId interface_id, const std::string &pattern); + bool CmdMap(); + bool CmdUnMap(); + bool CmdOnOff(const bool enable); + bool CmdReset(); + bool CmdSensitivity(const std::string ¶m_x, const std::string ¶m_y); + bool CmdSensitivityX(const std::string ¶m); + bool CmdSensitivityY(const std::string ¶m); + bool CmdSensitivity(); + bool CmdSensitivityX(); + bool CmdSensitivityY(); + bool CmdMinRate(const std::string ¶m); + bool CmdMinRate(); - void AddMessages(); + void AddMessages(); - std::vector<MouseInterfaceId> list_ids = {}; + std::vector<MouseInterfaceId> list_ids = {}; }; #endif diff --git a/src/hardware/mouse/mouse.cpp b/src/hardware/mouse/mouse.cpp index 6db7b6e52..6f99a6e1e 100644 --- a/src/hardware/mouse/mouse.cpp +++ b/src/hardware/mouse/mouse.cpp @@ -24,6 +24,7 @@ #include "mouse_queue.h" #include <algorithm> +#include <cctype> #include <sstream> #include <string> #include <vector> @@ -41,7 +42,7 @@ bool seamless_setting = false; static Bitu int74_ret_callback = 0; -static MouseQueue &queue = MouseQueue::GetInstance(); +static MouseQueue &mouse_queue = MouseQueue::GetInstance(); static ManyMouseGlue &manymouse = ManyMouseGlue::GetInstance(); // *************************************************************************** @@ -59,7 +60,7 @@ static Bitu int74_exit() static Bitu int74_handler() { MouseEvent ev; - queue.FetchEvent(ev); + mouse_queue.FetchEvent(ev); // Handle DOS events if (ev.request_dos) { @@ -112,7 +113,7 @@ static Bitu int74_handler() Bitu int74_ret_handler() { - queue.StartTimerIfNeeded(); + mouse_queue.StartTimerIfNeeded(); return CBRET_NONE; } @@ -155,7 +156,7 @@ void MOUSE_NewScreenParams(const uint16_t clip_x, const uint16_t clip_y, void MOUSE_NotifyResetDOS() { - queue.ClearEventsDOS(); + mouse_queue.ClearEventsDOS(); } void MOUSE_NotifyStateChanged() @@ -198,7 +199,7 @@ void MOUSE_NotifyFakePS2() if (interface && interface->IsUsingEvents()) { MouseEvent ev; ev.request_ps2 = true; - queue.AddEvent(ev); + mouse_queue.AddEvent(ev); } } @@ -237,7 +238,7 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel, for (auto &interface : mouse_interfaces) if (interface->IsUsingHostPointer()) interface->NotifyMoved(ev, x_rel, y_rel, x_abs, y_abs); - queue.AddEvent(ev); + mouse_queue.AddEvent(ev); } void MOUSE_EventMoved(const float x_rel, const float y_rel, @@ -247,7 +248,7 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel, if (interface && interface->IsUsingEvents()) { MouseEvent ev; interface->NotifyMoved(ev, x_rel, y_rel, 0, 0); - queue.AddEvent(ev); + mouse_queue.AddEvent(ev); } } @@ -257,7 +258,7 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed) for (auto &interface : mouse_interfaces) if (interface->IsUsingHostPointer()) interface->NotifyButton(ev, idx, pressed); - queue.AddEvent(ev); + mouse_queue.AddEvent(ev); } void MOUSE_EventButton(const uint8_t idx, const bool pressed, @@ -267,7 +268,7 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed, if (interface && interface->IsUsingEvents()) { MouseEvent ev; interface->NotifyButton(ev, idx, pressed); - queue.AddEvent(ev); + mouse_queue.AddEvent(ev); } } @@ -277,7 +278,7 @@ void MOUSE_EventWheel(const int16_t w_rel) for (auto &interface : mouse_interfaces) if (interface->IsUsingHostPointer()) interface->NotifyWheel(ev, w_rel); - queue.AddEvent(ev); + mouse_queue.AddEvent(ev); } void MOUSE_EventWheel(const int16_t w_rel, const MouseInterfaceId interface_id) @@ -286,7 +287,7 @@ void MOUSE_EventWheel(const int16_t w_rel, const MouseInterfaceId interface_id) if (interface && interface->IsUsingEvents()) { MouseEvent ev; interface->NotifyWheel(ev, w_rel); - queue.AddEvent(ev); + mouse_queue.AddEvent(ev); } } @@ -373,9 +374,7 @@ bool MouseControlAPI::PatternToRegex(const std::string &pattern, std::regex ® pattern_regex << "."; else if (character == '*') pattern_regex << ".*"; - else if ((character >= '0' && character <= '9') || - (character >= 'a' && character <= 'z') || - (character >= 'A' && character <= 'Z')) + else if (std::isalnum(character)) pattern_regex << character; else pattern_regex << "\\x" << static_cast<int>(character); @@ -448,8 +447,8 @@ bool MouseControlAPI::Reset(const MouseControlAPI::ListIDs &list_ids) } bool MouseControlAPI::SetSensitivity(const MouseControlAPI::ListIDs &list_ids, - const int8_t sensitivity_x, - const int8_t sensitivity_y) + const int16_t sensitivity_x, + const int16_t sensitivity_y) { if (sensitivity_x > mouse_predefined.sensitivity_user_max || sensitivity_x < -mouse_predefined.sensitivity_user_max || @@ -465,7 +464,7 @@ bool MouseControlAPI::SetSensitivity(const MouseControlAPI::ListIDs &list_ids, } bool MouseControlAPI::SetSensitivityX(const MouseControlAPI::ListIDs &list_ids, - const int8_t sensitivity_x) + const int16_t sensitivity_x) { if (sensitivity_x > mouse_predefined.sensitivity_user_max || sensitivity_x < -mouse_predefined.sensitivity_user_max) @@ -479,7 +478,7 @@ bool MouseControlAPI::SetSensitivityX(const MouseControlAPI::ListIDs &list_ids, } bool MouseControlAPI::SetSensitivityY(const MouseControlAPI::ListIDs &list_ids, - const int8_t sensitivity_y) + const int16_t sensitivity_y) { if (sensitivity_y > mouse_predefined.sensitivity_user_max || sensitivity_y < -mouse_predefined.sensitivity_user_max) @@ -544,12 +543,27 @@ const std::string &MouseControlAPI::GetValidMinRateStr() return out_str; } +std::string MouseControlAPI::GetInterfaceNameStr(const MouseInterfaceId interface_id) +{ + switch (interface_id) { + case MouseInterfaceId::DOS: return "DOS"; + case MouseInterfaceId::PS2: return "PS/2"; + case MouseInterfaceId::COM1: return "COM1"; + case MouseInterfaceId::COM2: return "COM2"; + case MouseInterfaceId::COM3: return "COM3"; + case MouseInterfaceId::COM4: return "COM4"; + case MouseInterfaceId::None: return ""; + default: + assert(false); // missing implementation + return nullptr; + } +} + 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()) + if (!contains(valid_list, value_hz)) return false; // invalid value auto list = get_relevant_interfaces(list_ids); diff --git a/src/hardware/mouse/mouse_common.cpp b/src/hardware/mouse/mouse_common.cpp index cad02c5e7..eb526ce9b 100644 --- a/src/hardware/mouse/mouse_common.cpp +++ b/src/hardware/mouse/mouse_common.cpp @@ -83,8 +83,8 @@ float MOUSE_GetBallisticsCoeff(const float speed) 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); + const auto period_in_ms = std::lround(1000.0f / MOUSE_ClampRateHz(rate_hz)); + return static_cast<uint8_t>(period_in_ms); } float MOUSE_ClampRelativeMovement(const float rel) diff --git a/src/hardware/mouse/mouse_config.cpp b/src/hardware/mouse/mouse_config.cpp index ce6dbe1a1..f81735790 100644 --- a/src/hardware/mouse/mouse_config.cpp +++ b/src/hardware/mouse/mouse_config.cpp @@ -24,6 +24,7 @@ #include "control.h" #include "math_utils.h" #include "setup.h" +#include "string_utils.h" #include "support.h" #include "video.h" @@ -41,22 +42,42 @@ CHECK_NARROWING(); MouseConfig mouse_config; MousePredefined mouse_predefined; -static const std::vector<std::string> list_models_ps2 = { - "standard", - "intellimouse", +static struct { + const std::string param_standard = "standard"; + const std::string param_intellimouse = "intellimouse"; #ifdef ENABLE_EXPLORER_MOUSE - "explorer", + const std::string param_explorer = "explorer"; #endif +} models_ps2; + +static struct { + const std::string param_2button = "2button"; + const std::string param_3button = "3button"; + const std::string param_wheel = "wheel"; + const std::string param_msm = "msm"; + const std::string param_2button_msm = "2button+msm"; + const std::string param_3button_msm = "3button+msm"; + const std::string param_wheel_msm = "wheel+msm"; +} models_com; + +static const char *list_models_ps2[] = { + models_ps2.param_standard.c_str(), + models_ps2.param_intellimouse.c_str(), +#ifdef ENABLE_EXPLORER_MOUSE + models_ps2.param_explorer.c_str(), +#endif + nullptr }; -static const std::vector<std::string> list_models_com = { - "2button", - "3button", - "wheel", - "msm", - "2button+msm", - "3button+msm", - "wheel+msm", +static const char *list_models_com[] = { + models_com.param_2button.c_str(), + models_com.param_3button.c_str(), + models_com.param_wheel.c_str(), + models_com.param_msm.c_str(), + models_com.param_2button_msm.c_str(), + models_com.param_3button_msm.c_str(), + models_com.param_wheel_msm.c_str(), + nullptr }; static const std::vector<uint16_t> list_rates = { @@ -66,7 +87,7 @@ static const std::vector<uint16_t> list_rates = { // 20", // PS/2 mouse // 30", // bus/InPort mouse 40, // PS/2 mouse, approx. limit for 1200 baud serial mouse - // 50, // bus/InPort 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 @@ -84,34 +105,34 @@ static const std::vector<uint16_t> list_rates = { // issues. }; -bool MouseConfig::ParseSerialModel(const std::string &model_str, - MouseModelCOM &model, bool &auto_msm) +bool MouseConfig::ParseCOMModel(const std::string &model_str, + MouseModelCOM &model, bool &auto_msm) { - if (model_str == list_models_com[0]) { + if (model_str == models_com.param_2button) { model = MouseModelCOM::Microsoft; auto_msm = false; return true; - } else if (model_str == list_models_com[1]) { + } else if (model_str == models_com.param_3button) { model = MouseModelCOM::Logitech; auto_msm = false; return true; - } else if (model_str == list_models_com[2]) { + } else if (model_str == models_com.param_wheel) { model = MouseModelCOM::Wheel; auto_msm = false; return true; - } else if (model_str == list_models_com[3]) { + } else if (model_str == models_com.param_msm) { model = MouseModelCOM::MouseSystems; auto_msm = false; return true; - } else if (model_str == list_models_com[4]) { + } else if (model_str == models_com.param_2button_msm) { model = MouseModelCOM::Microsoft; auto_msm = true; return true; - } else if (model_str == list_models_com[5]) { + } else if (model_str == models_com.param_3button_msm) { model = MouseModelCOM::Logitech; auto_msm = true; return true; - } else if (model_str == list_models_com[6]) { + } else if (model_str == models_com.param_wheel_msm) { model = MouseModelCOM::Wheel; auto_msm = true; return true; @@ -120,6 +141,21 @@ bool MouseConfig::ParseSerialModel(const std::string &model_str, return false; } +bool MouseConfig::ParsePS2Model(const std::string &model_str, MouseModelPS2 &model) +{ + if (model_str == models_ps2.param_standard) + model = MouseModelPS2::Standard; + else if (model_str == models_ps2.param_intellimouse) + model = MouseModelPS2::IntelliMouse; +#ifdef ENABLE_EXPLORER_MOUSE + else if (model_str == models_ps2.param_explorer) + model = MouseModelPS2::Explorer; +#endif + else + return false; + return true; +} + const std::vector<uint16_t> &MouseConfig::GetValidMinRateList() { return list_rates; @@ -148,64 +184,11 @@ static void config_read(Section *section) // Default mouse sensitivity - auto sensitivity_from_str = [](const std::string &str) { - const int32_t base_value = 50; - int32_t ret_val = base_value; // default - bool invalid_input = false; - - if (str.find('.') != std::string::npos) { - // Parameter supplied in a form of floating point - float tmp_float = 1.0f; - try { - tmp_float = std::stof(str); - } catch (...) { - invalid_input = true; - tmp_float = 1.0f; - } - // We need 'tmp_float' to be positive for further calculations - if (tmp_float < 0.0f) { - tmp_float = -tmp_float; - ret_val = -1; - } else if (tmp_float > 0.0f) - ret_val = 1; - else - ret_val = 0; - // Now calculate user steps as a logarithm - if (ret_val != 0) { - tmp_float = std::log(tmp_float) / std::log(2.0f); - 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); + mouse_config.sensitivity_x = static_cast<int16_t>( + prop_multi->GetSection()->Get_int("xsens")); + mouse_config.sensitivity_y = static_cast<int16_t>( + prop_multi->GetSection()->Get_int("ysens")); // DOS driver configuration @@ -214,42 +197,14 @@ static void config_read(Section *section) // 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; -#endif + MouseConfig::ParsePS2Model(prop_str, mouse_config.model_ps2); - // 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; - }; + // COM port mouse configuration prop_str = conf->Get_string("com_mouse_model"); - set_model_com(prop_str, mouse_config.model_com, mouse_config.model_com_auto_msm); + MouseConfig::ParseCOMModel(prop_str, + mouse_config.model_com, + mouse_config.model_com_auto_msm); // Start mouse emulation if ready mouse_shared.ready_config_mouse = true; @@ -261,7 +216,8 @@ 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; + Prop_bool *prop_bool = nullptr; + Prop_int *prop_int = nullptr; Prop_string *prop_str = nullptr; PropMultiVal *prop_multi = nullptr; @@ -269,16 +225,19 @@ static void config_init(Section_prop &secprop) 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" + "Default mouse sensitivity. 100 is a base value, 150 is 150% 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" + "The optional second parameter specifies vertical sensitivity (e.g. 100,200).\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_multi->GetSection()->Add_string("xsens", only_at_start, "1.0"); - prop_multi->GetSection()->Add_string("ysens", only_at_start, "1.0"); + prop_multi->SetValue("100"); + + prop_int = prop_multi->GetSection()->Add_int("xsens", only_at_start, 100); + prop_int->SetMinMax(-mouse_predefined.sensitivity_user_max, + mouse_predefined.sensitivity_user_max); + prop_int = prop_multi->GetSection()->Add_int("ysens", only_at_start, 100); + prop_int->SetMinMax(-mouse_predefined.sensitivity_user_max, + mouse_predefined.sensitivity_user_max); prop_bool = secprop.Add_bool("mouse_raw_input", always, true); prop_bool->Set_help( diff --git a/src/hardware/mouse/mouse_config.h b/src/hardware/mouse/mouse_config.h index 35ca040b0..b8e757342 100644 --- a/src/hardware/mouse/mouse_config.h +++ b/src/hardware/mouse/mouse_config.h @@ -32,21 +32,25 @@ struct MousePredefined { // 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; + const float sensitivity_dos = 1.0f; + const float sensitivity_ps2 = 1.0f; + const float sensitivity_vmm = 3.0f; + const float sensitivity_com = 1.0f; // 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; + // Maximum allowed user sensitivity value + const int16_t sensitivity_user_max = 999; // How many user steps causes sensitivity to double // (sensitivity works exponentially) const float sensitivity_double_steps = 10.0f; + + // IRQ used by PS/2 mouse - do not change unless you really know + // what you are doing! + const uint8_t IRQ_PS2 = 12; }; extern MousePredefined mouse_predefined; @@ -84,12 +88,11 @@ struct MouseConfig { // 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 + int16_t sensitivity_x = 50; // default sensitivity values + int16_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_driver = false; // whether DOS virtual mouse driver should be enabled bool dos_immediate = false; MouseModelPS2 model_ps2 = MouseModelPS2::Standard; @@ -100,8 +103,9 @@ struct MouseConfig { // 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 bool ParseCOMModel(const std::string &model_str, + MouseModelCOM &model, bool &auto_msm); + static bool ParsePS2Model(const std::string &model_str, MouseModelPS2 &model); }; extern MouseConfig mouse_config; diff --git a/src/hardware/mouse/mouse_interfaces.cpp b/src/hardware/mouse/mouse_interfaces.cpp index 379e2554b..f2a3620a4 100644 --- a/src/hardware/mouse/mouse_interfaces.cpp +++ b/src/hardware/mouse/mouse_interfaces.cpp @@ -27,6 +27,8 @@ CHECK_NARROWING(); +static MouseQueue &mouse_queue = MouseQueue::GetInstance(); + std::vector<MouseInterface *> mouse_interfaces = {}; // *************************************************************************** @@ -34,18 +36,18 @@ std::vector<MouseInterface *> mouse_interfaces = {}; // *************************************************************************** MouseInterfaceInfoEntry::MouseInterfaceInfoEntry(const MouseInterfaceId interface_id) - : idx(static_cast<uint8_t>(interface_id)) + : interface_idx(static_cast<uint8_t>(interface_id)) {} const MouseInterface &MouseInterfaceInfoEntry::Interface() const { - return *mouse_interfaces[idx]; + return *mouse_interfaces[interface_idx]; } const MousePhysical &MouseInterfaceInfoEntry::MappedPhysical() const { - const auto idx = Interface().GetMappedDeviceIdx(); - return ManyMouseGlue::GetInstance().physical_devices[idx]; + const auto mapped_idx = Interface().GetMappedDeviceIdx(); + return ManyMouseGlue::GetInstance().physical_devices[mapped_idx]; } bool MouseInterfaceInfoEntry::IsEmulated() const @@ -90,12 +92,12 @@ const std::string &MouseInterfaceInfoEntry::GetMappedDeviceName() const return MappedPhysical().GetName(); } -int8_t MouseInterfaceInfoEntry::GetSensitivityX() const +int16_t MouseInterfaceInfoEntry::GetSensitivityX() const { return Interface().GetSensitivityX(); } -int8_t MouseInterfaceInfoEntry::GetSensitivityY() const +int16_t MouseInterfaceInfoEntry::GetSensitivityY() const { return Interface().GetSensitivityY(); } @@ -142,6 +144,9 @@ const std::string &MousePhysicalInfoEntry::GetDeviceName() const class InterfaceDos final : public MouseInterface { public: + InterfaceDos(); + ~InterfaceDos() = default; + 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, @@ -153,8 +158,6 @@ public: private: friend class MouseInterface; - InterfaceDos(); - ~InterfaceDos() = default; InterfaceDos(const InterfaceDos &) = delete; InterfaceDos &operator=(const InterfaceDos &) = delete; @@ -167,6 +170,9 @@ private: class InterfacePS2 final : public MouseInterface { public: + InterfacePS2(); + ~InterfacePS2() = default; + 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, @@ -176,8 +182,6 @@ public: private: friend class MouseInterface; - InterfacePS2(); - ~InterfacePS2() = default; InterfacePS2(const InterfacePS2 &other) = delete; InterfacePS2 &operator=(const InterfacePS2 &other) = delete; @@ -193,6 +197,9 @@ private: class InterfaceCOM final : public MouseInterface { public: + InterfaceCOM(const uint8_t port_id); + ~InterfaceCOM() = default; + 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, @@ -207,9 +214,7 @@ public: private: friend class MouseInterface; - InterfaceCOM(const uint8_t port_id); InterfaceCOM() = delete; - ~InterfaceCOM() = default; InterfaceCOM(const InterfaceCOM &) = delete; InterfaceCOM &operator=(const InterfaceCOM &) = delete; @@ -220,29 +225,40 @@ private: // Base mouse interface // *************************************************************************** +static InterfaceDos interface_dos; +static InterfacePS2 interface_ps2; +static InterfaceCOM interface_com1(0); +static InterfaceCOM interface_com2(1); +static InterfaceCOM interface_com3(2); +static InterfaceCOM interface_com4(3); + 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); + const auto first = static_cast<uint8_t>(MouseInterfaceId::First); + const auto last = static_cast<uint8_t>(MouseInterfaceId::Last); - for (uint8_t i = i_first; i <= i_last; i++) + for (uint8_t i = first; i <= last; i++) switch (static_cast<MouseInterfaceId>(i)) { case MouseInterfaceId::DOS: - mouse_interfaces.emplace_back(new InterfaceDos()); + mouse_interfaces.push_back(&interface_dos); break; case MouseInterfaceId::PS2: - mouse_interfaces.emplace_back(new InterfacePS2()); + mouse_interfaces.push_back(&interface_ps2); break; case MouseInterfaceId::COM1: + mouse_interfaces.push_back(&interface_com1); + break; case MouseInterfaceId::COM2: + mouse_interfaces.push_back(&interface_com2); + break; case MouseInterfaceId::COM3: + mouse_interfaces.push_back(&interface_com3); + break; case MouseInterfaceId::COM4: - mouse_interfaces.emplace_back(new InterfaceCOM( - static_cast<uint8_t>(i - i_com1))); + mouse_interfaces.push_back(&interface_com4); break; default: assert(false); break; } @@ -290,11 +306,15 @@ MouseInterface::MouseInterface(const MouseInterfaceId interface_id, : interface_id(interface_id), sensitivity_predefined(sensitivity_predefined) { - ConfigResetSensitivity(); mouse_info.interfaces.emplace_back(MouseInterfaceInfoEntry(interface_id)); } -void MouseInterface::Init() {} +void MouseInterface::Init() +{ + // At this point configuration should already be loaded, + // so the default sensitivity is known + ConfigResetSensitivity(); +} uint8_t MouseInterface::GetInterfaceIdx() const { @@ -347,12 +367,12 @@ uint8_t MouseInterface::GetMappedDeviceIdx() const return mapped_idx; } -int8_t MouseInterface::GetSensitivityX() const +int16_t MouseInterface::GetSensitivityX() const { return sensitivity_user_x; } -int8_t MouseInterface::GetSensitivityY() const +int16_t MouseInterface::GetSensitivityY() const { return sensitivity_user_y; } @@ -362,9 +382,9 @@ uint16_t MouseInterface::GetRate() const return rate_hz; } -void MouseInterface::NotifyInterfaceRate(const uint16_t value_hz) +void MouseInterface::NotifyInterfaceRate(const uint16_t new_rate_hz) { - interface_rate_hz = value_hz; + interface_rate_hz = new_rate_hz; UpdateRate(); } @@ -437,30 +457,21 @@ void MouseInterface::ConfigReset() ConfigResetMinRate(); } -void MouseInterface::ConfigSetSensitivity(const int8_t value_x, const int8_t value_y) +void MouseInterface::ConfigSetSensitivity(const int16_t value_x, const int16_t value_y) { - if (!IsEmulated()) - return; - sensitivity_user_x = value_x; sensitivity_user_y = value_y; UpdateSensitivity(); } -void MouseInterface::ConfigSetSensitivityX(const int8_t value) +void MouseInterface::ConfigSetSensitivityX(const int16_t value) { - if (!IsEmulated()) - return; - sensitivity_user_x = value; UpdateSensitivity(); } -void MouseInterface::ConfigSetSensitivityY(const int8_t value) +void MouseInterface::ConfigSetSensitivityY(const int16_t value) { - if (!IsEmulated()) - return; - sensitivity_user_y = value; UpdateSensitivity(); } @@ -511,27 +522,12 @@ 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 - - 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 + auto calculate = [this](const int16_t setting) { + if (setting == 0) return 0.0f; - - power /= mouse_predefined.sensitivity_double_steps; - return scaling * std::pow(2.0f, power); + const float user_value = static_cast<float>(setting); + const float scaling = sensitivity_predefined / 100.0f; + return user_value * scaling; }; sensitivity_coeff_x = calculate(sensitivity_user_x); @@ -621,26 +617,26 @@ MouseButtons12S MouseInterface::GetButtonsSquished() const InterfaceDos::InterfaceDos() : MouseInterface(MouseInterfaceId::DOS, mouse_predefined.sensitivity_dos) -{ - UpdateSensitivity(); -} +{} void InterfaceDos::Init() { - if (mouse_config.dos_driver) + MouseInterface::Init(); + if (mouse_config.dos_driver) { + emulated = true; 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) { - ev.dos_moved = MOUSEDOS_NotifyMoved(x_rel * sensitivity_coeff_x, - y_rel * sensitivity_coeff_y, - x_abs, - 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; } @@ -686,17 +682,17 @@ void InterfaceDos::UpdateMinRate() void InterfaceDos::UpdateRate() { MouseInterface::UpdateRate(); - MouseQueue::GetInstance().SetRateDOS(rate_hz); + mouse_queue.SetRateDOS(rate_hz); } InterfacePS2::InterfacePS2() : MouseInterface(MouseInterfaceId::PS2, mouse_predefined.sensitivity_ps2) -{ - UpdateSensitivity(); -} +{} void InterfacePS2::Init() { + MouseInterface::Init(); + emulated = true; MOUSEPS2_Init(); MOUSEVMM_Init(); } @@ -754,18 +750,14 @@ void InterfacePS2::UpdateSensitivity() void InterfacePS2::UpdateRate() { MouseInterface::UpdateRate(); - MouseQueue::GetInstance().SetRatePS2(rate_hz); + mouse_queue.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) -{ - 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) diff --git a/src/hardware/mouse/mouse_interfaces.h b/src/hardware/mouse/mouse_interfaces.h index a0c754960..8974add8a 100644 --- a/src/hardware/mouse/mouse_interfaces.h +++ b/src/hardware/mouse/mouse_interfaces.h @@ -117,6 +117,10 @@ bool MOUSEVMM_NotifyWheel(const int16_t w_rel); class MouseInterface { public: + MouseInterface() = delete; + MouseInterface(const MouseInterface &) = delete; + MouseInterface &operator=(const MouseInterface &) = delete; + static void InitAllInstances(); static MouseInterface *Get(const MouseInterfaceId interface_id); static MouseInterface *GetDOS(); @@ -129,7 +133,7 @@ public: const bool pressed) = 0; virtual void NotifyWheel(MouseEvent &ev, const int16_t w_rel) = 0; - void NotifyInterfaceRate(const uint16_t rate_hz); + void NotifyInterfaceRate(const uint16_t new_rate_hz); virtual void NotifyBooting(); void NotifyDisconnect(); @@ -142,8 +146,8 @@ public: MouseInterfaceId GetInterfaceId() const; MouseMapStatus GetMapStatus() const; uint8_t GetMappedDeviceIdx() const; - int8_t GetSensitivityX() const; - int8_t GetSensitivityY() const; + int16_t GetSensitivityX() const; + int16_t GetSensitivityY() const; uint16_t GetMinRate() const; uint16_t GetRate() const; @@ -152,9 +156,9 @@ public: 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 ConfigSetSensitivity(const int16_t value_x, const int16_t value_y); + void ConfigSetSensitivityX(const int16_t value); + void ConfigSetSensitivityY(const int16_t value); void ConfigResetSensitivity(); void ConfigResetSensitivityX(); void ConfigResetSensitivityY(); @@ -191,30 +195,25 @@ protected: MouseButtonsAll GetButtonsJoined() const; MouseButtons12S GetButtonsSquished() const; - bool emulated = true; + bool emulated = false; - float sensitivity_coeff_x = 1.0f; // cached combined sensitivity - // coefficients + 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; + int16_t sensitivity_user_x = 0; + int16_t sensitivity_user_y = 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; - const MouseInterfaceId interface_id = MouseInterfaceId::None; 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) + 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 diff --git a/src/hardware/mouse/mouse_manymouse.cpp b/src/hardware/mouse/mouse_manymouse.cpp index 1cacc84db..2a1b8a0fa 100644 --- a/src/hardware/mouse/mouse_manymouse.cpp +++ b/src/hardware/mouse/mouse_manymouse.cpp @@ -26,6 +26,8 @@ #include "pic.h" #include "string_utils.h" +#include <algorithm> + CHECK_NARROWING(); void manymouse_tick(uint32_t) @@ -59,37 +61,49 @@ const std::string &MousePhysical::GetName() const ManyMouseGlue &ManyMouseGlue::GetInstance() { - static ManyMouseGlue *instance = nullptr; - if (!instance) - instance = new ManyMouseGlue(); - return *instance; + static ManyMouseGlue manymouse_glue; + return manymouse_glue; } #if C_MANYMOUSE +ManyMouseGlue::~ManyMouseGlue() +{ + PIC_RemoveEvents(manymouse_tick); + ManyMouse_Quit(); +} + void ManyMouseGlue::InitIfNeeded() { if (initialized || malfunction) return; - num_mice = ManyMouse_Init(); - if (num_mice < 0) { + // Initialize ManyMouse library, fetch number of mice + + const auto result = ManyMouse_Init(); + + if (result < 0) { + malfunction = true; + num_mice = 0; + LOG_ERR("MOUSE: ManyMouse initialization failed"); ManyMouse_Quit(); - malfunction = true; return; - } - initialized = true; + } else if (result > max_mice) { + num_mice = max_mice; - if (num_mice >= max_mice) { - num_mice = max_mice - 1; - static bool logged = false; - if (!logged) { - logged = true; + static bool already_warned = false; + if (!already_warned) { + already_warned = true; LOG_ERR("MOUSE: Up to %d simultaneously connected mice supported", max_mice); } - } + } else + num_mice = static_cast<uint8_t>(result); + + initialized = true; + + // Get and log ManyMouse driver name const auto new_driver_name = std::string(ManyMouse_DriverName()); if (new_driver_name != driver_name) { @@ -97,6 +111,8 @@ void ManyMouseGlue::InitIfNeeded() LOG_INFO("MOUSE: ManyMouse driver '%s'", driver_name.c_str()); } + // Scan for the physical mice + Rescan(); } @@ -160,21 +176,22 @@ void ManyMouseGlue::Rescan() std::string name; UTF8_RenderForDos(name_utf8, name); - const char character_nbsp = 0x7f; // non-breaking space + // Replace non-breaking space with a regular space + const char character_nbsp = 0x7f; const char character_space = 0x20; + std::replace(name.begin(), name.end(), character_nbsp, character_space); + // Remove non-ASCII and control characters 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' + // Try to rework into something useful name if we receive + // something with double manufacturer name, for example change: + // 'FooBar Corp FooBar Corp Incredible Mouse' into + // 'FooBar Corp Incredible Mouse' size_t pos = name.size() / 2 + 1; while (--pos > 2) { if (name[pos - 1] != ' ') @@ -187,13 +204,15 @@ void ManyMouseGlue::Rescan() } // 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(); + // but make sure name is indeed limited in length + constexpr size_t max_size = 64; + if (name.size() > max_size) + name.resize(max_size); + + // Strip trailing spaces, newlines, etc. + trim(name); - physical_devices.emplace_back(MousePhysical(name)); + physical_devices.emplace_back(name); mouse_info.physical.emplace_back(MousePhysicalInfoEntry( static_cast<uint8_t>(physical_devices.size() - 1))); } @@ -211,8 +230,10 @@ void ManyMouseGlue::RescanIfSafe() bool ManyMouseGlue::ProbeForMapping(uint8_t &device_id) { // Wait a little to speedup screen update + constexpr uint32_t ticks_threshold = 50; // time to wait idle in PIC ticks const auto pic_ticks_start = PIC_Ticks; - while (PIC_Ticks >= pic_ticks_start && PIC_Ticks - pic_ticks_start < 50) + while (PIC_Ticks >= pic_ticks_start && + PIC_Ticks - pic_ticks_start < ticks_threshold) CALLBACK_Idle(); // Make sure the module is initialized, @@ -228,7 +249,7 @@ bool ManyMouseGlue::ProbeForMapping(uint8_t &device_id) HandleEvent(event, true); // handle critical events bool success = false; - while (true) { + while (!shutdown_requested) { // Poll mouse events, handle critical ones if (!ManyMouse_PollEvent(&event)) { CALLBACK_Idle(); @@ -267,6 +288,8 @@ bool ManyMouseGlue::ProbeForMapping(uint8_t &device_id) uint8_t ManyMouseGlue::GetIdx(const std::regex ®ex) { + assert(max_mice < UINT8_MAX); + // Try to match the mouse name which is not mapped yet for (size_t i = 0; i < physical_devices.size(); i++) { @@ -282,7 +305,7 @@ uint8_t ManyMouseGlue::GetIdx(const std::regex ®ex) return static_cast<uint8_t>(i); } - return max_mice; // return value which will be considered out of range + return max_mice + 1; // return value which will be considered out of range } void ManyMouseGlue::Map(const uint8_t physical_idx, const MouseInterfaceId interface_id) @@ -420,6 +443,7 @@ void ManyMouseGlue::Tick() HandleEvent(event); // Report accumulated mouse movements + assert(rel_x.size() < UINT8_MAX); for (uint8_t idx = 0; idx < rel_x.size(); idx++) { if (rel_x[idx] == 0 && rel_y[idx] == 0) continue; @@ -440,6 +464,8 @@ void ManyMouseGlue::Tick() // ManyMouse is not available +ManyMouseGlue::~ManyMouseGlue() {} + void ManyMouseGlue::RescanIfSafe() { static bool already_warned = false; diff --git a/src/hardware/mouse/mouse_manymouse.h b/src/hardware/mouse/mouse_manymouse.h index 034aee515..66d6edb94 100644 --- a/src/hardware/mouse/mouse_manymouse.h +++ b/src/hardware/mouse/mouse_manymouse.h @@ -67,8 +67,8 @@ private: friend class MouseInterfaceInfoEntry; friend class MousePhysicalInfoEntry; - ManyMouseGlue() = default; - ~ManyMouseGlue() = delete; + ManyMouseGlue() = default; + ~ManyMouseGlue(); ManyMouseGlue(const ManyMouseGlue &) = delete; ManyMouseGlue &operator=(const ManyMouseGlue &) = delete; @@ -95,7 +95,7 @@ private: // config API usage uint32_t config_api_counter = 0; - int num_mice = 0; + uint8_t num_mice = 0; std::string driver_name = ""; @@ -103,7 +103,7 @@ private: std::vector<int> rel_y = {}; static constexpr uint8_t max_buttons = 3; - static constexpr uint8_t max_mice = UINT8_MAX; + static constexpr uint8_t max_mice = UINT8_MAX - 1; static constexpr double tick_interval = 5.0; #endif // C_MANYMOUSE diff --git a/src/hardware/mouse/mouse_queue.cpp b/src/hardware/mouse/mouse_queue.cpp index a9d173a37..282048561 100644 --- a/src/hardware/mouse/mouse_queue.cpp +++ b/src/hardware/mouse/mouse_queue.cpp @@ -66,10 +66,13 @@ void mouse_queue_tick(uint32_t) MouseQueue &MouseQueue::GetInstance() { - static MouseQueue *instance = nullptr; - if (!instance) - instance = new MouseQueue(); - return *instance; + static MouseQueue mouse_queue; + return mouse_queue; +} + +MouseQueue::~MouseQueue() +{ + PIC_RemoveEvents(mouse_queue_tick); } void MouseQueue::SetRateDOS(const uint16_t rate_hz) @@ -142,7 +145,7 @@ void MouseQueue::AddEvent(MouseEvent &ev) } else if (!timer_in_progress) { DEBUG_QUEUE("ActivateIRQ, in %s", __FUNCTION__); // If no timer in progress, handle the event now - PIC_ActivateIRQ(12); + PIC_ActivateIRQ(mouse_predefined.IRQ_PS2); } } @@ -259,9 +262,8 @@ void MouseQueue::UpdateDelayCounters() 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 base_delay, const uint8_t elapsed) { + return static_cast<uint8_t>((base_delay > elapsed) ? (base_delay - elapsed) : 0); }; delay.dos_ms = calc_new_delay(delay.dos_ms, elapsed); @@ -281,7 +283,7 @@ void MouseQueue::Tick() // interrupt; otherwise start the timer again if (HasReadyEventDos() || HasReadyEventPS2()) { DEBUG_QUEUE("ActivateIRQ, in %s", __FUNCTION__); - PIC_ActivateIRQ(12); + PIC_ActivateIRQ(mouse_predefined.IRQ_PS2); } else StartTimerIfNeeded(); } diff --git a/src/hardware/mouse/mouse_queue.h b/src/hardware/mouse/mouse_queue.h index e5cfe3c2c..becc80641 100644 --- a/src/hardware/mouse/mouse_queue.h +++ b/src/hardware/mouse/mouse_queue.h @@ -34,8 +34,8 @@ public: void StartTimerIfNeeded(); private: - MouseQueue() = default; - ~MouseQueue() = delete; + MouseQueue() = default; + ~MouseQueue(); MouseQueue(const MouseQueue &) = delete; MouseQueue &operator=(const MouseQueue &) = delete; diff --git a/src/hardware/mouse/mouseif_dos_driver.cpp b/src/hardware/mouse/mouseif_dos_driver.cpp index 08e5111d6..81587c2e5 100644 --- a/src/hardware/mouse/mouseif_dos_driver.cpp +++ b/src/hardware/mouse/mouseif_dos_driver.cpp @@ -214,29 +214,17 @@ 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); + return static_cast<uint8_t>(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); + return static_cast<uint16_t>(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); + return static_cast<int16_t>(x); } static uint16_t get_pos_x() @@ -311,7 +299,7 @@ static void draw_cursor_text() state.background.pos_x = state.background.pos_x / 2; // use current page (CV program) - uint8_t page = real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_PAGE); + const uint8_t page = real_readb(BIOSMEM_SEG, BIOSMEM_CURRENT_PAGE); if (state.cursor_type == MouseCursor::Software) { uint16_t result = 0; @@ -342,7 +330,7 @@ static void draw_cursor_text() state.background.pos_x) * 2); address /= 2; - uint16_t cr = real_readw(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS); + const 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)); @@ -710,7 +698,7 @@ static void reset_hardware() state.wheel_api = false; counter_w = 0; - PIC_SetIRQMask(12, false); // lower IRQ line + PIC_SetIRQMask(mouse_predefined.IRQ_PS2, false); // lower IRQ line // Reset mouse refresh rate rate_is_set = false; @@ -745,7 +733,7 @@ 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); + const 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"); @@ -921,8 +909,8 @@ static void move_cursor_seamless(const float x_rel, const float y_rel, }; // 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); + const float x = calculate(x_abs, mouse_video.res_x, mouse_video.clip_x); + const 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 @@ -1568,10 +1556,10 @@ static Bitu int33_handler() 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)); + const uint16_t raxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x0a)); + const uint16_t rbxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x08)); + const uint16_t rcxpt = real_readw(SegValue(ss), static_cast<uint16_t>(reg_sp + 0x06)); + const 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); @@ -1684,11 +1672,11 @@ void MOUSEDOS_NotifyRawInput(const bool enabled) void MOUSEDOS_Init() { // Callback for mouse interrupt 0x33 - auto call_int33 = CALLBACK_Allocate(); + const 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); + const RealPt int33_location = + RealMake(static_cast<uint16_t>(DOS_GetMemory(0x1) - 1), 0x10); CALLBACK_Setup(call_int33, &int33_handler, CB_MOUSE, @@ -1697,7 +1685,7 @@ void MOUSEDOS_Init() // Wasteland needs low(seg(int33))!=0 and low(ofs(int33))!=0 real_writed(0, 0x33 << 2, int33_location); - auto call_mouse_bd = CALLBACK_Allocate(); + const auto call_mouse_bd = CALLBACK_Allocate(); CALLBACK_Setup(call_mouse_bd, &mouse_bd_handler, CB_RETF8, @@ -1713,7 +1701,7 @@ void MOUSEDOS_Init() // iret // Callback for mouse user routine return - auto call_user = CALLBACK_Allocate(); + const auto call_user = CALLBACK_Allocate(); CALLBACK_Setup(call_user, &user_callback_handler, CB_RETF_CLI, "mouse user ret"); user_callback = CALLBACK_RealPointer(call_user); diff --git a/src/hardware/mouse/mouseif_ps2_bios.cpp b/src/hardware/mouse/mouseif_ps2_bios.cpp index 3ea8c9869..5ea009bb6 100644 --- a/src/hardware/mouse/mouseif_ps2_bios.cpp +++ b/src/hardware/mouse/mouseif_ps2_bios.cpp @@ -47,6 +47,14 @@ CHECK_NARROWING(); // - https://isdaman.com/alsos/hardware/mouse/ps2interface.htm // - https://wiki.osdev.org/Mouse_Input +static const std::vector<uint8_t> list_rates_hz = { + 10, 20, 40, 60, 80, 100, 200 // PS/2 mouse sampling rates +}; + +static const std::vector<uint8_t> list_resolutions = { + 1, 2, 4, 8 // PS/2 mouse resolution values +}; + static MouseButtonsAll buttons; // currently visible button state static MouseButtonsAll buttons_all; // state of all 5 buttons as on the host side static MouseButtons12S buttons_12S; // buttons with 3/4/5 quished together @@ -85,7 +93,7 @@ void MOUSEPS2_UpdateButtonSquish() buttons.data = squish ? buttons_12S.data : buttons_all.data; } -static void terminate_unlick_sequence() +static void terminate_unlock_sequence() { unlock_idx_im = 0; unlock_idx_xp = 0; @@ -93,7 +101,7 @@ static void terminate_unlick_sequence() static void set_protocol(const MouseModelPS2 new_protocol) { - terminate_unlick_sequence(); + terminate_unlock_sequence(); static bool first_time = true; if (first_time || protocol != new_protocol) { @@ -153,13 +161,13 @@ static int16_t get_scaled_movement(const int16_t d) case -5: return -9; case -4: return -6; case -3: return -3; - case -2: return -1; + case -2: [[fallthrough]]; case -1: return -1; - case 1: return 1; - case 2: return 1; - case 3: return 3; - case 4: return 6; - case 5: return 9; + case 1: [[fallthrough]]; + case 2: return 1; + case 3: return 3; + case 4: return 6; + case 5: return 9; default: return static_cast<int16_t>(2 * d); } } @@ -208,21 +216,21 @@ void MOUSEPS2_UpdatePacket() static_cast<int16_t>(-UINT8_MAX), static_cast<int16_t>(UINT8_MAX)); } else { - if ((dx > 0xff) || (dx < -0xff)) + if ((dx > UINT8_MAX) || (dx < -UINT8_MAX)) mdat.overflow_x = 1; - if ((dy > 0xff) || (dy < -0xff)) + if ((dy > UINT8_MAX) || (dy < -UINT8_MAX)) mdat.overflow_y = 1; } - dx %= 0x100; + dx = static_cast<int16_t>(dx % (UINT8_MAX + 1)); if (dx < 0) { - dx = static_cast<int16_t>(dx + 0x100); + dx = static_cast<int16_t>(dx + UINT8_MAX + 1); mdat.sign_x = 1; } - dy %= 0x100; + dy = static_cast<int16_t>(dy % (UINT8_MAX + 1)); if (dy < 0) { - dy = static_cast<int16_t>(dy + 0x100); + dy = static_cast<int16_t>(dy + UINT8_MAX + 1); mdat.sign_y = 1; } @@ -244,7 +252,7 @@ void MOUSEPS2_UpdatePacket() static void cmd_set_resolution(const uint8_t new_counts_mm) { - terminate_unlick_sequence(); + terminate_unlock_sequence(); if (new_counts_mm != 1 && new_counts_mm != 2 && new_counts_mm != 4 && new_counts_mm != 8) @@ -260,11 +268,9 @@ 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) { + if (!std::binary_search(list_rates_hz.begin(), list_rates_hz.end(), new_rate_hz)) { // Invalid parameter, set default - terminate_unlick_sequence(); + terminate_unlock_sequence(); rate_hz = 100; } else rate_hz = new_rate_hz; @@ -273,9 +279,9 @@ static void cmd_set_sample_rate(const uint8_t new_rate_hz) 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) { + auto process_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) { @@ -283,14 +289,18 @@ static void cmd_set_sample_rate(const uint8_t new_rate_hz) } }; - static const std::vector<uint8_t> seq_im = {200, 100, 80}; - static const std::vector<uint8_t> seq_xp = {200, 200, 80}; + static const std::vector<uint8_t> unlock_sequence_im = {200, 100, 80}; + static const std::vector<uint8_t> unlock_sequence_xp = {200, 200, 80}; if (mouse_config.model_ps2 == MouseModelPS2::IntelliMouse) - unlock(seq_im, unlock_idx_im, MouseModelPS2::IntelliMouse); + process_unlock(unlock_sequence_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); + process_unlock(unlock_sequence_im, + unlock_idx_im, + MouseModelPS2::IntelliMouse); + process_unlock(unlock_sequence_xp, unlock_idx_xp, MouseModelPS2::Explorer); } } @@ -311,7 +321,7 @@ static void cmd_reset() static void cmd_set_scaling_21(const bool enable) { - terminate_unlick_sequence(); + terminate_unlock_sequence(); scaling_21 = enable; } @@ -321,7 +331,12 @@ 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); - return (std::fabs(delta_x) >= 0.5f) || (std::fabs(delta_y) >= 0.5f); + // Threshold the accumulated movement needs to cross + // to be considered significant enough for new event + constexpr float threshold = 0.5f; + + return (std::fabs(delta_x) >= threshold) || + (std::fabs(delta_y) >= threshold); } bool MOUSEPS2_NotifyButton(const MouseButtons12S new_buttons_12S, @@ -370,8 +385,8 @@ static RealPt ps2_callback = 0; void MOUSEBIOS_Reset() { cmd_reset(); - PIC_SetIRQMask(12, false); // lower IRQ line - MOUSEVMM_Deactivate(); // VBADOS seems to expect this + PIC_SetIRQMask(mouse_predefined.IRQ_PS2, false); // lower IRQ line + MOUSEVMM_Deactivate(); // VBADOS seems to expect this } void MOUSEBIOS_SetCallback(const uint16_t pseg, const uint16_t pofs) @@ -399,30 +414,19 @@ bool MOUSEBIOS_SetPacketSize(const uint8_t packet_size) 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; - } + if (rate_id >= list_rates_hz.size()) + return false; + cmd_set_sample_rate(list_rates_hz[rate_id]); 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; - } + if (res_id >= list_resolutions.size()) + return false; + cmd_set_sample_rate(list_resolutions[res_id]); return true; } @@ -431,17 +435,18 @@ void MOUSEBIOS_SetScaling21(const bool enable) cmd_set_scaling_21(enable); } -bool MOUSEBIOS_SetState(const bool use) +bool MOUSEBIOS_Enable() { - if (use && !callback_init) { - mouse_shared.active_bios = false; - MOUSE_NotifyStateChanged(); - return false; - } else { - mouse_shared.active_bios = use; - MOUSE_NotifyStateChanged(); - return true; - } + mouse_shared.active_bios = callback_init; + MOUSE_NotifyStateChanged(); + return callback_init; +} + +bool MOUSEBIOS_Disable() +{ + mouse_shared.active_bios = false; + MOUSE_NotifyStateChanged(); + return true; } uint8_t MOUSEBIOS_GetResolution() @@ -504,7 +509,7 @@ Bitu MOUSEBIOS_DoCallback() CPU_Push16(packet[2]); CPU_Push16(packet[3]); } - CPU_Push16((uint16_t)0); + CPU_Push16(0u); CPU_Push16(RealSeg(ps2_callback)); CPU_Push16(RealOff(ps2_callback)); @@ -517,7 +522,7 @@ Bitu MOUSEBIOS_DoCallback() void MOUSEPS2_Init() { // Callback for ps2 user callback handling - auto call_ps2 = CALLBACK_Allocate(); + const auto call_ps2 = CALLBACK_Allocate(); CALLBACK_Setup(call_ps2, &callback_ret, CB_RETF, "ps2 bios callback"); ps2_callback = CALLBACK_RealPointer(call_ps2); diff --git a/src/hardware/serialport/serialmouse.cpp b/src/hardware/serialport/serialmouse.cpp index 745f740a1..1dc9dee73 100644 --- a/src/hardware/serialport/serialmouse.cpp +++ b/src/hardware/serialport/serialmouse.cpp @@ -62,7 +62,7 @@ CSerialMouse::CSerialMouse(const uint8_t id, CommandLine *cmd) std::string model_string; if (cmd->FindStringBegin("model:", model_string, false) && - !MouseConfig::ParseSerialModel(model_string, param_model, param_auto_msm)) { + !MouseConfig::ParseCOMModel(model_string, param_model, param_auto_msm)) { LOG_ERR("MOUSE (COM%d): Invalid model '%s'", port_num, model_string.c_str()); @@ -139,9 +139,7 @@ void CSerialMouse::BoostRate(const uint16_t rate_hz) } // Estimate current sampling rate, as precisely as possible - auto estimate = [](const uint16_t bauds, - const uint8_t byte_len, - const MouseModelCOM model) { + auto estimate = [this](const uint16_t bauds) { // In addition to byte_len, the mouse has to send // 3 more bits per each byte: start, parity, stop @@ -149,19 +147,19 @@ void CSerialMouse::BoostRate(const uint16_t rate_hz) 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); + return bauds / (static_cast<float>(port_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); + return bauds / (static_cast<float>(port_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; + rate_coeff = estimate(1200) / rate_hz; } void CSerialMouse::SetModel(const MouseModelCOM new_model) diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index b766c35af..b3740cfa2 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -951,12 +951,12 @@ static Bitu INT15_Handler(void) { case 0xc2: /* BIOS PS2 Pointing Device Support */ switch (reg_al) { case 0x00: // enable/disable - if (reg_bh == 0) { // disable - MOUSEBIOS_SetState(false); + if (reg_bh == 0) { // disable + MOUSEBIOS_Disable(); reg_ah = 0; CALLBACK_SCF(false); } else if (reg_bh == 0x01) { // enable - if (!MOUSEBIOS_SetState(true)) { + if (!MOUSEBIOS_Enable()) { reg_ah = 5; CALLBACK_SCF(true); break; @@ -978,7 +978,7 @@ static Bitu INT15_Handler(void) { reg_ah = 2; break; } - MOUSEBIOS_SetState(false); + MOUSEBIOS_Disable(); CALLBACK_SCF(false); reg_ah=0; break; |