diff --git a/Machines/Apple/ADB/Mouse.cpp b/Machines/Apple/ADB/Mouse.cpp index af3bec90d..2bd2e7ae6 100644 --- a/Machines/Apple/ADB/Mouse.cpp +++ b/Machines/Apple/ADB/Mouse.cpp @@ -12,5 +12,51 @@ using namespace Apple::ADB; Mouse::Mouse(Bus &bus) : ReactiveDevice(bus, 3) {} -void Mouse::perform_command(const Command &) { +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_; + + // Clamp deltas. + delta_x = std::max(std::min(delta_x, int16_t(127)), int16_t(-128)); + delta_y = std::max(std::min(delta_y, int16_t(127)), int16_t(-128)); + + // Figure out what that would look like, and don't respond if there's + // no change 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; + + // Post change. + last_posted_reg0_ = reg0; + post_response({uint8_t(reg0 >> 8), uint8_t(reg0)}); + } +} + +void Mouse::move(int x, int y) { + delta_x_ += int16_t(x); + delta_y_ += int16_t(y); + post_service_request(); +} + +int Mouse::get_number_of_buttons() { + return 2; +} + +void Mouse::set_button_pressed(int index, bool is_pressed) { + if(is_pressed) + button_flags_ |= (1 << index); + else + button_flags_ &= ~(1 << index); + post_service_request(); +} + +void Mouse::reset_all_buttons() { + button_flags_ = 0; + post_service_request(); } diff --git a/Machines/Apple/ADB/Mouse.hpp b/Machines/Apple/ADB/Mouse.hpp index 0ab032922..3e8a4dc1f 100644 --- a/Machines/Apple/ADB/Mouse.hpp +++ b/Machines/Apple/ADB/Mouse.hpp @@ -10,16 +10,26 @@ #define Mouse_hpp #include "ReactiveDevice.hpp" +#include "../../../Inputs/Mouse.hpp" namespace Apple { namespace ADB { -class Mouse: public ReactiveDevice { +class Mouse: public ReactiveDevice, public Inputs::Mouse { public: Mouse(Bus &); private: void perform_command(const Command &command) override; + + void move(int x, int y) override; + int get_number_of_buttons() override; + void set_button_pressed(int index, bool is_pressed) override; + void reset_all_buttons() override; + + std::atomic delta_x_, delta_y_; + std::atomic button_flags_ = 0; + uint16_t last_posted_reg0_ = 0; }; } diff --git a/Machines/Apple/ADB/ReactiveDevice.cpp b/Machines/Apple/ADB/ReactiveDevice.cpp index a55645d70..d8bbc4436 100644 --- a/Machines/Apple/ADB/ReactiveDevice.cpp +++ b/Machines/Apple/ADB/ReactiveDevice.cpp @@ -125,7 +125,7 @@ void ReactiveDevice::adb_bus_did_observe_event(Bus::Event event, uint8_t value) phase_ = Phase::AwaitingAttention; command_ = decode_command(value); - LOG(command_); +// LOG(command_); // If this command doesn't apply here, but a service request is requested, // post a service request. diff --git a/Machines/Apple/AppleIIgs/ADB.hpp b/Machines/Apple/AppleIIgs/ADB.hpp index ec10c0ba2..6ce473572 100644 --- a/Machines/Apple/AppleIIgs/ADB.hpp +++ b/Machines/Apple/AppleIIgs/ADB.hpp @@ -45,10 +45,16 @@ class GLU: public InstructionSet::M50740::PortHandler { bool get_option_button() const; void set_vertical_blank(bool); + bool get_vertical_blank() { + return vertical_blank_; + } Apple::ADB::Keyboard &keyboard() { return keyboard_; } + Inputs::Mouse &get_mouse() { + return mouse_; + } private: InstructionSet::M50740::Executor executor_; @@ -70,6 +76,8 @@ class GLU: public InstructionSet::M50740::PortHandler { uint8_t modifier_state_ = 0; + bool vertical_blank_ = false; + // For now, attach only a keyboard and mouse. Apple::ADB::Mouse mouse_; Apple::ADB::Keyboard keyboard_; diff --git a/Machines/Apple/AppleIIgs/AppleIIgs.cpp b/Machines/Apple/AppleIIgs/AppleIIgs.cpp index 3a92c5b12..50234875d 100644 --- a/Machines/Apple/AppleIIgs/AppleIIgs.cpp +++ b/Machines/Apple/AppleIIgs/AppleIIgs.cpp @@ -52,6 +52,7 @@ class ConcreteMachine: public MachineTypes::ScanProducer, public MachineTypes::TimedMachine, public MachineTypes::MappedKeyboardMachine, + public MachineTypes::MouseMachine, public CPU::MOS6502Esque::BusHandler { public: @@ -898,7 +899,9 @@ class ConcreteMachine: update_interrupts(); const bool is_vertical_blank = video_.last_valid()->get_is_vertical_blank(video_.time_since_flush()); - adb_glu_->set_vertical_blank(is_vertical_blank); + if(is_vertical_blank != adb_glu_.last_valid()->get_vertical_blank()) { + adb_glu_->set_vertical_blank(is_vertical_blank); + } } return duration; @@ -910,7 +913,7 @@ class ConcreteMachine: m65816_.set_irq_line(video_.last_valid()->get_interrupt_line() || sound_glu_.get_interrupt_line()); } - // MARK: - Keyboard input. + // MARK: - Input. KeyboardMapper *get_keyboard_mapper() final { return &keyboard_mapper_; } @@ -923,6 +926,10 @@ class ConcreteMachine: adb_glu_.last_valid()->keyboard().clear_all_keys(); } + Inputs::Mouse &get_mouse() final { + return adb_glu_.last_valid()->get_mouse(); + } + private: CPU::WDC65816::Processor m65816_; MemoryMap memory_;