== fabulous.systems ==
Welcome to the world of fabulous.systems

Creating New Installation Media for MS-DOS 4.0

#retrocomputing #msdos #operatingsystems

On April 25, 2024, Microsoft released the source code of MS-/PC-DOS 4.00 to the public, and the community managed to provide MS-DOS 4.01 as well.

While the original release was available as a set of six 5,25" floppy disks (and optionally three 3,5" disks for version 4.01), this open-source release does not have official installation media.

Recreating the original media would theoretically be possible, but I want to focus on the 720k images for this project. Having to swap around six floppies multiple times isn’t practical. Furthermore, we can build images for 1.44 MB floppy disks for increased compatibility: The SELECT utility used for the installation process doesn’t like it if you install it on floppies with a different format than the source disks are written in.

The open-source release is missing a few program files and the entire DOSSHELL environment, so that’s something we also have to deal with.

Let’s start with the missing files. To check if the correct floppy is present in the drive, the SELECT utility used to install MS-DOS 4.0 doesn’t check the disk label but directly checks if the files it is supposed to copy are available on the disk. If a file is missing, it simply tells you you have the wrong floppy inserted.

While this isn’t an issue for DOSSHELL at the moment—it is optional and only installed upon request—this is a massive problem for two other missing files.

In total, the following core files are missing from the open-source release:


HIMEM.SYS is the easiest one. It is not referenced in the SELECT code at all, which means it can’t be one of the “marker files” indicating a specific floppy disk. We can skip it altogether, and nothing will break.

The other two files, however, are mentioned in SEL_FILE.INC, which would cause an issue if the files were absent. To fix this, I created two simple executables with Turbo Pascal 5.5:

program Gwbasic;
  writeln('This release of MS-DOS 4.0 is based on the code released');
  writeln('to the general public in April 2024.');
  writeln('GWBASIC.EXE is not included in this release.');

Since SELECT doesn’t do any checksum comparison, it won’t complain about these stubs, and the installation will happily continue.


DOSSHELL, however, is an entirely different problem. While it is optional and not selected by default, the user can enable it during installation. This will inevitably break the installation since we don’t have any DOSSHELL components in the open-source release.

We need to disable DOSSHELL in two places:

MS-DOS Shell Option
The MS-DOS Shell Option screen

Review Selection
The Review Selection selection

The file responsible for handling both screens is SELECT3.ASM.

Conveniently, we get a hint on how to disable the first screen:

     82 ;  The CHOOSE SHELL SCREEN is always presented.
     83 ;  This screen allows the user to decide whether or not the DOS
     84 ;  shell will be installed.
     85 ;  Valid keys are ENTER, ESC, F1, F3 and numeric 1 and 2.
     86 ;----
     87 ; Note:  This screen (and, hence, all shell support) can be eradicated
     88 ;       by defining the symbol NOSHELL.
     89 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     90 choose_shell_screen:                                            ;AN000;
     92         INIT_PQUEUE             PAN_choose_shell                ;AN000; initialize queue
     93         PREPARE_PANEL           PAN_HBAR                        ;AN000; prepare horizontal bar
     94         PREPARE_CHILDREN                                        ;AN000; prepare child panels

NOSHELL EQU 1 defines the required symbol, and as expected, the first screen is skipped.

     82 ;  The CHOOSE SHELL SCREEN is always presented.
     83 ;  This screen allows the user to decide whether or not the DOS
     84 ;  shell will be installed.
     85 ;  Valid keys are ENTER, ESC, F1, F3 and numeric 1 and 2.
     86 ;----
     87 ; Note:  This screen (and, hence, all shell support) can be eradicated
     88 ;       by defining the symbol NOSHELL.
     89 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     90 choose_shell_screen:                                            ;AN000;
>>>  91 NOSHELL EQU 1
     93         INIT_PQUEUE             PAN_choose_shell                ;AN000; initialize queue
     94         PREPARE_PANEL           PAN_HBAR                        ;AN000; prepare horizontal bar
     95         PREPARE_CHILDREN                                        ;AN000; prepare child panels

Unfortunately, the “Review Selection” screen doesn’t honor this symbol. This screen can override all previously set variables regarding the features that should be enabled. Furthermore, the entire menu system is scattered across multiple files, and changing one entry means we have to rewrite all other menu options.

Forcing the return value to E_SHELL_NO, which would remove DOSSHELL integration, doesn’t work either.

I got it somewhat working once, but this caused the menu system to break, and I managed to “enable” XMA support on an emulated machine that definitely doesn’t support it. At this point, I realized that modifying the menu system was beyond my non-existent assembler skills.

The “Review Selection” screen is controlled by the REVIEW_DISK_SCREEN and REVIEW_DISKETTE_SCREEN functions in SELECT3.ASM. Since I couldn’t disable the menu option, I dusted off my crowbar:

    222            RET_SUPPORT          SUPPORT_STATUS,E_SHARE_C,F_SHARE;AN000;      SHARE support
    223            RET_SUPPORT          SUPPORT_STATUS,E_SHELL_C,F_SHELL;AN000;      SHELL support
    224            RET_SUPPORT          SUPPORT_STATUS,E_VDISK_C,F_VDISK;AN000;      VDISK support
>>> 225            INIT_VAR             F_SHELL,E_SHELL_NO
    226            PUSH_HEADING         REVIEW_DISK_SCREEN              ;AN000;    save screen address on SELECT STACK
    227            GOTO                 DOS_PARAMETERS_SCREEN           ;AN000;    goto the next screen (DOS_PARAMETERS)
    277            RET_SUPPORT          SUPPORT_STATUS,E_SHELL_B,F_SHELL;AN000;      SHELL support
    278            RET_SUPPORT          SUPPORT_STATUS,E_VDISK_B,F_VDISK;AN000;      VDISK support
>>> 279            INIT_VAR             F_SHELL,E_SHELL_NO
    280            PUSH_HEADING         REVIEW_DISKETTE_SCREEN          ;AN000; save screen address onto SELECT STACK
    281            GOTO                 DOS_PARAMETERS_SCREEN           ;AN000; goto the next screen (DOS_PARAMETERS)
    282         .ELSE                                                   ;AN000;

Using INIT_VAR here always forces F_SHELL to E_SHELL_NO, discarding the user’s selection which was previously stored with RET_SUPPORT. Thus, it effectively prevents DOSSHELL from ever being installed.

Yes, this is incredibly ugly, but also very effective.

Creating the disk images

With the fixed SELECT executable on hand, it was time to create the floppy images. Luckily, it fits on two 720kB floppies, so disk swapping is not too bad. Please note that it would also fit on a single 1,44MB floppy, but this will heavily confuse SELECT and break support for installing to a set of floppies.

For 3.5" floppy disks, the disk size doesn’t matter, so both 720kB and 1.44MB disks are a viable option, but you really should create both a dedicated INSTALL and OPERATING floppy. Unfortunately, you can’t split the images on two 1.2MB 5.25" disks since SELECT will expect all six floppies in this case.

Creating the floppy images was as simple as copying all required files using the official release as a template and making the first disk bootable.

Installing MS-DOS 4.0 on a hard drive worked without any issues. While the installation to a set of floppies should work, I had mixed results even when using the images from the original release, so your mileage may vary.


Have fun!

Do you have any comments or suggestions regarding this article? Feel free to join the discussion at our fabulous.community!