From c8a1586fa44871ea216e4024dd823fcdfc368489 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 17 Dec 2023 01:29:49 -0500 Subject: [PATCH 01/28] Implement makeWin2kImage --- README.md | 1 + flake.nix | 6 ++ makeWin2kImage/default.nix | 148 +++++++++++++++++++++++++++++++++++++ makeWin2kImage/run.nix | 43 +++++++++++ 4 files changed, 198 insertions(+) create mode 100644 makeWin2kImage/default.nix create mode 100644 makeWin2kImage/run.nix diff --git a/README.md b/README.md index d4f4ed1..386359d 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ Each of the outputs in this flake have their own image builders and `runScript`. - `makeWin30Image` - `makeWfwg311Image` - `makeWin98Image` +- `makeWin2kImage` They can each be passed the `dosPostInstall` argument arbitrary **dos commands** to be ran after Windows has been installed, for example here's how diff --git a/flake.nix b/flake.nix index 14ca955..eec33aa 100644 --- a/flake.nix +++ b/flake.nix @@ -60,6 +60,7 @@ makeWin30Image = pkgs.callPackage ./makeWin30Image {}; makeWfwg311Image = pkgs.callPackage ./makeWfwg311Image {}; makeWin98Image = pkgs.callPackage ./makeWin98Image {}; + makeWin2kImage = pkgs.callPackage ./makeWin2kImage {}; # makeSystem7Image = pkgs.callPackage ./makeSystem7Image {}; }; apps = { @@ -83,6 +84,10 @@ type = "app"; program = config.packages.win98-image.runScript; }; + win2k = { + type = "app"; + program = config.packages.win2k-image.runScript; + }; }; packages = rec { macos-ventura-image = config.legacyPackages.makeDarwinImage {}; @@ -90,6 +95,7 @@ win30-image = config.legacyPackages.makeWin30Image {}; wfwg311-image = config.legacyPackages.makeWfwg311Image {}; win98-image = config.legacyPackages.makeWin98Image {}; + win2k-image = config.legacyPackages.makeWin2kImage {}; #system7-image = config.legacyPackages.makeSystem7Image {}; #macos-repeatability-test = genOverridenDrvLinkFarm (macos-ventura-image.overrideAttrs { repeatabilityTest = true; }) 3; win98-repeatability-test = genOverridenDrvLinkFarm win98-image 100; diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix new file mode 100644 index 0000000..353d149 --- /dev/null +++ b/makeWin2kImage/default.nix @@ -0,0 +1,148 @@ +{ fetchurl, runCommand, p7zip, dosbox-x, xvfb-run, x11vnc, imagemagick +, tesseract, expect, vncdo, writeScript, writeShellScript, writeText +, makeWin98Image, callPackage }: +{ dosPostInstall ? "", ... }: +let + win98 = makeWin98Image { }; + win2k-installer = fetchurl { + name = "win2k.7z"; + urls = [ + "https://winworldpc.com/download/413638c2-8d18-c39a-11c3-a4e284a2c3a5/from/c39ac2af-c381-c2bf-1b25-11c3a4e284a2" + "https://winworldpc.com/download/413638c2-8d18-c39a-11c3-a4e284a2c3a5/from/c3ae6ee2-8099-713d-3411-c3a6e280947e" + "https://cloudflare-ipfs.com/ipfs/QmT7rGKU4WzQxwpfZqFgGwGSCrBbBm7SejUSPgDzxAgPye/Microsoft%20Windows%202000%20Professional%20(5.00.2195).7z" + ]; + sha512 = + "9cb026d8eaa3933d7ca0447c7e1b05fd1504a6063b16a86d5cca4dc04ef5d598bd8ae95dac6f10671422ece192b1aff94ecd505d2cd7a15981eaa4fd691f1489"; + }; + dosboxConf = writeText "dosbox.conf" '' + [dosbox] + memsize = 32 + + [autoexec] + imgmount C win98.img + imgmount D win2k.iso + boot -l C + ''; + tesseractScript = writeShellScript "tesseractScript" '' + export OMP_THREAD_LIMIT=1 + cd $(mktemp -d) + TEXT="" + while true + do + sleep 3 + ${vncdo}/bin/vncdo -s 127.0.0.1::5900 capture cap-small.png + ${imagemagick}/bin/convert cap-small.png -interpolate Integer -filter point -resize 400% cap.png + NEW_TEXT="$(${tesseract}/bin/tesseract cap.png stdout 2>/dev/null)" + if [ "$TEXT" != "$NEW_TEXT" ]; then + echo "$NEW_TEXT" + TEXT="$NEW_TEXT" + fi + done + ''; + expectScript = let + vncdoWrapper = writeScript "vncdoWrapper" '' + sleep 3 + ${vncdo}/bin/vncdo --force-caps -s 127.0.0.1::5900 "$@" + ''; + in writeScript "expect.sh" '' + #!${expect}/bin/expect -f + set debug 5 + set timeout -1 + spawn ${tesseractScript} + expect "Show this screen each time" + send_user "\n### WIN98 BOOTED ###\n" + exec ${vncdoWrapper} pause 10 key ctrl-esc pause 3 key r + expect "Type the name of" + exec ${vncdoWrapper} type com pause 1 type mand.com key enter + expect "Prompt" + exec ${vncdoWrapper} type d: key enter type setup key enter + expect "Windows 2000 CD" + exec ${vncdoWrapper} key enter + expect "Welcome to the Windows 2000" + exec ${vncdoWrapper} key enter + expect "License Agreement" + exec ${vncdoWrapper} key tab key enter + expect "Your Product Key" + exec ${vncdoWrapper} type rbdc9 pause 1 type vtrc8 pause 1 type d7972 pause 1 type j97jy pause 1 type prvmg pause 1 key enter + expect "Preparing to Upgrade to Windows 2000" + exec ${vncdoWrapper} key enter + expect "Provide Upgrade Packs" + exec ${vncdoWrapper} key enter + expect "File System" + exec ${vncdoWrapper} key enter + expect "Provide Updated Plug and Play Files" + exec ${vncdoWrapper} key enter + expect "Upgrade Report" + exec ${vncdoWrapper} key enter + expect "Setup found that" + exec ${vncdoWrapper} key tab key enter + expect "Setup now has the information" + exec ${vncdoWrapper} key enter + send_user "\n### WAITING TO BOOT INTO STAGE 2 ###\n" + expect "Password Creation" + exec ${vncdoWrapper} key enter + expect "It is unsafe" + exec ${vncdoWrapper} key enter + expect "Log On to Windows" + exec ${vncdoWrapper} key enter + expect "Getting Started with Windows 2000" + exec ${vncdoWrapper} pause 3 key ctrl-esc pause 3 key u pause 3 key down key down key enter + send_user "\n### OMG DID IT WORK???!!!! ###\n" + exit 0 ''; + iso = runCommand "win2k.iso" { } '' + echo "win2k-installer src: ${win2k-installer}" + mkdir win2k + ${p7zip}/bin/7z x -owin2k ${win2k-installer} + ls -lah win2k + mv win2k/*/*.iso $out + ''; + installedImage = runCommand "win2k.img" { + # set __impure = true; for debugging + # __impure = true; + buildInputs = [ dosbox-x xvfb-run x11vnc ]; + passthru = rec { + makeRunScript = callPackage ./run.nix; + runScript = makeRunScript { }; + }; + } '' + echo "iso src: ${iso}" + cp --no-preserve=mode ${iso} win2k.iso + cp --no-preserve=mode ${win98} win98.img + runDosboxVnc() { + xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true & + dosboxPID=$! + DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 & + } + ${expectScript} & + expectScriptPID=$! + for stage in $(seq 4); do + echo STAGE $stage + runDosboxVnc + wait $dosboxPID + done + wait $expectScriptPID + cp win98.img $out + ''; + postInstalledImage = let + dosboxConf-postInstall = writeText "dosbox.conf" '' + [dosbox] + memsize = 32 + + [cpu] + turbo=on + stop turbo on key = false + + [autoexec] + imgmount C win2k.img + ${dosPostInstall} + exit + ''; + in runCommand "win2k.img" { + buildInputs = [ dosbox-x ]; + inherit (installedImage) passthru; + } '' + cp --no-preserve=mode ${installedImage} ./win2k.img + SDL_VIDEODRIVER=dummy dosbox-x -conf ${dosboxConf-postInstall} + mv win2k.img $out + ''; +in if (dosPostInstall != "") then postInstalledImage else installedImage diff --git a/makeWin2kImage/run.nix b/makeWin2kImage/run.nix new file mode 100644 index 0000000..af66315 --- /dev/null +++ b/makeWin2kImage/run.nix @@ -0,0 +1,43 @@ +{ writeShellScriptBin, writeText, lib, dosbox-x, makeWin2kImage +, extraDosboxFlags ? [ ], diskImage ? makeWin2kImage { + dosPostInstall = '' + c: + echo win >> AUTOEXEC.BAT + ''; +} }: +let + dosboxConf = writeText "dosbox.conf" '' + [dosbox] + memsize = 32 + + [sdl] + autolock = true + + [autoexec] + imgmount C win2k.img + boot -l C + ''; +in writeShellScriptBin "run-win2k.sh" '' + args=( + -conf ${dosboxConf} + ${lib.concatStringsSep " " extraDosboxFlags} + "$@" + ) + + if [ ! -f win2k.img ]; then + echo "win2k.img not found, making disk image ./win2k.img" + cp --no-preserve=mode ${diskImage} ./win2k.img + fi + + run_dosbox() { + ${dosbox-x}/bin/dosbox-x "''${args[@]}" + } + + run_dosbox + + if [ $? -ne 0 ]; then + echo "Dosbox crashed. Re-running with SDL_VIDEODRIVER=x11." + SDL_VIDEODRIVER=x11 run_dosbox + fi +'' + From 3236b517e6922e822339c78d18bf0c6c525a1b08 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 31 Dec 2023 00:52:17 -0500 Subject: [PATCH 02/28] Stash changes --- makeWin2kImage/default.nix | 76 +++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 353d149..66c214f 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -1,7 +1,11 @@ -{ fetchurl, runCommand, p7zip, dosbox-x, xvfb-run, x11vnc, imagemagick +# https://fabulous.systems/posts/2023/07/installing-windows-2000-in-dosbox-x/ + +{ lib, fetchurl, runCommand, p7zip, dosbox-x, xvfb-run, x11vnc, imagemagick , tesseract, expect, vncdo, writeScript, writeShellScript, writeText , makeWin98Image, callPackage }: -{ dosPostInstall ? "", ... }: +{ dosPostInstall ? "", +# NTFS not supported in dosbox-x, image builds with it probably won't work +useNTFS ? false, ... }: let win98 = makeWin98Image { }; win2k-installer = fetchurl { @@ -19,9 +23,9 @@ let memsize = 32 [autoexec] - imgmount C win98.img - imgmount D win2k.iso - boot -l C + imgmount c win2k.img + imgmount d win2k.iso + boot -l c ''; tesseractScript = writeShellScript "tesseractScript" '' export OMP_THREAD_LIMIT=1 @@ -49,26 +53,62 @@ let set debug 5 set timeout -1 spawn ${tesseractScript} - expect "Show this screen each time" + expect "Recycle Bin" send_user "\n### WIN98 BOOTED ###\n" - exec ${vncdoWrapper} pause 10 key ctrl-esc pause 3 key r - expect "Type the name of" - exec ${vncdoWrapper} type com pause 1 type mand.com key enter - expect "Prompt" - exec ${vncdoWrapper} type d: key enter type setup key enter - expect "Windows 2000 CD" + while { 1 } { + exec sleep 10 + send_user "\n### TRYING TO OPEN WIN2K SETUP ###\n" + expect { + "Windows 2000 CD" { break } + "Prompt" { + send_user "\n### OPENING WIN2K SETUP ###\n" + exec ${vncdoWrapper} type d: key enter type setup key enter + } + "Type the name of" { + send_user "\n### OPENING COMMAND.COM ###\n" + exec ${vncdoWrapper} type com pause 1 type mand.com key enter + } + "Programs" { + send_user "\n### OPENING RUN PROMPT ###\n" + exec ${vncdoWrapper} key r + } + "Internet A" { + send_user "\n### OPENING START MENU ###\n" + exec ${vncdoWrapper} key ctrl-esc + } + } + } exec ${vncdoWrapper} key enter expect "Welcome to the Windows 2000" - exec ${vncdoWrapper} key enter + exec ${vncdoWrapper} key down key enter expect "License Agreement" exec ${vncdoWrapper} key tab key enter expect "Your Product Key" - exec ${vncdoWrapper} type rbdc9 pause 1 type vtrc8 pause 1 type d7972 pause 1 type j97jy pause 1 type prvmg pause 1 key enter - expect "Preparing to Upgrade to Windows 2000" + while { 1 } { + send_user "\n### ENTERING PRODUCT KEY ###\n" + exec ${vncdoWrapper} type rbdc9 pause 1 type vtrc8 pause 1 type d7972 pause 1 type j97jy pause 1 type prvmg pause 1 key enter + expect { + "Select Special Options" { break } + "Do Windows 2000 Eetup E4" { + send_user "\n### RETRYING ENTERING PRODUCT KEY ###\n" + exec ${vncdoWrapper} key enter + exec ${vncdoWrapper} key tab key tab key tab key tab + for {set i 0} {$i < 25} {incr i} { + exec ${vncdoWrapper} key bsp + } + } + } + } exec ${vncdoWrapper} key enter + expect "To set up Windows 2000 now, press ENTER." + exec ${vncdoWrapper} key enter + expect "The following list shows the existing partitions" + exec ${vncdoWrapper} key enter + expect "Provide Upgrade Packs" exec ${vncdoWrapper} key enter expect "File System" + ${lib.optionalString useNTFS "exec ${vncdoWrapper} key up"} exec ${vncdoWrapper} key enter expect "Provide Updated Plug and Play Files" exec ${vncdoWrapper} key enter @@ -76,7 +116,7 @@ let exec ${vncdoWrapper} key enter expect "Setup found that" exec ${vncdoWrapper} key tab key enter - expect "Setup now has the information" + expect "Setup now has the" exec ${vncdoWrapper} key enter send_user "\n### WAITING TO BOOT INTO STAGE 2 ###\n" expect "Password Creation" @@ -107,7 +147,7 @@ let } '' echo "iso src: ${iso}" cp --no-preserve=mode ${iso} win2k.iso - cp --no-preserve=mode ${win98} win98.img + cp --no-preserve=mode ${win98} win2k.img runDosboxVnc() { xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true & dosboxPID=$! @@ -133,7 +173,7 @@ let stop turbo on key = false [autoexec] - imgmount C win2k.img + imgmount c win2k.img ${dosPostInstall} exit ''; From 7f6a960e6a7fa114ec00927dffc9ccacb0647bff Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 31 Dec 2023 01:46:50 -0500 Subject: [PATCH 03/28] win2k: switch to unattended install --- makeWin2kImage/default.nix | 177 ++++++++++--------------------------- makeWin2kImage/run.nix | 7 +- 2 files changed, 48 insertions(+), 136 deletions(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 66c214f..d765bdb 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -1,13 +1,37 @@ -# https://fabulous.systems/posts/2023/07/installing-windows-2000-in-dosbox-x/ - { lib, fetchurl, runCommand, p7zip, dosbox-x, xvfb-run, x11vnc, imagemagick , tesseract, expect, vncdo, writeScript, writeShellScript, writeText , makeWin98Image, callPackage }: -{ dosPostInstall ? "", -# NTFS not supported in dosbox-x, image builds with it probably won't work -useNTFS ? false, ... }: +{ dosPostInstall ? "", answerFile ? writeText "answers.ini" + (lib.generators.toINI { } { + Data = { + AutoPartition = 1; + MsDosInitiated = "0"; + UnattendedInstall = "Yes"; + }; + Unattended = { + UnattendMode = "FullUnattended"; + OemSkipEula = "Yes"; + OemPreinstall = "No"; + TargetPath = "WINDOWS"; + }; + GuiUnattended = { + AdminPassword = "*"; + AutoLogon = "Yes"; + OEMSkipRegional = 1; + TimeZone = 4; + OemSkipWelcome = 1; + }; + UserData = { + FullName = "user"; + OrgName = "NixThePlanet"; + ComputerName = "*"; + ProductID = "RBDC9-VTRC8-D7972-J97JY-PRVMG"; + }; + RegionalSettings.LanguageGroup = 1; + Identification.JoinWorkgroup = "WORKGROUP"; + Networking.InstallDefaultComponents = "Yes"; + }) }: let - win98 = makeWin98Image { }; win2k-installer = fetchurl { name = "win2k.7z"; urls = [ @@ -22,113 +46,19 @@ let [dosbox] memsize = 32 + [cpu] + turbo=on + stop turbo on key = false + [autoexec] - imgmount c win2k.img + mount a . + if not exist a:\win2k.img imgmake win2k.img -t hd_1gig + imgmount c win2k.img -t hdd imgmount d win2k.iso + c: + if not exist c:\windows d:\i386\winnt /s:d:\ /u:a:\answers.ini boot -l c ''; - tesseractScript = writeShellScript "tesseractScript" '' - export OMP_THREAD_LIMIT=1 - cd $(mktemp -d) - TEXT="" - while true - do - sleep 3 - ${vncdo}/bin/vncdo -s 127.0.0.1::5900 capture cap-small.png - ${imagemagick}/bin/convert cap-small.png -interpolate Integer -filter point -resize 400% cap.png - NEW_TEXT="$(${tesseract}/bin/tesseract cap.png stdout 2>/dev/null)" - if [ "$TEXT" != "$NEW_TEXT" ]; then - echo "$NEW_TEXT" - TEXT="$NEW_TEXT" - fi - done - ''; - expectScript = let - vncdoWrapper = writeScript "vncdoWrapper" '' - sleep 3 - ${vncdo}/bin/vncdo --force-caps -s 127.0.0.1::5900 "$@" - ''; - in writeScript "expect.sh" '' - #!${expect}/bin/expect -f - set debug 5 - set timeout -1 - spawn ${tesseractScript} - expect "Recycle Bin" - send_user "\n### WIN98 BOOTED ###\n" - while { 1 } { - exec sleep 10 - send_user "\n### TRYING TO OPEN WIN2K SETUP ###\n" - expect { - "Windows 2000 CD" { break } - "Prompt" { - send_user "\n### OPENING WIN2K SETUP ###\n" - exec ${vncdoWrapper} type d: key enter type setup key enter - } - "Type the name of" { - send_user "\n### OPENING COMMAND.COM ###\n" - exec ${vncdoWrapper} type com pause 1 type mand.com key enter - } - "Programs" { - send_user "\n### OPENING RUN PROMPT ###\n" - exec ${vncdoWrapper} key r - } - "Internet A" { - send_user "\n### OPENING START MENU ###\n" - exec ${vncdoWrapper} key ctrl-esc - } - } - } - exec ${vncdoWrapper} key enter - expect "Welcome to the Windows 2000" - exec ${vncdoWrapper} key down key enter - expect "License Agreement" - exec ${vncdoWrapper} key tab key enter - expect "Your Product Key" - while { 1 } { - send_user "\n### ENTERING PRODUCT KEY ###\n" - exec ${vncdoWrapper} type rbdc9 pause 1 type vtrc8 pause 1 type d7972 pause 1 type j97jy pause 1 type prvmg pause 1 key enter - expect { - "Select Special Options" { break } - "Do Windows 2000 Eetup E4" { - send_user "\n### RETRYING ENTERING PRODUCT KEY ###\n" - exec ${vncdoWrapper} key enter - exec ${vncdoWrapper} key tab key tab key tab key tab - for {set i 0} {$i < 25} {incr i} { - exec ${vncdoWrapper} key bsp - } - } - } - } - exec ${vncdoWrapper} key enter - expect "To set up Windows 2000 now, press ENTER." - exec ${vncdoWrapper} key enter - expect "The following list shows the existing partitions" - exec ${vncdoWrapper} key enter - - expect "Provide Upgrade Packs" - exec ${vncdoWrapper} key enter - expect "File System" - ${lib.optionalString useNTFS "exec ${vncdoWrapper} key up"} - exec ${vncdoWrapper} key enter - expect "Provide Updated Plug and Play Files" - exec ${vncdoWrapper} key enter - expect "Upgrade Report" - exec ${vncdoWrapper} key enter - expect "Setup found that" - exec ${vncdoWrapper} key tab key enter - expect "Setup now has the" - exec ${vncdoWrapper} key enter - send_user "\n### WAITING TO BOOT INTO STAGE 2 ###\n" - expect "Password Creation" - exec ${vncdoWrapper} key enter - expect "It is unsafe" - exec ${vncdoWrapper} key enter - expect "Log On to Windows" - exec ${vncdoWrapper} key enter - expect "Getting Started with Windows 2000" - exec ${vncdoWrapper} pause 3 key ctrl-esc pause 3 key u pause 3 key down key down key enter - send_user "\n### OMG DID IT WORK???!!!! ###\n" - exit 0 ''; iso = runCommand "win2k.iso" { } '' echo "win2k-installer src: ${win2k-installer}" mkdir win2k @@ -137,9 +67,6 @@ let mv win2k/*/*.iso $out ''; installedImage = runCommand "win2k.img" { - # set __impure = true; for debugging - # __impure = true; - buildInputs = [ dosbox-x xvfb-run x11vnc ]; passthru = rec { makeRunScript = callPackage ./run.nix; runScript = makeRunScript { }; @@ -147,21 +74,12 @@ let } '' echo "iso src: ${iso}" cp --no-preserve=mode ${iso} win2k.iso - cp --no-preserve=mode ${win98} win2k.img - runDosboxVnc() { - xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true & - dosboxPID=$! - DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 & - } - ${expectScript} & - expectScriptPID=$! - for stage in $(seq 4); do + cp --no-preserve=mode ${answerFile} answers.ini + for stage in $(seq 100); do echo STAGE $stage - runDosboxVnc - wait $dosboxPID + ${lib.meta.getExe dosbox-x} -conf ${dosboxConf} done - wait $expectScriptPID - cp win98.img $out + cp win2k.img $out ''; postInstalledImage = let dosboxConf-postInstall = writeText "dosbox.conf" '' @@ -177,12 +95,11 @@ let ${dosPostInstall} exit ''; - in runCommand "win2k.img" { - buildInputs = [ dosbox-x ]; - inherit (installedImage) passthru; - } '' + in runCommand "win2k.img" { inherit (installedImage) passthru; } '' cp --no-preserve=mode ${installedImage} ./win2k.img - SDL_VIDEODRIVER=dummy dosbox-x -conf ${dosboxConf-postInstall} + SDL_VIDEODRIVER=dummy ${ + lib.meta.getExe dosbox-x + } -conf ${dosboxConf-postInstall} mv win2k.img $out ''; in if (dosPostInstall != "") then postInstalledImage else installedImage diff --git a/makeWin2kImage/run.nix b/makeWin2kImage/run.nix index af66315..2b261cb 100644 --- a/makeWin2kImage/run.nix +++ b/makeWin2kImage/run.nix @@ -1,10 +1,5 @@ { writeShellScriptBin, writeText, lib, dosbox-x, makeWin2kImage -, extraDosboxFlags ? [ ], diskImage ? makeWin2kImage { - dosPostInstall = '' - c: - echo win >> AUTOEXEC.BAT - ''; -} }: +, extraDosboxFlags ? [ ], diskImage ? makeWin2kImage { } }: let dosboxConf = writeText "dosbox.conf" '' [dosbox] From 6d19d3a6797cbb74ca87bb4ef4c85465a1fb42ba Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 31 Dec 2023 02:47:20 -0500 Subject: [PATCH 04/28] win2k: fix winnt init check --- makeWin2kImage/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index d765bdb..851e664 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -56,7 +56,7 @@ let imgmount c win2k.img -t hdd imgmount d win2k.iso c: - if not exist c:\windows d:\i386\winnt /s:d:\ /u:a:\answers.ini + if not exist c:\ntldr d:\i386\winnt /s:d:\ /u:a:\answers.ini boot -l c ''; iso = runCommand "win2k.iso" { } '' From d8374046127afe1490321520d8108a0facc3faaa Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 31 Dec 2023 17:36:24 -0500 Subject: [PATCH 05/28] win2k: disable turbo, move answers to separate file, and set dosbox to restart one time --- makeWin2kImage/answers.nix | 29 +++++++++++++++++++++ makeWin2kImage/default.nix | 52 +++++--------------------------------- 2 files changed, 35 insertions(+), 46 deletions(-) create mode 100644 makeWin2kImage/answers.nix diff --git a/makeWin2kImage/answers.nix b/makeWin2kImage/answers.nix new file mode 100644 index 0000000..584c6d5 --- /dev/null +++ b/makeWin2kImage/answers.nix @@ -0,0 +1,29 @@ +{ + Data = { + AutoPartition = 1; + MsDosInitiated = "0"; + UnattendedInstall = "Yes"; + }; + Unattended = { + UnattendMode = "FullUnattended"; + OemSkipEula = "Yes"; + OemPreinstall = "No"; + TargetPath = "WINDOWS"; + }; + GuiUnattended = { + AdminPassword = "*"; + AutoLogon = "Yes"; + OEMSkipRegional = 1; + TimeZone = 4; + OemSkipWelcome = 1; + }; + UserData = { + FullName = "user"; + OrgName = "NixThePlanet"; + ComputerName = "*"; + ProductID = "RBDC9-VTRC8-D7972-J97JY-PRVMG"; + }; + RegionalSettings.LanguageGroup = 1; + Identification.JoinWorkgroup = "WORKGROUP"; + Networking.InstallDefaultComponents = "Yes"; +} diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 851e664..4161a3a 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -1,36 +1,6 @@ -{ lib, fetchurl, runCommand, p7zip, dosbox-x, xvfb-run, x11vnc, imagemagick -, tesseract, expect, vncdo, writeScript, writeShellScript, writeText -, makeWin98Image, callPackage }: -{ dosPostInstall ? "", answerFile ? writeText "answers.ini" - (lib.generators.toINI { } { - Data = { - AutoPartition = 1; - MsDosInitiated = "0"; - UnattendedInstall = "Yes"; - }; - Unattended = { - UnattendMode = "FullUnattended"; - OemSkipEula = "Yes"; - OemPreinstall = "No"; - TargetPath = "WINDOWS"; - }; - GuiUnattended = { - AdminPassword = "*"; - AutoLogon = "Yes"; - OEMSkipRegional = 1; - TimeZone = 4; - OemSkipWelcome = 1; - }; - UserData = { - FullName = "user"; - OrgName = "NixThePlanet"; - ComputerName = "*"; - ProductID = "RBDC9-VTRC8-D7972-J97JY-PRVMG"; - }; - RegionalSettings.LanguageGroup = 1; - Identification.JoinWorkgroup = "WORKGROUP"; - Networking.InstallDefaultComponents = "Yes"; - }) }: +{ lib, fetchurl, runCommand, p7zip, dosbox-x, writeText, callPackage }: +{ dosPostInstall ? "", answerFile ? + writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: let win2k-installer = fetchurl { name = "win2k.7z"; @@ -46,10 +16,6 @@ let [dosbox] memsize = 32 - [cpu] - turbo=on - stop turbo on key = false - [autoexec] mount a . if not exist a:\win2k.img imgmake win2k.img -t hd_1gig @@ -75,9 +41,9 @@ let echo "iso src: ${iso}" cp --no-preserve=mode ${iso} win2k.iso cp --no-preserve=mode ${answerFile} answers.ini - for stage in $(seq 100); do + for stage in 1 2; do echo STAGE $stage - ${lib.meta.getExe dosbox-x} -conf ${dosboxConf} + SDL_VIDEODRIVER=dummy ${lib.getExe dosbox-x} -conf ${dosboxConf} || true done cp win2k.img $out ''; @@ -86,10 +52,6 @@ let [dosbox] memsize = 32 - [cpu] - turbo=on - stop turbo on key = false - [autoexec] imgmount c win2k.img ${dosPostInstall} @@ -97,9 +59,7 @@ let ''; in runCommand "win2k.img" { inherit (installedImage) passthru; } '' cp --no-preserve=mode ${installedImage} ./win2k.img - SDL_VIDEODRIVER=dummy ${ - lib.meta.getExe dosbox-x - } -conf ${dosboxConf-postInstall} + SDL_VIDEODRIVER=dummy ${lib.getExe dosbox-x} -conf ${dosboxConf-postInstall} mv win2k.img $out ''; in if (dosPostInstall != "") then postInstalledImage else installedImage From 1a617b46f3aab8e33caa1dc1eea4e8c4c13a4447 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 31 Dec 2023 18:19:13 -0500 Subject: [PATCH 06/28] win2k: add comments --- makeWin2kImage/answers.nix | 13 +++++++++++++ makeWin2kImage/default.nix | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/makeWin2kImage/answers.nix b/makeWin2kImage/answers.nix index 584c6d5..4f5abf4 100644 --- a/makeWin2kImage/answers.nix +++ b/makeWin2kImage/answers.nix @@ -1,3 +1,16 @@ +# Windows 2000's unattended installation feature is a bit tricky to figure out. +# The SUPPORT/TOOLS/SETUP.EXE in the install disk ISO crashes DOSBox-X, but +# SUPPORT/TOOLS/SREADME.DOC says that it doesn't install the relevant deployment +# tools in DEPLOY.CAB anyway. If you extract SUPPORT/TOOLS/DEPLOY.CAB with +# cabextract, there is setupmgr.exe inside that has a GUI for creating the +# answer files. It must be run in the same directory as setupmgx.dll, also +# included in DEPLOY.CAB. There is also documentation in DEPLOY.CAB in the +# deptool.chm, readme.txt, and unattend.doc files. The setupmgr.exe tool +# doesn't ask for a product key, so that has to be added to UserData.ProductID +# separately. Otherwise, during the install there will be an error asking the +# user to input it. The unattend.doc file also contains documentation of the +# different answer file options. + { Data = { AutoPartition = 1; diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 4161a3a..bbb2f64 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -1,3 +1,8 @@ +# Fabulous.systems demonstrated that installing Windows 2000 in DOSBox-X is possible in +# https://fabulous.systems/posts/2023/07/installing-windows-2000-in-dosbox-x/ +# but this package uses a different approach, installing from scratch instead of +# from Windows 98 and using an answer file for unattended installation. + { lib, fetchurl, runCommand, p7zip, dosbox-x, writeText, callPackage }: { dosPostInstall ? "", answerFile ? writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: @@ -16,6 +21,9 @@ let [dosbox] memsize = 32 + [cpu] + turbo = off # Turbo prevents the boot screen from progressing + [autoexec] mount a . if not exist a:\win2k.img imgmake win2k.img -t hd_1gig From 17b503a10b259a4e9c0555c38587df03c70980f2 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 31 Dec 2023 18:20:41 -0500 Subject: [PATCH 07/28] win2k: add win2k-repeatability-test --- flake.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/flake.nix b/flake.nix index eec33aa..f45c260 100644 --- a/flake.nix +++ b/flake.nix @@ -98,6 +98,7 @@ win2k-image = config.legacyPackages.makeWin2kImage {}; #system7-image = config.legacyPackages.makeSystem7Image {}; #macos-repeatability-test = genOverridenDrvLinkFarm (macos-ventura-image.overrideAttrs { repeatabilityTest = true; }) 3; + win2k-repeatability-test = genOverridenDrvLinkFarm win2k-image 100; win98-repeatability-test = genOverridenDrvLinkFarm win98-image 100; wfwg311-repeatability-test = genOverridenDrvLinkFarm wfwg311-image 100; win30-repeatability-test = genOverridenDrvLinkFarm win30-image 100; From ea4d86595fc69fe70f4f38934d4736b7d3eb8958 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 31 Dec 2023 18:57:05 -0500 Subject: [PATCH 08/28] win2k: add unattend.doc web link to comment --- makeWin2kImage/answers.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/makeWin2kImage/answers.nix b/makeWin2kImage/answers.nix index 4f5abf4..328f4bf 100644 --- a/makeWin2kImage/answers.nix +++ b/makeWin2kImage/answers.nix @@ -9,7 +9,8 @@ # doesn't ask for a product key, so that has to be added to UserData.ProductID # separately. Otherwise, during the install there will be an error asking the # user to input it. The unattend.doc file also contains documentation of the -# different answer file options. +# different answer file options. A web version of unattend.doc is at +# https://web.archive.org/web/20040314065512/https://www.microsoft.com/technet/prodtechnol/Windows2000Pro/deploy/unattend/default.mspx { Data = { From f953930f166074702f4ec909064a5241dc6397e1 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Mon, 1 Jan 2024 19:11:37 -0500 Subject: [PATCH 09/28] win2k: add vnc and tesseract for output logs --- makeWin2kImage/default.nix | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index bbb2f64..07df51c 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -3,7 +3,8 @@ # but this package uses a different approach, installing from scratch instead of # from Windows 98 and using an answer file for unattended installation. -{ lib, fetchurl, runCommand, p7zip, dosbox-x, writeText, callPackage }: +{ lib, fetchurl, runCommand, p7zip, dosbox-x, x11vnc, tesseract, vncdo, xvfb-run +, writeText, writeShellScript, callPackage }: { dosPostInstall ? "", answerFile ? writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: let @@ -40,7 +41,25 @@ let ls -lah win2k mv win2k/*/*.iso $out ''; + tesseractScript = writeShellScript "tesseractScript" '' + export OMP_THREAD_LIMIT=1 + cd $(mktemp -d) + TEXT="" + while true + do + sleep 3 + ${vncdo}/bin/vncdo -s 127.0.0.1::5900 capture cap.png + NEW_TEXT="$(${tesseract}/bin/tesseract cap.png stdout 2>/dev/null)" + if [ "$TEXT" != "$NEW_TEXT" ]; then + echo "$NEW_TEXT" + TEXT="$NEW_TEXT" + fi + done + ''; installedImage = runCommand "win2k.img" { + # set __impure = true; for debugging + # __impure = true; + buildInputs = [ dosbox-x xvfb-run x11vnc ]; passthru = rec { makeRunScript = callPackage ./run.nix; runScript = makeRunScript { }; @@ -49,9 +68,17 @@ let echo "iso src: ${iso}" cp --no-preserve=mode ${iso} win2k.iso cp --no-preserve=mode ${answerFile} answers.ini + # This install is fully unattended, but a VNC server and tesseract script are still started for log output and debugging + ( + while true; do + DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 || true + echo RESTARTING VNC + done + ) & + ${tesseractScript} & for stage in 1 2; do echo STAGE $stage - SDL_VIDEODRIVER=dummy ${lib.getExe dosbox-x} -conf ${dosboxConf} || true + xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true done cp win2k.img $out ''; From 6129b0d620db438dc5880139d39e15533a9d62a2 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Fri, 5 Jan 2024 17:48:00 -0500 Subject: [PATCH 10/28] win2k: disable rate limit and enable turbo in stage 1 --- makeWin2kImage/default.nix | 42 ++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 07df51c..61ce47d 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -18,22 +18,27 @@ let sha512 = "9cb026d8eaa3933d7ca0447c7e1b05fd1504a6063b16a86d5cca4dc04ef5d598bd8ae95dac6f10671422ece192b1aff94ecd505d2cd7a15981eaa4fd691f1489"; }; - dosboxConf = writeText "dosbox.conf" '' - [dosbox] - memsize = 32 + dosboxConf = stage: + writeText "dosbox.conf" '' + [dosbox] + memsize = 32 - [cpu] - turbo = off # Turbo prevents the boot screen from progressing + [dos] + hard drive data rate limit = 0 + floppy drive data rate limit = 0 - [autoexec] - mount a . - if not exist a:\win2k.img imgmake win2k.img -t hd_1gig - imgmount c win2k.img -t hdd - imgmount d win2k.iso - c: - if not exist c:\ntldr d:\i386\winnt /s:d:\ /u:a:\answers.ini - boot -l c - ''; + [cpu] + # Turbo prevents the boot screen from progressing in stage 2 + turbo = ${if stage == 2 then "off" else "on"} + + [autoexec] + mount a . + if not exist a:\win2k.img imgmake win2k.img -t hd_1gig + imgmount c win2k.img -t hdd + imgmount d win2k.iso + if not exist c:\ntldr d:\i386\winnt /s:d: /u:a:answers.ini + boot -l c + ''; iso = runCommand "win2k.iso" { } '' echo "win2k-installer src: ${win2k-installer}" mkdir win2k @@ -76,10 +81,11 @@ let done ) & ${tesseractScript} & - for stage in 1 2; do - echo STAGE $stage - xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true - done + ${lib.strings.concatMapStrings (stage: '' + echo STAGE ${toString stage} + xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" \ + dosbox-x -conf ${dosboxConf stage} || true + '') [ 1 2 ]} cp win2k.img $out ''; postInstalledImage = let From fa13e70255646288b738bcf7cce8cd3cf8c31f8e Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 17 Dec 2023 13:52:43 -0500 Subject: [PATCH 11/28] Start makeWinXPImage --- flake.nix | 6 ++ makeWinXPImage/default.nix | 117 +++++++++++++++++++++++++++++++++++++ makeWinXPImage/run.nix | 40 +++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 makeWinXPImage/default.nix create mode 100644 makeWinXPImage/run.nix diff --git a/flake.nix b/flake.nix index f45c260..4589a89 100644 --- a/flake.nix +++ b/flake.nix @@ -61,6 +61,7 @@ makeWfwg311Image = pkgs.callPackage ./makeWfwg311Image {}; makeWin98Image = pkgs.callPackage ./makeWin98Image {}; makeWin2kImage = pkgs.callPackage ./makeWin2kImage {}; + makeWinXPImage = pkgs.callPackage ./makeWinXPImage {}; # makeSystem7Image = pkgs.callPackage ./makeSystem7Image {}; }; apps = { @@ -88,6 +89,10 @@ type = "app"; program = config.packages.win2k-image.runScript; }; + winxp = { + type = "app"; + program = config.packages.winxp-image.runScript; + }; }; packages = rec { macos-ventura-image = config.legacyPackages.makeDarwinImage {}; @@ -96,6 +101,7 @@ wfwg311-image = config.legacyPackages.makeWfwg311Image {}; win98-image = config.legacyPackages.makeWin98Image {}; win2k-image = config.legacyPackages.makeWin2kImage {}; + winxp-image = config.legacyPackages.makeWinXPImage {}; #system7-image = config.legacyPackages.makeSystem7Image {}; #macos-repeatability-test = genOverridenDrvLinkFarm (macos-ventura-image.overrideAttrs { repeatabilityTest = true; }) 3; win2k-repeatability-test = genOverridenDrvLinkFarm win2k-image 100; diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix new file mode 100644 index 0000000..9478ae5 --- /dev/null +++ b/makeWinXPImage/default.nix @@ -0,0 +1,117 @@ +{ fetchtorrent, runCommand, dosbox-x, xvfb-run, x11vnc, tesseract, expect, vncdo +, writeScript, writeShellScript, writeText, fetchFromGitHub, makeWin2kImage +, callPackage }: +{ dosPostInstall ? "", ... }: +let + win2k = makeWin2kImage { }; + winxp-installer = fetchtorrent { + url = + "https://archive.org/download/WinXPProSP3x86/WinXPProSP3x86_archive.torrent"; + hash = "sha256-NDCPO4gT4rgfB76HrF/HtaRNzSfpXJUSHbqLqECvkpU="; + }; + dosboxConf = writeText "dosbox.conf" '' + [dosbox] + memsize = 64 + + [cpu] + cputype = pentium + + [autoexec] + imgmount C win2k.img + imgmount D winxp.iso + boot -l C + ''; + tesseractScript = writeShellScript "tesseractScript" '' + export OMP_THREAD_LIMIT=1 + cd $(mktemp -d) + TEXT="" + while true + do + sleep 3 + ${vncdo}/bin/vncdo -s 127.0.0.1::5900 capture cap.png + NEW_TEXT="$(${tesseract}/bin/tesseract cap.png stdout 2>/dev/null)" + if [ "$TEXT" != "$NEW_TEXT" ]; then + echo OCR "$NEW_TEXT" + TEXT="$NEW_TEXT" + fi + done + ''; + expectScript = let + vncdoWrapper = writeScript "vncdoWrapper" '' + sleep 3 + ${vncdo}/bin/vncdo --force-caps -s 127.0.0.1::5900 "$@" + ''; + in writeScript "expect.sh" '' + #!${expect}/bin/expect -f + set debug 5 + set timeout -1 + spawn ${tesseractScript} + expect "Log 0n to Windows" + exec ${vncdoWrapper} key enter + expect "Getting started with" + exec ${vncdoWrapper} pause 3 key alt-f4 pause 3 key ctrl-esc pause 3 key r pause 3 type cmd.exe key enter + expect " Copyright 1985-1999 Microsoft Corp" + exec ${vncdoWrapper} type "d:" key enter type "setup" key enter + expect "Welcome to Microsoft Windows XP" + exec ${vncdoWrapper} key i + expect "Welcome to Windows Setup" + exec ${vncdoWrapper} key enter + expect "License Agreement" + exec ${vncdoWrapper} key tab key enter + expect "Your Product Key" + exec ${vncdoWrapper} type mrx3f type 47b9t type 2487j type kwkmf type rpwby key enter + expect "Get Updated Setup Files" + exec ${vncdoWrapper} key down key enter + expect "TODO" + exec ${vncdoWrapper} TODO + expect "TODO" + send_user "\n### OMG DID IT WORK???!!!! ###\n" + exit 0 + ''; + installedImage = runCommand "winxp.img" { + # set __impure = true; for debugging + __impure = true; + buildInputs = [ dosbox-x xvfb-run x11vnc ]; + passthru = rec { + makeRunScript = callPackage ./run.nix; + runScript = makeRunScript { }; + }; + } '' + echo "winxp-installer src: ${winxp-installer}" + cp --no-preserve=mode ${winxp-installer}/*.iso winxp.iso + cp --no-preserve=mode ${win2k} win2k.img + runDosboxVnc() { + xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true & + dosboxPID=$! + DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 & + } + ${expectScript} & + expectScriptPID=$! + for stage in $(seq 100); do + echo STAGE $stage + runDosboxVnc + wait $dosboxPID + done + wait $expectScriptPID + cp win2k.img $out + ''; + postInstalledImage = let + dosboxConf-postInstall = writeText "dosbox.conf" '' + [cpu] + turbo=on + stop turbo on key = false + + [autoexec] + imgmount C winxp.img + ${dosPostInstall} + exit + ''; + in runCommand "winxp.img" { + buildInputs = [ dosbox-x ]; + inherit (installedImage) passthru; + } '' + cp --no-preserve=mode ${installedImage} ./winxp.img + SDL_VIDEODRIVER=dummy dosbox-x -conf ${dosboxConf-postInstall} + mv winxp.img $out + ''; +in if (dosPostInstall != "") then postInstalledImage else installedImage diff --git a/makeWinXPImage/run.nix b/makeWinXPImage/run.nix new file mode 100644 index 0000000..e596d8b --- /dev/null +++ b/makeWinXPImage/run.nix @@ -0,0 +1,40 @@ +{ writeShellScriptBin, writeText, lib, dosbox-x, makeWinXPImage +, extraDosboxFlags ? [ ], diskImage ? makeWinXPImage { + dosPostInstall = '' + c: + echo win >> AUTOEXEC.BAT + ''; +} }: +let + dosboxConf = writeText "dosbox.conf" '' + [sdl] + autolock = true + + [autoexec] + imgmount C win2k.img + boot -l C + ''; +in writeShellScriptBin "run-win2k.sh" '' + args=( + -conf ${dosboxConf} + ${lib.concatStringsSep " " extraDosboxFlags} + "$@" + ) + + if [ ! -f winxp.img ]; then + echo "winxp.img not found, making disk image ./winxp.img" + cp --no-preserve=mode ${diskImage} ./winxp.img + fi + + run_dosbox() { + ${dosbox-x}/bin/dosbox-x "''${args[@]}" + } + + run_dosbox + + if [ $? -ne 0 ]; then + echo "Dosbox crashed. Re-running with SDL_VIDEODRIVER=x11." + SDL_VIDEODRIVER=x11 run_dosbox + fi +'' + From 4327cf11ec19dd4102ba5cea04e5a7f37fc0eee3 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Mon, 1 Jan 2024 18:22:01 -0500 Subject: [PATCH 12/28] Stash changes --- makeWinXPImage/answers.nix | 28 ++++++++++++ makeWinXPImage/default.nix | 94 ++++++++++++-------------------------- makeWinXPImage/run.nix | 17 +++---- 3 files changed, 65 insertions(+), 74 deletions(-) create mode 100644 makeWinXPImage/answers.nix diff --git a/makeWinXPImage/answers.nix b/makeWinXPImage/answers.nix new file mode 100644 index 0000000..c404de3 --- /dev/null +++ b/makeWinXPImage/answers.nix @@ -0,0 +1,28 @@ +{ + Data = { + AutoPartition = 1; + MsDosInitiated = "0"; + UnattendedInstall = "Yes"; + }; + Unattended = { + UnattendMode = "FullUnattended"; + OemSkipEula = "Yes"; + OemPreinstall = "No"; + TargetPath = "WINDOWS"; + }; + GuiUnattended = { + AdminPassword = "*"; + EncryptedAdminPassword = "NO"; + OEMSkipRegional = 1; + TimeZone = 4; + OemSkipWelcome = 1; + }; + UserData = { + ProductKey = "MRX3F-47B9T-2487J-KWKMF-RPWBY"; + FullName = "user"; + OrgName = "NixThePlanet"; + ComputerName = "*"; + }; + Identification.JoinWorkgroup = "WORKGROUP"; + Networking.InstallDefaultComponents = "Yes"; +} diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index 9478ae5..dbac9aa 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -1,7 +1,7 @@ -{ fetchtorrent, runCommand, dosbox-x, xvfb-run, x11vnc, tesseract, expect, vncdo -, writeScript, writeShellScript, writeText, fetchFromGitHub, makeWin2kImage -, callPackage }: -{ dosPostInstall ? "", ... }: +{ lib, fetchtorrent, runCommand, dosbox-x, xvfb-run, x11vnc, writeText +, makeWin2kImage, callPackage }: +{ dosPostInstall ? "", answerFile ? + writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: let win2k = makeWin2kImage { }; winxp-installer = fetchtorrent { @@ -13,60 +13,16 @@ let [dosbox] memsize = 64 + [dos] + ver = 7.0 # Need long filenames support to edit the C drive in autoexec + [cpu] cputype = pentium [autoexec] - imgmount C win2k.img - imgmount D winxp.iso - boot -l C - ''; - tesseractScript = writeShellScript "tesseractScript" '' - export OMP_THREAD_LIMIT=1 - cd $(mktemp -d) - TEXT="" - while true - do - sleep 3 - ${vncdo}/bin/vncdo -s 127.0.0.1::5900 capture cap.png - NEW_TEXT="$(${tesseract}/bin/tesseract cap.png stdout 2>/dev/null)" - if [ "$TEXT" != "$NEW_TEXT" ]; then - echo OCR "$NEW_TEXT" - TEXT="$NEW_TEXT" - fi - done - ''; - expectScript = let - vncdoWrapper = writeScript "vncdoWrapper" '' - sleep 3 - ${vncdo}/bin/vncdo --force-caps -s 127.0.0.1::5900 "$@" - ''; - in writeScript "expect.sh" '' - #!${expect}/bin/expect -f - set debug 5 - set timeout -1 - spawn ${tesseractScript} - expect "Log 0n to Windows" - exec ${vncdoWrapper} key enter - expect "Getting started with" - exec ${vncdoWrapper} pause 3 key alt-f4 pause 3 key ctrl-esc pause 3 key r pause 3 type cmd.exe key enter - expect " Copyright 1985-1999 Microsoft Corp" - exec ${vncdoWrapper} type "d:" key enter type "setup" key enter - expect "Welcome to Microsoft Windows XP" - exec ${vncdoWrapper} key i - expect "Welcome to Windows Setup" - exec ${vncdoWrapper} key enter - expect "License Agreement" - exec ${vncdoWrapper} key tab key enter - expect "Your Product Key" - exec ${vncdoWrapper} type mrx3f type 47b9t type 2487j type kwkmf type rpwby key enter - expect "Get Updated Setup Files" - exec ${vncdoWrapper} key down key enter - expect "TODO" - exec ${vncdoWrapper} TODO - expect "TODO" - send_user "\n### OMG DID IT WORK???!!!! ###\n" - exit 0 + imgmount c win2k.img + imgmount d winxp.iso + boot -l c ''; installedImage = runCommand "winxp.img" { # set __impure = true; for debugging @@ -80,29 +36,35 @@ let echo "winxp-installer src: ${winxp-installer}" cp --no-preserve=mode ${winxp-installer}/*.iso winxp.iso cp --no-preserve=mode ${win2k} win2k.img - runDosboxVnc() { - xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true & - dosboxPID=$! - DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 & - } - ${expectScript} & - expectScriptPID=$! + cp --no-preserve=mode ${answerFile} answers.ini + SDL_VIDEODRIVER=dummy dosbox-x -nopromptfolder -hostrun \ + -c 'imgmount c win2k.img' \ + -c 'mount a .' \ + -c 'xcopy a:/answers.ini c:/' \ + -c 'echo d:\\i386\\winnt32.exe /unattend:c:\\answers.ini > "c:/Documents and Settings/All Users/Start Menu/Programs/Startup/start-xp-install.bat"' \ + -c 'exit' + false + rm -f answers.ini + ( + while true; do + DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 || true + echo RESTARTING VNC + done + ) & for stage in $(seq 100); do echo STAGE $stage - runDosboxVnc - wait $dosboxPID + xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true done - wait $expectScriptPID cp win2k.img $out ''; postInstalledImage = let dosboxConf-postInstall = writeText "dosbox.conf" '' [cpu] - turbo=on + turbo = on stop turbo on key = false [autoexec] - imgmount C winxp.img + imgmount c winxp.img ${dosPostInstall} exit ''; diff --git a/makeWinXPImage/run.nix b/makeWinXPImage/run.nix index e596d8b..9cb5026 100644 --- a/makeWinXPImage/run.nix +++ b/makeWinXPImage/run.nix @@ -1,20 +1,21 @@ { writeShellScriptBin, writeText, lib, dosbox-x, makeWinXPImage -, extraDosboxFlags ? [ ], diskImage ? makeWinXPImage { - dosPostInstall = '' - c: - echo win >> AUTOEXEC.BAT - ''; -} }: +, extraDosboxFlags ? [ ], diskImage ? makeWinXPImage { } }: let dosboxConf = writeText "dosbox.conf" '' + [dosbox] + memsize = 64 + + [cpu] + cputype = pentium + [sdl] autolock = true [autoexec] - imgmount C win2k.img + imgmount C winxp.img boot -l C ''; -in writeShellScriptBin "run-win2k.sh" '' +in writeShellScriptBin "run-winxp.sh" '' args=( -conf ${dosboxConf} ${lib.concatStringsSep " " extraDosboxFlags} From ef97a06ca252e94e69b955f8d7ed073df7d63f34 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:49:32 -0500 Subject: [PATCH 13/28] winxp: fix win2k bootstrap --- makeWinXPImage/default.nix | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index dbac9aa..fb25b0f 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -1,3 +1,5 @@ +# The installer from DOS (winnt.exe) doesn't work, so use winnt32.exe from Windows 2000 + { lib, fetchtorrent, runCommand, dosbox-x, xvfb-run, x11vnc, writeText , makeWin2kImage, callPackage }: { dosPostInstall ? "", answerFile ? @@ -13,15 +15,13 @@ let [dosbox] memsize = 64 - [dos] - ver = 7.0 # Need long filenames support to edit the C drive in autoexec - [cpu] cputype = pentium [autoexec] imgmount c win2k.img imgmount d winxp.iso + imgmount e winxp.img boot -l c ''; installedImage = runCommand "winxp.img" { @@ -36,14 +36,22 @@ let echo "winxp-installer src: ${winxp-installer}" cp --no-preserve=mode ${winxp-installer}/*.iso winxp.iso cp --no-preserve=mode ${win2k} win2k.img + # Copy answer file to win2k.img and add autostart script that runs the XP installer cp --no-preserve=mode ${answerFile} answers.ini - SDL_VIDEODRIVER=dummy dosbox-x -nopromptfolder -hostrun \ - -c 'imgmount c win2k.img' \ - -c 'mount a .' \ - -c 'xcopy a:/answers.ini c:/' \ - -c 'echo d:\\i386\\winnt32.exe /unattend:c:\\answers.ini > "c:/Documents and Settings/All Users/Start Menu/Programs/Startup/start-xp-install.bat"' \ - -c 'exit' - false + SDL_VIDEODRIVER=dummy dosbox-x -conf ${ + writeText "dosbox.conf" '' + [dos] + ver = 7.0 # Need long filenames support to edit the C drive in autoexec + + [autoexec] + imgmake winxp.img -t hd_2gig + imgmount c win2k.img + mount a . + xcopy a:/answers.ini c:/ + echo d:\i386\winnt32.exe /unattend:c:\answers.ini > "c:\Documents and Settings\All Users\Start Menu\Programs\Startup\start-xp-install.bat" + exit + '' + } rm -f answers.ini ( while true; do @@ -55,7 +63,7 @@ let echo STAGE $stage xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true done - cp win2k.img $out + cp winxp.img $out ''; postInstalledImage = let dosboxConf-postInstall = writeText "dosbox.conf" '' From 2158295decdb9826c8495cebcf700d15551d31ec Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Thu, 4 Jan 2024 19:18:26 -0500 Subject: [PATCH 14/28] winxp: actually installs successfully now! --- makeWin2kImage/default.nix | 3 ++ makeWinXPImage/default.nix | 79 ++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 61ce47d..21edc13 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -93,6 +93,9 @@ let [dosbox] memsize = 32 + [dos] + ver = 8.0 + [autoexec] imgmount c win2k.img ${dosPostInstall} diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index fb25b0f..3c4508c 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -1,7 +1,7 @@ # The installer from DOS (winnt.exe) doesn't work, so use winnt32.exe from Windows 2000 -{ lib, fetchtorrent, runCommand, dosbox-x, xvfb-run, x11vnc, writeText -, makeWin2kImage, callPackage }: +{ lib, fetchtorrent, runCommand, p7zip, cdrkit, dosbox-x, xvfb-run, x11vnc +, writeText, makeWin2kImage, callPackage }: { dosPostInstall ? "", answerFile ? writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: let @@ -13,46 +13,73 @@ let }; dosboxConf = writeText "dosbox.conf" '' [dosbox] - memsize = 64 + memsize = 128 + machine = svga_s3trio64v+ + + [dos] + ver = 8.0 [cpu] - cputype = pentium + cputype = ppro_slow + core = dynamic_rec + cycles = max + + [serial] + serial1 = disabled + serial2 = disabled + serial3 = disabled + serial4 = disabled + serial5 = disabled + serial6 = disabled + serial7 = disabled + serial8 = disabled + serial9 = disabled + + [parallel] + parallel1 = disabled + parallel2 = disabled + parallel3 = disabled + parallel4 = disabled + parallel5 = disabled + parallel6 = disabled + parallel7 = disabled + parallel8 = disabled + parallel9 = disabled + dongle = false [autoexec] imgmount c win2k.img imgmount d winxp.iso - imgmount e winxp.img boot -l c ''; installedImage = runCommand "winxp.img" { # set __impure = true; for debugging __impure = true; - buildInputs = [ dosbox-x xvfb-run x11vnc ]; + buildInputs = [ p7zip cdrkit dosbox-x xvfb-run x11vnc ]; passthru = rec { makeRunScript = callPackage ./run.nix; runScript = makeRunScript { }; }; } '' - echo "winxp-installer src: ${winxp-installer}" - cp --no-preserve=mode ${winxp-installer}/*.iso winxp.iso + ln -s ${winxp-installer}/*.iso winxp.iso cp --no-preserve=mode ${win2k} win2k.img - # Copy answer file to win2k.img and add autostart script that runs the XP installer cp --no-preserve=mode ${answerFile} answers.ini - SDL_VIDEODRIVER=dummy dosbox-x -conf ${ - writeText "dosbox.conf" '' - [dos] - ver = 7.0 # Need long filenames support to edit the C drive in autoexec + # Copy answer file to win2k.img and add autostart script that runs the XP installer + ( + SDL_VIDEODRIVER=dummy dosbox-x -conf ${ + writeText "dosbox.conf" '' + [dos] + ver = 8.0 # Need long filenames support to edit the C drive in autoexec - [autoexec] - imgmake winxp.img -t hd_2gig - imgmount c win2k.img - mount a . - xcopy a:/answers.ini c:/ - echo d:\i386\winnt32.exe /unattend:c:\answers.ini > "c:\Documents and Settings\All Users\Start Menu\Programs\Startup\start-xp-install.bat" - exit - '' - } - rm -f answers.ini + [autoexec] + mount a . + imgmount c win2k.img + copy a:\answers.ini c:\ + echo d:\i386\winnt32.exe /unattend:c:\answers.ini /debug4:c:\log.txt /dudisable > "c:\Documents and Settings\All Users\Start Menu\Programs\Startup\start-xp-install.bat" + exit + '' + } + ) ( while true; do DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 || true @@ -63,7 +90,8 @@ let echo STAGE $stage xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true done - cp winxp.img $out + mkdir $out + cp win2k.img $out ''; postInstalledImage = let dosboxConf-postInstall = writeText "dosbox.conf" '' @@ -71,6 +99,9 @@ let turbo = on stop turbo on key = false + [dos] + ver = 8.0 + [autoexec] imgmount c winxp.img ${dosPostInstall} From 98ee0a6461fe28d3dcf8ae0cf2b1419aad56dd59 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:06:42 -0500 Subject: [PATCH 15/28] winxp: remove unneeded dosbox options --- makeWinXPImage/default.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index 3c4508c..30ec170 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -21,8 +21,6 @@ let [cpu] cputype = ppro_slow - core = dynamic_rec - cycles = max [serial] serial1 = disabled From 578aeb6e3b6c90b76e020ecba798eebabc28a363 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:07:09 -0500 Subject: [PATCH 16/28] winxp: remove unneeeded winnt32.exe flags --- makeWinXPImage/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index 30ec170..ad37509 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -73,7 +73,7 @@ let mount a . imgmount c win2k.img copy a:\answers.ini c:\ - echo d:\i386\winnt32.exe /unattend:c:\answers.ini /debug4:c:\log.txt /dudisable > "c:\Documents and Settings\All Users\Start Menu\Programs\Startup\start-xp-install.bat" + echo d:\i386\winnt32.exe /unattend:c:\answers.ini > "c:\Documents and Settings\All Users\Start Menu\Programs\Startup\start-xp-install.bat" exit '' } From 8782d4ca07ae7a93ad1d0a6006a34689b43929e7 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Thu, 4 Jan 2024 22:07:31 -0500 Subject: [PATCH 17/28] winxp: set number of stages --- makeWinXPImage/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index ad37509..abadc7a 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -84,7 +84,7 @@ let echo RESTARTING VNC done ) & - for stage in $(seq 100); do + for stage in $(seq 3); do echo STAGE $stage xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true done From 2c9ab82e7cb5ef548a2a3511b20677fcf02d1e8c Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Fri, 5 Jan 2024 01:00:06 -0500 Subject: [PATCH 18/28] winxp: remove unneeded machine key in config --- makeWinXPImage/default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index abadc7a..958f1c6 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -14,7 +14,6 @@ let dosboxConf = writeText "dosbox.conf" '' [dosbox] memsize = 128 - machine = svga_s3trio64v+ [dos] ver = 8.0 From a2b4979e2972bd29b623fada4588aa403eccf2e9 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Fri, 5 Jan 2024 01:00:29 -0500 Subject: [PATCH 19/28] winxp: remove unneeded serial disables --- makeWinXPImage/default.nix | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index 958f1c6..6d3ffb3 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -21,17 +21,6 @@ let [cpu] cputype = ppro_slow - [serial] - serial1 = disabled - serial2 = disabled - serial3 = disabled - serial4 = disabled - serial5 = disabled - serial6 = disabled - serial7 = disabled - serial8 = disabled - serial9 = disabled - [parallel] parallel1 = disabled parallel2 = disabled From fa6474eeb461bcee0048ec0238eb8a685b27077f Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:17:20 -0500 Subject: [PATCH 20/28] winxp: remove unneeded parallel disables --- makeWinXPImage/default.nix | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index 6d3ffb3..b70389c 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -21,18 +21,6 @@ let [cpu] cputype = ppro_slow - [parallel] - parallel1 = disabled - parallel2 = disabled - parallel3 = disabled - parallel4 = disabled - parallel5 = disabled - parallel6 = disabled - parallel7 = disabled - parallel8 = disabled - parallel9 = disabled - dongle = false - [autoexec] imgmount c win2k.img imgmount d winxp.iso From e69eaae77a95630af8afa3608ddad5107c0cd2bd Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Fri, 5 Jan 2024 19:45:40 -0500 Subject: [PATCH 21/28] winxp: disable drive data rate limit --- makeWinXPImage/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index b70389c..0e5cfcc 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -17,9 +17,12 @@ let [dos] ver = 8.0 + hard drive data rate limit = 0 + floppy drive data rate limit = 0 [cpu] cputype = ppro_slow + turbo = off # TODO: enable after stage 1 [autoexec] imgmount c win2k.img From 7116ed7fed0137f0b1b8b2dc67b02856dd969709 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Fri, 5 Jan 2024 21:42:59 -0500 Subject: [PATCH 22/28] win2k: remove dos.ver --- makeWin2kImage/default.nix | 3 --- 1 file changed, 3 deletions(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 21edc13..61ce47d 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -93,9 +93,6 @@ let [dosbox] memsize = 32 - [dos] - ver = 8.0 - [autoexec] imgmount c win2k.img ${dosPostInstall} From 350b0b3959fedc73df7f64d39afb490cbae5da82 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sat, 6 Jan 2024 03:16:12 -0500 Subject: [PATCH 23/28] winxp: add tesseract and use smaller image --- makeWin2kImage/default.nix | 4 +- makeWinXPImage/default.nix | 77 +++++++++++++++++++++++++------------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/makeWin2kImage/default.nix b/makeWin2kImage/default.nix index 61ce47d..c9f5189 100644 --- a/makeWin2kImage/default.nix +++ b/makeWin2kImage/default.nix @@ -5,7 +5,7 @@ { lib, fetchurl, runCommand, p7zip, dosbox-x, x11vnc, tesseract, vncdo, xvfb-run , writeText, writeShellScript, callPackage }: -{ dosPostInstall ? "", answerFile ? +{ dosPostInstall ? "", imageType ? "hd_1gig", answerFile ? writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: let win2k-installer = fetchurl { @@ -33,7 +33,7 @@ let [autoexec] mount a . - if not exist a:\win2k.img imgmake win2k.img -t hd_1gig + if not exist a:\win2k.img imgmake win2k.img -t ${imageType} imgmount c win2k.img -t hdd imgmount d win2k.iso if not exist c:\ntldr d:\i386\winnt /s:d: /u:a:answers.ini diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index 0e5cfcc..1809fcb 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -1,38 +1,61 @@ # The installer from DOS (winnt.exe) doesn't work, so use winnt32.exe from Windows 2000 -{ lib, fetchtorrent, runCommand, p7zip, cdrkit, dosbox-x, xvfb-run, x11vnc -, writeText, makeWin2kImage, callPackage }: +{ lib, fetchtorrent, runCommand, dosbox-x, xvfb-run, x11vnc, vncdo, tesseract +, writeText, writeShellScript, makeWin2kImage, callPackage }: { dosPostInstall ? "", answerFile ? writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: let - win2k = makeWin2kImage { }; + win2k = makeWin2kImage { imageType = "hd_2gig"; }; winxp-installer = fetchtorrent { url = "https://archive.org/download/WinXPProSP3x86/WinXPProSP3x86_archive.torrent"; hash = "sha256-NDCPO4gT4rgfB76HrF/HtaRNzSfpXJUSHbqLqECvkpU="; }; - dosboxConf = writeText "dosbox.conf" '' - [dosbox] - memsize = 128 + dosboxConf = stage: + writeText "dosbox.conf" '' + [dosbox] + memsize = 128 - [dos] - ver = 8.0 - hard drive data rate limit = 0 - floppy drive data rate limit = 0 + [dos] + ver = 7.0 # Need long filenames support to edit the C drive in autoexec + hard drive data rate limit = 0 + floppy drive data rate limit = 0 - [cpu] - cputype = ppro_slow - turbo = off # TODO: enable after stage 1 + [cpu] + cputype = ppro_slow + # Turbo breaks win2k boot so disable during the win2k boostrap + # TODO: turbo = ${if stage == 1 then "off" else "on"} - [autoexec] - imgmount c win2k.img - imgmount d winxp.iso - boot -l c + [autoexec] + imgmount c win2k.img + imgmount d winxp.iso + ${lib.optionalString (stage == 2) '' + # After the XP install is bootstrapped, remove the old Windows 2000 files to make space for XP + deltree /y c:\WINDOWS + deltree /y "c:\Documents and Settings" + deltree /y "c:\Program Files" + ''} + boot -l c + ''; + tesseractScript = writeShellScript "tesseractScript" '' + export OMP_THREAD_LIMIT=1 + cd $(mktemp -d) + TEXT="" + while true + do + sleep 3 + ${vncdo}/bin/vncdo -s 127.0.0.1::5900 capture cap.png + NEW_TEXT="$(${tesseract}/bin/tesseract cap.png stdout 2>/dev/null)" + if [ "$TEXT" != "$NEW_TEXT" ]; then + echo "$NEW_TEXT" + TEXT="$NEW_TEXT" + fi + done ''; installedImage = runCommand "winxp.img" { # set __impure = true; for debugging __impure = true; - buildInputs = [ p7zip cdrkit dosbox-x xvfb-run x11vnc ]; + buildInputs = [ dosbox-x xvfb-run x11vnc ]; passthru = rec { makeRunScript = callPackage ./run.nix; runScript = makeRunScript { }; @@ -46,7 +69,7 @@ let SDL_VIDEODRIVER=dummy dosbox-x -conf ${ writeText "dosbox.conf" '' [dos] - ver = 8.0 # Need long filenames support to edit the C drive in autoexec + ver = 7.0 # Need long filenames support to edit the C drive in autoexec [autoexec] mount a . @@ -63,10 +86,15 @@ let echo RESTARTING VNC done ) & - for stage in $(seq 3); do - echo STAGE $stage - xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true - done + ${tesseractScript} & + # TODO: + # The following list shows the existing partitions + # ENTER-Install + ${lib.strings.concatMapStrings (stage: '' + echo STAGE ${toString stage} + xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" \ + dosbox-x -conf ${dosboxConf stage} || true + '') (lib.range 1 3)} mkdir $out cp win2k.img $out ''; @@ -76,9 +104,6 @@ let turbo = on stop turbo on key = false - [dos] - ver = 8.0 - [autoexec] imgmount c winxp.img ${dosPostInstall} From 89f23b31253a966dcc8d418664cde01c9031a229 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sat, 6 Jan 2024 03:28:57 -0500 Subject: [PATCH 24/28] winxp: add expect script --- makeWinXPImage/default.nix | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index 1809fcb..f1f2790 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -1,7 +1,8 @@ # The installer from DOS (winnt.exe) doesn't work, so use winnt32.exe from Windows 2000 { lib, fetchtorrent, runCommand, dosbox-x, xvfb-run, x11vnc, vncdo, tesseract -, writeText, writeShellScript, makeWin2kImage, callPackage }: +, expect, writeText, writeShellScript, writeScript, makeWin2kImage, callPackage +}: { dosPostInstall ? "", answerFile ? writeText "answers.ini" (lib.generators.toINI { } (import ./answers.nix)) }: let @@ -52,6 +53,21 @@ let fi done ''; + expectScript = let + vncdoWrapper = writeScript "vncdoWrapper" '' + sleep 3 + ${vncdo}/bin/vncdo --force-caps -s 127.0.0.1::5900 "$@" + ''; + in writeScript "expect.sh" '' + #!${expect}/bin/expect -f + set debug 5 + set timeout -1 + spawn ${tesseractScript} + expect "ENTER-Install" + exec ${vncdoWrapper} key enter + # Keep running until killed so the entire build gets tesseract log output + while { 1 } { sleep 10000 } + ''; installedImage = runCommand "winxp.img" { # set __impure = true; for debugging __impure = true; @@ -86,10 +102,7 @@ let echo RESTARTING VNC done ) & - ${tesseractScript} & - # TODO: - # The following list shows the existing partitions - # ENTER-Install + ${expectScript} & ${lib.strings.concatMapStrings (stage: '' echo STAGE ${toString stage} xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" \ From 5425c9df0dee371beab50012459212258eb713c6 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sat, 6 Jan 2024 20:59:30 -0500 Subject: [PATCH 25/28] winxp: remove __impure --- makeWinXPImage/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index f1f2790..fa01e1b 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -70,7 +70,7 @@ let ''; installedImage = runCommand "winxp.img" { # set __impure = true; for debugging - __impure = true; + # __impure = true; buildInputs = [ dosbox-x xvfb-run x11vnc ]; passthru = rec { makeRunScript = callPackage ./run.nix; From 177ba30f76ff1b505631cdf7dc5aa82255ee54e0 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 7 Jan 2024 00:37:48 -0500 Subject: [PATCH 26/28] winxp: don't put output in directory --- makeWinXPImage/default.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index fa01e1b..a6f8913 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -108,7 +108,6 @@ let xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" \ dosbox-x -conf ${dosboxConf stage} || true '') (lib.range 1 3)} - mkdir $out cp win2k.img $out ''; postInstalledImage = let From f9a0414d2a7ca92f63663f35eb4ccc7f2c480831 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 7 Jan 2024 00:38:16 -0500 Subject: [PATCH 27/28] winxp: run: upgrade memsize and cputype --- makeWinXPImage/run.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makeWinXPImage/run.nix b/makeWinXPImage/run.nix index 9cb5026..336ff30 100644 --- a/makeWinXPImage/run.nix +++ b/makeWinXPImage/run.nix @@ -3,10 +3,10 @@ let dosboxConf = writeText "dosbox.conf" '' [dosbox] - memsize = 64 + memsize = 128 [cpu] - cputype = pentium + cputype = ppro_slow [sdl] autolock = true From bdf934a32797b0f36554ec3a6db225b0c9f84212 Mon Sep 17 00:00:00 2001 From: Benjamin Levy <7348004+io12@users.noreply.github.com> Date: Sun, 7 Jan 2024 00:43:21 -0500 Subject: [PATCH 28/28] winxp: enable turbo in middle part --- makeWinXPImage/default.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/makeWinXPImage/default.nix b/makeWinXPImage/default.nix index a6f8913..afe13c2 100644 --- a/makeWinXPImage/default.nix +++ b/makeWinXPImage/default.nix @@ -24,8 +24,8 @@ let [cpu] cputype = ppro_slow - # Turbo breaks win2k boot so disable during the win2k boostrap - # TODO: turbo = ${if stage == 1 then "off" else "on"} + # Turbo breaks win2k boot and final stage + turbo = ${if builtins.elem stage [ 1 3 ] then "off" else "on"} [autoexec] imgmount c win2k.img