
Quake, выпущенный в июне 1996 года, за срок своей жизни был вынужден оседлать три технологические волны. Наряду с появлением карт аппаратного 3D-ускорения и развитием Интернета, сложности у разработчиков игры вызвала и смена поколений операционных систем.

Стремясь к распространению Windows 95 и Windows NT, Microsoft начала процесс замены своей старой операционной системы MS-DOS. С 1996 по 1997 год доля DOS на рынке упала на 50%. Некоторые разработчики, например Blizzard North, делали рискованный шаг и создавали игры наподобие Diablo только для Windows 95. Компания id Software же пошла на подвиг по созданию единого двоичного файла quake.exe, способного работать и в DOS, и в Windows.
Ещё более впечатляет то, что разработчикам удалось реализовать стек TCP/IP Quake лучше, чем у Windows 95. Давайте разберёмся, как им это удалось.
Краткое введение в Quake.exe
quake.exe — это исполняемый файл DOS. Для DOOM компания id Software использовала компилятор Watcom , но для кросс-компиляции Quake на серверах Alpha она перешла на порт GCC под названием djgpp[1].
$ file quake.exe
quake.exe: MS-DOS executable, COFF for MS-DOS, DJGPP go32 DOS extender
Аналогично DOS/4GW компилятора watcom, djgpp предоставлял разработчикам расширитель, позволяющий писать программы с плоской 32-битной адресацией вместо ужасного реального 16-битного режима, предписываемого DOS. Расширитель работает с клиентом и сервером. В случае Quake клиент расширителя встроен в quake.exe, а сервер находится в cwsdpmi.exe.
С самого начала разработки id попросила у создателей djgpp, чтобы их клиент DPMI мог работать не только на сервере DPMI djgpp, но и на сервере DPMI Windows 95.


Может показаться неочевидным, насколько сложно было djgpp заставить клиент DPMI работать с другим сервером DPMI, но если немного знать, как работает такая система, это поражает. Реймонд Чен, тогда занимавшийся разработкой ядра Microsoft, лучше всех описал то, как следует воспринимать эту ситуацию:
Клиентское приложение писалось с предположением о том, что оно будет использовать расширитель MS-DOS, включённый в состав приложения, но на самом деле он общается с хостом DPMI из комплекта Windows.
То, что программы работают практически без проблем, несмотря на выполнение в чужом расширителе, в зависимости от точки зрения или совершенно поражает, или совершенно очевидно.
Совершенно поражает это тем, что мы берём программу, написанную для выполнения в одной среде, и запускаем в другой среде. Или же это совершенно очевидно, потому что разработчики использовали один и тот же интерфейс DPMI, а поскольку интерфейс имеет одинаковое поведение, естественно, что программа продолжит работать, потому что ведь для этого и нужны интерфейсы!
— Реймонд Чен[2]
Именно благодаря возможности работы с сервером DPMI Windows 95 quake.exe смог запускаться и в DOS, и в Windows 95.
Quake.exe в DOS
Для запуска DOOM требовались всего два файла: doom.exe и doom.wad. У Quake же было много разных файлов:
$ find quake
./mgenvxd.vxd ./genvxd.dll ./qlaunch.exe ./id1/pak0.pak ./pdipx.com
./cwsdpmi.exe ./q95.bat ./id1/config.cfg ./quake.exe ./quakeudp.dll
Поначалу всё это кажется неразберихой, но для запуска Quake в DOS требовались всего четыре файла, а именно движок игры quake.exe, файл конфигурации config.cfg, файл ресурсов pak0.pak и сервер расширителя DOS cwsdpmi.exe.
./mgenvxd.vxd ./genvxd.dll ./qlaunch.exe ./id1/pak0.pak ./pdipx.com
./cwsdpmi.exe ./q95.bat ./id1/config.cfg ./quake.exe ./quakeudp.dll
Quake.exe в DOS.EXE: многопользовательский режим

Quake поддерживал четыре типа многопользовательских протоколов.
Два режима позволяли игрокам сразиться в дуэли один на один (1v1). Оба этих режима ожидали, что устройство подключено к разъёму COM компьютера PC. Режим модема позволял звонить на телефонный номер противника (прощайте, денежки), а нуль-модемный кабель (называемый в игре режимом «Direct Connect») требовал, чтобы компьютеры находились рядом друг с другом.
IPX и TCP/IP позволяли участвовать в гораздо более интересных сражениях (deathmatch) с участием до шестнадцати игроков. Технология IPX предназначалась для локальных сетей (LAN), в которых все машины находились в считанных метрах друг от друга, а TCP/IP позволял связываться с любой точкой мира.
Стоит отметить,что в DOS режимы IPX и TCP по умолчанию были отключены (выделены серым).
Quake.exe в DOS.EXE: отключенные многопользовательские режимы

В комплекте Quake был файл PDIPX.EXE, загружавший резидентную программу DOS IPX. Эта резидентная программа (TSR) общалась с драйвером пакетов, который, в свою очередь, общался с сетевой картой. Quake мог проверять наличие этой резидентной программы DOS и в случае её обнаружения позволял игрокам выбирать IPX.
Использование TCP/IP было практически невозможной задачей. У DOS не было стека TCP/IP, и он был таким сложным, что резидентную программу для него под DOS продавал только один поставщик.
TSR называлась BWNFS. Эта программа, разработанная Beame & Whiteside, в 1996 году стоила $395 ($830 по ценам 2025 года!)[3]. Разумно предположить, что очень немногие игроки играли в Quake под DOS через TCP/IP.
Quake.exe в Windows 95
Запуск quake.exe в Windows 95 не представлял вообще никаких проблем. Исполняемый файл загружался в «эмулятор DOS»[4] Windows 95, виртуализирующий память, прерывания и сигналы[5]. Игра работала точно так же, как в DOS, предоставляя те же самые варианты многопользовательских режимов. Это было удобно, потому что пользователям не приходилось загружать драйвер мыши и настраивать переменную окружения BLASTER, чтобы заработала звуковая карта.
Однако гораздо менее удобно было то, что при таком запуске Quake требовалось 16 МиБ ОЗУ. Quake нужно всего 8 МиБ, но Windows 95 добавляла приличный оверхед! Здесь используются те же файлы, что и при запуске из DOS, за исключением cwsdpmi.exe, потому что клиент DJGPP распознаёт и использует встроенный сервер DPMI Windows.
./mgenvxd.vxd ./genvxd.dll ./qlaunch.exe ./id1/pak0.pak ./pdipx.com
./cwsdpmi.exe ./q95.bat ./id1/config.cfg ./quake.exe ./quakeudp.dll
С учётом того, что исполняемый файл DOS запускался в виртуальной машине Windows 95, работа Quake на полной скорости впечатляет. Предполагаю, что в полноэкранном режиме операциям записи и чтения из памяти VGA предоставляется прямой доступ к оборудованию.
Волшебный скрипт Q95.bat

Запуск quake.exe из DOS или Windows — не единственные варианты запуска Quake. Есть и третий — запуск q95.bat.
В этом случае на рабочем столе Windows 95 на короткое время появляется всплывающее окно «Launching Quake».
Текст в окне подсказывает, что происходит. Quake загружается с туннелем в Winsock — стек TCP/IP Microsoft. Есть и подсказка о том, кто это делает: «Powered by Mpath». Но не особо понятно, как всё это работает.
Mpath
Mpath Interactive — это компания, занимавшаяся онлайн-играми. Она предоставляла платные сервисы, позволявшие игрокам находить друг друга, а также работала реселлером услуг Интернет-провайдеров[6]. В её интересах было помогать игровым компаниям выпускать проекты с возможностью игры по Интернету. Вспоминает Ларри Хастингс, работавший тогда в Mpath:
В те времена в первичном бульоне, который представлял собой Интернет середины 90-х, многопользовательские онлайн-режимы только зарождались. Если кто-то хотел сыграть в многопользовательскую игру через Интернет, ему или требовались точная информация о хосте и порте, или подключение к игровому многопользовательскому онлайн-сервису. А на 1995 год их было всего два: мы и Total Entertainment Network. Возможно, вы подумаете, что разработчики игр приходили к нам и умоляли добавить их игру в наш сервис... но нет! У нас не только была команда лицензирования, которая заключала договоры на лицензирование игр под наш сервис, но нам и приходилось платить разработчику за право лицензировать его игру; часто это были исключительные права. Мы получили Quake и Unreal; у TEN были Duke Nukem 3D и NASCAR.
Использование Mplayer происходило так: сначала нужно было запустить «Gizmo» — программу для Windows, своего рода браузер игр. Она знала, какие совместимые игры установлены у пользователя, и позволяла просматривать многопользовательские сессии, доступные для каждой из игр; мы называли их «комнатами». К играм в Quake можно было подключаться в любой момент, поэтому пользователь мог просто найти игру и сразу войти в неё; это было нехарактерно для большинства игр того времени. Или же можно было найти «комнату», в которой другой пользователь предлагал скоро запустить игру. Также можно было создать собственную. Пользователь указывал название комнаты, а в Mplayer Gizmo имелся UI для каждой игры, позволявший настраивать параметры игры (карту, опции и так далее). В комнате имелся текстовый и аудиочат, и даже общая «белая доска» — простая программа для рисования. Как только владелец «комнаты» запускал матч, Gizmo всех остальных пользователей автоматически запускали файл игры, после чего он автоматически подключался к этому онлайн-матчу и начинал играть.
Чтобы игра работала в Mplayer, её необходимо было интегрировать в программный стек Mplayer. По большей мере работа по интеграции выполнялась инженерами Mpath: мы получали от разработчиков игры исходный код, а «инженеры по портированию» делали так, чтобы она работала в Mplayer. Часто для этого требовалось модифицировать и клиент, и сервер, чтобы они могли обмениваться данными с серверами Mplayer.
Первые версии Quake предназначались только для DOS и для общения со стеком TCP/IP Windows 95 использовали Chunnel. (Можно сказать, что Chunnel был своего рода thunk, наподобие Win32s компании Microsoft.) Если не ошибаюсь, по договору мы давали компании id лицензию Chunnel, а она в обмен на это предоставляла возможность добавления Quake в Mplayer. То есть Quake для DOS поддерживал запуск Mplayer через Chunnel наряду с подключением к открытым игровым серверам в Интернете через хост и порт.
— Ларри Хастингс (в почтовой переписке со мной).
Ларри любезно поделился парой историй о Quake.
Вскоре после получения первой сборки игры мы играли по Интернету в deathmatch с командой id. Мы находились в Купертино (Калифорния), в офисе на Бэндли-Драйв (сейчас там расположен фитнес-центр для сотрудников Apple). Разработчики, разумеется, находились в Меските (Техас). Да, это был настоящий deathmatch через Интернет, очень захватывающий!
Точно помню, что одним из участников со стороны id был Тим Уиллитс. Он просто порвал нас, потому что не только гораздо больше играл в Quake, но и знал, где спрятаны все секреты. Помню, как один раз увидел его, выбегающего из тайного прохода с ракетницей. Или он не увидел меня, или я вскоре умер.
— Ларри Хастингс (в почтовой переписке со мной)
Я спросил, как был устроен Chunnel, но тут мне не повезло.
Я не работал над Chunnel. В основном им занимался британец по имени Генри; фамилию я забыл, это было тридцать лет назад. Помню только, как он выглядел, и что он ездил на крутой тачке — белом Merkur XR4Ti.
— Ларри Хастингс (в почтовой переписке со мной)
Ghidra
Даже если мы зашли в тупик, у нас всё равно остаётся Ghidra и потрясающее сообщество doomworld (спасибо, xttl[7]). Проведя много времени за декомпиляцией и общением, я выяснил, что все файлы, которых мы не касались ранее, были частью Chunnel Mpath.
./mgenvxd.vxd ./genvxd.dll ./qlaunch.exe ./id1/pak0.pak ./pdipx.com
./cwsdpmi.exe ./q95.bat ./id1/config.cfg ./quake.exe ./quakeudp.dll

q95.bat — это просто небольшой скрипт для запуска основной программы mpath. В qlaunch.exe содержатся все функции MPlayer. Однако роль этого исполняемого файла ограничена.
Он просто загружает quakeudp.dll. Несмотря на своё название, эта DLL — основа Quake Chunnel. Это мост к стеку TCP/UDP/IP Microsoft (wsock32.dll). Кроме того, он запускает Quake с параметром -path , чтобы игра загрузила API сетевых сокетов BSD sys/socket.h. Также он загружает менеджер драйверов виртуальных устройств genvxd.dll.
Виртуальное устройство — это трюк, позволяющий исполняемому файлу DOS запускаться в «эмуляторе DOS» Windows 95 для общения с win32. Динамическая библиотека genvxd.dll загружает драйвер виртуального устройства[8] GENVXD.VXD, устанавливающий себя для ответов на прерывание 0x48.
Последний кусок пазла находится на стороне Quake. Реализация sys/socket.h BSD под названием mpplc.c — это код, предоставляемый Mpath. Он занимается сопровождением каждого вызова функций сокетов BSD, а затем при помощи клиента DPMI вызывает программное прерывание, получаемое на стороне win32. Данные передаются по описанному выше конвейеру, после чего выполняется их обратное преобразование genvxd.dll и маршрутизация к wsock32.dll. Обратите внимание на симметрию функций в обработке mplib.c и символов в обратной обработке genvxd.dll.

Похоже, в компиляции Mpath принимал участие Джон Кэш: его имя можно увидеть в символах mgenvxd.vxd.
F:\cashcode\GENVXD\bin\Mgenvxd.pdb
Исходный код mgenvxd.vxd, genvxd.dll, qlaunch.exe и quakeudp.dll так никогда и не опубликовали, это была проприетарная запатентованная технология Mpath. Скорее всего, id получила разрешение на выпуск только клиентской её части.
Насколько я понимаю, именно благодаря этому Quake мог отправлять пакеты TCP и UDP через IP. Эта сложная конструкция устарела, когда id перестала распространять исполняемый файл DOS (последним был vquake.exe). После декабря 1996 года winquake.exe, glquake.exe и все двоичные файлы QuakeWorld стали исключительно приложениями win32 с прямым доступом к wsock32.dll.
Ссылки
[1] Why did ID choose DJGPP for Quake?
[2] Getting MS-DOS games to run on Windows 95
[4] Microsoft Windows Chicago Reviewer’s Guide, p69
[5] Writing Windows VxDs and device drivers
[6] MPlayer.com
Комментарии (4)

BulldozerBSG
20.11.2025 13:40Ещё более впечатляет то, что разработчикам удалось реализовать стек TCP/IP Quake лучше, чем у Windows 95. Давайте разберёмся, как им это удалось.
Какая прелесть. А из прочитанного мы выясняем что в квейке никакого стека TCP/IP не было, а был врапер (от Mpath) для доступа к winsock32 API из под подсистемы "DOS". То есть без виндового стека это не могло работать от слова совсем.
Sazonov
Extension - это не расширитель, а расширение ;)
В целом тяжело читается из-за обилия аббревиатур, которые не расшифровываются в тексте.