# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT # # The Win16 port's Windows: Windows for Workgroups 3.11 set up on a DOSBox # Staging PC (scripts/dosbox-win16.conf) as a host folder that is drive C:, # for the win311 component. Sourced, not executed. # # Windows is not downloaded from anywhere: its files are private ones # (installer/files.sha1), the owner's install disc and display driver disk, # brought in with ./install.sh import or the private bundle. From them: # # 1. Windows' own Setup runs unattended in DOSBox (SETUP /H: with the # answers in win16SetupAnswers): no network, the stock VGA driver and # PS/2 mouse, nothing optional, Setup back to DOS at the end. Then the # Sound Blaster 1.5 driver and its virtual device are expanded from the # disc with its own EXPAND.EXE. # 2. The S3 Trio64V+ 1.70.04 driver is put in at 800x600 in 256 colours, # and the Sound Blaster driver turned on, editing SYSTEM.INI the way # the driver disk's OEMSETUP.INF (its D808S profile) and Control Panel # would. The swap file is off. # # The win16 gates and joey-run (scripts/lib/win16Gate.sh) copy the result # for each run and name the program as Windows' shell, so Windows ends when # the program does. Win16 code only ever runs on DOSBox's emulated CPU: # running it natively (the 32-bit Wine's winevdm) crashed the host's kernel. WIN16_FIRMWARE="toolchains/firmware/win16" WIN16_ISO="$WIN16_FIRMWARE/wfw311.iso" WIN16_S3_FILES="S3TRIO.DRV VDDS3764.386 VGA_ENG.3GR" WIN16_DOSBOX_CONF="scripts/dosbox-win16.conf" WIN16_INI_TOOL="tools/winIni.py" # Setup takes about 20 s at full speed. WIN16_SETUP_SECONDS=300 # win16Configure CDIR -- step 2: the S3 driver, the Sound Blaster, no swap # file. win16Configure() { local windows="$1/WINDOWS" local name for name in $WIN16_S3_FILES; do cp "$JOEY_REPO/$WIN16_FIRMWARE/s3/$name" "$windows/SYSTEM/$name" done python3 "$JOEY_REPO/$WIN16_INI_TOOL" "$windows/SYSTEM.INI" \ set boot display.drv s3trio.drv \ set boot 386grabber vga_eng.3gr \ set boot.description display.drv "S3 Trio64V 1.70.04 800x600 256 C SF" \ set 386Enh display vdds3764.386 \ set 386Enh Paging no \ add 386Enh device vsbd.386 \ set DISPLAY dac-type nbt \ set DISPLAY polygon-support on \ set DISPLAY ellipse-support on \ set DISPLAY scache on \ set DISPLAY textrmw 0 \ set DISPLAY fastmmio on \ set DISPLAY screen-size 800 \ set DISPLAY color-format 8 \ set DISPLAY dpi 96 \ set Debug OutputTo NUL \ set drivers wave sndblst2.drv \ set sndblst.drv port 220 \ set sndblst.drv int 7 } # win16Files -- every private file the image is made from. win16Files() { local name printf '%s\n' "$WIN16_ISO" for name in $WIN16_S3_FILES; do printf '%s\n' "$WIN16_FIRMWARE/s3/$name" done } # win16Pin -- changes with the private files and with the recipe. win16Pin() { local file { for file in $(win16Files); do privateSha1For "$file" done declare -f win16Configure win16Prepare win16Setup win16SetupAnswers cat "$JOEY_REPO/$WIN16_DOSBOX_CONF" "$JOEY_REPO/$WIN16_INI_TOOL" } | sha256sum | cut -d' ' -f1 } # win16Prepare OUTDIR -- make OUTDIR/c, Windows set up and configured. win16Prepare() { local out="$1" local build local file for file in $(win16Files); do privateEnsure "$file" done build="$(freshBuildDir "$compId")" mkdir -p "$build/c" win16SetupAnswers > "$build/c/SETUP.SHH" info "setting up Windows for Workgroups 3.11 in DOSBox (unattended)" win16Setup "$build" || die "Windows Setup did not finish; its DOSBox log: $build/dosbox.log" rm -f "$build/c/SETUP.SHH" win16Configure "$build/c" win16Verify "$build/c" || die "the Windows set up in $build/c is incomplete" rm -rf "${out:?}/c" mkdir -p "$out" mv "$build/c" "$out/c" dropBuildDir "$compId" } # win16Setup BUILD -- step 1, on a private display: Setup, then the Sound # Blaster driver off the disc. DOSBox exits when the last command has run. win16Setup() { local build="$1" local windows='C:\WINDOWS\SYSTEM' local xvfb local display local rc Xvfb -displayfd 3 -screen 0 1024x768x24 -nolisten tcp 3> "$build/display" > /dev/null 2>&1 & xvfb=$! for _ in 1 2 3 4 5 6 7 8 9 10; do [ -s "$build/display" ] && break sleep 0.5 done display=":$(cat "$build/display")" XDG_CONFIG_HOME="$build/xdg" DISPLAY="$display" SDL_AUDIODRIVER=dummy \ timeout -s KILL "$WIN16_SETUP_SECONDS" "$JOEY_OPT/dosbox/dosbox" --noprimaryconf --nolocalconf \ --conf "$JOEY_REPO/$WIN16_DOSBOX_CONF" --set "nosound=true" \ -c "MOUNT C \"$build/c\"" \ -c "IMGMOUNT D \"$JOEY_REPO/$WIN16_ISO\" -t iso" \ -c "C:" \ -c 'D:\SETUP /H:C:\SETUP.SHH' \ -c "D:\\EXPAND D:\\SNDBLST2.DR_ $windows\\SNDBLST2.DRV" \ -c "D:\\EXPAND D:\\VSBD.38_ $windows\\VSBD.386" \ -c "EXIT" > "$build/dosbox.log" 2>&1 rc=$? kill "$xvfb" 2> /dev/null || true wait "$xvfb" 2> /dev/null || true [ "$rc" -eq 0 ] && [ -f "$build/c/WINDOWS/WIN.COM" ] } # win16SetupAnswers -- Setup's answer file (SETUP.SHH, the format of the # sample on the disc), CRLF. win16SetupAnswers() { printf '%s\r\n' \ '[sysinfo]' 'showsysinfo=no' '' \ '[configuration]' 'machine=ibm_compatible' 'display=vga' 'mouse=ps2mouse' 'network=nonet' \ 'keyboard=t4s0enha' 'language=enu' 'kblayout=nodll' '' \ '[windir]' 'c:\windows' '' \ '[userinfo]' '"JoeyLib"' '' \ '[dontinstall]' 'accessories' 'readmes' 'games' 'screensavers' 'bitmaps' '' \ '[endinstall]' 'configfiles=save' 'endopt=exit' } # win16Verify CDIR -- Windows is there and set up for the port. win16Verify() { local windows="$1/WINDOWS" local name [ -f "$windows/WIN.COM" ] || return 1 for name in $WIN16_S3_FILES SNDBLST2.DRV VSBD.386; do [ -s "$windows/SYSTEM/$name" ] || return 1 done tr -d '\r' < "$windows/SYSTEM.INI" | grep -qx 'display.drv=s3trio.drv' || return 1 tr -d '\r' < "$windows/SYSTEM.INI" | grep -qx 'wave=sndblst2.drv' }