Skip to content

Commit

Permalink
Implement makeWin98Image
Browse files Browse the repository at this point in the history
  • Loading branch information
io12 committed Dec 21, 2023
1 parent 3f14942 commit fd70987
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ Each of the outputs in this flake have their own image builders and `runScript`.
- `makeMsDos622Image`
- `makeWin30Image`
- `makeWfwg311Image`
- `makeWin98Image`

They can each be passed the `dosPostInstall` argument arbitrary **dos
commands** to be ran after Windows has been installed, for example here's how
Expand Down
7 changes: 7 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
makeMsDos622Image = pkgs.callPackage ./makeMsDos622Image {};
makeWin30Image = pkgs.callPackage ./makeWin30Image {};
makeWfwg311Image = pkgs.callPackage ./makeWfwg311Image {};
makeWin98Image = pkgs.callPackage ./makeWin98Image {};
# makeSystem7Image = pkgs.callPackage ./makeSystem7Image {};
};
apps = {
Expand All @@ -78,14 +79,20 @@
type = "app";
program = config.packages.wfwg311-image.runScript;
};
win98 = {
type = "app";
program = config.packages.win98-image.runScript;
};
};
packages = rec {
macos-ventura-image = config.legacyPackages.makeDarwinImage {};
msdos622-image = config.legacyPackages.makeMsDos622Image {};
win30-image = config.legacyPackages.makeWin30Image {};
wfwg311-image = config.legacyPackages.makeWfwg311Image {};
win98-image = config.legacyPackages.makeWin98Image {};
#system7-image = config.legacyPackages.makeSystem7Image {};
#macos-repeatability-test = genOverridenDrvLinkFarm (macos-ventura-image.overrideAttrs { repeatabilityTest = true; }) 3;
win98-repeatability-test = genOverridenDrvLinkFarm win98-image 100;
wfwg311-repeatability-test = genOverridenDrvLinkFarm wfwg311-image 100;
win30-repeatability-test = genOverridenDrvLinkFarm win30-image 100;
msDos622-repeatability-test = genOverridenDrvLinkFarm msdos622-image 100;
Expand Down
188 changes: 188 additions & 0 deletions makeWin98Image/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# https://dosbox-x.com/wiki/Guide%3AInstalling-Windows-98#_installation_method_2

{ lib, fetchurl, runCommand, p7zip, dosbox-x, xvfb-run, x11vnc, tesseract
, expect, vncdo, imagemagick, writeScript, writeShellScript, writeText
, fetchFromGitHub, callPackage }:
{ dosPostInstall ? "", ... }:
let
win98-installer = fetchurl {
name = "win98.7z";
urls = [
"https://winworldpc.com/download/c3b4c382-3210-e280-9d7b-11c3a4c2ac5a/from/c39ac2af-c381-c2bf-1b25-11c3a4e284a2"
"https://winworldpc.com/download/c3b4c382-3210-e280-9d7b-11c3a4c2ac5a/from/c3ae6ee2-8099-713d-3411-c3a6e280947e"
"https://cloudflare-ipfs.com/ipfs/QmTTNMpQALDzioSNdDJyr94rkz5tHoAHCDa155fvHyJb4L/Microsoft%20Windows%2098%20Second%20Edition%20(4.10.2222)%20(Retail%20Full).7z"
];
hash = "sha256-47M3azg2ikc7VlFTEJA7elPGovAtSmhOtZqq8j2TJmU=";
};
dosboxConf = writeText "dosbox.conf" ''
[cpu]
turbo=on
stop turbo on key = false
[autoexec]
if exist win98.img (
imgmount c win98.img
boot c:
) else (
imgmake win98.img -t hd_520
imgmount c win98.img -t hdd -fs fat
imgmount d win98.iso
xcopy d:\win98 c:\win98 /i /e
c:
cd \win98
setup
)
'';
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)"
echo "$NEW_TEXT"
TEXT="$NEW_TEXT"
done
'';
expectScript = let
vncdoWrapper = writeScript "vncdoWrapper" ''
sleep 3
echo VNCDO "$@" >2
${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 "To continue, press ENTER"
exec ${vncdoWrapper} key enter
expect "click Continue"
exec ${vncdoWrapper} key enter
expect "License Agreement"
send_user "\n### LICENSE AGREEMENT ###\n"
exec ${vncdoWrapper} key tab key enter
expect "Windows Product Key"
send_user "\n### PRODUCT KEY ###\n"
${lib.strings.concatMapStrings (c: ''
exec ${vncdoWrapper} key ${c}
'') (lib.strings.stringToCharacters "w7xtc2ywfbk6bptgmhmvb6fdy")}
exec ${vncdoWrapper} key enter
expect "Select Directory"
expect "other than the default"
send_user "\n### SELECT INSTALL DIR ###\n"
exec ${vncdoWrapper} key enter
expect "Setup Options"
send_user "\n### SETUP OPTIONS ###\n"
exec ${vncdoWrapper} key enter
expect "User Information"
send_user "\n### USER INFORMATION ###\n"
exec ${vncdoWrapper} type admin key enter
expect "Windows Components"
send_user "\n### WINDOWS COMPONENTS ###\n"
exec ${vncdoWrapper} key enter
expect "Identification"
send_user "\n### IDENTIFICATION ###\n"
exec ${vncdoWrapper} key enter
expect "Establishing Your Location"
send_user "\n### ESTABLISHING YOUR LOCATION ###\n"
exec ${vncdoWrapper} key enter
expect "Start Copying Files"
send_user "\n### START COPYING FILES ###\n"
exec ${vncdoWrapper} key enter
expect "Date/Time Properties"
send_user "\n### DATE/TIME PROPERTIES ###\n"
exec ${vncdoWrapper} key enter
expect "Enter Windows Password"
send_user "\n### ENTER WINDOWS PASSWORD ###\n"
exec ${vncdoWrapper} key enter
expect "Recycle Bin"
set opening_start_menu 1
while { $opening_start_menu } {
send_user "\n### TRYING TO OPEN START MENU ###\n"
exec ${vncdoWrapper} pause 10 key ctrl-esc
set timeout 10
expect {
"Programs" {
send_user "\n### OPENED START MENU ###\n"
set opening_start_menu 0
}
"Recycle Bin" {
send_user "\n### START MENU NOT OPENED YET (recycle bin) ###\n"
}
timeout {
send_user "\n### START MENU NOT OPENED YET (timeout) ###\n"
}
}
set timeout -1
}
send_user "\n### OPENING SHUT DOWN PROMPT ###\n"
exec ${vncdoWrapper} key u
send_user "\n### TRIGGERING SHUTDOWN ###\n"
exec ${vncdoWrapper} key enter
send_user "\n### OMG DID IT WORK???!!!! ###\n"
exit 0 '';
iso = runCommand "win98.iso" { } ''
echo "win98-installer src: ${win98-installer}"
mkdir win98
${p7zip}/bin/7z x -owin98 ${win98-installer}
ls -lah win98
mv win98/*.iso $out
'';
installedImage = runCommand "win98.img" {
# set __impure = true; for debugging
# __impure = true;
buildInputs = [ p7zip dosbox-x xvfb-run x11vnc ];
passthru = rec {
makeRunScript = callPackage ./run.nix;
runScript = makeRunScript { };
};
} ''
echo "iso src: ${iso}"
cp --no-preserve=mode ${iso} win98.iso
(
while true; do
DISPLAY=:99 XAUTHORITY=/tmp/xvfb.auth x11vnc -many -shared -display :99 >/dev/null 2>&1 || true
echo RESTARTING VNC
done
) &
runDosbox() {
xvfb-run -l -s ":99 -auth /tmp/xvfb.auth -ac -screen 0 800x600x24" dosbox-x -conf ${dosboxConf} || true &
dosboxPID=$!
}
echo STAGE 1
runDosbox
${expectScript} &
expectScriptPID=$!
wait $dosboxPID
# Run dosbox-x a second time since it exits during the install
echo STAGE 2
runDosbox
wait $dosboxPID
echo DOSBOX EXITED
wait $expectScriptPID
cp win98.img $out
'';
postInstalledImage = let
dosboxConf-postInstall = writeText "dosbox.conf" ''
[cpu]
turbo=on
stop turbo on key = false
[autoexec]
imgmount c win98.img
${dosPostInstall}
exit
'';
in runCommand "win98.img" {
buildInputs = [ dosbox-x ];
inherit (installedImage) passthru;
} ''
cp --no-preserve=mode ${installedImage} ./win98.img
SDL_VIDEODRIVER=dummy dosbox-x -conf ${dosboxConf-postInstall}
mv win98.img $out
'';
in if (dosPostInstall != "") then postInstalledImage else installedImage
40 changes: 40 additions & 0 deletions makeWin98Image/run.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{ writeShellScriptBin, writeText, lib, dosbox-x, makeWin98Image
, extraDosboxFlags ? [ ], diskImage ? makeWin98Image {
dosPostInstall = ''
c:
echo win >> AUTOEXEC.BAT
'';
} }:
let
dosboxConf = writeText "dosbox.conf" ''
[sdl]
autolock = true
[autoexec]
imgmount C win98.img
boot -l C
'';
in writeShellScriptBin "run-win98.sh" ''
args=(
-conf ${dosboxConf}
${lib.concatStringsSep " " extraDosboxFlags}
"$@"
)
if [ ! -f win98.img ]; then
echo "win98.img not found, making disk image ./win98.img"
cp --no-preserve=mode ${diskImage} ./win98.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
''

0 comments on commit fd70987

Please sign in to comment.