experiments
Today

Легенда о хардкоре: Duke Nukem 3D, Watcom и FreeBSD

Как утверждают психологи «все проблемы человека происходят из детства» — все что не дали родители в юном возрасте потом обязательно проявит себя во взрослой жизни.

В моем, весьма специфическом случае такой нереализованной мечтой детства долгое время оставался.. компилятор Watcom, дорваться до которого удалось лишь спустя почти тридцать лет.

Рассказываю об этом удивительном проекте.

Сборка и запуск Duke Nukem 3D в самом неожиданном месте.

Детская травма

Хотя я уже неоднократно и красочно описывал разные интересные компиляторы далекого (и не очень) прошлого, история с Watcom C/C++ отличается:

о его существовании я узнал будучи еще совсем подростком.

Но поскольку жил тогда сильно далеко от столиц — найти такое чудо на местных BBS развалах CD-дисков было проблематично.

А когда заветные диски все же удалось раздобыть, возникла куда большая проблема — как в этом всем разобраться, в 16-то лет:

Так выглядела среда разработки Watcom C/C++ 11, 1995 год.

Увы, но чуда тогда не случилось, Цукерберг так и не позвонил и моя карьера программиста ушла в сторону Java и серверов приложений, вместо нативной разработки на C++. Ну, а продукт от Watcom постепенно терял свои лидерские позиции среди инструментов разработки и уже к началу 2000х полностью пропал из актуальной повестки.

Наверное теперь вы задаетесь вопросом:

откуда подросток из глухих сибирских краев вообще мог узнать о столь специфичной вещи, чтобы потом ее целенаправленно искать?

Все довольно просто и даже очевидно:

In the mid-1990s some of the most technically ambitious DOS computer games such as Doom, Descent, Duke Nukem 3D, Rise of the Triad, and Tomb Raider were built using Watcom C/C++ using the DOS/4GW protected mode extender with the Watcom compiler.

Да да, те самые «компьютерные игоры», увлечение которыми в моем случае пошло сильно не туда — вместо того чтобы в них играть и деградировать, я начал их препари.. разбирать на части, в попытках понять как же оно устроено.

Знаменитый DOS/4GW фигурировал в описании системных требований почти каждой компьютерной игры тех лет, а слово «Watcom» быстро нашлось при визуальном осмотре EXE-файла, из которого запускалась одна из самых любимых игр:

В EXE-файле известного Duke Nukem 3D.

Так я узнал, что на свете существуют компиляторы Watcom.

Легендарная мощь

Теперь серьезно.

Набор оптимизирующих компиляторов и средств разработки Watcom C/C++ долгое время оставался одним из лучших инструментов для профессиональных программистов, в первую очередь из-за своей производительности:

In a February 1989 overview of optimizing C compilers, BYTE praised Watcom C 6.5's "unmatched execution speed" and noted that it was the most ANSI C-compliant.

Еще одной причиной народной любви к этому тулчейну была его портабельность  — Watcom C/C++ поддерживал много разных платформ, причем как на хосте, так и в качестве целевых:

Из рекламного блока в журнале 1995 года.

Собственно списком выше закрывались практически все потребности Windows-программистов тех лет, поскольку Watcom C/C++ поддерживал все актуальные на тот момент платформы и архитектуры.

Еще это довольно редкий случай поддержки Novell Netware в качестве целевой платформы — не так много компиляторов позволяли подобное.

Рекламный блок про Watcom C/C++ из все того же журнала 1995 года.

Печальная история

К сожалению Watcom пришлось повторить судьбу многих других легендарных проектов:

In 2000, Sybase, who owned Watcom International Corporation halted the commercial sale of the Watcom C/C++ and Fortran compilers.

Компанию-производителя, которая стояла за этим легендарным проектом банально купил более крупный игрок.

Прекрасно понимаю что «бизнес есть бизнес», но по какой-то причине уникальные проекты, будучи поглощенными крупной компанией, неизменно проигрывают корпоративной бюрократии. После чего они скатываются, теряя свою уникальность, окончательно загибаясь в корпоративных застенках.

Так что печальная история Watcom C/C++ на самом деле весьма обыденна, но в данном случае это был еще не конец.

OpenWatcom

Цитируя википедию:

In 2003, SciTech Software Inc, a customer of Sybase, negotiated wth Sybase, to have the code for the compilers released as an open source project under a new name, OpenWatcom.[2]

Так на свет появился новый проект «Open Watcom» — открытый форк Watcom C/C++, разрабатываемый по открытой модели и с прицелом на сообщество энтузиастов.

К сожалению компания SciTech, организовавшая сей праздник щедрости несколько переоценила собственные возможности:

проект компилятора это «серьезно и надолго», требует участия огромного количества высоквалифицированных программистов.

Которые разумеется бесплатно не работают.

Видимо именно от такого надрыва компания и закончила свои корпоративные дни в 2008 году, будучи проданной канадской Alt Richmond Inc. Которая ныне также не существует.

На фоне всех этих печальных событий, к середине 2010 года работы над проектом «Open Watcom» были свернуты:

The last stable version endorsed by the original openwatcom.org team was 1.9, released in June 2010.[3][4]

OpenWatcom V2

Но интерес к проекту OpenWatcom все же сохранился, поэтому уже к 2015 году «упавшее знамя» разработки было подхвачено сообществом — теми самыми энтузиастами, ради которых проект когда-то открывали:

We are back!
Open Watcom is like a mythical bird Phoenix that never dies
and rises again from the ashes.
So do we.
The reports of our death are greatly exaggerated.

Так появился проект OpenWatcom V2 — открытый форк открытой версии компилятора Watcom C/C++.

Несмотря на столь бодрые заявления новой команды и обнадеживающий поток свежих коммитов в репозитории, ныне проект находится скорее в «цифровом чистилище», зависнув между возрождением и окончательной смертью:

стабильных релизов как таковых нет с 2015 года и народ выкладывает «daily builds» — ежедневные сборки.

Поэтому как новая версия 2.0 так и устаревшая, но пока еще поддерживаемая 1.9 на самом деле собираются из разных master-веток и с текущим набором коммитов.

Вот такие привратности судьбы в стиле «Игры престолов» Дж. Мартина — падение от «very popular compiler for high-end games» до дважды закрытого проекта, форкнутого на потеху энтузиастам.

Коллекционная сборка Watcom C/C++ 10 из 1994 года, отсюда.

Славные гусарские традиции и FreeBSD

Как уже упоминал выше, Watcom и оба его продолжения — весьма портабельны, причем расширение списка поддерживаемых платформ является одним из постоянных направлений работ:

There is ongoing work to extend the targeting to Linux and modern BSD operating systems, running on x86, PowerPC, and other processors.

Все настолько поехали далеко зашло, что в скрипте сборки присутствует даже Haiku и DragonFly, хотя конечно есть определенные сомнения в стабильности работы на столь редких платформах .

Как бы то ни было, компиляторы Watcom воспринимались программистами как инструмент в первую очередь Windows-разработки.

Так что идея собрать «OpenWatcom v2» под FreeBSD, затем полученным компилятором собрать известный исторический проект под MS-DOS — показалась.. крайне забавной.

А когда закончим — сможете поцеловать компилятору.. например управляющий интерфейс, в честь славных гусарских традиций прошлого, ага.

Так выглядит оригинальный отладчик Watcom 10. Отсюда.

Справка для обывателей

Прежде чем снова погружать читателей во мрак хардкора со сборкой компиляторов из исходников под звуки бубна, стоит все же рассказать о более легком пути, который внезапно есть.

Десяток лет практики в C/C++ это конечно не заменит, но немного времени и психического здоровья вам точно сохранит.

Во-первых существуют готовые сборки OpenWatcom: 2.0, 1.9, которые достаточно скачать и распаковать.

Каждая такая сборка содержит набор компиляторов для всех поддерживаемых платформ: MS-DOS, Windows, Linux и так далее, с разделением на 16, 32 и 64-битные версии, чем мы дальше будем активно пользоваться.

Но поддержки FreeBSD в готовых сборках разумеется нет.

Во-вторых, если вдруг Бог наказал вас использованием ArchLinux вместо операционной системы, в AUR есть готовые пакеты с OpenWatcom, как 2.0 так и 1.9 версий, которые достаточно «просто установить».

Ну и само собой разумеется, для «Windows-бояр» ничего устанавливать не придется само упадет, достаточно распаковать и прочитать инструкцию.

Новые приключения неуловимых

Ну что ж, честно предупредив о возможных последствиях в виде потерянного времени и сломаной психики, можно наконец начинать выносить читателям мозг.

Для всех шагов ниже использовалась самая последняя на момент создания статьи FreeBSD 15.1.

Впрочем и на более ранних версиях особых проблем замечено не было.

Начнем с малоизвестного для простых обывателей факта:

для того чтобы собрать из исходников компилятор, нужен.. другой компилятор.

Который называется bootstrap compiler и используется на начальных этапах сборки таких проектов.

В качестве bootstrap-компилятора в моем случае использовался gcc13, который должен быть установлен в системе вместе со всем своим окружением.

Дополнительно, для отдельных стадий сборки, потребуется эмулятор Dosbox, также доступный в портах.

Ввиду особенности FreeBSD в виде приделывания номера версии к управляющим приложениям GCC, необходимо создать ссылку:

ln -s /usr/local/bin/g++13 /usr/local/bin/g++

Альтернативный вариант это ручная правка скриптов сборки, с массовой заменой вызываемого g++ на g++13, скрипты довольно большие и сложные, поэтому если захотите такое провернуть — правок будет много.

Но вернемся к нашей сборке.

Сборка OpenWatcom

Ультимативно и не мелочась, забираем исходники OpenWatcom сразу из master-ветки:

git clone --depth 1 https://github.com/open-watcom/open-watcom-v2.git

История коммитов весьма объемна, поэтому стоит указать ключ --depth 1.

Следующим шагом необходимо создать копию скрипта с настройками локального окружения, чтобы не было проблем со слиянием правок при обновлении репозитория:

cp setvars.sh local_setvars.sh

Затем изменить локальную копию — необходимо найти и раскомментировать параметр OWDOSBOX, указывающий на название исполняемого файла эмулятора Dosbox:

export OWDOSBOX=dosbox

Дальше необходимо этот скрипт запустить, чтобы в окружении появились все заданные там переменные (для bash):

source ./local_setvars.sh

При запуске отобразится используемый bootstrap-компилятор:

Теперь наконец запускаем саму сборку, не забывая молиться:

./build.sh

Сразу предупреждаю, процесс сборки будет идти долго даже на мощном компьютере, сравнимо по времени со сборкой ядра Linux, OpenOffice и других крупных проектов. На диске должно быть ~4Гб свободного места.

Объясняется это тем, что в процессе будут собираться компиляторы и инструментарий под все поддерживаемые ОС и архитектуры.

Тот самый процесс, уникальный в своем безумии: так собирается OpenWatcom под FreeBSD.

Если вам повезет и сборка завершится успешно, следующим шагом будет необходимо собрать релизную версию:

./build.sh rel

Который будет находиться в каталоге rel.

Так выглядит завершенная релизная сборка OpenWatcom под FreeBSD.

Дальше копируем готовую релизную сборку в то самое место, откуда собираемся потом использовать:

mkdir /opt/app/watcom
cp -r rel/* /opt/app/watcom/ 

Теперь создаем скрипт с переменными окружения, который будет необходимо подключать до начала использования OpenWatcom:

#!/bin/sh
export WATCOM=/opt/app/watcom 
export PATH=$WATCOM/binb64:$PATH 
export INCLUDE=$WATCOM/h:$WATCOM/h/nt 
export EDPATH=$WATCOM/eddats 
export WIPFC=$WATCOM/wipfc

Поскольку в переменную PATH добавляется каталог binb64, после применения скрипта будет использоваться нативная сборка OpenWatcom для FreeBSD, не для Linux или Windows:

Так выглядит нативный компилятор OpenWatcom под FreeBSD. Теперь вы видели все.

Тем не менее, нативная сборка, как оказалось, вполне неплохо справляется с задачами кросс-компиляции под DOS и даже Windows, что мы будем использовать далее.

Сборка Duke Nukem 3D из исходников в IDE, с помощью собранного из исходников OpenWatcom. На FreeBSD.

辻斬り

Цудзигири (辻斬り или 辻斬, дословно: убийство на перекрестке, англ. Tsujigiri) — японская практика, когда самурай, получив новую катану или разрабатывая новый вид боя или оружия, испытывал его эффективность, нападая на случайного оппонента.

Катаны у меня пока нет, зато есть собранный из исходников компилятор и острое желание проверить его на первом встречном практике.

Конечно можно было ограничиться примерами, которые идут в комплекте с OpenWatcom и на этом успокоиться, благо там весьма неплохая и функциональная подборка:

Классический "Hello, world" в виде приложения для 32-битной Windows NT, собрано и запущено под FreeBSD.

Но подумав, что это будет слишком уж скучно для читателей и недостойно упоминания в летописях, собрал с помощью OpenWatcom действительно интересный исторический проект — тот самый «Duke Nukem 3D», с которого когда-то началось мое с ним знакомство.

Duke Nukem 3D

Duke Nukem 3D это такая древняя (1997 год) стрелялка, где инопланетные монстры, «свинокопы» с дробовиками, стрельба из ракетниц с двух рук и прочие милые подростковые радости:

"Come get some!" (ц)

Пока другие дети яростно резались в эту замечательную игру по сети, бодро отстреливая инопланетных монстров и друг друга, я ковырял исходники пытался делать карты в редакторе уровней Build, создав в итоге с его помощью.. собственную школу!

В нынешние неспокойные времена беготня по виртуальному учебному заведению с пистолетом в руке конечно вызовет определенные вопросы и общественное порицание, но в мои школьные годы на такие шалости смотрели сильно проще.

Поэтому позже я продолжил интересную практику картостроения уже в серии игр Quake.

Но про мой замечательный опыт игростроя расскажу как-нибудь отдельно, благо это весьма интересная история, а пока вернемся к истории с Watcom и сборкой «Duke Nukem 3D» из исходников.

Конечно же исходный код столь популярной и коммерчески успешной игры увидел свет далеко не сразу:

Сохраненная копия ныне несуществующего сайта компании 3D Realms.

Целых семь лет фанаты донимали разработчиков, кивая в сторону ID Software, создавшую практику раскрытия исходников собственных игр. И наконец это случилось:

1 апреля 2003 года исходный код игры «Duke Nukem 3D» увидел свет.

Но поскольку на дворе были 2000е и к тому времени появилась бесплатная версия OpenWatcom, разработчики решили помочь энтузиастам, переделав оригинальную сборку, чтобы игру можно было собрать обоими версиями компиляторов:

Duke was originally written with the Watcom 10.0 C/C++ compiler. 
This code has been updated to allow it to compile under the free version 
of the Watcom compiler available from their webpage 
(http://www.openwatcom.org).

Таким образом официальная версия исходников Duke Nukem 3D, увидевшая свет в 2003м году поддерживала сборку с помощью OpenWatcom, но к сожалению его первой версии, которую затем форкнут энтузиасты.

Поскольку 1.x версия OpenWatcom (включая даже последнюю в линейке 1.9) имеет проблемы совместимости с 2.0, для того чтобы собрать из исходников «Duke Nukem 3D» именно второй версией придется мигрировать проект — переделывать скрипты сборки и (немного) исходники.

Хотя такая миграция и не представляет серьезной проблемы, делать ее вручную не придется, поскольку известный в узких кругах товарищ neozeed уже успел это сделать за нас, выложив в отдельном репозитории версию исходников с поддержкой OpenWatcom 2.0.

Забираем:

git clone https://github.com/neozeed/duke3d-openwatcom2.git

Собир.. увы но нет, дальше начинаем думать, поскольку следующие шаги весьма нетривиальны.

Ниже я покажу два варианта сборки:

  • из-под DOS с помощью Dosbox и DOS-версии OpenWatcom;
  • по боярски из-под Wine и с помощью Watcom IDE.

Оба варианта по своему экстремальны, поскольку дело будет происходить на FreeBSD, но самое интересное вас ожидает как обычно в конце повествования.

Чистый DOS

Как уже упоминал выше, при сборке OpenWatcom создаются версии компиляторов под все поддерживаемые платформы:

Собирается по-умолчанию далеко не все, поэтому список ниже не полный:

  • binb64 — 64-битная сборка под FreeBSD
  • binl — 32-битная сборка под Linux
  • binl64 — 64-битная сборка под Linux, не собирается по-умолчанию
  • binnt - 32-битная cборка для Windows
  • binnt64 - 64-битная сборка для Windows
  • binp — сборка для OS/2
  • binw — 16-битная сборка для Windows и DOS

С учетом такого подхода, система сборки wmake в подкаталоге binw будет представлять собой приложение для DOS:

А в версии для Windows — в подкаталоге binnt это будет уже Win32-приложение:

Следующий важный нюанс заключается в том чтобы задать переменные окружения для работы с компилятором OpenWatcom, причем так чтобы их увидел эмулятор Dosbox.

Создаем новый каталог duke3d-work:

mkdir duke3d-work

Линкуем внутрь каталог с Watcom, чтобы не иметь проблем с длинными путями каталогов:

ln -s /opt/app/watcom ./watcom

Копируем исходники Duke Nukem 3D:

cp -R /opt/src/duke3d-openwatcom2/ ./duke3d

Теперь создаем в корне файл env.bat с таким содержимым:

@ECHO OFF
SET WATCOM=C:\WATCOM
SET PATH=%WATCOM%\BINW;%PATH%
SET EDPATH=%WATCOM%\EDDAT
SET INCLUDE=%WATCOM%\H
REM SET LIB=
REM SET WWINHELP=%WATCOM%\BINW

И стартуем Dosbox с указанием этого файла, обязательно из текущего каталога:

dosbox env.bat 

В результате запустится эмулятор DOS с подготовленным окружением для сборки:

Теперь переходим в каталог DUKE3D и запускаем сборку проекта:

CD DUKE3D
WMAKE

Надо отметить, что сборка происходит весьма неспешно — несмотря на небольшое количество файлов в проекте, исходного кода в каждом из них навалено с избытком:

Так происходит сборка Duke Nukem 3D из исходников.

К сожалению сборка немного сломана, поэтому через какое-то время процесс прервется с ошибкой:

Ошибки происходят из-за того что игра использует части движка Build (что логично), который необходимо собирать отдельно до самой игры.

Так что переходим в каталог с движком и запускаем отдельную сборку:

CD BUILD\SRC
WMAKE

Движок должен собраться без ошибок:

Теперь возвращаемся обратно в каталог с игрой и повторно запускаем сборку:

CD ..\..
WMAKE

Все требуемые файлы найдутся, кроме одного:

Как именно получилось, что один из ключевых файлов движка оказался пропущен в скрипте сборки от neozeed гадать не берусь, но для исправления ситуации необходимо добавить новый блок в build\src\makefile:

mmulti.obj : mmulti.c
	wcc386 mmulti /4r /s /or

Затем выполнить сборку отдельно для этого файла, чтобы получить искомый mmulti.obj:

CD BUILD\SRC
WMAKE MMULTI.OBJ

В результате должен собраться этот пропущенный файл:

Возвращаемся в каталог с игрой, удаляем game.obj, который окажется битым из-за пропущенного файла и заново запускаем сборку:

CD ..\..
DEL GAME.OBJ
WMAKE

На этот раз сборка должна завершиться успешно и даже сформируется заветный DUKE3D.EXE, но появится сообщение с ошибкой про отсутствующие инструменты для встраивания DOS4/GW:

Взять эти два файла можно например тут, их необходимо скопировать в каталог binw, где расположена DOS-версия OpenWatcom, после чего удалить недоделанный DUKE3D.EXE и перезапустить сборку:

DEL DUKE3D.EXE
WMAKE

Теперь наконец релизная сборка успешно завершится:

Файл D3D.EXE будет той самой релизной версией игры.

Но это все — скучные и непонятные «буковки на черном экране», все приличные программисты как известно используют такую штуку как «среда разработки» и у Watcom она очень даже есть.

Так выглядит Open Watcom IDE в работе, с открытым проектом Duke Nukem 3D.

Wine, Watcom и IDE

Среда разработки официально называется Watcom Integrated Development Environment и собирается из исходников при сборке компилятора, к сожалению только для Windows-платформ. Использование требует предварительно заданных переменных окружения, поэтому ее запуск из-под Wine — весьма нетривиальное занятие.

К счастью, автор успел съесть целую стаю собак на нетривиальных проектах и история с Watcom на этом шаге не обрывается.

В корневом каталоге проекта, рядом с env.bat, который мы создавали ранее для сборки с помощью Dosbox, создаем еще один файл env-nt.bat с таким содержимым:

@ECHO OFF
SET WATCOM=z:\opt\app\watcom
SET PATH=%WATCOM%\BINNT;%PATH%
SET EDPATH=%WATCOM%\EDDAT
SET INCLUDE=%WATCOM%\H;%WATCOM\H\NT%
REM SET LIB=
REM SET WWINHELP=%WATCOM%\BINNT

Из интересного тут путь в переменной WATCOM, который должен указывать на каталог с релизной сборкой OpenWatcom, но при этом иметь том Z: и разделитель в стиле Windows.

Том Z: это специальная уличная магия из Wine для бесшовного доступа к файловой системе хоста, с ее помощью можно указать путь к каталогу, который физически находится на диске FreeBSD, но должен использоваться из программы для Windows.

Запуск также представляет определенную проблему, поскольку с недавних пор Wine для FreeBSD поставляется только 64-битной версии и для эмуляции 32-битных приложений используется специальный цирк на конной тяге запуск.

Вводим:

wine wineconsole

Запустится новое приложение-терминал, аналог cmd.exe, работающий на базе Wine. Вводим уже в нем:

ent-nt.bat

Затем проверяем командой set, что переменная WATCOM указывает на нужный каталог:

Теперь наконец запускаем среду разработки:

ide.exe

Среда очень быстрая, хотя и весьма специфичная на нынешние времена, работает и сборка и отладка и запуск финального приложения, но разумеется в пределах возможностей Wine, поэтому запустить или отладить приложение для DOS, OS/2 или Win16 так просто не получится.

Вот так выглядит сборка и запуск Win32-версии знаменитой игры «Life», которую можно найти в примерах для OpenWatcom:

Теперь можно вернуться к проекту «Duke Nukem 3D» и собрать его наконец «по взрослому» — из среды разработки.

В меню File->Open Project выбираем файл duke3d.wpj и нажимаем кнопку Open:

Откроется проект со списком файлов с исходниками , по двойному клику на файле запустится редактор, в котором собственно и происходит работа с исходным кодом:

Вот так когда-то происходила разработка ваших любимых игр.

Собрать проект можно кнопкой «Make current target» на панели инструментов:

Сборка из среды довольно серьезно отличается от версии с wmake, поэтому при запуске появятся новые интересные ошибки:

Не буду в очередной раз утомлять последовательным перечислением всех багов, найденных в процессе сборки из IDE и сразу расскажу как все это забороть:

  • копируем файлы из каталога libs в корень проекта;
  • копируем файлы mmulti.obj, cache1d.obj, engine.obj,a.obj из каталога build\src в корень проекта.

После этого сборка из IDE должна завершиться успешно:

Надо добавить, что сборка из IDE не прикручивает расширитель DOS4/GW.

Вот таким нехитрым способом (даже двумя) мы получили исполняемый файл знаменитой игры «Duke Nukem 3D», собранный из исходников с помощью компилятора Watcom — чего только не сделаешь из-за детских комплексов.

Самое время попробовать запустить.

Одна из многочисленных "пасхалок" Duke Nukem 3D.

Грандиозный провал

Ввиду прошлой известности и популярности, архивы с «Duke Nukem 3D» до сих пор можно легко найти в интернете. Ныне оригинальная игра является «abandonware» (заброшенным софтом), поэтому свободно доступна для скачивания с фанатских сайтов.

Скачиваем, например отсюда, распаковываем архив, заменяем DUKE3D.EXE на собственноручно собранную копию (D3D.EXE в случае сборки из-под DOS) и пробуем запустить с помощью Dosbox.

И получаем.. грандиозный провал:

На самом деле это уже "продвинутая" версия Dosbox, называется Dosbox-X. Но падает с таким же треском.

Думаю на этом месте многие читатели вздохнули с облегчением и обрадовались:

«гусарский наскок» с шашкой на танк с нестабильными сборками из исходников под неподдерживаемой операционной системой закончился предсказуемо.

На пятнадцатой минуте статьи, после шагов по сборке компилятора, запуску и сборке самого Duke Nukem 3D из исходников, получился.. битый EXE-файл, попытка запуска которого вешает эмулятор.

И наверное на этом печальном абзаце статья бы и закончилась, будучи списанной в утиль за столь позорный провал. Если бы автор был нормальным обычным человеком.

Та самая сцена из х\ф "Святые из Бундока".

И разразилась битва

К несчастью для окружающих компилятора воспитывали и образовывали меня советские инженеры, привившие крайне специфическое отношение к компьютерной технике:

cо времен получения инженерного диплома, все что ездит, плавает и летает считаю законной целью для своих экспериментов и сильно огорчаюсь когда машина делает не то что мне хочется.

Поэтому конечно автор не отступил и как уже можно было заметить по заглавной картинке к статье — все-таки повесил «отрубленную голову OpenWatcom» у себя над камином.

Теперь рассказываю как это было.

Первым делом я попробовал замедлить эмуляцию, задав более точную настройку CPU, соответствующую компьютерам тех лет в ~/.dosbox/dosbox-<версия>.conf:

..
[cpu]
core=normal
cputype=pentium
cycles=fixed 30000
..

Там же полностью отключил звук, затем переключил реализацию движка отрисовки на более совместимую.

К сожалению ничего из этого не помогло и собранная с таким трудом версия DUKE3D.EXE продолжала вешать эмулятор, тогда как оригинальная работала без каких-либо проблем.

Пробовал и запуск в полной эмуляции оригинального MS-DOS 6.22 с помощью 86Box, пробовал и другую реализацию расширителя памяти dos32a — с его помощью эмулятор перестал падать, но вместо картинки был лишь черный экран.

Следующим шагом был отказ от собранной под FreeBSD версии OpenWatcom и проверка на готовом билде для Linux:

Одна из готовых сборок OpenWatcom v2 под Linux.

Увы, но все это не помогло и собранная из исходников версия «Duke Nukem 3D» продолжала стабильно вылетать, выбешивая автора роняя эмулятор.

Следующим шагом был отказ от сборки, созданной для поддержки OpenWatcom v2 в пользу оригинальных исходников, раскрытых в 2003м году.

Забрав оригинал из этого репозитория на Github, я последовательно прошелся по всем правкам, созданным neozeed и добился таки сборки оригинальных исходников с помощью второй версии OpenWatcom.

Но даже этот радикальный шаг не помог и собранная версия игры продолжала падать.

Зато я заметил важную деталь:

Каталог с оригинальными исходниками на Github.

Даже в оригинальной версии почему-то присутствовали готовые объектные файлы (.OBJ), несмотря на наличие рядом исходного кода.

Это врядли могло быть недосмотром, поскольку перед выкладкой исходники специально чистили от лишнего мусора.

Как оказалось в дальнейшем, веская причина действительно была.

Решив проверить, как поведет себя собранное приложение будучи слинкованным с готовыми объектными файлами из оригинальной версии 2003 года, я перекинул их в свою копию и собрал билд.

Получившийся программный «франкенштейн».. внезапно заработал!

Таким образом, поиск проблемного места сократился до четырех объектных файлов. Дальше все было совсем просто:

методом исключения, последовательно подменяя исторические OBJ-файлы на собранные вручную, был наконец определен виновник сбоев.

Все свелось к одному единственному файлу A.OBJ и его исходному коду A.ASM.

Когда в тему даже линк на группу.

Ассемблер наносит ответный удар

Разумеется красочный рассказ выше про поиск причины сбоя можно было сильно сократить или вообще оставить за кадром, оставив лишь сухую сводку, из серии «проблема была решена».

Но тогда у читателей осталось бы ошибочное представление о поиске решения столь нетривиальной проблемы как о чем-то простом и обыденном.

В реальности это был весьма напряжненный процесс «кровавого ресерча», который закончился успехом практически случайно.

Но вернемся к нашему A.OBJ.

Оказалось, что сей интересный файл содержит ключевую часть игрового движка Build, на котором работает «Duke Nukem 3D», а его исходный код A.ASM представляет собой ~2000 строк на чистом ассемблере. Что весьма немало для чистого ассемблера, не каждый демосценер осилит столько наклепать.

Причем ассемблерный код написан так, что собрать его возможно только с помощью WASM из пакета OpenWatcom:

;Warning: IN THIS FILE, ALL SEGMENTS ARE REMOVED.  THIS MEANS THAT DS:[]
;MUST BE ADDED FOR ALL SELF-MODIFIES FOR MASM TO WORK.

Поскольку ничем другим (TASM/MASM/JWASM) собрать действительно не получилось, я решил обратиться к Марксу первоисточникам, прочитав наконец описание сборки:

the assembly is built with version 10, and the audio library is version 11

И все встало на свои места.

Позже были найдены и другие интересные проблемы, связанные со спецификой ассемблера от Watcom, затем подтвердились требуемые шаги по сборке Duke Nukem 3D строго определенной версией Watcom:

For Duke3D v1.5, use Watcom C 10.0 and *not* any other version; Not even 10.0a or 10.0b. For any of Matt's EXEs, use Watcom C 10.6a (and no other version)

Это чудо, что мой «кавалерийский наскок» с нестабильной версией OpenWatcom v2 и под FreeBSD вообще позволил хоть что-то собрать.

Был найден пост с готовым Watcom-окружением для сборки Duke Nukem (у все того же neozeed), в приложенном архиве находится все необходимое:

Watcom C/C++ 10 и оригинальные исходники Duke Nukem 1.5

Запустить сборку проще всего из Dosbox, распаковываем архив на диск и переходим в каталог, затем вводим:

dosbox .

Таким образом эмулятор запустится с текущим каталогом в качестве диска С: Затем вызываем скрипт для установки переменных окружения:

WATCOM\SETVARS.BAT

Переходим в каталог с исходниками движка и запускаем сборку проблемного A.ASM:

CD DUKE3D\BUILD\SRC
WASM A.ASM

Ошибок не будет и в результате появится тот самый A.OBJ — причина всех бед и несчастий при сборке Duke Nukem 3D.

Так это выглядит в действии:

Так выглядит сборка проблемного A.OBJ с помощью оригинального Watcom 10.

Все, дальше достаточно скопировать полученный A.OBJ к себе и пересобрать DUKE3D.EXE — получим наконец нормально работающую игру времен моего детства.

Все герои в сборе.

Эпилог

На этом завершается «легенда о хардкоре» — удивительном компиляторе Watcom с непростой судьбой и туманными перспективами.

Хотя статья создавалась в первую очередь ради знакомства читателей, не заставших «те времена» со этим интересным и уникальным проектом, прекрасно понимаю что игра «Duke Nukem 3D» также станет для многих открытием.

Если вам интересно «просто поиграть» в золотую классику — разумеется есть куда более простые способы это сделать, нежели сборка игры из ее исходников, тем более исторических и под FreeBSD.

Для примера, активно развивается проект EDuke32 — современная версия движка «Build», поддерживающая не только «Duke Nukem 3D», но и многие другие игры, c поддержкой современных ОС, готовыми сборками и сильно улучшенной графикой — все как вы любите.