Why doesn't PC/GEOS 1.x work on DOS 6 and up? This is a question I've wondered about for a long time. Recently, I've felt compelled to investigate and solve some of those lingering mysteries that I didn't have the time to solve way back when.
Of course, you can get PC/GEOS 1.x to run on MS-DOS 6 by loading
setver.exe in config.sys, and forcing the
PC/GEOS kernel.exe to run using DOS version 5. But, I wanted to dig into it and understand exactly what the
problem is. Thus, I decended to my dark chambers to begin working my tried and true arcane magic upon PC/GEOS.
What is PC/GEOS?
PC/GEOS is a lesser known graphical desktop environment for DOS, decended from the legendary Graphical Environment Operating System for systems like the Commodore 64.
It was also the environment upon which the America Online client for DOS was based.
As I dug into it, I learned more than I ever wanted to know about it. As with all things that I reverse engineer, it inevitably yielded to me it's long-kept secrets.
The problem in this case is quite simple. When PC/GEOS starts, it probes for information about all the drives detected by DOS. This part of GEOS is called the "Drive Module." If you were looking at a disassembly of the initialization routine for that module, you'd see the following:
If after looking at that the problem isn't self-evident, then I'll explain.
Before the subroutine, there's a 8-byte long table. This is a jump table used by the subroutine. If you look at the code starting at the probe_drives label, you can see clearly what it does. It takes the DOS major version number (e.g. 6), subtracts 2 (since the first entry is for DOS 2,) and multiplies the result by the size of a single word (2 - since all the addresses here are 1 word long).
It then uses this number (8 in the case of DOS 6) as an index into the aforementioned table, and makes a call
to that address. Since there's no entry for DOS 6, it winds up going to
cs:0x5756. You might recognize
that offset as the bytecode representation of the first two instructions of the subroutine (push si, push di).
Since PC/GEOS works fine on DOS 6 with setver, I can postulate that this is likely the only compatibility problem between the two.
For the authors of PC/GEOS, it would have been a simple matter of adding an entry to the jump table and reassembling the exe. Although, I can't help but wonder why they didn't at least add a check to ensure the index used in the call didn't go beyond the table, and handle that case appropriately. Maybe they figured this version would have reached its end of life by the time DOS 6 was released.
In order to fix the problem, I added a new subroutine to be called in place of
checks the DOS major version, adjusts it if necessary, and then jumps to
This is easy to do, since
init_drive_module is only called in one place. I added the function to the end of
the last page in the exe, since there was plenty of room left. However, there's a temporary address pointer at
the end of the segment whose address is used to denote the end of the PC/GEOS kernel code.
There are a grand total of 7 references to that temporary pointer, and since the kernel relocates that particular segment before calling the main initialization routine, there's one more place to patch. In total, implementing this fix required patching the kernel in 11 different places.
For the curious, the
ret instruction here is not necessary since we're using a
jmp, which doesn't
push a return address onto the stack, and the routine being jumped into includes a proper
return back to the line after the call in
init_drive_module. However, I included it for the hell of
it, since I needed to have some padding there anyhow. The version of the function that gets patched into
the kernel also has a couple of
nops to ensure proper alignment of the temporary pointer.
It should be run from the PC/GEOS installation directory where
KERNEL.EXE resides (usually
It's important to note, however, that this patch will only cause PC/GEOS to work on DOS implementations that
are compatible with DOS 5, and report version numbers above 5. This will not change anything for versions of DOS
less than 5, and DR-DOS.