joncampbell123 / dosbox-x

DOSBox-X fork of the DOSBox project
GNU General Public License v2.0
2.83k stars 383 forks source link

Running Dynamic (contents) Win9x Image in DosBox-X #5292

Closed joeskeen closed 1 hour ago

joeskeen commented 2 days ago

Question

I've been trying to create a solution for running many old software titles from my childhood. As all of these titles ran on Windows 9x or earlier, I'm seeking for a DosBox-based solution. My prototype solution ran Windows 3.1 in normal DosBox, and would have separate dosbox.conf files per game that would mount the shared Windows 3.1 HD, the game disk image, then run the game in Windows using RUNEXIT and finally exit DosBox. This mostly works OK, but comes with a few downsides:

For the last reason listed, I have decided to go with DosBox-X for my next version of this. My vision:

After doing some prototyping, I got the overlayfs to work great. However, when trying to mount the overlayfs mount point directory into DosBox-X, it became clear that I wasn't going to be able to boot into Windows 98 that way, as you can only BOOT into disk image files, not local directories.

So, my next idea was to overlay the filesystem, then copy everything into a disk image, then imgmount the image into DosBox-X, boot, then profit. But unfortunately, I have had a terrible time trying to get this to work as well. Things I've tried:

So my question is, given the aims I listed above, is there any sane way to do this? I was hoping that FAT disk images would more or less work with each other, but DosBox-X seems to hate images created outside of it, and Linux seems to hate images created by DosBox-X. Or is there some way I can mount the directory and run Windows 98 without using an image file?

Have you checked that no similar question(s) exist?

Code of Conduct & Contributing Guidelines

joeskeen commented 2 days ago

FWIW, this is my current script I'm running:

# remove old image if it exists
fusermount -u mnt 2>/dev/null
rm -f 2G.img

truncate -s 2G 2G.img                       # creates the image file
echo 'type=06,bootable' | sfdisk 2G.img     # creates a single bootable partition that takes up the whole disk
sfdisk -l 2G.img                            # shows the partition table
sfdisk -g 2G.img                            # shows the geometry of the disk
mkfs.fat -mbr=y -F 16 2G.img                # formats the partition as FAT
mkdir -p mnt                                # creates a mount point
fusefat -o rw+ -o umask=777 2G.img mnt      # mounts the image with open permissions
cp -r win98se/* mnt                         # copy all files from the directory where the Windows-installed disk image was extracted to
ls -alh mnt                                 # shows the contents of the image - looks great from the Linux side

# When trying to mount the image in DOSBox-X (`imgmount c 2G.img`) , the following error occurs:
# Could not extract drive geometry from image.
# Use parameter -size bps,spc,hpc,cyl to specify the geometry.
# Unable to detect geometry
# 
# so I mount it using:
# imgmount c 2G.img -size 512,63,255,261 -o partidx=1
# 
# This works, kinda, but try running `dir c:` and you'll see that the file names are not there.
# Also, the disk is not bootable, even though fdisk says it is.
Torinde commented 2 days ago

Good initiative! I like the triple layer separation:

  1. base Win9x installation
  2. Win9x + game1/2/3/...
  3. Win9x + game1 + user1/2/3/...
  4. even more levels/branches may be useful, e.g. savestate/snapshot-like capability for each user to go different routes in a game, etc.

You may check if dynamic and differencing VHDs, your requirements seem similar to those for eXoWin9x.

rderooy commented 2 days ago

As you found out, and as documented on the Wiki, you cannot boot from folders. And the support for non-bootable folder mounts when booting an OS in DOSBox-X is limited (any changes will not be saved).

For mounting, I have not had issues with using gnome-disk-image-mounter with mounting FAT images created using imgmake. e.g., as specified on the DOSBox-X wiki:

gnome-disk-image-mounter -w hdd.img

You can umount it as a regular user afterwards.

Alternatively, you can have a script that you run from within DOSBox-X that does the necessary steps. e.g.,

[autoexec]
@echo off
imgmake hdd.img -t hd_2gig
imgmount c hdd.img
IF NOT EXIST C:\WINDOWS\WIN.COM GOTO INSTALL
IMGMOUNT 0 empty -fs none -t floppy -size 512,15,2,80
IMGMOUNT 1 empty -fs none -t floppy -size 512,36,2,80
IMGMOUNT C hdd.img -ide 1m
IMGMOUNT D empty -t iso -ide 2m
boot c:
GOTO END

:INSTALL
cls
echo 1) Windows 98 RTM
echo 2) Windows 98 OEM
echo 3) Windows 98SE OEM
echo 4) Windows 98SE OEM CD-ROM boot
echo.
choice /c:1234 /N Select OS to install

IF ERRORLEVEL == 4 goto CDBOOT
IF ERRORLEVEL == 3 imgmount D "CD/Windows 98 Second Edition.iso" -u
IF ERRORLEVEL == 2 imgmount D "CD/Windows 98 First Edition.iso" -u
IF ERRORLEVEL == 1 imgmount D "CD/Windows_98_retail.iso" -u
GOTO COPY

:CDBOOT
imgmount D "CD/Windows 98 Second Edition.iso"
imgmount A -bootcd D
boot a:
goto END

:COPY
xcopy d:\win98 c:\windows\options\cabs /i /e
c:
cd windows\options\cabs
cls
echo 1) Install using response file
echo 2) Manual installation
echo.
choice /c:12 /N Select option

IF ERRORLEVEL == 2 GOTO DRIVERS

mount x .
copy x:\MSBATCH.INF .
mount x -u

:DRIVERS
cls
echo 1) Copy drivers to C:\DRIVERS
echo 2) Skip copying drivers
echo.
choice /C:12 /N Select option

IF ERRORLEVEL == 2 GOTO SETUP

mount x .
mkdir c:\drivers
xcopy x:\drivers\s3 c:\drivers\s3 /i /e
xcopy x:\drivers\sb c:\drivers\sb /i /e
xcopy x:\drivers\voodoo c:\drivers\voodoo /i /e
mount x -u

:SETUP
echo "Running Windows 98 SETUP.EXE"
CONFIG -SET TURBO=ON
setup /IS 

:END
joeskeen commented 1 hour ago

Thanks @Torinde and @rderooy! I've gotten things working, although there are SO MANY LAYERS lol.

I'm using a differencing VHD for each layer:

This provides the right level of sandboxing for my purposes (although someone could tweak it for further save state shenanigans).

To get a game to launch, there's a lot going on:

You can take my implementation out for a drive by cloning and following instructions in my GitHub repo: https://github.com/joeskeen/oldgames