mirror of
https://github.com/felixrieseberg/windows95.git
synced 2026-05-09 00:24:09 +00:00
Shared text clipboard via VMware backdoor + W95TOOLS.EXE guest agent (#361)
Three layers: v86 — src/vmware.js gains the legacy text-clipboard backdoor commands (GETSELLENGTH/GETNEXTPIECE/SETSELLENGTH/SETNEXTPIECE, 6–9). The host stages bytes via the vmware-clipboard-host bus event; the guest pushes via 8/9 and the device emits vmware-clipboard-guest when the buffer fills. Same wire protocol as open-vm-tools' pre-RPC copy/paste. Committed on the windows95-base fork branch; libv86.js rebuilt here. renderer — src/renderer/clipboard.ts polls Electron's clipboard (no change event exists), translates host UTF-8/LF ↔ guest CP-1252/CRLF, and bounces bytes through the two bus events. Echo-suppressed so a value we just wrote does not come back as a change. guest — guest-tools/agent/W95TOOLS.EXE is a 22 KB hidden-window agent that joins the Win32 clipboard-viewer chain (push-on-copy) and polls the backdoor on a 250 ms timer (pull-from-host). Win9x runs ring-3 with the I/O bitmap wide open, so a plain IN EAX,DX from a user process reaches the port — no driver needed. Named for growth: time sync and host-initiated shutdown will live here too. Built with Open Watcom v2 inside Docker (Makefile + Dockerfile alongside the source); subsystem 4.0, no msvcrt, runs on Win95 RTM. Install: copy \\HOST\TOOLS\agent\W95TOOLS.EXE into the guest and drop a shortcut in StartUp. Text only, 64 KB cap.
This commit is contained in:
@@ -35,11 +35,13 @@ That branch merges four feature branches, each upstreamable on its own:
|
|||||||
writes to target only `current_interface`, but per ATA spec they're
|
writes to target only `current_interface`, but per ATA spec they're
|
||||||
channel-shared (one register file on the IDE cable; both drives latch
|
channel-shared (one register file on the IDE cable; both drives latch
|
||||||
the same value).
|
the same value).
|
||||||
- **`vmware-abspointer`** — `src/vmware.js` implements the VMware mouse
|
- **`vmware-abspointer`** — `src/vmware.js` implements the VMware
|
||||||
backdoor (port `0x5658`, GETVERSION + ABSPOINTER_*) so a guest driver
|
backdoor (port `0x5658`): GETVERSION + ABSPOINTER_* so a guest driver
|
||||||
(VBADOS VBMOUSE) can read absolute cursor position and track the host
|
(VBADOS VBMOUSE) can read absolute cursor position and track the host
|
||||||
cursor 1:1 without pointer lock. Consumes the `mouse-absolute` bus
|
cursor 1:1 without pointer lock, and the legacy text-clipboard commands
|
||||||
event that `MouseAdapter` already emits.
|
6–9 so `W95TOOLS.EXE` (guest-tools/agent) can sync `CF_TEXT` with
|
||||||
|
the host. Consumes `mouse-absolute` and `vmware-clipboard-host` bus
|
||||||
|
events; emits `vmware-absolute-mouse` and `vmware-clipboard-guest`.
|
||||||
- **`vga-defer-vbe-disable-v86`** — `src/vga.js` defers `dispi[4]=0`
|
- **`vga-defer-vbe-disable-v86`** — `src/vga.js` defers `dispi[4]=0`
|
||||||
written from V86 mode until a legacy attribute-mode write reaches the
|
written from V86 mode until a legacy attribute-mode write reaches the
|
||||||
hardware. Win9x's VDD virtualises ports 3B0–3DF for a windowed DOS VM
|
hardware. Win9x's VDD virtualises ports 3B0–3DF for a windowed DOS VM
|
||||||
|
|||||||
@@ -21,3 +21,23 @@ Install inside the guest:
|
|||||||
absolute mouse driver**.
|
absolute mouse driver**.
|
||||||
3. Reboot. The app detects the driver and stops grabbing pointer lock;
|
3. Reboot. The app detects the driver and stops grabbing pointer lock;
|
||||||
ESC still toggles lock for games that want raw relative input.
|
ESC still toggles lock for games that want raw relative input.
|
||||||
|
|
||||||
|
## agent/ — W95TOOLS guest agent
|
||||||
|
|
||||||
|
`W95TOOLS.EXE` is a hidden-window agent that talks to the emulator over
|
||||||
|
the VMware backdoor (port 0x5658). Currently it does one thing: bridges
|
||||||
|
Windows 95's `CF_TEXT` clipboard to the host (legacy backdoor commands
|
||||||
|
6–9; host side is `src/renderer/clipboard.ts`, which polls Electron's
|
||||||
|
clipboard). It's also where time sync, host-initiated shutdown, and a
|
||||||
|
tray icon will live when those land.
|
||||||
|
|
||||||
|
Install inside the guest:
|
||||||
|
|
||||||
|
1. Copy `\\HOST\TOOLS\agent\W95TOOLS.EXE` to `C:\WINDOWS\`.
|
||||||
|
2. Drop a shortcut to it in
|
||||||
|
`C:\WINDOWS\Start Menu\Programs\StartUp` so it runs on login.
|
||||||
|
|
||||||
|
Copy text on either side and it appears on the other within ~250 ms.
|
||||||
|
Text only; conversion is Windows-1252 ↔ UTF-8 with CRLF ↔ LF, capped at
|
||||||
|
64 KB. Built from `w95tools.c` with Open Watcom v2 — `make -C
|
||||||
|
guest-tools/agent` (needs Docker).
|
||||||
|
|||||||
12
guest-tools/agent/Dockerfile
Normal file
12
guest-tools/agent/Dockerfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
FROM --platform=linux/amd64 debian:bookworm-slim
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends curl xz-utils ca-certificates make && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN mkdir -p /opt/watcom && \
|
||||||
|
curl -fsSL https://github.com/open-watcom/open-watcom-v2/releases/download/Current-build/ow-snapshot.tar.xz \
|
||||||
|
| tar -xJ -C /opt/watcom
|
||||||
|
ENV WATCOM=/opt/watcom
|
||||||
|
ENV PATH=$WATCOM/binl64:$PATH
|
||||||
|
ENV INCLUDE=$WATCOM/h:$WATCOM/h/nt
|
||||||
|
ENV LIB=$WATCOM/lib386:$WATCOM/lib386/nt
|
||||||
|
WORKDIR /work
|
||||||
30
guest-tools/agent/Makefile
Normal file
30
guest-tools/agent/Makefile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Build W95TOOLS.EXE for Windows 95 with Open Watcom v2, inside Docker.
|
||||||
|
#
|
||||||
|
# Watcom is the only readily-available cross-compiler that emits a PE binary
|
||||||
|
# Win95 RTM will load (subsystem 4.0, no msvcrt). mingw-w64 targets NT. The
|
||||||
|
# macOS-native Watcom binaries are unsigned and Gatekeeper kills them, so we
|
||||||
|
# run the linux/amd64 build under Docker instead.
|
||||||
|
|
||||||
|
IMAGE := windows95-ow2
|
||||||
|
# Docker Desktop's bind-mount file sync races with recently-edited files; work
|
||||||
|
# around it by piping the source on stdin and building in /tmp inside the
|
||||||
|
# container, then dumping the EXE bytes back over stdout.
|
||||||
|
DOCKER := docker run --rm -i --platform linux/amd64 $(IMAGE)
|
||||||
|
CFLAGS := -bt=nt -3r -zq -wx -we -os -s
|
||||||
|
|
||||||
|
.PHONY: all image clean
|
||||||
|
|
||||||
|
all: W95TOOLS.EXE
|
||||||
|
|
||||||
|
image:
|
||||||
|
docker build --platform linux/amd64 -t $(IMAGE) .
|
||||||
|
|
||||||
|
W95TOOLS.EXE: w95tools.c image
|
||||||
|
$(DOCKER) sh -c 'cd /tmp && cat >w95tools.c && \
|
||||||
|
wcc386 $(CFLAGS) w95tools.c && \
|
||||||
|
wlink system nt_win option quiet name W95TOOLS.EXE \
|
||||||
|
file w95tools.o library kernel32,user32 && \
|
||||||
|
cat W95TOOLS.EXE' <w95tools.c >$@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f W95TOOLS.EXE
|
||||||
BIN
guest-tools/agent/W95TOOLS.EXE
Normal file
BIN
guest-tools/agent/W95TOOLS.EXE
Normal file
Binary file not shown.
181
guest-tools/agent/w95tools.c
Normal file
181
guest-tools/agent/w95tools.c
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* W95TOOLS — guest-side integration agent for the windows95 emulator.
|
||||||
|
*
|
||||||
|
* Currently: bidirectional text clipboard. Talks to the emulator over the
|
||||||
|
* legacy VMware backdoor (port 0x5658; implemented in v86's vmware.js).
|
||||||
|
* Joins the Win32 clipboard-viewer chain so guest copies are pushed
|
||||||
|
* immediately, and polls the backdoor on a timer so host copies show up
|
||||||
|
* within ~250 ms.
|
||||||
|
*
|
||||||
|
* Win9x runs ring-3 code with the I/O bitmap wide open, so a plain IN works
|
||||||
|
* from a user process — no driver needed. On NT this would #GP; we don't run
|
||||||
|
* there.
|
||||||
|
*
|
||||||
|
* Build with Open Watcom v2 (see Makefile). Links USER32/KERNEL32 only,
|
||||||
|
* runs on Win95 RTM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define VMW_MAGIC 0x564D5868UL
|
||||||
|
#define VMW_PORT 0x5658
|
||||||
|
#define CMD_GETLEN 6
|
||||||
|
#define CMD_GETDATA 7
|
||||||
|
#define CMD_SETLEN 8
|
||||||
|
#define CMD_SETDATA 9
|
||||||
|
#define CMD_VERSION 10
|
||||||
|
|
||||||
|
#define POLL_MS 250
|
||||||
|
#define MAX_CLIP 0xFFFF
|
||||||
|
|
||||||
|
extern unsigned long bd(unsigned long cmd, unsigned long arg);
|
||||||
|
#pragma aux bd = \
|
||||||
|
"mov eax, 564D5868h" \
|
||||||
|
"mov edx, 5658h" \
|
||||||
|
"in eax, dx" \
|
||||||
|
parm [ecx] [ebx] \
|
||||||
|
value [eax] \
|
||||||
|
modify [edx];
|
||||||
|
|
||||||
|
extern unsigned long bd_ebx(unsigned long cmd, unsigned long arg);
|
||||||
|
#pragma aux bd_ebx = \
|
||||||
|
"mov eax, 564D5868h" \
|
||||||
|
"mov edx, 5658h" \
|
||||||
|
"in eax, dx" \
|
||||||
|
parm [ecx] [ebx] \
|
||||||
|
value [ebx] \
|
||||||
|
modify [eax edx];
|
||||||
|
|
||||||
|
static HWND g_next;
|
||||||
|
static int g_ignore;
|
||||||
|
|
||||||
|
static void push_to_host(HWND hwnd)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
char *p;
|
||||||
|
unsigned long len, i, w;
|
||||||
|
|
||||||
|
if (!IsClipboardFormatAvailable(CF_TEXT)) {
|
||||||
|
bd(CMD_SETLEN, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!OpenClipboard(hwnd)) return;
|
||||||
|
h = GetClipboardData(CF_TEXT);
|
||||||
|
if (h && (p = (char *)GlobalLock(h)) != 0) {
|
||||||
|
len = lstrlen(p);
|
||||||
|
if (len > MAX_CLIP) len = MAX_CLIP;
|
||||||
|
bd(CMD_SETLEN, len);
|
||||||
|
for (i = 0; i < len; i += 4) {
|
||||||
|
w = (unsigned char)p[i];
|
||||||
|
if (i + 1 < len) w |= (unsigned long)(unsigned char)p[i+1] << 8;
|
||||||
|
if (i + 2 < len) w |= (unsigned long)(unsigned char)p[i+2] << 16;
|
||||||
|
if (i + 3 < len) w |= (unsigned long)(unsigned char)p[i+3] << 24;
|
||||||
|
bd(CMD_SETDATA, w);
|
||||||
|
}
|
||||||
|
GlobalUnlock(h);
|
||||||
|
}
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pull_from_host(HWND hwnd)
|
||||||
|
{
|
||||||
|
long len;
|
||||||
|
unsigned long i, w;
|
||||||
|
HGLOBAL h;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
len = (long)bd(CMD_GETLEN, 0);
|
||||||
|
if (len < 0) return;
|
||||||
|
if (len > MAX_CLIP) len = MAX_CLIP;
|
||||||
|
|
||||||
|
h = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (DWORD)len + 1);
|
||||||
|
if (!h) return;
|
||||||
|
p = (char *)GlobalLock(h);
|
||||||
|
for (i = 0; i < (unsigned long)len; i += 4) {
|
||||||
|
w = bd(CMD_GETDATA, 0);
|
||||||
|
p[i] = (char)w;
|
||||||
|
if (i + 1 < (unsigned long)len) p[i+1] = (char)(w >> 8);
|
||||||
|
if (i + 2 < (unsigned long)len) p[i+2] = (char)(w >> 16);
|
||||||
|
if (i + 3 < (unsigned long)len) p[i+3] = (char)(w >> 24);
|
||||||
|
}
|
||||||
|
p[len] = 0;
|
||||||
|
GlobalUnlock(h);
|
||||||
|
|
||||||
|
if (!OpenClipboard(hwnd)) { GlobalFree(h); return; }
|
||||||
|
g_ignore++;
|
||||||
|
EmptyClipboard();
|
||||||
|
SetClipboardData(CF_TEXT, h);
|
||||||
|
CloseClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
|
||||||
|
{
|
||||||
|
switch (msg) {
|
||||||
|
case WM_CREATE:
|
||||||
|
g_next = SetClipboardViewer(hwnd);
|
||||||
|
SetTimer(hwnd, 1, POLL_MS, 0);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_DRAWCLIPBOARD:
|
||||||
|
if (g_ignore > 0) g_ignore--;
|
||||||
|
else push_to_host(hwnd);
|
||||||
|
if (g_next) SendMessage(g_next, msg, wp, lp);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_CHANGECBCHAIN:
|
||||||
|
if ((HWND)wp == g_next) g_next = (HWND)lp;
|
||||||
|
else if (g_next) SendMessage(g_next, msg, wp, lp);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_TIMER:
|
||||||
|
pull_from_host(hwnd);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
ChangeClipboardChain(hwnd, g_next);
|
||||||
|
KillTimer(hwnd, 1);
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProc(hwnd, msg, wp, lp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PASCAL WinMain(HINSTANCE hi, HINSTANCE hp, LPSTR cmd, int show)
|
||||||
|
{
|
||||||
|
WNDCLASS wc;
|
||||||
|
HWND hwnd;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
(void)hp; (void)cmd; (void)show;
|
||||||
|
|
||||||
|
if (CreateMutex(0, FALSE, "W95Tools") && GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bd_ebx(CMD_VERSION, 0) != VMW_MAGIC) {
|
||||||
|
MessageBox(0, "VMware backdoor not present.", "W95Tools", MB_OK | MB_ICONSTOP);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wc.style = 0;
|
||||||
|
wc.lpfnWndProc = WndProc;
|
||||||
|
wc.cbClsExtra = 0;
|
||||||
|
wc.cbWndExtra = 0;
|
||||||
|
wc.hInstance = hi;
|
||||||
|
wc.hIcon = 0;
|
||||||
|
wc.hCursor = 0;
|
||||||
|
wc.hbrBackground = 0;
|
||||||
|
wc.lpszMenuName = 0;
|
||||||
|
wc.lpszClassName = "W95Tools";
|
||||||
|
RegisterClass(&wc);
|
||||||
|
|
||||||
|
hwnd = CreateWindow("W95Tools", "W95Tools", WS_OVERLAPPED,
|
||||||
|
0, 0, 0, 0, 0, 0, hi, 0);
|
||||||
|
if (!hwnd) return 1;
|
||||||
|
|
||||||
|
while (GetMessage(&msg, 0, 0, 0) > 0) {
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
62
src/renderer/clipboard.ts
Normal file
62
src/renderer/clipboard.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// Bidirectional text clipboard between the host and the Win95 guest.
|
||||||
|
//
|
||||||
|
// Transport is the legacy VMware backdoor clipboard protocol (port 0x5658,
|
||||||
|
// commands 6–9) implemented in v86's vmware.js. Inside the guest, W95TOOLS.EXE
|
||||||
|
// (guest-tools/agent) polls the backdoor and bridges it to CF_TEXT via the
|
||||||
|
// Win32 clipboard-viewer chain. Out here we poll Electron's clipboard — there
|
||||||
|
// is no change event — and translate between host UTF-8/LF and guest
|
||||||
|
// Windows-1252/CRLF.
|
||||||
|
|
||||||
|
import { clipboard } from "electron";
|
||||||
|
|
||||||
|
const CP1252 = new TextDecoder("windows-1252");
|
||||||
|
// v86's vmware.js and the guest agent both clamp to 64 KB; clamp here too so
|
||||||
|
// a huge host clipboard never even gets allocated/encoded.
|
||||||
|
const CLIP_MAX = 0x10000;
|
||||||
|
|
||||||
|
function fromGuest(bytes: Uint8Array): string {
|
||||||
|
return CP1252.decode(bytes).replace(/\r\n/g, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toGuest(text: string): Uint8Array {
|
||||||
|
const s = text.slice(0, CLIP_MAX).replace(/\r\n|\n/g, "\r\n");
|
||||||
|
const n = Math.min(s.length, CLIP_MAX);
|
||||||
|
const out = new Uint8Array(n);
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const c = s.charCodeAt(i);
|
||||||
|
out[i] = c < 256 ? c : 0x3f;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setupClipboardSync(emulator: any): () => void {
|
||||||
|
// Track the last value seen on each side so a value we just wrote doesn't
|
||||||
|
// bounce back as a "change" from the other side.
|
||||||
|
let lastHost = clipboard.readText();
|
||||||
|
let lastGuest = "";
|
||||||
|
|
||||||
|
emulator.add_listener("vmware-clipboard-guest", (bytes: Uint8Array) => {
|
||||||
|
const text = fromGuest(bytes);
|
||||||
|
if (text === lastHost || text === lastGuest) return;
|
||||||
|
lastGuest = text;
|
||||||
|
lastHost = text;
|
||||||
|
clipboard.writeText(text);
|
||||||
|
console.log("[clip] guest → host", text.length, "chars");
|
||||||
|
});
|
||||||
|
|
||||||
|
const poll = () => {
|
||||||
|
const text = clipboard.readText();
|
||||||
|
if (text === lastHost) return;
|
||||||
|
lastHost = text;
|
||||||
|
if (text === lastGuest) return;
|
||||||
|
emulator.bus.send("vmware-clipboard-host", toGuest(text));
|
||||||
|
console.log("[clip] host → guest", text.length, "chars");
|
||||||
|
};
|
||||||
|
|
||||||
|
const id = window.setInterval(poll, 500);
|
||||||
|
window.addEventListener("focus", poll);
|
||||||
|
return () => {
|
||||||
|
window.clearInterval(id);
|
||||||
|
window.removeEventListener("focus", poll);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import { resetState } from "./utils/reset-state";
|
|||||||
import { setupSmbShare } from "./smb";
|
import { setupSmbShare } from "./smb";
|
||||||
import { setupTcpRelay } from "./net/tcp-relay";
|
import { setupTcpRelay } from "./net/tcp-relay";
|
||||||
import { setupDnsShim } from "./net/dns-shim";
|
import { setupDnsShim } from "./net/dns-shim";
|
||||||
|
import { setupClipboardSync } from "./clipboard";
|
||||||
import { startProbe } from "./debug-harness";
|
import { startProbe } from "./debug-harness";
|
||||||
import { SyncFileBuffer } from "./sync-file-buffer";
|
import { SyncFileBuffer } from "./sync-file-buffer";
|
||||||
|
|
||||||
@@ -406,6 +407,10 @@ export class Emulator extends React.Component<{}, EmulatorState> {
|
|||||||
startProbe(window["emulator"]);
|
startProbe(window["emulator"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Host ↔ guest text clipboard. The guest side is W95TOOLS.EXE on the
|
||||||
|
// TOOLS share; until that's running this is a no-op poller.
|
||||||
|
setupClipboardSync(window["emulator"]);
|
||||||
|
|
||||||
// New v86 instance
|
// New v86 instance
|
||||||
// Mouse stays disabled until either the pointer is captured or the guest's
|
// Mouse stays disabled until either the pointer is captured or the guest's
|
||||||
// VMware-backdoor mouse driver requests absolute mode.
|
// VMware-backdoor mouse driver requests absolute mode.
|
||||||
|
|||||||
@@ -426,13 +426,13 @@ this.mouse_clicks=this.mouse_delta_x=this.mouse_delta_y=0;break;case 245:this.en
|
|||||||
0;break;default:y(a)}this.mouse_irq()}}else if(this.read_controller_output_port)this.read_controller_output_port=!1,this.controller_output_port=a;else{y(a);this.mouse_buffer.clear();this.kbd_buffer.clear();this.kbd_buffer.push(250);switch(a){case 237:this.next_read_led=!0;break;case 240:this.next_handle_scan_code_set=!0;break;case 242:this.kbd_buffer.push(171);this.kbd_buffer.push(131);break;case 243:this.next_read_rate=!0;break;case 244:this.enable_keyboard_stream=!0;break;case 245:this.enable_keyboard_stream=
|
0;break;default:y(a)}this.mouse_irq()}}else if(this.read_controller_output_port)this.read_controller_output_port=!1,this.controller_output_port=a;else{y(a);this.mouse_buffer.clear();this.kbd_buffer.clear();this.kbd_buffer.push(250);switch(a){case 237:this.next_read_led=!0;break;case 240:this.next_handle_scan_code_set=!0;break;case 242:this.kbd_buffer.push(171);this.kbd_buffer.push(131);break;case 243:this.next_read_rate=!0;break;case 244:this.enable_keyboard_stream=!0;break;case 245:this.enable_keyboard_stream=
|
||||||
!1;break;case 246:break;case 255:this.kbd_buffer.clear();this.kbd_buffer.push(250);this.kbd_buffer.push(170);this.kbd_buffer.push(0);break;default:y(a)}this.kbd_irq()}};
|
!1;break;case 246:break;case 255:this.kbd_buffer.clear();this.kbd_buffer.push(250);this.kbd_buffer.push(170);this.kbd_buffer.push(0);break;default:y(a)}this.kbd_irq()}};
|
||||||
Gc.prototype.port64_write=function(a){y(a);switch(a){case 32:this.kbd_buffer.clear();this.mouse_buffer.clear();this.kbd_buffer.push(this.command_register);this.kbd_irq();break;case 96:this.read_command_register=!0;break;case 209:this.read_controller_output_port=!0;break;case 211:this.read_output_register=!0;break;case 212:this.next_is_mouse_command=!0;break;case 167:this.command_register|=32;break;case 168:this.command_register&=-33;break;case 169:this.kbd_buffer.clear();this.mouse_buffer.clear();
|
Gc.prototype.port64_write=function(a){y(a);switch(a){case 32:this.kbd_buffer.clear();this.mouse_buffer.clear();this.kbd_buffer.push(this.command_register);this.kbd_irq();break;case 96:this.read_command_register=!0;break;case 209:this.read_controller_output_port=!0;break;case 211:this.read_output_register=!0;break;case 212:this.next_is_mouse_command=!0;break;case 167:this.command_register|=32;break;case 168:this.command_register&=-33;break;case 169:this.kbd_buffer.clear();this.mouse_buffer.clear();
|
||||||
this.kbd_buffer.push(0);this.kbd_irq();break;case 170:this.kbd_buffer.clear();this.mouse_buffer.clear();this.kbd_buffer.push(85);this.kbd_irq();break;case 171:this.kbd_buffer.clear();this.mouse_buffer.clear();this.kbd_buffer.push(0);this.kbd_irq();break;case 173:this.command_register|=16;break;case 174:this.command_register&=-17;break;case 254:this.cpu.reboot_internal();break;default:y(a)}};function Hc(a,b){this.cpu=a;this.bus=b;this.absolute=this.enabled=!1;this.queue=[];this.buttons=0;this.last_y=this.last_x=-1;this.tail_is_move=!1;this.clip_out=new Uint8Array(0);this.clip_out_cursor=0;this.clip_out_fresh=!1;this.clip_in=new Uint8Array(0);this.clip_in_cursor=0;this.bus.register("vmware-clipboard-host",function(c){this.clip_out=65536<c.length?c.subarray(0,65536):c;this.clip_out_cursor=0;this.clip_out_fresh=!0},this);this.bus.register("mouse-absolute",function(c){const d=Math.max(0,
|
this.kbd_buffer.push(0);this.kbd_irq();break;case 170:this.kbd_buffer.clear();this.mouse_buffer.clear();this.kbd_buffer.push(85);this.kbd_irq();break;case 171:this.kbd_buffer.clear();this.mouse_buffer.clear();this.kbd_buffer.push(0);this.kbd_irq();break;case 173:this.command_register|=16;break;case 174:this.command_register&=-17;break;case 254:this.cpu.reboot_internal();break;default:y(a)}};function Hc(a,b){function c(){}this.cpu=a;this.bus=b;this.absolute=this.enabled=!1;this.queue=[];this.buttons=0;this.last_y=this.last_x=-1;this.tail_is_move=!1;this.clip_out=new Uint8Array(0);this.clip_out_cursor=0;this.clip_out_fresh=!1;this.clip_in=new Uint8Array(0);this.clip_in_cursor=0;this.bus.register("vmware-clipboard-host",function(d){this.clip_out=65536<d.length?d.subarray(0,65536):d;this.clip_out_cursor=0;this.clip_out_fresh=!0},this);this.bus.register("mouse-absolute",function(d){const e=
|
||||||
Math.min(65535,Math.round(c[0]/c[2]*65535)));c=Math.max(0,Math.min(65535,Math.round(c[1]/c[3]*65535)));if(d!==this.last_x||c!==this.last_y)this.last_x=d,this.last_y=c,this.push_packet(0,!0)},this);this.bus.register("mouse-click",function(c){this.buttons=(c[0]?32:0)|(c[1]?8:0)|(c[2]?16:0);this.push_packet(0,!1)},this);this.bus.register("mouse-wheel",function(c){this.push_packet(-c[0]|0,!1)},this);a.io.register_read(22104,this,void 0,void 0,this.port_read32);a.io.register_write(22104,this,void 0,void 0,
|
Math.max(0,Math.min(65535,Math.round(d[0]/d[2]*65535)));d=Math.max(0,Math.min(65535,Math.round(d[1]/d[3]*65535)));if(e!==this.last_x||d!==this.last_y)this.last_x=e,this.last_y=d,this.push_packet(0,!0)},this);this.bus.register("mouse-click",function(d){this.buttons=(d[0]?32:0)|(d[1]?8:0)|(d[2]?16:0);this.push_packet(0,!1)},this);this.bus.register("mouse-wheel",function(d){this.push_packet(-d[0]|0,!1)},this);a.io.register_read(22104,this,function(){return 255},function(){return 65535},this.port_read32);
|
||||||
this.port_write32)}Hc.prototype.push_packet=function(a,b){!this.enabled||!this.absolute||0>this.last_x||(b&&this.tail_is_move&&4<=this.queue.length?(this.queue[this.queue.length-3]=this.last_x,this.queue[this.queue.length-2]=this.last_y):1024<this.queue.length+4?(this.enabled=!1,this.queue.length=0):(this.queue.push(this.buttons,this.last_x,this.last_y,a),this.tail_is_move=b))};
|
a.io.register_write(22104,this,c,c,c)}Hc.prototype.push_packet=function(a,b){!this.enabled||!this.absolute||0>this.last_x||(b&&this.tail_is_move&&4<=this.queue.length?(this.queue[this.queue.length-3]=this.last_x,this.queue[this.queue.length-2]=this.last_y):1024<this.queue.length+4?(this.enabled=!1,this.queue.length=0):(this.queue.push(this.buttons,this.last_x,this.last_y,a),this.tail_is_move=b))};
|
||||||
Hc.prototype.port_read32=function(){var a=this.cpu.reg32;if(1447909480!==(a[0]|0))return-1;switch(a[1]&65535){case 10:return a[3]=1447909480,6;case 6:if(!this.clip_out_fresh)break;this.clip_out_fresh=!1;this.clip_out_cursor=0;return this.clip_out.length;case 7:var b=this.clip_out;a=this.clip_out_cursor;b=b[a]|0|(b[a+1]|0)<<8|(b[a+2]|0)<<16|(b[a+3]|0)<<24;this.clip_out_cursor=a+4;return b;case 8:return a=Math.min(a[3]>>>0,65536),this.clip_in=new Uint8Array(a),this.clip_in_cursor=0,0===a&&this.bus.send("vmware-clipboard-guest",
|
Hc.prototype.port_read32=function(){var a=this.cpu.reg32;if(1447909480!==a[0])return-1;switch(a[1]&65535){case 10:return a[3]=1447909480,6;case 6:if(!this.clip_out_fresh)break;this.clip_out_fresh=!1;this.clip_out_cursor=0;return this.clip_out.length;case 7:var b=this.clip_out;a=this.clip_out_cursor;b=b[a]|0|(b[a+1]|0)<<8|(b[a+2]|0)<<16|(b[a+3]|0)<<24;this.clip_out_cursor=a+4;return b;case 8:return a=Math.min(a[3]>>>0,65536),this.clip_in=new Uint8Array(a),this.clip_in_cursor=0,0===a&&this.bus.send("vmware-clipboard-guest",
|
||||||
this.clip_in),0;case 9:b=this.clip_in;a=a[3]>>>0;var c=this.clip_in_cursor;c<b.length&&(b[c++]=a);c<b.length&&(b[c++]=a>>>8);c<b.length&&(b[c++]=a>>>16);c<b.length&&(b[c++]=a>>>24);this.clip_in_cursor=c;c>=b.length&&(this.bus.send("vmware-clipboard-guest",b),this.clip_in=new Uint8Array(0),this.clip_in_cursor=0);return 0;case 40:return this.enabled?this.queue.length:-65536;case 39:b=Math.min(a[3]>>>0,4,this.queue.length);c=[0,0,0,0];for(let d=0;d<b;d++)c[d]=this.queue.shift();a[3]=c[1];a[1]=c[2];a[2]=
|
this.clip_in),0;case 9:b=this.clip_in;a=a[3]>>>0;var c=this.clip_in_cursor;c<b.length&&(b[c++]=a);c<b.length&&(b[c++]=a>>>8);c<b.length&&(b[c++]=a>>>16);c<b.length&&(b[c++]=a>>>24);this.clip_in_cursor=c;c>=b.length&&(this.bus.send("vmware-clipboard-guest",b),this.clip_in=new Uint8Array(0),this.clip_in_cursor=0);return 0;case 40:return this.enabled?this.queue.length:-65536;case 39:b=Math.min(a[3]>>>0,4,this.queue.length);c=[0,0,0,0];for(let d=0;d<b;d++)c[d]=this.queue.shift();a[3]=c[1];a[1]=c[2];a[2]=
|
||||||
c[3];return c[0];case 41:switch(a[3]|0){case 1161905490:this.enabled=!0;this.queue.length=0;this.tail_is_move=!1;this.queue.push(876762442);break;case 245:this.absolute=this.enabled=!1;this.queue.length=0;this.bus.send("vmware-absolute-mouse",!1);break;case 1396851026:this.absolute=!0;this.bus.send("vmware-absolute-mouse",!0);break;case 1279611474:this.absolute=!1,this.bus.send("vmware-absolute-mouse",!1)}return 0}return-1};Hc.prototype.port_write32=function(){};
|
c[3];return c[0];case 41:switch(a[3]){case 1161905490:this.enabled=!0;this.queue.length=0;this.tail_is_move=!1;this.queue.push(876762442);break;case 245:this.absolute=this.enabled=!1;this.queue.length=0;this.bus.send("vmware-absolute-mouse",!1);break;case 1396851026:this.absolute=!0;this.bus.send("vmware-absolute-mouse",!0);break;case 1279611474:this.absolute=!1,this.bus.send("vmware-absolute-mouse",!1)}return 0}return-1};Hc.prototype.get_state=function(){return[this.enabled,this.absolute]};
|
||||||
Hc.prototype.get_state=function(){return[this.enabled,this.absolute]};Hc.prototype.set_state=function(a){this.enabled=a[0];this.absolute=a[1];this.bus.send("vmware-absolute-mouse",this.absolute)};const Ic=DataView.prototype,Jc={size:1,get:Ic.getUint8,set:Ic.setUint8},Kc={size:2,get:Ic.getUint16,set:Ic.setUint16},U={size:4,get:Ic.getUint32,set:Ic.setUint32},Mc=Lc([{magic:U},{class:Jc},{data:Jc},{version0:Jc},{osabi:Jc},{abiversion:Jc},{pad0:function(a){return{size:a,get:()=>-1}}(7)},{type:Kc},{machine:Kc},{version1:U},{entry:U},{phoff:U},{shoff:U},{flags:U},{ehsize:Kc},{phentsize:Kc},{phnum:Kc},{shentsize:Kc},{shnum:Kc},{shstrndx:Kc}]);console.assert(52===Mc.reduce((a,b)=>a+b.size,0));
|
Hc.prototype.set_state=function(a){this.enabled=a[0];this.absolute=a[1];this.bus.send("vmware-absolute-mouse",this.absolute)};const Ic=DataView.prototype,Jc={size:1,get:Ic.getUint8,set:Ic.setUint8},Kc={size:2,get:Ic.getUint16,set:Ic.setUint16},U={size:4,get:Ic.getUint32,set:Ic.setUint32},Mc=Lc([{magic:U},{class:Jc},{data:Jc},{version0:Jc},{osabi:Jc},{abiversion:Jc},{pad0:function(a){return{size:a,get:()=>-1}}(7)},{type:Kc},{machine:Kc},{version1:U},{entry:U},{phoff:U},{shoff:U},{flags:U},{ehsize:Kc},{phentsize:Kc},{phnum:Kc},{shentsize:Kc},{shnum:Kc},{shstrndx:Kc}]);console.assert(52===Mc.reduce((a,b)=>a+b.size,0));
|
||||||
const Nc=Lc([{type:U},{offset:U},{vaddr:U},{paddr:U},{filesz:U},{memsz:U},{flags:U},{align:U}]);console.assert(32===Nc.reduce((a,b)=>a+b.size,0));const Oc=Lc([{name:U},{type:U},{flags:U},{addr:U},{offset:U},{size:U},{link:U},{info:U},{addralign:U},{entsize:U}]);console.assert(40===Oc.reduce((a,b)=>a+b.size,0));function Lc(a){return a.map(function(b){var c=Object.keys(b);console.assert(1===c.length);c=c[0];b=b[c];console.assert(0<b.size);return{name:c,type:b,size:b.size,get:b.get,set:b.set}})}
|
const Nc=Lc([{type:U},{offset:U},{vaddr:U},{paddr:U},{filesz:U},{memsz:U},{flags:U},{align:U}]);console.assert(32===Nc.reduce((a,b)=>a+b.size,0));const Oc=Lc([{name:U},{type:U},{flags:U},{addr:U},{offset:U},{size:U},{link:U},{info:U},{addralign:U},{entsize:U}]);console.assert(40===Oc.reduce((a,b)=>a+b.size,0));function Lc(a){return a.map(function(b){var c=Object.keys(b);console.assert(1===c.length);c=c[0];b=b[c];console.assert(0<b.size);return{name:c,type:b,size:b.size,get:b.get,set:b.set}})}
|
||||||
function Pc(a,b){const c={};let d=0;for(const e of b)b=e.get.call(a,d,!0),console.assert(void 0===c[e.name]),c[e.name]=b,d+=e.size;return[c,d]}function Qc(a,b,c){const d=[];let e=0;for(var f=0;f<c;f++){const [g,h]=Pc(new DataView(a.buffer,a.byteOffset+e,void 0),b);d.push(g);e+=h}return[d,e]};const Rc={[0]:0,[1]:525,[2]:525,[3]:350,[4]:350,[5]:350};
|
function Pc(a,b){const c={};let d=0;for(const e of b)b=e.get.call(a,d,!0),console.assert(void 0===c[e.name]),c[e.name]=b,d+=e.size;return[c,d]}function Qc(a,b,c){const d=[];let e=0;for(var f=0;f<c;f++){const [g,h]=Pc(new DataView(a.buffer,a.byteOffset+e,void 0),b);d.push(g);e+=h}return[d,e]};const Rc={[0]:0,[1]:525,[2]:525,[3]:350,[4]:350,[5]:350};
|
||||||
function V(a,b,c,d){this.io=a.io;this.cpu=a;this.dma=a.devices.dma;this.cmd_table=this.build_cmd_lookup_table();this.sra=0;this.srb=192;this.dor=12;this.tdr=0;this.msr=128;this.dsr=0;this.cmd_phase=1;this.cmd_flags=this.cmd_code=0;this.cmd_buffer=new Uint8Array(17);this.cmd_remaining=this.cmd_cursor=0;this.response_data=new Uint8Array(15);this.reset_sense_int_count=this.curr_drive_no=this.status1=this.status0=this.response_length=this.response_cursor=0;this.locked=!1;this.head_load_time=this.step_rate_interval=
|
function V(a,b,c,d){this.io=a.io;this.cpu=a;this.dma=a.devices.dma;this.cmd_table=this.build_cmd_lookup_table();this.sra=0;this.srb=192;this.dor=12;this.tdr=0;this.msr=128;this.dsr=0;this.cmd_phase=1;this.cmd_flags=this.cmd_code=0;this.cmd_buffer=new Uint8Array(17);this.cmd_remaining=this.cmd_cursor=0;this.response_data=new Uint8Array(15);this.reset_sense_int_count=this.curr_drive_no=this.status1=this.status0=this.response_length=this.response_cursor=0;this.locked=!1;this.head_load_time=this.step_rate_interval=
|
||||||
|
|||||||
Reference in New Issue
Block a user