From 17f1f05064398ee848093752107c87581bf0cfb5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2023 15:02:25 -0400 Subject: [PATCH 1/6] Hit and hope appears to have fixed mouse input. --- Machines/Apple/AppleIIgs/ADB.cpp | 12 ++++++++---- Machines/Apple/AppleIIgs/AppleIIgs.cpp | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Machines/Apple/AppleIIgs/ADB.cpp b/Machines/Apple/AppleIIgs/ADB.cpp index 32afec75d..eb3b31f6d 100644 --- a/Machines/Apple/AppleIIgs/ADB.cpp +++ b/Machines/Apple/AppleIIgs/ADB.cpp @@ -76,11 +76,15 @@ uint8_t GLU::get_mouse_data() { // b5–b0: mouse delta. const uint8_t result = registers_[visible_mouse_register_]; - if(visible_mouse_register_ == 2) { - ++visible_mouse_register_; - } else { + if(visible_mouse_register_ == 3) { status_ &= ~uint8_t(CPUFlags::MouseDataFull); } + + // Spelt out at tedious length because Clang has trust issues. + static constexpr int first_register = 2; + static constexpr int second_register = 3; + static constexpr int flip_mask = first_register ^ second_register; + visible_mouse_register_ ^= flip_mask; return result; } @@ -116,7 +120,7 @@ uint8_t GLU::get_status() { // b2: 1 = keyboard data interrupt is enabled. // b1: 1 = mouse x-data is available; 0 = y. // b0: 1 = command register is full (set when command is written); 0 = empty (cleared when data is read). - return status_ | ((visible_mouse_register_ == 2) ? uint8_t(CPUFlags::MouseXIsAvailable) : 0); + return status_ | ((visible_mouse_register_ == 2) ? 0 : uint8_t(CPUFlags::MouseXIsAvailable)); } void GLU::set_status(uint8_t status) { diff --git a/Machines/Apple/AppleIIgs/AppleIIgs.cpp b/Machines/Apple/AppleIIgs/AppleIIgs.cpp index a61f69462..d440db65a 100644 --- a/Machines/Apple/AppleIIgs/AppleIIgs.cpp +++ b/Machines/Apple/AppleIIgs/AppleIIgs.cpp @@ -752,7 +752,7 @@ class ConcreteMachine: is_1Mhz = true; break; case Read(0xc045): - // MMDELTAX byte. + // MMDELTAY byte. *value = 0; is_1Mhz = true; break; From 1125286b9640711a13dea6b1334f474fcb299b78 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2023 15:03:28 -0400 Subject: [PATCH 2/6] Add note to self. --- Machines/Apple/ADB/Mouse.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Machines/Apple/ADB/Mouse.cpp b/Machines/Apple/ADB/Mouse.cpp index ba0a5310f..bd610be51 100644 --- a/Machines/Apple/ADB/Mouse.cpp +++ b/Machines/Apple/ADB/Mouse.cpp @@ -41,6 +41,7 @@ void Mouse::perform_command(const Command &command) { } void Mouse::move(int x, int y) { + // TODO: cap movement speed, feeding changes in slowly. delta_x_ += int16_t(x); delta_y_ += int16_t(y); post_service_request(); From 3e2a82b638f40a0155272ab1d57fb69759373a78 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2023 15:32:48 -0400 Subject: [PATCH 3/6] Add delta capper. --- Machines/Apple/ADB/Mouse.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/Machines/Apple/ADB/Mouse.cpp b/Machines/Apple/ADB/Mouse.cpp index bd610be51..1f5676493 100644 --- a/Machines/Apple/ADB/Mouse.cpp +++ b/Machines/Apple/ADB/Mouse.cpp @@ -15,24 +15,34 @@ using namespace Apple::ADB; Mouse::Mouse(Bus &bus) : ReactiveDevice(bus, 3) {} void Mouse::perform_command(const Command &command) { - if(command.type == Command::Type::Talk && command.reg == 0) { - // Read current deltas and buttons, thread safely. - auto delta_x = delta_x_.exchange(0); - auto delta_y = delta_y_.exchange(0); - const int buttons = button_flags_; + static constexpr int16_t max_delta = 30; - // Clamp deltas. - delta_x = std::clamp(delta_x, int16_t(-128), int16_t(127)); - delta_y = std::clamp(delta_y, int16_t(-128), int16_t(127)); + if(command.type == Command::Type::Talk && command.reg == 0) { + // Read and clamp current deltas and buttons. + // + // There's some small chance of creating negative feedback here — taking too much off delta_x_ or delta_y_ + // due to a change in the underlying value between the load and the arithmetic. But if that occurs it means + // the user moved the mouse again in the interim, so it'll just play out as very slight latency. + auto delta_x = delta_x_.load(std::memory_order::memory_order_relaxed); + auto delta_y = delta_y_.load(std::memory_order::memory_order_relaxed); + if(abs(delta_x) > max_delta || abs(delta_y) > max_delta) { + int max = std::max(abs(delta_x), abs(delta_y)); + delta_x = delta_x * max_delta / max; + delta_y = delta_y * max_delta / max; + } + + const int buttons = button_flags_.load(std::memory_order::memory_order_relaxed); + delta_x_ -= delta_x; + delta_y_ -= delta_y; // Figure out what that would look like, and don't respond if there's - // no change to report. + // no change or deltas to report. const uint16_t reg0 = ((buttons & 1) ? 0x0000 : 0x8000) | ((buttons & 2) ? 0x0000 : 0x0080) | uint16_t(delta_x & 0x7f) | uint16_t((delta_y & 0x7f) << 8); - if(reg0 == last_posted_reg0_) return; + if(!(reg0 & 0x7f7f) && (reg0 & 0x8080) == (last_posted_reg0_ & 0x8080)) return; // Post change. last_posted_reg0_ = reg0; @@ -41,7 +51,6 @@ void Mouse::perform_command(const Command &command) { } void Mouse::move(int x, int y) { - // TODO: cap movement speed, feeding changes in slowly. delta_x_ += int16_t(x); delta_y_ += int16_t(y); post_service_request(); From b8e7c2b8ac076e3f3789e366b2ae5012acb43862 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2023 15:33:30 -0400 Subject: [PATCH 4/6] Remove printf. --- Machines/Apple/AppleIIgs/ADB.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Machines/Apple/AppleIIgs/ADB.cpp b/Machines/Apple/AppleIIgs/ADB.cpp index eb3b31f6d..3ffd099f0 100644 --- a/Machines/Apple/AppleIIgs/ADB.cpp +++ b/Machines/Apple/AppleIIgs/ADB.cpp @@ -227,7 +227,6 @@ void GLU::set_port_output(int port, uint8_t value) { case 3: status_ |= uint8_t(CPUFlags::MouseDataFull); visible_mouse_register_ = 2; - printf("Mouse: %d <- %02x\n", register_address_, register_latch_); break; case 7: status_ |= uint8_t(CPUFlags::CommandDataIsValid); break; } From fa82fb46b93dcbdd3da45de06618cf928fc94385 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2023 15:33:47 -0400 Subject: [PATCH 5/6] Acknowledge ever-revolving earth. --- .../xcshareddata/xcschemes/Clock Signal.xcscheme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index 3534e9926..474fa352e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -1,7 +1,7 @@ + version = "1.8"> From 357a324e87eaf7d3690e8e88ad6ad1a6a7ac9fe7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 20 Aug 2023 15:34:40 -0400 Subject: [PATCH 6/6] Add exposition. --- Machines/Apple/ADB/Mouse.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Machines/Apple/ADB/Mouse.cpp b/Machines/Apple/ADB/Mouse.cpp index 1f5676493..60336a0b4 100644 --- a/Machines/Apple/ADB/Mouse.cpp +++ b/Machines/Apple/ADB/Mouse.cpp @@ -15,6 +15,8 @@ using namespace Apple::ADB; Mouse::Mouse(Bus &bus) : ReactiveDevice(bus, 3) {} void Mouse::perform_command(const Command &command) { + // This was picked empirically based on experimentation with the IIgs. + // Possible TODO: consider whether this is appropriate for other machines. static constexpr int16_t max_delta = 30; if(command.type == Command::Type::Talk && command.reg == 0) {