From 09ed611a7fc24103e436e0dc88a27c589a18803b Mon Sep 17 00:00:00 2001 From: Kroese Date: Wed, 26 Aug 2026 03:43:28 +0200 Subject: [PATCH] feat: Default to SVGA device for Windows 95/98/ME (#2194) --- src/batch.sh | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/legacy.sh | 2 +- 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/batch.sh b/src/batch.sh index a2abe480..90674df6 100644 --- a/src/batch.sh +++ b/src/batch.sh @@ -138,6 +138,7 @@ Win9xInstall() { local display="$win9x/vmdisp9x" local audio95="$win9x/alcx95" local audiowdm="$win9x/alcxwdm" + local vmware_display="$win9x/vmsvga" extractDrivers "$drivers" || return 1 @@ -171,7 +172,7 @@ Win9xInstall() { return 1 fi - if ! patchWin9xSetupFiles "$id" "$target" "$desc" "$patcher" "$qemouse" "$display"; then + if ! patchWin9xSetupFiles "$id" "$target" "$desc" "$patcher" "$qemouse" "$display" "$vmware_display"; then rm -rf "$drivers" || : return 1 fi @@ -556,6 +557,7 @@ patchWin9xSetupFiles() { local patcher="$4" local qemouse="$5" local display="$6" + local vmware_display="$7" chmod 755 "$patcher" || { error "Failed to make Patcher9x executable!" @@ -580,6 +582,7 @@ patchWin9xSetupFiles() { fi stageWin9xDisplayDriver "$target" "$display" "$desc" || return 1 + stageWin9xVMwareDriver "$target" "$vmware_display" "$desc" || return 1 if ! mv -f -- \ "$target/VMDISP9X/vmdisp9x.inf" \ @@ -1176,6 +1179,100 @@ stageWin9xDisplayDriver() { return 1 fi + # Keep VMDisp9x available for QEMU STD VGA, but let the official VMware + # driver own VMware SVGA-II. Comment only the matching model in our staged + # INF so the original driver archive remains untouched. + if ! python3 - "$dest/vmdisp9x.inf" <<'PY' +from pathlib import Path +import sys + +path = Path(sys.argv[1]) +lines = path.read_bytes().splitlines(keepends=True) +needle = br'PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD' +matches = [] + +for index, line in enumerate(lines): + stripped = line.lstrip(b' \t') + if stripped.startswith(b';'): + continue + if needle in stripped.upper(): + matches.append(index) + +if len(matches) != 1: + raise SystemExit(f'expected exactly one active VMware SVGA-II model, found {len(matches)}') + +index = matches[0] +indent = len(lines[index]) - len(lines[index].lstrip(b' \t')) +lines[index] = lines[index][:indent] + b'; ' + lines[index][indent:] +path.write_bytes(b''.join(lines)) +PY + then + error "Failed to reserve VMware SVGA-II for the official VMware driver!" + return 1 + fi + + if grep -iF 'PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD' "$dest/vmdisp9x.inf" | + grep -Ev '^[[:space:]]*;' >/dev/null; then + error "Failed to remove the active VMware SVGA-II VMDisp9x model!" + return 1 + fi + + if ! grep -iF 'PCI\VEN_15AD&DEV_0405&SUBSYS_040515AD' "$dest/vmdisp9x.inf" | + grep -Eq '^[[:space:]]*;'; then + error "Failed to verify the VMware SVGA-II VMDisp9x model change!" + return 1 + fi + + return 0 +} + +stageWin9xVMwareDriver() { + + local target="$1" + local source="$2" + local desc="$3" + + local file + + for file in \ + vmx_svga.inf \ + VMX_SVGA.DRV \ + VMX_SVGA.vxd; do + + if [ ! -s "$source/$file" ]; then + error "Failed to locate required VMware SVGA driver file: $file" + return 1 + fi + + done + + if ! cp -f -- \ + "$source/vmx_svga.inf" \ + "$source/VMX_SVGA.DRV" \ + "$source/VMX_SVGA.vxd" \ + "$target/"; then + + error "Failed to add the VMware SVGA driver to $desc setup files!" + return 1 + fi + + for file in \ + vmx_svga.inf \ + VMX_SVGA.DRV \ + VMX_SVGA.vxd; do + + if ! cmp -s -- "$source/$file" "$target/$file"; then + error "Failed to verify the staged VMware SVGA driver file: $file" + return 1 + fi + + done + + if ! grep -Fqi 'PCI\VEN_15AD&DEV_0405' "$target/vmx_svga.inf"; then + error "Failed to verify the VMware SVGA-II hardware ID!" + return 1 + fi + return 0 } diff --git a/src/legacy.sh b/src/legacy.sh index 439a9747..4b8d110a 100644 --- a/src/legacy.sh +++ b/src/legacy.sh @@ -31,7 +31,7 @@ setMachine() { "winnt4" ) writeState "vga" "cirrus" || return 1 ;; - "win2k"* | "winxp"* | "win2003"* ) + "win9"* | "win2k"* | "winxp"* | "win2003"* ) writeState "vga" "vmware" || return 1 ;; *) writeState "vga" "std" || return 1 ;;