mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +00:00
Merge pull request #1156 from TomHarte/IIgsMouseMystery
Without rhythm or rhyme, fix IIgs GSOS mouse movement.
This commit is contained in:
commit
b5dc84c431
@ -15,24 +15,36 @@ 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_;
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
@ -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) {
|
||||
@ -223,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;
|
||||
}
|
||||
|
@ -752,7 +752,7 @@ class ConcreteMachine:
|
||||
is_1Mhz = true;
|
||||
break;
|
||||
case Read(0xc045):
|
||||
// MMDELTAX byte.
|
||||
// MMDELTAY byte.
|
||||
*value = 0;
|
||||
is_1Mhz = true;
|
||||
break;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1400"
|
||||
version = "1.3">
|
||||
version = "1.8">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
|
Loading…
Reference in New Issue
Block a user