
Изучение истории исполняемых файлов Quake прояснило логику их появления. Изначальный quake.exe поддерживал работу как в DOS, так и в Windows 95. За ним последовал vquake.exe, предназначенный для аппаратного ускорения с использованием чипа Vérité 1000. Позднее id Software представила glquake.exe, открывший доступ к аппаратному ускорению для видеокарт с драйверами OpenGL. А для полного переворота в сетевых deathmatch-сражениях был выпущен QuakeWorld со своими сервером (qwsv.exe) и клиентом (qwcl.exe).
Однако предназначение winquake.exe оставалось для меня загадкой вплоть до недавнего времени. В этой статье я поделюсь результатами своего исследования этого исполняемого файла.
Производительность quake.exe
Хотя quake.exe функционировал как в DOS, так и в Windows 95, его производительность существенно различалась. Небольшое тестирование, проведённое на моём компьютере (Pentium MMX 233 МГц, Matrox Mystique, разрешение 320×200, экран 101%, звук включён), дало следующие результаты:
|
Конфигурация |
Частота кадров |
|
|
48 fps |
|
|
38 fps |
Эта разница в частоте кадров — одна из ключевых причин появления WinQuake. quake.exe под управлением Windows 95 работал примерно на 25% медленнее, чем при запуске из DOS. Такое снижение производительности было предсказуемо, поскольку Windows 95 запускала DOS-приложения в виртуальной машине («DOS Box»), где виртуализация памяти, прерываний и сигналов создавала значительные накладные расходы.
Ещё одним важным фактором был так называемый Quake Chunnel. quake.exe мог взаимодействовать с сетевым стеком TCP/IP Windows 95, но только через сложную и неэффективную технологию Mpath, связывающую «DOS Box» с 32-битными DLL-библиотеками. Переход на чисто 32-битное приложение позволил id Software получить прямой доступ к winsock.dll.
Помимо этого, id Software стремилась обеспечить работоспособность Quake в Windows NT. Однако, несмотря на все усилия, разработчики DJGPP не смогли добиться совместимости своего DPMI-клиента в quake.exe с виртуальной DOS-машиной Windows NT (NTVDM).
В NT не работают ближние указатели — это сильно разочаровало iD, которая провела несколько телефонных конференций с Microsoft.
Чарльз Сэндманн[1]
Как работает winquake.exe
Чтобы понять принцип работы winquake.exe, стоит начать с изучения файла WQREADME.TXT, где описаны все доступные режимы. Эти режимы конфигурируются с помощью скрипта wq.bat:
Опции запуска WinQuake:
wq max: включены все функции, но работает не на всех системах
wq fast: максимальная скорость, но работает не на всех системах
wq fastvid: максимальная скорость видео, но более безопасный и, возможно, медленный звук
wq fastsnd: максимальная скорость звука, но более безопасное и, возможно, медленное видео
wq safe: запустится с большой вероятностью, но может быть медленнее
wq verysafe: почти точно запустится, но может быть медленнее и без звука
Ниже представлены результаты, полученные мной для каждого из этих режимов на той же системе с Pentium MMX 233 МГц и идентичной конфигурацией:
|
Конфигурация |
Частота кадров |
|
|
42.4 fp. |
|
|
41.8 fp. |
|
|
45.0 fps |
|
|
41.8 fp. |
|
|
45.0 fps |
|
|
40.0 fps* |
Результаты впечатляют: winquake.exe смог достичь производительности, которая лишь на 6% уступала quake.exe, запущенному в DOS. Цель была достигнута. Но каким образом?
Бэкенды winquake.exe
Каждый режим работы winquake.exe определяется набором флагов командной строки. Анализ показывает наличие трёх основных типов бэкендов: для ввода, звука и видео.
max winquake -dinput
fast winquake
fastvid winquake -wavonly
fastsnd winquake -nodirectdraw -nowindirect
safe winquake -wavonly -nodirectdraw -nowindirect
verysafe winquake -dibonly -nosound -nojoy
Примечательно, что режим fastvid, который демонстрирует наибольшую частоту кадров, использует стандартные параметры, но при этом отключает аудио-бэкенд!
Интересный факт: fastvid также является названием инструмента, разработанного для устранения проблем с крайне низкой скоростью записи видео на процессорах Pentium Pro с чипсетами, имеющими дефект в реализации «Write Posting». Однако эта опция в qw.bat не имеет к нему отношения.
Бэкенды аудио
WinQuake способен обрабатывать звуковые эффекты (музыка воспроизводится с CD-дорожек) с использованием двух различных аудио-бэкендов (флаг -nosound полностью отключает звук).
Первый — это DirectSound (интерфейс dsound.h из пакета DirectX), а второй, который id Software называет «wave sound», на самом деле является winmm.h — аудио-API Windows MultiMedia, появившимся ещё в Windows 3.1.
При наличии DirectSound WinQuake по умолчанию использует его для минимизации задержек. Однако этот бэкенд заметно увеличивает нагрузку на процессор, снижая частоту кадров примерно на 10%. Использование флага -wavonly позволяет принудительно активировать WinMM, что приводит к увеличению задержек звука, но при этом повышает общую частоту кадров.
Бэкенды ввода
Для обработки пользовательского ввода WinQuake использует либо DirectInput (интерфейс dinput.h из DirectX), либо более старый Windows API winuser.h.
По умолчанию активирован winuser.h. Однако при использовании ключа -dinput можно задействовать DirectInput, что незначительно улучшает плавность движений и отзывчивость при резких поворотах. Вероятно, этот режим не был выбран как основной из-за потенциального отсутствия установленного DirectX у пользователей или из-за возможных проблем с драйверами.
Ввод с джойстиков обрабатывается через joystickapi.h. Судя по всему, стабильность драйверов для джойстиков также вызывала вопросы, поэтому id Software предусмотрела возможность его отключения с помощью флага -nojoy.
Бэкенды видео
Наибольший интерес для меня представляли видео-бэкенды. WinQuake способен функционировать в пяти различных режимах, используя GDI, VGA, VESA, Accelerated VESA или DirectDraw.
Бэкенд видео DIB
Graphics Device Interface (GDI) (wingdi.h) служил основой для отрисовки всей графики в Windows 95. Приложения обычно не обращались к нему напрямую, используя вместо этого winuser.h, который уже взаимодействовал с низкоуровневым wingdi.h.
WinQuake способен выполнять рендеринг в Device-Independent Bitmap (DIB) — это поверхность, накладываемая на окно через GDI. Поскольку такая поверхность может быть любого размера, отпадает необходимость в распознавании «режима дисплея». WinQuake жёстко устанавливает свои режимы DIB с квадратными пикселями в разрешениях 320×240, 640×480 и 800×600.
Режим DIB, будучи полностью соответствующим стандартам Windows, является наиболее надёжным и гарантированно работоспособным. В то же время это и самый медленный способ отрисовки экрана, так как WinQuake сначала рендерит изображение в DIB-буфер, который затем передаётся GDI, а уже оттуда — в видеокарту.
Несмотря на пониженную скорость, аппаратное ускорение в этом режиме всё же возможно. Многие производители графических карт, стремясь обеспечить высокую производительность в Windows 95, реализовали аппаратное ускорение для таких ключевых функций, как bitBlt.
Наконец, режим DIB — единственный, поддерживающий оконный режим. Все остальные режимы работают исключительно в полноэкранном режиме. Примечательно, что DIB также может имитировать полноэкранный режим: если WinQuake запустить с флагом dibonly, игра будет отображаться в окне без рамки, занимающем весь экран.
Многоплатформенная графическая библиотека SciTech (MGL)
Для всех операций, не связанных с DIB, WinQuake использует MegaGraph Graphics Library от компании SciTech. Это была довольно дорогая разработка (стоимостью $499 в 1997 году, что эквивалентно $1000 в 2025 году)[2], но её ценность оправдывалась тем, что она привнесла систематизацию в хаотичный мир видеосистем 1997 года, особенно для игр, не использовавших GDI.
WinQuake требовалось взаимодействовать со следующими типами видеосистем:
1. VBEAF : VESA Accelerator Function
2. VBE2 : Линейный кадровый буфер VESA для прямого записи/чтения VRAM.
3. DirectDraw : Доступна только при установленном DirectX.
4. StandardVGA : Старый добрый видеорежим VGA.
При своём запуске WinQuake регистрирует драйверы, которые должны быть загружены MGL (см. функцию registerAllDispDrivers). Затем MGL перечисляет все поддерживаемые разрешения и выбирает наиболее эффективные драйверы для доступа к ним.
void registerAllDispDrivers(void) {
/* Несмотря на то, что эти драйверы требуют WinDirect, мы регистрируем
* их, чтобы они всё равно были доступны, даже если DirectDraw
* присутствует, а пользователь отключил высокопроизводительные
* режимы WinDirect.
*/
MGL_registerDriver(MGL_VGA8NAME,VGA8_driver);
if (useWinDirect){
MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver);
if (!COM_CheckParm ("-novbeaf"))
MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver);
}
if (useDirectDraw) {
MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver);
}
}
Перечень режимов и выбранные драйверы MGL можно увидеть, выполнив команду vid_describemodes в консоли Quake. На приведённых ниже скриншотах демонстрируется почти полный набор драйверов, включая VGA8.DRV, DDRAW.DRV, LINEAR8.DRV, а также оконные DIB-режимы.




До ознакомления с исходным кодом MGL я совершенно не был знаком с VBE/AF. Судя по всему, эта технология не обрела широкой популярности, и драйверы для неё разрабатывались лишь ограниченным кругом производителей.
Библиотека MGL нашла применение во множестве игр, среди которых: WinQuake, Hexen II, Grand Theft Auto, Maui Mallard in Cold Shadow, Total Mayhem и Balls of Steel.
Видеосистема DirectDraw
Microsoft ясно понимала, что GDI, хоть и был адекватен для стандартных приложений, совершенно не справлялся с требованиями видеоигр. Ещё в Windows 3.1 компания выпустила WinG (Windows for Games) — SDK для разработчиков игр, призванный обеспечить более прямой доступ к полному экрану. Вторая версия WinG была переименована в DirectX и включала API для полноэкранного 2D-режима, получивший название DirectDraw.
Несмотря на высокую безопасность и надёжность, Microsoft Windows налагала значительные ограничения на приложения. Одним из последствий этого стало то, что игры и другие графические приложения, требующие высокой производительности, лишились возможности прямого доступа к аппаратным ресурсам для достижения максимальной скорости и расширения функциональности. Долгие годы программисты продолжали работать в DOS, а пользователям Windows приходилось переключаться в DOS-режим для запуска игр, симуляций и прочих графических программ. В итоге возникло серьёзное противоречие: графическая операционная система, в которой графические приложения работали крайне неэффективно.
Первым шагом к решению этой проблемы стал продукт под названием WinG. Его первая версия, выпущенная в 1994 году, требовала Win32 в Windows 3.1. Ключевой особенностью WinG была возможность для игрового программиста быстро передавать битовые карты из системной памяти в видеопамять. Это позволило создавать игры для Windows со значительно более высокой производительностью.
Microsoft позднее переименовала новую версию Game SDK в DirectX 2. Последующие версии выходили как DirectX 3, DirectX 5, DirectX 6 и актуальный на тот момент DirectX 7.
Фенг Юань, «Windows Graphics Programming Win32 GDI and DirectDraw»
DirectDraw значительно превосходил GDI по производительности, однако из-за потенциальных ошибок в драйверах или отсутствия DirectX в системе он не всегда гарантировал стабильную работу. Его можно было принудительно отключить с помощью флага nodirectdraw.
Видеосистема WinDirect
Внимательные читатели могли заметить одну очевидную аномалию: приложениям Win32 был запрещён прямой доступ к оборудованию. Как же тогда MGL могла обходить GDI/DirectDraw и взаимодействовать напрямую с VBEAF, VBE и VGA?
Это стало возможным благодаря проприетарной технологии SciTech под названием WinDirect. Принцип её работы подробно описан в SciTech MGL Reference Guide v4.pdf.
Что такое WinDirect?
WinDirect — ключевой компонент SciTech MGL: это пакет среды исполнения для DOS и Windows 95, предоставляющий прямой доступ к дисплейному оборудованию для 16- и 32-битных приложений. Традиционно приложения Windows должны были осуществлять весь графический вывод через стандартный Graphics Device Interface (GDI). Несмотря на мощь и многофункциональность GDI, он не отличался высокой скоростью для графики, требуемой в приложениях реального времени, таких как видеоигры.
WinDirect преодолевает это ограничение, позволяя высокопроизводительным приложениям отключать стандартный интерфейс GDI и получать полный контроль над оборудованием для отображения графики, подобно тому, как это происходило в DOS. После отключения GDI интерактивные графические приложения могут перепрограммировать контроллер дисплея и записывать данные непосредственно в видеопамять. Приложение, использующее WinDirect, может запрограммировать любой графический режим VGA, например, 320x200x256, перепрограммировать контроллер и реализовывать графику в стиле стандартного VGA ModeX или вызывать стандартные сервисы VESA BIOS для реализации графики SuperVGA высокого разрешения.
MGL v4 Programmer Guide[3]
Руководство программиста MGL v4 является бесценным источником информации. Если вас, как и меня, интересовало назначение библиотек WDIR32.DLL и WDIR16.DLL, поставлявшихся с WinQuake, то ответ найден: в документации они упоминаются как компоненты WinDIRECT. Аналогично, там же описываются PMPRO16.DLL и PMPRO32.DLL как независимый от расширителя DOS API для сервисов защищённого режима. В этом же документе упоминается и Zen Timer Майкла Абраша!
Исходный код MGL не был включён в WinQuake; дистрибутив содержал лишь заголовки и уже скомпилированную 32-битную библиотеку MGLLT.LIB (MGL Lite), необходимую для компиляции. SciTech опубликовала исходники в 2000 году[4], но сейчас они уже недоступны. На GitHub[5] можно найти версию MGL v5, которая к тому времени претерпела значительные изменения (например, WinDirect был удалён).
К счастью, неравнодушный пользователь сохранил зеркало MGL v4. Если вы хотите изучить её самостоятельно, установите mglb405.exe и mgls405.exe. В качестве альтернативы можно загрузить мою сборку src.rar.
Подведём итог
Подводя итог, winquake.exe эффективно находил оптимальный путь для рендеринга графики, используя либо DirectDraw, либо WinDirect. Даже при вынужденном переключении на режим DIB, он всё равно предлагал преимущества по сравнению с quake.exe. Кроме того, возможность выбора аудио-бэкенда позволяла пользователям приоритезировать либо высокую частоту кадров, либо минимальные задержки звука. В результате игроки получали превосходный игровой опыт, что полностью оправдало усилия разработчиков.
Спустя более чем три десятилетия, winquake.exe по-прежнему запускается в Windows 11. Хотя полноэкранный режим не адаптирован под широкоформатные дисплеи, оконный режим функционирует безупречно. Это впечатляющее свидетельство приверженности Microsoft обратной совместимости, несмотря на иногда спорные архитектурные решения.
Источники
[1] Why did ID choose DJGPP for Quake?
[3] Руководство программиста MGL v4
[4] SciTech выпускает исходный код MGL 4.0 OpenGL



