![image](https://habrastorage.org/getpro/habr/post_images/1be/d93/579/1bed935796ddf566046772fd3043e678.png)
Я изучал ванильный исходный код игры Wolfenstein 3D 1992 года. Несмотря на то, что ей уже 25 лет, и она совершенно устарела для современных платформ, её всё равно можно скомпилировать, если воссоздать окружение.
Для этого требуется всего лишь:
- Исходный код Wolfenstein 3D.
- DosBox.
- Компилятор Borland C++ 3.1.
- Wolfenstein 3D shareware (чтобы позаимствовать ресурсы).
Настройка файловой системы
Откроем командную строку и создадим две папки, по одной для каждого из необходимых дисков DOS:
cd ~
mkdir system
cd system
mkdir c
mkdir a
cd ~
Скачиваем файлы
- Скачиваем Borland 3.1 в
system/a
. - Скачиваем исходный код Wolfenstein 3D в
system/c
- Скачиваем файлы VGA в
system/c
(в конце статьи я объясню, зачем это нужно).
cd system/a
curl -O http://fabiensanglard.net/Compile_Like_Its_1992/tools/BCPP31.zip
cd ../c
curl -O http://fabiensanglard.net/Compile_Like_Its_1992/tools/wolfsrc.zip
curl -O http://fabiensanglard.net/Compile_Like_Its_1992/tools/vgafiles.zip
Теперь все файлы находятся в файловой системе. Просто чтобы проверить, введём:
cd ..
find ~/system
У вас должно получиться следующее:
/Users/fabiensanglard/system
/Users/fabiensanglard/system/a
/Users/fabiensanglard/system/a/BCPP31.zip
/Users/fabiensanglard/system/c
/Users/fabiensanglard/system/c/vgafiles.zip
/Users/fabiensanglard/system/c/wolfsrc.zip
Распаковываем всё
cd ~/system/a
unzip BCPP31.zip
cd ~/system/c
unzip vgafiles.zip
unzip wolfsrc.zip
DosBox
Скачаем и запустим DosBox:
![](https://habrastorage.org/getpro/habr/post_images/238/5e5/e06/2385e5e06855f3948567318ed0fb1159.png)
Монтируем
Смонтируем файловую систему, по одной папке для каждого из дисков:
Z:/> mount c ~/system/c
Z:/> mount a ~/system/a
Устанавливаем компилятор
Настало время установить Borland C++ 3.1:
Z:\> a:
A:\> cd BCPP31
A:\> install
![](https://habrastorage.org/getpro/habr/post_images/722/1ad/2bc/7221ad2bc2fc89c032e7360900090282.png)
Нажмите «ввод» при выборе исходного диска (должен быть выбран диск A)
![](https://habrastorage.org/getpro/habr/post_images/1c2/7b2/f27/1c27b2f27ac9ac0db05ef6d8ceaaa0cc.png)
Оставим все параметры по умолчанию и выберем «Start Installation»:
![](https://habrastorage.org/getpro/habr/post_images/6ad/b2e/b58/6adb2eb586f40e43dbc34a4d7a16f78c.png)
Уведомления предупреждают, что не удаётся найти папку Microsoft Windows, но она нам не нужна, просто нажмём «ввод».
![](https://habrastorage.org/getpro/habr/post_images/b13/d0e/9d3/b13d0e9d3adbcf491ed0fbf9fb84ab95.png)
![](https://habrastorage.org/getpro/habr/post_images/5a4/aa1/784/5a4aa1784fa0a5cf1ed10399b84a25e1.png)
![](https://habrastorage.org/getpro/habr/post_images/d8b/36b/37f/d8b36b37f646400fa84ea47502a4017d.png)
Устанавливаем исходный код Wolfenstein 3D
Система работает и в ней есть компилятор: настало время распаковывать (снова) исходный код.
A:\> c:
C:\> cd C:\> install
![](https://habrastorage.org/getpro/habr/post_images/5f4/506/1bc/5f45061bc98973fe604d4f6419b8f017.png)
Введём «C»
![](https://habrastorage.org/getpro/habr/post_images/153/934/3f0/1539343f020b6fea6a8cb6ba8c8b51d6.png)
Оставим путь по умолчанию:
\WOLFSRC
![](https://habrastorage.org/getpro/habr/post_images/f8a/7a0/14c/f8a7a014caad18e2b494267d97f7cbdf.png)
Подтвердим («Y») создание директории.
Устанавливается!
![](https://habrastorage.org/getpro/habr/post_images/aa9/9bc/df4/aa99bcdf4c205bc6dee79c8a7e31e54c.png)
Компилируем
Запускаем Borland C++ 3.1:
C:\> cd C:\> cd borlandc
C:\> cd bin
C:\> bc.exe
![](https://habrastorage.org/getpro/habr/post_images/0ae/b2f/007/0aeb2f007ade10ffaebbef440f47d562.png)
После нажатия на OK, используем мышь или горячие клавиши, чтобы выбрать Project > Open Project
..\..\WOLFSRC\WOLF3D.PRJ
:![](https://habrastorage.org/getpro/habr/post_images/038/8a7/799/0388a7799f42c525a17db63f5e39975c.png)
Выберем Options > Directories и изменим значение следующим образом:
Include Directories: C:\BORLANDC\INCLUDE
Library Directories: C:\BORLANDC\LIB
Ouptput Directories: OBJ
Source Directories: C:\WOLFSRC
![](https://habrastorage.org/getpro/habr/post_images/75d/b8c/055/75db8c05557419dcd59b94345e1776ee.png)
Попробуем скомпилировать: Compile -> Build All
![](https://habrastorage.org/getpro/habr/post_images/242/324/bfd/242324bfd3c1a11981abbfeb34decf57.png)
Мы получим ошибку: «Cannot find executable TASM»
![](https://habrastorage.org/getpro/habr/post_images/bd6/a32/4d8/bd6a324d83bb10155c927f1f7b721a44.png)
Выйдем из Borland C++, нужно настроить PATH:
C:\> CD ..
C:\> PATH=C:\BORLANDC\BIN
C:\> BC.EXE
Снова попробуем скомпилировать (Compile -> Build All):
![](https://habrastorage.org/getpro/habr/post_images/2ca/fe1/5fb/2cafe15fba7f39b87f8964eca3de3bf5.png)
Компилирование выполнилось, но возникла ошибка компоновки: «Unable to find OBJ file», потому что путь к SIGNON.OBJ и GAMEPAL.OBJ в проекте указан неверно.
Они отмечены в
C:\SOURCE\WOLF\
:![](https://habrastorage.org/getpro/habr/post_images/b6a/2de/c58/b6a2dec58c74e5705891a988816c6676.png)
Удаляем их из проекта (Выберем Projext > Delete item). Добавим их снова через PROJECT > Add Item…. Добавляем
WOLFSRC\OBJ\SIGNON.OBJ
и WOLFSRC\OBJ\GAMEPAL.OBJ
![](https://habrastorage.org/getpro/habr/post_images/c0f/1e8/291/c0f1e82911897d60923133bab0b2a89d.png)
Попробуем скомпилировать снова (Compile > Build All)
![](https://habrastorage.org/getpro/habr/post_images/e33/2e4/a06/e332e4a0617de1e772c68b5f84361d9f.png)
Сработало! Но запустится ли игра?
![](https://habrastorage.org/getpro/habr/post_images/119/cd7/2a1/119cd72a1ae1b61abf2b85980fa44f5e.png)
Достаём ресурсы
Скачайте shareware-версию, или даже лучше: купите как полную версию Wolfenstein 3D.
cd ~/system/c
curl -O http://fabiensanglard.net/Compile_Like_Its_1992/tools/1wolf14.zip
unzip 1wolf14.zip
Вернёмся в DosBox и установим игру в
C:\WOLF3D
. C:\> c:
C:\> cd C:\> cd 1wolf14
C:\1WOLF14> install
После установки игры скопируем только что скомпилированный файл .EXE в папку игры,
C:\> c:
C:\> cd wolf3d
C:\WOLF3D> copy WOLF3D.EXE WOLF3D.OLD
C:\WOLF3D> copy ../WOLRSRC/WOLF.EXE
Запускаем игру
Попробуем запустить:
C:\> cd wolf3d
C:\WOLF3D> copy WOLF3D.EXE WOLF3D.OLD
C:\WOLF3D> copy ../WOLRSRC/OBJ/WOLF3D.EXE .
C:\WOLF3D> WOLF3D.EXE
Хм, выглядит странно…
![](https://habrastorage.org/getpro/habr/post_images/715/0fd/a3a/7150fda3a814d7347ec7ffa8b656e2c5.png)
Ой…
![](https://habrastorage.org/getpro/habr/post_images/945/52f/cd9/94552fcd92d25c7c39d7345b7215f1f7.png)
Что?
![](https://habrastorage.org/getpro/habr/post_images/0aa/e6a/caa/0aae6acaaff24b66f7fcf7e3977d497f.png)
Не припомню, чтобы игра была такой…
![](https://habrastorage.org/getpro/habr/post_images/7ff/6ae/010/7ff6ae0100182cd362b1199f906569f1.png)
Так, где-то возникла ошибка!
Что случилось?
Дело в конвейере производства игры и в том, как он использовался движком. Когда Адриан Кармак и Кевин Клауд заканчивали работу над всеми графическими файлами, они использовали инструмент IGRABed для их упаковки. В результате получалось 3+2 файла.
- VGAHEAD.WL1
- VGAGRAPH.WL1
- VGADICT.WL1
Файл VGAHEAD — это индекс, содержащий указатели на VGAGRAPH, в котором хранятся данные, сжатые алгоритмом Хаффмана. VGADICT содержит словари Хаффмана для распаковки данных.
Два других созданных файла:
- GRE.H
- GRE.EQU
компилируются в движок, как показано на рисунке ниже:
![](https://habrastorage.org/getpro/habr/post_images/f8c/56f/f87/f8c56ff87a3f3ca9967936cb19ecbe4b.png)
Для чего нужны файлы
.H
и .EQU
? Если вкратце, то они позволяют получать доступ по имени. Когда IGRABed собирает все файлы, он также создаёт перечисление (enum) с соответствующими индексами:GRE.H
enum{
H_WOLFLOGOPIC
GETPSYCHEDPIC
L_GUYPIC
.
.
} graphicnums
GRE.EQU
H_WOLFLOGOPIC = 0
GETPSYCHEDPIC = 1
L_GUYPIC = 2
Таким образом, когда движок запрашивает нужный ресурс, он может использовать логическое имя (L_GUYPIC), а не «магическое число» (2).
Это значит, что движок выпускался с жёстко заданными индексами изображений в файлах VGA. Поскольку ресурсы и база кода эволюционировали после выпуска wolf3D shareware (в Spear of Destiny), новые скомпилированные индексы игры не совпадают с расположением исходных файлов ресурсов.
Запускаем игру (снова)
К счастью, у этой проблемы есть простое решение: кто-то сгенерировал ресурсы VGA заново, чтобы они совпадали с индексами в файлах .H и .EQU, выпущенных с исходным кодом. Просто скопируем эти файлы (если вы используете ресурсы из shareware-версии, то нужно будет изменить расширение файлов с .WL6 на .WL1).
C:\> copy C:\vgafiles\VGADICT.WL6 C:\WOLF3D\VGADICT.WL1
C:\> copy C:\vgafiles\VGAGRAPH.WL6 C:\WOLF3D\VGAGRAPH.WL1
C:\> copy C:\vgafiles\VGAHEAD.WL6 C:\WOLF3D\VGAHEAD.WL1
Попробуем снова:
C:\WOLF3D> WOLF3D.EXE
Работает!
![](https://habrastorage.org/getpro/habr/post_images/cb4/ba8/a40/cb4ba8a40163cfb96a916e6debad0966.png)
Но мы всё ещё не закончили!
Буфер кадров VGA и соотношение сторон экрана
Это может быть неочевидно для людей, никогда не видевших оригинальную игру, но представленная выше картинка из DosBox не совсем совпадает с тем, что видели игроки в 1992 году. Буфер кадров VGA имел размер 320x200, но у ЭЛТ-мониторов соотношение сторон равно 4:3. Это значит, что буфер кадров при отправке на монитор вертикально растягивался. В DosBox есть опция для компенсации этого:
vi ~/Library/Preferences/DOSBox\ 0.74\ Preferences
[render]
# frameskip: количество кадров, пропускаемых DOSBox при отрисовке кадра.
# aspect: выполнять коррекцию соотношения сторон. Если способ вывода не поддерживает масштабирование, то это может привести к замедлению работы!
# scaler: используется для расширения/улучшения режимов низкого разрешения.
# Если использована опция 'forced', то scaler используется, даже когда результат может оказаться неправильным.
# Возможные значения: none, normal2x, normal3x, advmame2x, advmame3x, advinterp2x, advinterp3x, ...
frameskip=0
aspect=false
scaler=normal2x
Поменяем значение aspect на true.
Попробуем снова:
C:\WOLF3D> WOLF3D.EXE
Наконец-то заработало!
![](https://habrastorage.org/getpro/habr/post_images/1be/d93/579/1bed935796ddf566046772fd3043e678.png)
![](https://habrastorage.org/getpro/habr/post_images/224/e88/787/224e88787659516fc3a36525bfbda421.png)
![](https://habrastorage.org/getpro/habr/post_images/972/e3e/cb8/972e3ecb860493126cf67c7c5c79a468.png)
Поделиться с друзьями
iCpu
Не думал, что скажу это, но… Тогда это было проще.
icCE
Вот первая мысль была, конечно проще. С другой стороны, я собираю старые машины и их периодически включаю. Когда начинаешь что-то делать, возникают неожиданные проблемы. Кажется и железо нормальное, а по тем временам вообще топ и помнишь все. Но нет, несовместимость в разных местах, косяки разработчиков.
![](https://habrastorage.org/web/882/d19/ec6/882d19ec6fba44638ee281ba8f350e68.jpg)
Времени на установку занимает порядочно. Вспомнить, что раньше все это еще надо было найти и скачать (про купить можно забыть). Почитать доки как установить. Это сейчас,dosbox трах бах и готово.
Вот попробовать на такой матери скомпилировать :) Интересно долго будет?
iCpu
Обратно, попробуйте собрать тот же OpenSSL на какой-нибудь нестандартной архитектуре или операционной системе. Я не говорю о миграции на «Эльбрусы», даже просто переход на какой-нибудь старый x86 форк Дивана — огромная боль. И тем более, сборка движка Source с сохранением приличной производительности на ARM5.
Так что всё относительно, медлительность сборки и отсутствие удобных средств разработки с лихвой компенсируется общей примитивностью конкретного оборудования и небольшим объёмом кодовой базы.
icCE
ну вы тут смешиваете, хотя и это в общем на текущий момент не помеха.
Есть тулчайны, эмуляторы — которые в общем делают жизнь проще.
Сборка движку Source для ARM5, это уже не просто взять исходники и собрать. Это уже оптимизация под архитектуру. В статье мы этим не занимаемся.
Сейчас для каждого уже настолько обыденность интернета и доступности информации вокруг. У каждого мобильник которым он может снять видео, фото, записать голос и сразу опубликовать для всех. Еще в 2003 году не было такого обилие и живем мы в такой роскоши жалкие 10 лет (по моим примеркам все стало меняться в 2007-2008 годах). Только старые вещи дают понять, насколько все было сурово. Как мы выкачивали инфу через BBS/FIDO/USENET. Поэтому да, сейчас проще такие вещи делать.
iCpu
Доступность? Попробуйте найти даташит на какой-нибудь не очень обычный контроллер, да хотя бы алгоритмы получения POST-кодов по PCI-e и их список. Получение информации о BIOS'е, комплектующих и прочем — так же. Всё это гуглится с огромным трудом, и, что хуже, с куда большим трудом реверсится. А ряд запросов просто не гуглится, потому что какой-то умник сделал сокращение или название в унисон модному хештегу, так что даже белый пояс по гугл-фу не даёт пробиться сквозь решёточки.
Я в одном согласен, раньше было очень по другому.
da-nie
О! У меня почти такая же есть. :) Надо попробовать как-нибудь её достать и запустить BC3.1. :) А сама игра на ней идёт так: https://www.youtube.com/watch?v=4hYXPHeZ7aA
Кстати, Idot сделал на OpenGL Wolf-3D. :)
icCE
Ну эту мать удалось спасти, так как батарейка сделала свое черное дело.
Ремонтом уже занимался не я, так как у меня ушло бы больше времени.
Вот тут можно посмотреть, что в общем делали. Там и взрывы были :)
da-nie
Там 8 МГц процессор. И турбо, действительно, не включено.
А каким образом 8 МГб поставить на такую плату? Там же память на рассыпухе.
icCE
Тогда не удивительно, что тормоза на весь экран. Но все равно, надо отдать должное, что Кармак и команда сделали возможным запуск на 80286 с такими параметрами.
icCE
На моей плате есть SIPP, это прообраз SIMM и он обратно совместим (кроме ног)
У меня есть мать 80286 и с simm разъемами сразу.
Другой момент, что в общем и целом для обывателя эти 8MB на 80286 вообще не нужны.
da-nie
А, увидел, внизу для SIPP места. Только SIPP совместим по ножкам с SIMM-30 Pin.
icCE
Ну все верно. Simm 30 pin :)
Мать понимает 2 мегабайтные модули.
По ногам я имел ввиду механически. Сейчас идет пайка к модулям ног, так как замена разъема может быть фатальна для платы.
Pinsky
Думал, что будет статья критикующая использование make-файлов и autotools и рекомендации перейти на более современные инструменты/виденье того, как должно быть.
OlegTar
Через 4 года выйдет первый квейк, и какой прорыв! Просто пропасть…
kostus1974
borland c++ 3 мать его 1! странное чувство возникло, что-то давно забытое… как запах школьной столовой в первом классе… но нет, это не слёзы умиления. хорошо, что этого больше нет.
shukan
Вы правы. Этого больше нет.
MasMaX
Первый набор команд заменяется одной строчкой:
mkdir -p ~/system/{a,c}
Это так, придирки немного))))
jankovsky
Зачем такие игры если их так сложно запустить. Еще и графика странная. Наверное пародия на олдскул.
MasMaX
Тег «ирония» забыл
spikedviper
Вы, наверное, хотели пошутить, но у вас это не вышло.
relia
Года 4 назад качнул OpenGL порт Duke Nukem 3D v 1.4 — у меня запускается на Windows 7 X64. К так и не увиденным мной в 90ых годах 60fps (играл в режиме VGA и с 9...12fps) добавилось еще и разрешение FullHD (правда синтетика сглаженная из исходных спрайтов, но все-таки). Побаловался немного — налетела ностальжи по студенческим годам :) Что-то в таких погружениях в светлые момент прошлого все-таки есть.
Pusk1
Спасибо за статью. Очень приятные воспоминания от окошек Борланда. Вспомнилось, как успевал сходить в туалет покурить, пока небольшой проект C++ компилировался на XT:) Паскаль компилировался на порядок быстрее.
В 1992-м с файлами чаще из Norton Comander работали, но это придирки. Если такой хардкор с командной строкой, то где автономный компилятор?:)
safari2012
Турбо Паскаль (даже с турбовижн) компилировался за считанные секунды. А мои одногрупники, которые отважились пересесть на C++, не только покурить, но иногда даже пообедать успевали :)
HEKOT
А я до сих пор держу дома Virtual Pascal, на котором работал году эдак в 98. Кстати, кросс-компилятор для Win32, OS/2 и linux. Использую его, когда надо написать какую-нибудь мелочёвку и получить тёплые и ламповые ощущения от процесса.
Rastishka
О, а не пробовали подправить чтобы было HD разрешение?
CarambaPirat
А как без ресурсов подправить до HD? там же ресурсы не резиновые
Rastishka
Нет, чисто чтобы стены без ступенек были.
А ресурсы пусть остаются какие есть. =)
Rastishka
За что минусы? Почему нельзя подправить разрешение, а ресурсы пусть растягиваются на принципу nearest neighbor? Ну да, что то сползет, если абсолютными координатами задано.
relia
Статья написана переводчиком, о чем есть метка в заголовке, — он слово в слово перевел страницу http://fabiensanglard.net/Compile_Like_Its_1992/index.php
![image](https://habrastorage.org/getpro/habr/comment_images/842/655/440/842655440e218d84d6aca8c0ac5695e3.jpg)
HD порты уже есть: http://www-personal.umich.edu/~jimw/games/
RiseOfDeath
Должен заметить, что он выглядит отвратительно.
relia
IMHO не отвратительней исходника
Pinsky
Позвольте не согласиться.
Luke0208
Думаю многие будут согласны, что графика в играх не важна. Даже мучатся с компиляцией ради нее — приятно)
Optimus_990
Тут главное — процесс))
К сожалению лично не застал эту игру, хорошо помню первый Doom.
perfect_genius
Надо было ещё бинарно сверить.