Quake is an impressive title. Much has been written about the 3D stack (software and hardware accelerated) and the Internet protocol to replace NetQuake. Lately I am super into studying how id Software managed to navigate the OS switch from DOS to Windows 95. They had to make sure they game worked on both platform. Wrapping my head around how they did it is proving difficult so maybe people here can contribute and help solve this mystery.
I am studying the file from the shareware version.
1CWSDPMI.EXE: MS-DOS executable 2GENVXD.DLL: PE32 executable (DLL) (GUI) Intel 80386, for MS Windows 3MGENVXD.VXD: MS-DOS executable, LE executable for MS Windows (VxD) 4PDIPX.COM: DOS executable (COM) 5Q95.BAT: ASCII text 6QLAUNCH.EXE: PE32 executable (GUI) Intel 80386, for MS Windows 7QUAKE.EXE: MS-DOS executable, COFF for MS-DOS, DJGPP go32 DOS extender 8QUAKEUDP.DLL: PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
QUAKE.EXE: The game engine. It can be started from DOS (in which case it uses DJGPP DPMI server) or Windows 95 (in which case it uses Microsoft DPMI server). The DOS source code in net_dos.c shows that it supports the following network configuration: loopback, serial, Beame & Whiteside TCP/IP, IPX, and Win95 TCP/IP. However not all of these are available depending on the context in which the engine runs (DOS/Windows, or if TSR such as PDIPX or ETHDEV27 for Beame & Whiteside TCP/IP are loaded).
CWSDPMI.EXE: The DPMI server from DJGPP. Manages protected mode stuff.
PDIPX.COM : A TSR that implement a Packet Driver interface and convert it to IPX traffic.
Q95.BAT : How you are supposed to start Quake under Windows 95 IF YOU WANTED MORE NETWORK CAPABILITIES. You actually see a windows flashing when you do that that says "WinSock Tunnel Powered by MPath" which I assume meant MPlayer.
QUAKEUDP.DLL : The bridge to WSOCK32.DLL. Despite its name, it gives access to the whole Windows's TCPIP stack, not only the UDP part. It exports functions such as GameDLLInit, and GameDLLInit. This is likely a component authored by MPath.
Now we enter the area where I am still digging. Namely, QLAUNCH.EXE, MGENVXD.VXD, and GENVXD.DLL. Here is where I am and I would welcome anybody insight or ideas to dig further.
QLAUNCH.EXE : I have started to diassemble it with ghidra and found the location where GameDLLXXX functions are retrieved. This happens on the argument passed via Q95.BAT, namely QUAKEUDP.DLL so it all makes sense. There is even a fallback to MPLAYER.DLL. So far so good. And then? Q95.bat gives QUAKE.EXE as an argument so it must be used to be loaded but I have not found how yet. Also does it uses the two files GENVXD?
MGENVXD.VXD : This a Windows Virtual Device. I don't know what it emulates. Easter eggs, string returned a nugget F:\cashcode\GENVXD\bin\Mgenvxd.pdb so it was authored by John Cash and this may be a debug version they shipped.
GENVXD.DLL : A dll that I have no idea how it is loaded. There is a string \\.\MGenVxD.VXD and a DeviceIoControl which according to Windows 95 DDK documentation means this is what is loading MGENVXD.VXD.
The two big questions I am trying to answer are:
- How does QLAUNCH load QUAKE.EXE into a DOS VM?
- What are GENVXD emulating? IPX? There is code in net_dos.c IPX driver with an interrupt 0x2f which seems to be how MS-DOS can communicate with the XvD so that would make sense.
Decided to create an account here, as posting on X would be rather painful experience.
Both MGENVXD and GENVXD seems to be part of "mplayer" library. But in version that I have (GOG, Quake The Offering), it doesn't look like they're used.
In quake these calls can be found - again in unused - mpllib.c and mpllpc.c.
There's similar code used in Red Alert: Command & Conquer.
I briefely looked at the code, and it looks like it's a channel to provide some Windows APIs functionality to game run in a
"dos window" (called DOS Box inside quake readme). There's also following piece to support that, which I found in: https://www.hydrogen18.com/blog/peeking-under … nd-conquer.html
Update 2020-06-08 Larry Hastings reached out to me directly to correct some of my assumptions. It turns out the source code that […] Show full quote
Update 2020-06-08 Larry Hastings reached out to me directly to correct some of my assumptions. It turns out the source code that I presumed
was in fact the MPlayer implementation is not. In fact it is a piece of software called the "chunnel" which allows a DOS mode application
running on Windows 95 to interact with the networking stack provided by Windows. He also shared some details of how MPlayer integrated
with games. I've reproduced it here, with the names of other individuals removed.
First, most companies didn't do their own integration with Mplayer; they just sent us a code drop and we had to figure out how t […] Show full quote
First, most companies didn't do their own integration with Mplayer; they just sent us a code drop and we had to figure out how to build
it and do all the integration work ourselves. But I think Westwood was the exception to the rule. I remember one of our
"porting engineers" took a trip out to visit Westwood before Red Alert shipped. He was very impressed by the RA network model!
Second, all Mplayer assets were sold to GameSpy, who didn't want any of the online services (Mplayer / POP.X / Global Rankings).
All they wanted was the userbase, and... the ad sales team, maybe? Anyway, GameSpy folded in 2013, and their assets were sold to
Glu Mobile, so I guess theoretically they own the IP now. Meanwhile, in 1998 TEN pivoted to do "classic" online games, in 1999
they rebranded themselves as Pogo.com, and in 2001 they were bought by... EA! So EA is probably safe shipping the TEN code.
And I doubt anybody cares about the Mplayer code either, it's long dead.
Third, remember how I said companies tended to do a code drop and Mplayer did the integration work themselves?
That was true of id software too. The Mplayer code you saw inside Quake 1 is not integration with the Mplayer gaming service!
It's actually technology we licensed to id called the "chunnel", written by a British programmer guy named ***.
The "chunnel" was a library that let 386 protected mode DOS programs running under Windows make calls into Windows 95's
Winsock networking stack. Remember, this is circa 1996, gaming under Windows hadn't quite happened yet.
Quake initially shipped as a DOS program and wasn't ported to Win32 until a year or two later.
The "chunnel" solved a real problem for id, letting their 386 protected mode DOS program participate in network play
when run under Windows. Part of how they showed their thanks was, Mplayer got every id game (while it was a going concern).
Note that if you run early versions of Quake for DOS, like the initial shareware demo, the "splash screen" has the original
Mplayer logo (the golden waveform), and a note about "technology licensed from". And that explains the "-mpath" command-line
setting for the DOS builds of Quake 😉
Besides -mpath, it is quite possible, that some other options from quake command line were passed to the lib, but I don't want to speculate
too much about it. (I'm mostly refering to -winmem and -winlock)
Gritty details
Let's get back to code, the lib is also used in Witchhaven2:
There are visible MGenInitVxD and MGenUninitVxD exports, which I haven't seen anywhere in quake source, there's no implementation,
but not a big issue here, what MGenInitVxD is basically load VXD, and issue three Ioctls, ioctls are called via ids: 1, 2, 5, we can find them in Witchhaven2's mgenord.h
In my case mgenvxd.vxd has 9883 bytes and md5: 4c7fc48ca4d16f4efbcf176c4eb0538e
DeviceIoControl dispatcher is located at 0xC0000390, actual dispatch table is at 0xC00002D4.
0x1 MGENVXD_REGISTER_ORD - looks like some initialization
0x2 MGENVXD_GETMEM_ORD - allocates requested chunk of memory - with PAGELOCKED and PAGEZEROINIT flags (0x81), and creates `rtq_node` there, the APIs below operate on those
0x5 MGENVXD_MAKEDQS_ORD - registers interrupt handler 0x48 - the DOS application running under Windows, will use that handler through Windows VMM (Virtual Machine Manager).
MGENVXD_DEVICE_ID is passed in low WORD, while id in high WORD.
Note: in the dll itself, I haven't seen functions corresponding to MGENVXD_WAKEUPDLL_ORD or MGENVXD_WAIT_ORD.
Interrupt handlers form a chain, so the mplayer handler located at 0xC0001312 is "being nice" and there's a check if low-word equals MGENVXD_DEVICE_ID (0x18AA),
if it's not previous handler in chain is called, if it is, actual handler is called, which is located at 0xC0000CF0.
Given, that I don't see the dll used, I don't think it has much sense to describe particular handlers.
There's a great resource, an old book by Karen Hazzah: Writing Windows VxDs and Device Drivers .
Last but not least: I love your books and your work.