@@ -8,6 +8,10 @@ import { BusConnector } from "./bus.js";
88const VMWARE_PORT = 0x5658 ;
99const VMWARE_MAGIC = 0x564D5868 ;
1010
11+ const CMD_GETSELLENGTH = 6 ;
12+ const CMD_GETNEXTPIECE = 7 ;
13+ const CMD_SETSELLENGTH = 8 ;
14+ const CMD_SETNEXTPIECE = 9 ;
1115const CMD_GETVERSION = 10 ;
1216const CMD_GETTIME = 23 ;
1317const CMD_ABSPOINTER_DATA = 39 ;
@@ -32,14 +36,17 @@ const BUTTON_MIDDLE = 0x08;
3236const RELATIVE_PACKET = 0x00010000 ;
3337
3438const QUEUE_MAX = 1024 ;
39+ const CLIP_MAX = 0x10000 ;
3540
3641/**
3742 * VMware backdoor (port 0x5658). Lets a guest driver read absolute pointer
3843 * position so the guest cursor can track the host cursor 1:1 without pointer
39- * lock, and implements GETTIME (23) so a guest agent can keep the guest clock
40- * in sync with the host (guests only read the RTC at boot, so a restored
41- * state resumes with a stale clock). PS/2 still supplies the mouse IRQ; the
42- * driver reads this port on each IRQ12. While the host pointer is locked
44+ * lock, lets a guest agent sync the clipboard with the host using the legacy
45+ * text commands (6–9), and implements GETTIME (23) so a guest agent can keep
46+ * the guest clock in sync with the host (guests only read the RTC at boot, so
47+ * a restored state resumes with a stale clock). PS/2 still supplies the mouse
48+ * IRQ; the driver reads this port on each IRQ12. While the host pointer is
49+ * locked
4350 * (e.g. for games), movement is reported as relative packets instead, since
4451 * no meaningful absolute position exists.
4552 *
@@ -69,6 +76,22 @@ export function VMwareMouse(cpu, bus)
6976 this . last_y = - 1 ;
7077 this . tail_is_move = false ;
7178
79+ /** @type {Uint8Array } host→guest text staged for the guest to read */
80+ this . clip_out = new Uint8Array ( 0 ) ;
81+ this . clip_out_cursor = 0 ;
82+ this . clip_out_fresh = false ;
83+
84+ /** @type {Uint8Array } guest→host text being received */
85+ this . clip_in = new Uint8Array ( 0 ) ;
86+ this . clip_in_cursor = 0 ;
87+
88+ this . bus . register ( "vmware-clipboard-host" , function ( data )
89+ {
90+ this . clip_out = data . length > CLIP_MAX ? data . subarray ( 0 , CLIP_MAX ) : data ;
91+ this . clip_out_cursor = 0 ;
92+ this . clip_out_fresh = true ;
93+ } , this ) ;
94+
7295 /**
7396 * Whether the host pointer is currently locked (browser pointer lock).
7497 * While locked, the host cursor position is meaningless, so movement is
@@ -225,6 +248,56 @@ VMwareMouse.prototype.port_read32 = function()
225248 reg32 [ REG_EBX ] = VMWARE_MAGIC ;
226249 return 6 ;
227250
251+ case CMD_GETSELLENGTH :
252+ if ( ! this . clip_out_fresh )
253+ {
254+ return 0xFFFFFFFF | 0 ;
255+ }
256+ this . clip_out_fresh = false ;
257+ this . clip_out_cursor = 0 ;
258+ return this . clip_out . length ;
259+
260+ case CMD_GETNEXTPIECE :
261+ {
262+ const c = this . clip_out ;
263+ let i = this . clip_out_cursor ;
264+ const v = ( c [ i ] | 0 ) | ( c [ i + 1 ] | 0 ) << 8 |
265+ ( c [ i + 2 ] | 0 ) << 16 | ( c [ i + 3 ] | 0 ) << 24 ;
266+ this . clip_out_cursor = i + 4 ;
267+ return v ;
268+ }
269+
270+ case CMD_SETSELLENGTH :
271+ {
272+ const n = Math . min ( reg32 [ REG_EBX ] >>> 0 , CLIP_MAX ) ;
273+ this . clip_in = new Uint8Array ( n ) ;
274+ this . clip_in_cursor = 0 ;
275+ if ( n === 0 )
276+ {
277+ this . bus . send ( "vmware-clipboard-guest" , this . clip_in ) ;
278+ }
279+ return 0 ;
280+ }
281+
282+ case CMD_SETNEXTPIECE :
283+ {
284+ const c = this . clip_in ;
285+ const v = reg32 [ REG_EBX ] >>> 0 ;
286+ let i = this . clip_in_cursor ;
287+ if ( i < c . length ) c [ i ++ ] = v ;
288+ if ( i < c . length ) c [ i ++ ] = v >>> 8 ;
289+ if ( i < c . length ) c [ i ++ ] = v >>> 16 ;
290+ if ( i < c . length ) c [ i ++ ] = v >>> 24 ;
291+ this . clip_in_cursor = i ;
292+ if ( i >= c . length )
293+ {
294+ this . bus . send ( "vmware-clipboard-guest" , c ) ;
295+ this . clip_in = new Uint8Array ( 0 ) ;
296+ this . clip_in_cursor = 0 ;
297+ }
298+ return 0 ;
299+ }
300+
228301 case CMD_GETTIME :
229302 {
230303 // EAX = host time in seconds since the Unix epoch (UTC),
0 commit comments