I recently tried to install the infamous Lotus 1-2-3 Release 3 from 1989 in a VM. The program disks included both DOS and OS/2 executables, and both were failing. The DOS version stopped with “Cannot initialize system driver” immediately after showing the splash screen, while the OS/2 version failed with the message “Error loading driver file LTSNW” at about the same point. Google was of no help whatsoever, as often happens with software that old.
The OS/2 problem was easy to fix. For some reason, the 1-2-3 installer does not modify OS/2’s CONFIG.SYS to make sure the C:\123R3 (or equivalent) directory is on the LIBPATH. When 123OS2.EXE attempts to dynamically load LTSNW.DLL (apparently some sort of a Novell NetWare interface library), it will fail. Editing LIBPATH appropriately is all it takes to fix the problem. On some systems, LIBPATH contains the current directory (“.”); in that case, 1-2-3 starts as long as it’s launched from its own directory.
The failure of the DOS version was a much tougher nut to crack. The error message was rather non-specific. No version of DOS and no memory manager configuration I tried solved the problem, they all failed in the same way (except in a DPMI environment, 1-2-3 R3.0 refused to start outright, as it requires VCPI). I had a hunch that the issue might have something to do with the BIOS used by VirtualBox, specifically with the contents of the interrupt vector table (IVT).
I tried making sure the last vector (FFh) in the IVT is empty (contains zeros) and voilà—Lotus 1-2-3 R3 started up! But that didn’t make sense… because on many systems, the last portion of the IVT is used as a temporary stack by the BIOS, and the contents of the last 30 or so vectors are unpredictable. Then I tried modifying the contents of other vectors and found that zeroing vector 81h also allowed 1-2-3 to run.
The problem was that neither vector FFh nor 81h has any particular function, certainly nothing even remotely relevant to 1-2-3. In the end I looked at the disassembly of LTSSYS.DLD and realized that 1-2-3 R3 looks for unused interrupts in the 81h-FFh vector range. It doesn’t matter which vector is unused (zeroed), but at least one vector in that range must be available; if it’s not, the LTSSYS.DLD module (the “system driver”) will fail to initialize.
Note that 1-2-3 R3.1 (shown above) may require more unused vectors in the IVT, but for R3.0 one is enough. Release 3.1 also includes a newer version of the DOS/16M DOS extender with support for DPMI, and can thus be launched in DPMI environments such as Windows 3.1.