From 56b741466a259719afe4ced01387ef7245bc0e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?pixelsuft=E2=80=AE?= <68371847+Pixelsuft@users.noreply.github.com> Date: Sat, 21 May 2022 03:26:57 +0700 Subject: [PATCH] PS2 Mouse Wheel Support (#657) --- src/ps2.js | 78 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/src/ps2.js b/src/ps2.js index d42eb811..9185341f 100644 --- a/src/ps2.js +++ b/src/ps2.js @@ -66,6 +66,15 @@ function PS2(cpu, bus) /** @type {number} */ this.sample_rate = 100; + /** @type {number} */ + this.intellimouse_activation_counter = 0; + + /** @type {number} */ + this.mouse_id = 0x00; + + /** @type {number} */ + this.wheel_movement = 0; + /** @type {number} */ this.resolution = 4; @@ -106,8 +115,10 @@ function PS2(cpu, bus) this.bus.register("mouse-wheel", function(data) { - // TODO: Mouse Wheel - // http://www.computer-engineering.org/ps2mouse/ + this.wheel_movement -= data[0]; + this.wheel_movement -= data[1] * 2; // X Wheel Movement + this.wheel_movement = Math.min(7, Math.max(-8, this.wheel_movement)); + this.send_mouse_packet(0, 0); }, this); this.command_register = 1 | 4; @@ -153,6 +164,8 @@ PS2.prototype.get_state = function() state[22] = this.read_command_register; state[23] = this.controller_output_port; state[24] = this.read_controller_output_port; + state[25] = this.mouse_id; + state[26] = this.intellimouse_activation_counter; return state; }; @@ -184,6 +197,8 @@ PS2.prototype.set_state = function(state) this.read_command_register = state[22]; this.controller_output_port = state[23]; this.read_controller_output_port = state[24]; + this.mouse_id = state[25] || 0; + this.intellimouse_activation_counter = state[26] || 0; this.next_byte_is_ready = false; this.next_byte_is_aux = false; @@ -332,6 +347,21 @@ PS2.prototype.send_mouse_packet = function(dx, dy) this.mouse_buffer.push(delta_x); this.mouse_buffer.push(delta_y); + if(this.mouse_id === 0x04) + { + this.mouse_buffer.push( + 0 << 5 | // TODO: 5th button + 0 << 4 | // TODO: 4th button + this.wheel_movement & 0xF + ); + this.wheel_movement = 0; + } + else if(this.mouse_id === 0x03) + { + this.mouse_buffer.push(this.wheel_movement); // Byte 4 - Z Movement + this.wheel_movement = 0; + } + if(PS2_LOG_VERBOSE) { dbg_log("adding mouse packets: " + [info_byte, dx, dy], LOG_PS2); @@ -447,7 +477,31 @@ PS2.prototype.port60_write = function(write_byte) this.mouse_buffer.push(0xFA); this.sample_rate = write_byte; - dbg_log("mouse sample rate: " + h(write_byte), LOG_PS2); + if(this.mouse_id === 0x03) + { + if(this.intellimouse_activation_counter === 0 && this.sample_rate === 200) this.intellimouse_activation_counter = 1; + else if(this.intellimouse_activation_counter === 1 && this.sample_rate === 200) this.intellimouse_activation_counter = 2; + else if(this.intellimouse_activation_counter === 2 && this.sample_rate === 80) { + // Host sends sample rate 200->200->80 to activate Intellimouse 4th, 5th buttons + this.intellimouse_activation_counter = 0; + this.mouse_id = 0x04; + } + else this.intellimouse_activation_counter = 0; + } + else if(this.mouse_id === 0x00) + { + if(this.intellimouse_activation_counter === 0 && this.sample_rate === 200) + this.intellimouse_activation_counter = 1; + else if(this.intellimouse_activation_counter === 1 && this.sample_rate === 100) + this.intellimouse_activation_counter = 2; + else if(this.intellimouse_activation_counter === 2 && this.sample_rate === 80) { + // Host sends sample rate 200->100->80 to activate Intellimouse wheel + this.intellimouse_activation_counter = 0; + this.mouse_id = 0x03; + } + else this.intellimouse_activation_counter = 0; + } + dbg_log("mouse sample rate: " + h(write_byte) + ", mouse id: " + h(this.mouse_id), LOG_PS2); if(!this.sample_rate) { dbg_log("invalid sample rate, reset to 100", LOG_PS2); @@ -545,10 +599,13 @@ PS2.prototype.port60_write = function(write_byte) break; case 0xF2: // MouseID Byte - this.mouse_buffer.push(0); - this.mouse_buffer.push(0); + dbg_log("required id: " + h(this.mouse_id), LOG_PS2); + this.mouse_buffer.push(this.mouse_id); + // this.mouse_buffer.push(this.mouse_id); this.mouse_clicks = this.mouse_delta_x = this.mouse_delta_y = 0; + // this.send_mouse_packet(0, 0); + this.raise_irq(); break; case 0xF3: // sample rate @@ -572,6 +629,9 @@ PS2.prototype.port60_write = function(write_byte) this.sample_rate = 100; this.scaling2 = false; this.resolution = 4; + this.intellimouse_activation_counter = 0; + this.mouse_id = 0x00; + this.wheel_movement = 0; break; case 0xFF: // reset, send completion code @@ -587,6 +647,10 @@ PS2.prototype.port60_write = function(write_byte) this.scaling2 = false; this.resolution = 4; + this.intellimouse_activation_counter = 0; + this.mouse_id = 0x00; + this.wheel_movement = 0; + this.mouse_clicks = this.mouse_delta_x = this.mouse_delta_y = 0; break; @@ -596,11 +660,11 @@ PS2.prototype.port60_write = function(write_byte) this.mouse_irq(); } - else if (this.read_controller_output_port) + else if(this.read_controller_output_port) { this.read_controller_output_port = false; this.controller_output_port = write_byte; - // If we ever want to implement A20 masking, here is where + // If we ever want to implement A20 masking, here is where // we should turn the masking off if the second bit is on } else