Если вам успели надоесть и азиатки и знойные африканки и даже развратные животные, рассказываю про одну редкую UNIX-систему из далекого прошлого, которая был возвращена из небытия и выведена в интернет.
Так это выглядит в работе.
История
OSF/1 это еще одна редкая UNIX-система из далекого прошлого, которую вы врядли могли наблюдать в живую:
Прямой участник корпоративных Unix‑разборок 90х известных как Unix Wars, но в отличие от A/UX (которую автор оживил и запустил в прошлом выпуске) OSF/1 не канула в лету в бурные 90е а будучи переименованной в TRUE64 UNIX поддерживалась аж до 2012го года.
Вот вам и «динозавр», внезапно отказавшийся умирать.
Еще из интересных фактов стоит упомянуть использование этой ОС для суперкомпьютеров:
OpenBSD/luna88k running inside GXemul, on an emulated SGI O2 running OpenBSD/sgi (on a FreeBSD/amd64 host). Теперь попробуйте осознать прочитанное.
Эмулятор
Полностью оно называется Gavare's eXperimental Emulator за авторством Anders Gavare и согласно официальному описанию с сайта проекта, считает себя фреймворком для виртуализации:
GXemul is a framework for full-system computer architecture emulation, mostly written in 2003-2005. Several real machines were implemented within the framework, consisting of processors (ARM, MIPS, Motorola 88K, PowerPC, and SuperH) and surrounding hardware components such as framebuffers, interrupt controllers, busses, disk controllers, and serial controllers. The emulation is working well enough to allow several unmodified "guest" operating systems to run.
По сути это такой сильно разросшийся «pet project», созданный одним энтузиастом ради эмуляции особо редких систем:
Простым обывателям из этого списка знакомы наверное только игровые платформы, в лучшем случае еще «малинка» (Rastberri Pi) а про некоторые особо редкие не знал даже автор, так что будут еще изыскания и эксперименты, посвященные этому удивительному проекту.
Сборка
К сожалению эмулятор достаточно давно не развивается, его последняя релизная версия 0.7.0 была выпущена в далеком уже 2021м году и содержала лишь мелкие исправления. Поэтому есть определенные проблемы со сборкой в современном окружении, которые опять придется исправлять вручную.
В этот раз все действия производились на обычном Mageia Linux, без BSD и прочих изысков, с использованием стандартного GCC:
This should work on most Unix-like systems, with few or no modifications to the source code. The basic requirement is a reasonably modern C compiler (C99).
Эмулятор написан все же на C++ а не на чистом С, поэтому для сборки требуется компилятор C++, который ныне устанавливается отдельным пакетом.
Но в остальном автор не врет:
GXemul does not require any additional third-party libraries to build.
И проект действительно не использует никаких внешних библиотек. Кроме X11, ради эмуляции графического экрана:
X11 headers and libraries: for graphical framebuffer emulation.
Так что ничего дополнительно устанавливать не придется.
С версии 0.6 разработка переехала на Github, откуда мы и заберем последние правки исходников (ветка master):
Главная проблема с этим эмулятором — неправильная работа с некоторыми эмулируемыми ОС без специального ключа сборки --debug:
When compiling on Linux via a modern GCC please bear in mind that the emulator wont work correctly if compiled with -O optimization flags. Please use -debug configure option to disable such optimization
Что выяснилось далеко не с первой попытки.
Изучаемая OSF/1 как раз из числа проблемных, поэтому попытка запуска в версии эмулятора, собранного без этого волшебного ключа выдает kernel panic:
Теперь вы тоже видели как выглядел kernel panic в 1992м, поздравляю.
Согласно официальному описанию, ключ --debug всего лишь отвечает за отладочную сборку:
configure for a debug build (turn off optimizations)
На практике все несколько сложнее и этим ключом помимо отключения оптимизаций, еще собирается отдельный оконный отладчик. Чтобы не вводить параметр каждый раз, я прописал в начале скрипта configure вот такой параметр:
DEBUG=YES
Скрипт кстати не из известного пакета autotools а полностью собственной разработки. После каждой правки configure скрипта или шаблонов Makefile.skel (см. ниже) необходимо перезапускать настройку вызовом:
./configure
Теперь запускаем make для запуска сборки и ждем приключений.
Первая ошибка не заставит себя ждать:
Связана она с изменениями в спецификации самого языка C++ и по-хорошему стоило бы эту логику переделать. Но поскольку это не мой личный проект, пошел по пути упрощения — просто переключив используемую версию спецификации при сборке.
Файл, в котором появляется эта ошибка, включается в сборку только при ключе --debug , так что без него вы эту ошибку вообще не увидите.
В файле src/main/Makefile.skel в конец значения параметра CXXFLAGS необходимо дописать указание на версию спецификации --std=c++14:
В этот раз сборка должна завершиться успешно и в корне проекта появится бинарник gxemul:
Запуск
К сожалению не удалось найти установочный диск OSF/1, поэтому я использовал готовый образ диска, в котором ОС уже была развернута.
Взят он был отсюда, также продублирован в нашем Телеграм-канале, если владелец сайта вдруг решит заблокировать доступ.
Команда запуска выглядит так:
./gxemul -e 3max -X -d osf1_mips.img -j vmunix
Где -e 3max указание на тип эмулируемой машины, 3max это например DECstation 5000/200 (3MAX):
Ключ -X указывает использовать графический фреймбуфер, без него вы не увидите графического приглашения. Ключ -d указывает на путь к образу диска (в архиве по ссылке выше) а вот -j это уже особая уличная магия:
-j name set the name of the kernel;
for DECstation emulation, this passes the name to the bootloader, for example: --j netbsd (NetBSD/pmax)
-j bsd (OpenBSD/pmax)
-j vmsprite (Sprite/pmax)
-j vmunix (Ultrix/RISC)
Войти в систему можно под учетной записью root с паролем Jaguar64.
Новый пользователь создается в терминале xterm, с помощью команды adduser:
Изменить пароль можно стандартной командой passwd.
Сеть
Разумеется без поддержки сети толку от такой эмуляции было бы немного. К счастью эмулятор сделает за вас большую часть работы по пробросу сети в эмулируемую систему (сторону хоста) — сам поднимет виртуальный интерфейс, назначит IP‑адрес и даже выставит DNS.
Вам остается только вторая половина — настроить сеть в системе 1992 года.
Как уже описал выше, эмулятор сам создает виртуальный сетевой адаптер, который со стороны гостевой OSF/1 называется ln0.
Должна отрабатывать команда:
ifconfig ln0
В выводе должно быть видно текущее состояние адаптера.
Также эмулятор самостоятельно создает исходящий адаптер с IP-адресом 10.0.0.254, который также является маршрутизатором.
Эти детали отображаются в консоли при запуске эмулятора:
The installed MIPS C compiler is good enough to compile some basic things, and gcc 2.9.5 should compile fine. Apparently binutils is broken, but ld is installed anyway.
Думаю реальная проблема в лицензиях, которые в те времена выдавались на компиляторы в коммерческих UNIX-системах.
Конец ноября в Питере — крайне мрачное время года, на улице лишь холод, сырость и уныние. Что определенно влияет на психику местных обитателей, порождая в головах самые нездоровые желания и идеи, которые затем попадают в криминальную хронику.
Видимо по этой причине, одним мрачным осенним днем мне захотелось создать графическое приложение на современном C++ под.. классический Mac из 90х.
В действии.
История
Честно не знаю что вам сказать, на этот раз у меня нет оправданий или логических объяснений для того что я опять сотворил.
Cпишем на плохую погоду и рептилоидов с Нибиру:
рассказываю и показываю как создавать приложения на современном C++ для классического Apple Macintosh начала 90х.
Примерно такого:
Macintosh Quadra 700. Компьютер как компьютер.
The Macintosh Quadra 700 is a personal computer designed, manufactured and sold by Apple Computer from October 1991 to March 1993.
Сам я никогда не видел такие машины в живую, поскольку в годы когда они выпускались был совсем зеленой школотой и жил в далеких сибирских пердях. Хотя даже живи я посреди Нью-Йорка в 90е — врядли бы смог позволить компьютер за почти шесть штук баксов:
The Quadra 700 originally had a list price of US$5,700
Такое и сегодня далеко не для всех.
Однако времена славы Макинтошей давно прошли, ныне все эти некогда «звездные» компьютеры — те что еще остались в рабочем состоянии, являются музейными экспонатами и предметами коллекционирования.
Поэтому, то что опишу ниже — точно не имеет никакого практического применения:
все это лишь эталонная, дистиллированная дичь, без примесей и добавок.
Это на тот случай, если вы вдруг ожидаете от статьи чего-то большего.
Весь сетап целиком.
Все началось, когда были выкованы мегакольц.. ээ нет, это из немного другой эпической сказки. В нашей все было проще — автор самым банальным образом набрел в сети на один интересный репозиторий, обещающий экзотическое путешествие в мир ужаса неведомые дали:
A GCC-based cross-compilation environment for 68K and PowerPC Macs. Why? Because there is no decent C++17 Compiler targeting Apple's System 6. If that's not a sufficient reason for you, I'm sure you will find something more useful elsewhere.
Разве можно было пройти мимо столь вдохновляющего описания?
Я тоже не удержался, убив в итоге несколько лишних дней на оживление и запуск этого чудовища чуда. Но прежде чем пойдем дальше, стоит рассказать читателям немного старой доброй матчасти:
почему автор так возбудился на какой-то неведомый набор консольных программ без картинок с голыми женщинами, еще и делающий с точки зрения обывателя не пойми что.
Матчасть
Представьте, что на вашем столе лежит вот такой кусок текстолита с железом, для которого надо написать программу:
Хотя именно этот девайс на самом деле весьма мощный.
Да, на фото выше самый настоящий компьютер:
c процессором, памятью и портами ввода-вывода — все как положено.
Но только слишком слабый для развертывания полноценной среды разработки непосредственно на нем.
Поэтому если вы не маньяк-психопат LISP-разработчик — будет откровенно сложно вести какую-либо разработку на такой хне без кросс-компиляции.
Кросс-компиляция это когда на обычном офисном компьютере без отрыва от игор cобирается приложение, предназначенное для запуска на принципиально другом устройстве:
смартфоне, роутере, соковыжималке, встраиваемой платформе умного дома, коптере или еще каком боевом роботе.
Или на другой операционной системе — сборка на линуксе под Windows это тоже вполне себе кросс-компиляция.
Тулчейн для кросс-компиляции обычно устанавливается (и даже собирается) отдельно, часто бывая очень сложным. Еще он содержит компиляторы, линкеры, ассемблеры для «вражеской» архитектуры и многое другое, не менее интересное.
В некоторых случаях тулчейн включает и части целевой системы:
заголовочные файлы, ресурсы и даже готовые библиотеки для линковки.
Без которых создавать что-то сложнее «Hello, world» с помощью кросс-компиляции было бы проблематично.
Так выглядит тот самый "Hello,world", собранный через кросс-компиляцию и запущенный в эмуляторе с MacOS 7.
Retro68
Теперь, после раскрытия матчасти можно переходить к этому замечательному проекту, чтобы оценить по достоинству масштаб проделанной работы и ее важность:
a gcc-based cross-compiler for classic 68K and PPC Macintoshes
Во-первых «gcc-based», что означает определенную совместимость с нормальными и современными компиляторами, а также отсутствие экзотических проблем, характерных для редких и/или устаревших компиляторов, вроде bcc.
Во-вторых тут две разных целевых архитектуры: 68k и PowerPC.
А значит можно собирать софт для всей линейки Маков с начала 90х и до начала 2000х — до MacOS X Tiger, последней поддерживающей архитектуру PowerPC.
Но пожалуй самое важное это поддержка трех разных UI-фреймворков на целевых системах:
Что означает возможность создавать приложения с графическим интерфейсом для всего зоопарка винтажных маков.
Типа такого:
Так выглядит демо с диалогом, созданное при помощи кросс-компиляции.
И все это без доступа к самому физическому устройству и пыток разработкой непосредственно в эмуляторе. Кстати процесс переноса собранного приложения (в примерах) в целевую систему также максимально упрощен:
сразу собирается готовый образ диска, который затем можно записать на носитель, либо подсунуть эмулятору.
Терминал
Когда только начинал собирать материал для этой статьи, узнал что в первых MacOS (внезапно) не было консоли и абсолютно все приложения были только и исключительно графическими:
возможно собрать в графическое, с таким псевдо-терминалом в комплекте:
Тоже является заслугой тулчейна Retro68 и ключем линковки при сборке:
LDFLAGS=-lRetroConsole
Сборка на FreeBSD
Тулчейн официально поддерживает несколько популярных операционных систем:
Linux, Mac OS X or Windows (via Cygwin)
И действительно совершенно спокойно, без каких-либо проблем и нюансов собирается на линуксе.
Что мне показалось слишком скучным, поэтому ради гусарской забавы портировал этот проект на FreeBSD.
Всегда так делаю.
Если вам такие забавы не близки, сообщаю что для линукса достаточно по шагам выполнить инструкцию в README. И все сразу будет хорошо, только не у вас.
Ну а мы как обычно пойдем путем хардкора — соберем весь тулчейн на FreeeBSD с нуля.
Кстати форк Retro68 с поддержкой сборки на FreeBSD выложен в отдельном репозитории. Первым делом надо установить ряд инструментов для разработки и системных библиотек:
Теперь надо немного изменить скрипт сборки, для учета особенностей FreeBSD.
Первым делом заменяем вызовы make на gmake, поскольку FreeBSD использует свою версию утилиты make, несовместимую с GNU-версией. Которая конечно также присутствует в пакетах, но только называется gmake.
Дальше необходимо переделать вызовы configure для вложенных проектов из скрипта сборки, суть правок:
пробросить указание на использование библиотек из каталога /usr/local, куда устанавливаются все внешние с точки зрения системы библиотеки в FreeBSD.
Тут уже нельзя использовать переменные окружения CFLAGS и LDFLAGS из-за особенностей сборки GCC и необходимо передавать пути для ключевых библиотек специальными аргументами:
Таким же образом необходимо поправить еще два места в скрипте сборки: раз и два.
После чего можно запускать сборку.
Запускается она из отдельного каталога:
mkdir ../Retro68-build cd ../Retro68-build ../Retro68/build-toolchain.bash
После весьма продолжительной (даже на мощном компьютере) и жутко выглядящей сборки, по накалу страстей на экране напоминающей знаменитый make buildworld из FreeBSD:
..все упадет на вот такой «страшной» ошибке:
Для исправления ситуации, надо всего лишь изменить один import в файле portable_endian.h , в этом месте:
Суть проблемы в том что расположение заголовка endian.h поменялось и теперь его необходимо включать без указания каталога sys:
# include <endian.h>
Исправляем импорт и перезапускаем сборку.
Однако через какое-то время напряженной работы и в очередной раз напугав обывателя простыней текста, сборка.. опять упадет.
На этот раз падение произойдет на стадии сборки из cmake:
Несмотря на весь внешний ужас, исправляется эта ошибка очень просто (если знать где копать разумеется):
удалением импорта этого заголовка из файла PEFTools/MakePEF.cc
Поскольку его содержимое в последних версиях FreeBSD добавили в stdlib. Так что смело удаляем импорт и перезапускаем сборку.
Следующее падение сборки и следующая проблема заключается в пересечении заголовков — системного, из самой FreeBSD и локального — из библиотеки libelf:
Тут к сожалению я не нашел изящного решения, достойного быть упомянутым в летописях, поэтому сделал «колхоз»:
скопировал файл gelf.h из libelf/include в каталог Elf2Mac, и поменял ссылки на этот заголовок из глобального на локальный.
Было:
#include <gelf.h>
Стало:
#include "gelf.h"
Поменять ссылки необходимо во всех файлах проекта Elf2Mac где встречается данный импорт. Наконец последняя ошибка сборки, связанная с особенностями FreeBSD:
Связана эта ошибка с тем, что часть необходимых структур для работы с сетью на FreeBSD вынесена в отдельный заголовок.
Готовый к использованию тулчейн будет находиться в каталоге toolchain, который стоит добавить в переменную окружения PATH.
Теперь переходим к эмулятору, поскольку живого Mac тех лет, на котором возможно запустить результат сборки у меня нет.
Эмулятор
Вообще эмуляторов винтажных Mac довольно много, поскольку маководы это сектанты очень увлеченные люди и многие из них используют и устаревшие компьютеры Apple и устаревший софт до сих пор, всячески отвергая прогресс и здравый смысл.
Такова сила бренда, созданного Стивом Джобсом.
Я буду использовать один из самых популярных и известных эмуляторов классических Macintosh:
Basilisk II is an Open Source 68k Macintosh emulator.
Разработан он был еще в начале 2000х, немецким инженером Christian Bauer, ныне активная разработка уже не ведется. Поэтому вместо нее я использовал более современный форк, в котором решены вопросы совместимости с современным же окружением и обновлены используемые библиотеки.
И внезапно добавлен JIT (Just-In-Time Compiler).
Еще форкнутая версия немного стабильнее, с более адекватным поведением перехвата курсора.
Эмулятор использует следующие библиотеки, которые необходимо установить до попыток сборки:
Еще вот тут находится крайне интересная табличка, с описанием практически каждого доступного ROM, его особенностей и работоспособности.
Напомню, что для этой статьи я эмулировал модель Quadra 600:
Для эмулятора использовался вот такой ROM-файл:
Указав в разделе «Volumes» путь к образу диска с MacOS7, затем в разделе «Memory/Misc» путь к ROM-файлу, можно наконец запускать эмулятор:
Теперь переходим к самому веселому — к разработке.
Разработка с помощью Retro68
Собственно после сборки Retro68, у вас будет все что нужно для разработки конечного софта, поскольку в каталоге build-target/Samples будут собранные примеры приложений:
Эти примеры собираются автоматически, во время сборки самого тулчейна Retro68, в качестве дополнительных тестов работоспособности.
Для сборки во всех случаях используется cmake, исходники находятся в каталоге Retro68/Samples.
Чтобы собрать проект с HelloWorld отдельно, выполняем:
сd /opt/src/Retro68/Samples/HelloWorld mkdir build cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=/opt/src/Retro68-build/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake gmake
Результат сборки:
Каждый пример при сборке генерирует образ диска, который можно сразу подключить к эмулятору:
Достаточно указать путь к dsk-файлу, который находится в каталоге build и запустить эмулятор:
На рабочем столе появится иконка с названием, совпадающим с названием примера:
После двойного клика по этой иконке, раскроется окно с содержимым этого виртуального диска в виде единственного запускаемого файла:
Двойной клик по файлу HelloWorld запустит наше приложение.
Примеры приложений
Как уже упоминал, в составе Retro68 есть довольно много демонстрационных приложений.
Каждый пример раскрывает аспект разработки и создан так, чтобы его можно было использовать в качестве основы для собственных проектов.
Автор тулчейна постарался, поэтому все примеры логичны, просты и понятны.
Retro68/Samples/Raytracer
Трассировщик лучей, реализующий генерацию псевдотрехмерной картинки в реальном времени. Собственно процесс отрисовки в этом приложении как раз показан на заглавной картинке к статье.
В проекте на самом деле присутствуют сразу две реализации, одна на С, другая на C++, видимо для сравнения во время работы.
Так выглядит финальный результат рендеринга:
Проект ценен в первую очередь как демонстрация расчетной логики и операций с числами с плавающей точкой.
Retro68/Samples/Dialog
Демонстрация работы с модальными диалогами — как задавать размеры и расположение элементов, как создавать формы ввода, как получать вводимые данные и так далее.
В работе:
Retro68/Samples/WDEF
Демонстрация работы с многооконными интерфейсами (MDI), создание окна с кастомным оформлением и работа с ресурсами окон.
Так это выглядит в действии:
Кратко по остальным примерам, реализующим какую-то специфическую логику.
Retro68/Samples/MPWTool
Реализует расширение для MPW (Macintosh Programmer's Workshop), точнее для MPWShell, с обработкой запуска оттуда и корректного возвращения в консоль.
Retro68/Samples/SharedLibrary
Реализует разделяемую библиотеку и приложение, его использующее в рантайме.
Retro68/Samples/SystemExtension
Пример простейшего расширения для самой операционной системы MacOS 7, в данном случае вся видимая логика заключается в показе новой иконки при запуске ОС.
Retro68/Samples/Launcher
Реализует запуск сторонних приложений через перетаскивание (Drag&Drop).
"Masters of Hardcore" - вбейте в поиск если не жалко уши и соседей.
Настоящий хардкор
Вы же не думали, что я успокоюсь на банальной сборке тулчейна с эмулятором под FreeBSD и запуске пары тестов?
Clapkit (CLassic APplication KIT) is a framework for developing applications for Classic Mac OS (System 7.x - Mac OS 9.x), basically a C++/object-oriented wrapper for Macintosh Toolbox functions.
Да, глаза вас не подводят, это самый настоящий современный графический фреймворк для компьютеров начала 90х.
Так это выглядит:
Картина неизвестного питерского художника "Мак под маком".
Так выглядит код:
#include <ckApp.h>
int main() {
CKApp* app = CKNew CKApp();
app->CKNewMsgBoxNote("Hello world!", nullptr, "OK", nullptr, [app](int button) { app->CKQuit(); }); // Run loop: without this, your app will quit as soon as it launches. while (!app->CKLoop(5)); delete app; return 0; }
Так выглядит мое тестовое приложение на современном C++, собранное с помощью cmake на FreeBSD и запущенное на MacOS 7 из 90х:
Поддержки юникода тогда еще не было, как и локализации на русский, поэтому "великий и могучий" есть лишь в комментариях.
Ну что дорогие читатели, ударим шизой по осенней летней хандре?
MPW
Конечно ударим, но прежде стоит рассказать про нормальную разработку для продукции Apple, как это происходило у нормальных людей.
Ее вполне можно использовать до сих пор, благо образов дисков в сети хватает. Именно так я и советую поступать (т.е. использовать MPW) в случае любого более-менее серьезного проекта, поскольку где и когда закончатся возможности кросс-компиляции и вы опустите руки — предсказать не берусь.
Как-то так MPW выглядит в эмуляторе:
Тут находится отличная статья по созданию «Hello, world» на MPW в эмуляторе, которой вполне хватит для начала приключений. Но в этот раз нам нужен не MPW а только его часть — системные заголовки, которые мы будем использовать для злодейства сборки.
В Retro68, в каталоге InterfacesAndLibraries находится файл Readme.md, содержимое которого явно намекает на дальнейшие действия:
Find a copy of Apple's Universal Interfaces 3.x (preferrably 3.4) and put them here.
Вообще «Find a copy» это такой толерантный и социально приемлемый синоним старого доброго «скачать варез», прямо из 90х. Потому как купить официально старое ПО уже не представляется возможным, если подобное вдруг придет в голову. Даже если компания-разработчик существует (как в случае Apple), старые версии своих продуктов она так просто не продаст.
Потому что есть поддержка, гарантии и защита прав потребителей.
И репутация компании.
Поэтому сообщаю по секрету, что «найти» эти самые универсальные интерфейсы можно например тут:
Сборка построена на cmake, но перед тем как собирать Clapkit, необходимо указать путь к Retro68 в скрипте сборки:
# Ensure Retro68 toolchain is set BEFORE defining project set(CMAKE_TOOLCHAIN_FILE "/opt/src/Retro68-build/toolchain/m68k-apple-macos/cmake/retro68.toolchain.cmake")
К сожалению в проекте есть небольшой баг с пропущенными заголовками, из-за которых он не собирается.
Для исправления достаточно добавить в include/ckTypes.h два импорта:
#include <Quickdraw.h> #include <Events.h>
В репозитории проекта находится готовый Showcase с демонстрацией возможностей фреймворка, на базе которого я и делал свое тестовое приложение (см. ниже).
Так выглядит сам Showcase в работе:
Напоминаю, что все это создано с помощью кросс-компиляции и затем запущено в целевой MacOS 7.
Выглядит заметно веселее, чем примеры из самого Retro68, согласитесь.
Тестовый образец
Я не хотел сразу пускаться во все тяжкие и портировать Doom/Quake/Cyberpunk 2077 под винтажные Маки из 90х — надо же оставить место воображению, поэтому мой тестовый образец для этой статьи это в первую очередь пример автономного, отделяемого приложения с минимальной логикой.
Которое собирается без привязки к иерархии каталогов Clapkit или Retro68.
отображает меню «Yo» в Finder, с единственным пунктом «Run me», по клику на который вызывается модальный диалог с двумя кнопками. По нажатию на «Quit» произойдет завершение работы программы.
Фигня-фигней, но только разработано и собрано оно полностью и целиком вне инфраструктуры MacOS и без средств разработки от Apple, даже без техники Apple.
На современном С++, под FreeBSD темной питерской ночью.
Так выглядит основной код на C++, файл main.cpp:
#include "main.h" #include <ckMenu.h>
CKTestAlexs* app;
int main() { // класс переименован ради тестов app = CKNew CKTestAlexs(); // false - не использовать стандартные пункты меню CKMenuBar* menuBar = CKNew CKMenuBar(false); // добавляем свой пункт меню в Finder CKMenu* menuTests = CKNew CKMenu("Yo"); menuBar->AddMenu(menuTests); // затем элемент в выпадающем списке CKMenuItem* item = CKNew CKMenuItem("Run me", 'R', [&item](CKEvent e) { // по клику произойдет отображение стандартного // модального диалога app->CKNewMsgBoxNote("Welcome to old school!", "Hello world", "Mkay", "Quit", [](int button) { // если нажали Quit - завершить работу приложения. if (button == 0) { app->CKQuit(); } }); }); // связывание элемента с пунктом меню menuTests->AddItem(item); // связывание меню с приложением app->CKSetMenu(menuBar); // бесконечный цикл ожидания для отрисовки, // без которого приложение сразу завершится while (!app->CKLoop(5)); delete app; return 0; }
Класс описан в заголовке main.h, декларации методов я убрал за ненадобностью:
#include <ckApp.h>
class CKTestAlexs : public CKApp { };
Так выглядит скрипт сборки для cmake, как можно заметить тут происходит автоматическое скачивание родительского фреймворка Clapkit и наложение патча с пропущенными импортами (описаны выше):
cmake_minimum_required(VERSION 3.16)
# Ensure Retro68 toolchain is set BEFORE defining project set(RETRO68_PATH "/opt/src/Retro68-build/toolchain/m68k-apple-macos") set(CMAKE_TOOLCHAIN_FILE "${RETRO68_PATH}/cmake/retro68.toolchain.cmake")
# Include Retro68 headers include_directories(${RETRO68_PATH}/include)
# Set default build type to Release if not specified if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type (Debug or Release)" FORCE) endif()
set(CLAPKIT_LOCAL_PATH "${CMAKE_SOURCE_DIR}/../../") option(USE_LOCAL_CLAPKIT "Use local checkout of clapkit instead of fetching from Git" ON)
if(USE_LOCAL_CLAPKIT AND EXISTS "${CLAPKIT_LOCAL_PATH}/CMakeLists.txt") message(STATUS "Using local clapkit at ${CLAPKIT_LOCAL_PATH}") add_subdirectory(${CLAPKIT_LOCAL_PATH} clapkit) set(USE_LOCAL_CLAPKIT ON) else()
Through some luck and a little persistence I have actually managed to get Rust code running on classic Mac OS (I’ve tried Mac OS 7.5 and 8.1)
Репозиторий находится тут, проект достаточно свежий (2023 год) и вполне рабочий.
Но предупреждаю сразу, что от исходного кода может случиться сердечный приступ, если любите классический C — на это лучше не смотреть.
Так оно выглядит в работе:
Кстати приложение сетевое, так что на Rust реализована не только работа с интерфейсом, но и с TCP/IP и даже HTTP протоколом.
Для операционной системы из 1994 года.
P.S.
Статья была опубликована на Хабре, более вольный оригинал как обычно в нашем блоге, форк Retro68 с поддержкой сборки на FreeBSD выложен в отдельном репозитории на Github.
То что описано в этой статье — за гранью понимания обычного разработчика и тем более обычного человека, далекого от ИТ. Честно и при всем желании не смогу объяснить даже подготовленным «молодым специалистам» от разработки, протирающим штаны в опенспейсе за шлепаньем форм для очередного корпоративного маркетплейса насколько круто то что описано ниже.
Если программирование для вас не более чем «работа за деньги» — пожалуйста закройте эту статью и забудьте автора как страшный сон, потому что описанное ниже вам точно не надо.
The goal of the Binary Golf Grand Prix is to challenge programmers to make the smallest possible binary that fits within certain constraints.
Cуть развлечения заключается в том чтобы создать минимально возможный запускаемый бинарник (нативное приложение), который делает хоть что‑то интересное.
Но этого показалось мало, поэтому помимо основной задачи, джентельмены каждый год придумывают себе дополнительные:
The binary you will craft will be the same executable when flipped backwards.
Да, вы все правильно поняли, а некоторые наверное даже сильно удивились с такой постановки вопроса, поскольку задача заключается в создании приложения, которое бы продолжило запускаться даже его бинарное содержимое перевернуть:
Критериев оценки в столь замечательном конкурсе два длина и толщина:
размер запускаемого бинарника и «процент реиспользования» байт при запуске в обратном порядке.
В оригинале:
Scores will be calculated based on both the size of the executable, as well asthe percentage of bytes executed when it is run.
Так что у джентельменов все серьезно.
Исходный код всех работ с описанием выложен на Github, также тут можно посмотреть разбор победителей этого замечательного конкурса за 2020й год и дальше не читать. Но если вы все же решили продолжить, то ниже будет описан реальный запуск каждой работы этого удивительного конкурса.
This was tested and built on Ubuntu 20.04 with kernel 5.4.0-42-generic.
Из-за последних изменений в ядре, бинарник более не работает на последних ядрах, по крайней мере мне не удалось запустить ни на одной из подконтрольных систем, увы.
Я разобрал один только первый год этой замечательной олимпиады, в следующих было уже заметно больше участников и куча интересных и сложных примеров, точно достойных внимания истинного джентельмена.
Отдельно доставляет блог создателя конкурса BGGP, некоторые материалы оттуда точно будут переведены в ближайшем будущем.
Если в большинстве современных RPG вы с первых минут — великий Избранный, который одной левой рашит подземелья, то в оригинальной Outward вы были, прямо скажем, никем. Обычным бродягой, которого могла отправить на тот свет банальная простуда или забытый бутерброд. И именно за эту беспощадную честность игру полюбили.
Канадцы из Nine Dots Studio делают полноценный сиквел. Философия Outward 2 осталась неизменной: вы всё еще не пуп земли. Но сам мир, механики и масштабы наших будущих страданий выросли в разы.
Игра выходит в ранний доступ 7 июля 2026 года, так что время морально подготовиться еще есть. А пока давайте разберем, что именно нас ждет в Аурае полвека спустя.
Мир, который живет без вас
Сюжет стартует через 50 лет после событий первой части. Нас снова выкидывают в мир Аурай, состоящий из четырех огромных регионов, где биомы и погода — это не просто красивые декорации, а ваш главный враг.
Разработчики наконец-то прикрутили полноценный календарь и смену сезонов, и это не косметическая фишка. Пришла зима? Реки замерзли. А значит, там, где летом вы искали лодку или мост, теперь можно просто пройти по льду. Жители городов тоже перестали быть прибитыми к полу манекенами — теперь они живут по расписанию и имитируют бурную деятельность.
Реиграбельность обещают бешеную. На старте дадут выбрать один из трех сценариев и целых 11 жизненных путей. Ваша предыстория напрямую определяет, где и с чем в карманах вы начнете игру. Плюс никуда не делись фракции (их три) — выбираете одну, и сюжетная ветка уходит в свое русло.
Отдельный интерес вызывают Иммакулаты. Помните тех жутких ребят из оригинала? За 50 лет их усмирили с помощью рун. Теперь эти бессмертные существа, которым не нужна еда и сон, пытаются как-то ужиться с обычными людьми. Размножаться они не могут, а местные жители всё еще косо на них смотрят из-за былых «заслуг». В общем, драма обеспечена.
Хардкор как стиль жизни
Элементы выживания здесь — это база. Голод, жажда, температура, болячки, выносливость и мана требуют постоянного контроля. Разбить лагерь, сварить похлебку и разобраться с забитым инвентарем — такая же важная часть геймплея, как и махание мечом.
Главный прикол оригинала перекочевал и сюда: в игре до сих пор нет GPS. Карта есть, но волшебной стрелочки «вы находитесь здесь» на ней не ждите. Ориентироваться придется по старинке: увидел странную скалу, сверился с картой, посмотрел на мох на деревьях и пошел, надеясь, что не в логово к людоедам.
А еще ваш огромный походный рюкзак всё так же режет мобильность. Перед серьезным махачом его нужно буквально скидывать на землю, иначе уворачиваться от ударов вы будете со скоростью беременной черепахи. Из хороших новостей: для тех, кто страдает синдромом Плюшкина, добавили вьючных животных.
Боевка: больше динамики, меньше «дерева»
Боевую систему знатно перелопатили. Она стала плавнее и отзывчивее — переходы от уклонений к атаке или блоку больше не ощущаются так, будто персонаж прогружает анимацию.
Главная фича боевки Outward 2 — парное оружие. В руки можно взять вообще любую комбинацию. Хотите бегать с факелом и чакрамом? Пожалуйста. Двуручники тоже прокачали, добавив им новые мувсеты.
С магией всё по-прежнему сурово и атмосферно. Это вам не «Скайрим», где фаерболы кастуются спамом одной кнопки. Магия в Outward — это ритуал. Нужны сигилы, правильные камни и четкая последовательность действий. Хочешь выдать мощный спелл? Сначала начерти всё на земле и подготовь площадку, а уже потом воюй.
Прокачка тоже преобразилась. В игре 8 деревьев навыков, но углубиться дадут только в три специализации. Скиллы всё так же покупаем у наставников за серебро, но добавилась система «практики». Характеристики растут от ваших действий: часто машете топором — качается сила; постоянно кувыркаетесь — растет ловкость.
Экран Game Over отменяется
Самое сладкое в Outward — это система поражений. Кнопки «загрузить быстрое сохранение» тут нет (игра сохраняется автоматом), но и после проигранного боя вы не умираете. Вместо этого игра генерирует уникальное последствие. И нет, это не халява.
Выглядит это примерно так. Вы огребаете от бандита. Теряете сознание. Приходите в себя глубокой ночью в лесу. Рюкзака нет. Кое-как наощупь находите свои шмотки в кустах, но тут вылезает местная фауна и с двух ударов снова отправляет вас в нокаут, потому что стамина на нуле. На этот раз везет: вас находит случайный путник и оттаскивает в город.
Вы живы, но есть нюанс. Каждое такое избиение оставляет долгосрочные травмы. Например, вывих запястья. Пластырем это не заклеить — нужна долгая реабилитация. Из-за травмы вы временно не можете держать щит или двуручник, а в поход идти надо. Приходится импровизировать: достаете из сундука старый кремневый пистолет, берете его в здоровую руку и идете мстить. Делаете выстрел, долго и потно перезаряжаетесь, добиваете врага и понимаете, что геймплей сгенерировал вам шикарную историю.
Ну а для тех, кому и этого мало, завезли опциональный хардкорный режим: при каждом падении в бою есть честный 20%-й шанс, что персонаж откинет концы окончательно и сейв просто удалится.
Outward 2 остается игрой, которая не прощает спешки. Она заставляет думать до того, как вы обнажите оружие. Снять рюкзак, выпить баффы, расставить ловушки, оценить шансы. Если лететь напролом, вы будете просыпаться лицом в грязи каждые полчаса.
Так что, пока мой персонаж будет лечить вывихнутую ногу, я, пожалуй, просто похожу хвостиком за городскими стражниками и втихаря пособираю лут с монстров, которых они убивают. Никакого геройства — я тут просто травник!
Помимо всем известной Apple, на свете существовала еще одна «фруктовая» компания, выпускавшая очень популярные компьютеры.
И сейчас мы цинично оживим и запустим эмулятор этих замечательных машин.
Главный герой все же справа а не слева.
Поскольку и сама компания и ее компьютеры и даже их эмулятор (вместе с его автором) — с берегов «туманного альбиона», большая часть ссылок в статье ведет в никуда на ресурсы, заблокированные для доступа из РФ, родной РКН к этому никакого отношения не имеет.
Поэтому надеваем монокли, цилиндры и поднимаем тост «За обход иностранных блокировок».
Изучая материалы из недавнего компьютерного прошлого, в который уж раз убеждаюсь:
за каждой успешной историей в ИТ есть натуральное кладбище из неудач и провалов.
А нынешние и всем известные «лидеры ИТ-индустрии» были отнюдь не первыми в своем деле и часто далеко не самыми инновационными. Еще у людей короткая память:
вчерашний «лидер рынка» и «король продаж» может легко и просто, а главное — невероятно быстро пропасть с концами из информационного поля.
Невзирая на всю шумиху в прессе, мощный пиар и даже народную любовь. Наша сегодняшняя история как раз про такую компанию:
Apricot Computers Ltd., originally Applied Computer Techniques Ltd. (ACT), was a British electronic company active from 1965 to 2005.
Who owned up to 30% market share in the UK, extended its sales in the USA and was ahead of IBM in the mid-80s in Europe?
Who was the first to launch speech recognition system for PC… in 1984?
Who introduced the first 3.5’’ floppy drive? The infrared trackball ? The keyboard with programmable functions keys along with a built-in LCD screen?
Who decided to deliver stylish designs, high resolution screens (800×400 in 1983), through a fully integrated conception in Scotland, allowing to manufacture in the early 90s one of the world’s most secure x86-based PCs?
Как видите, история получается более чем увлекательная, поскольку даже для весьма подкованного в винтажных вопросах автора эти факты оказались сюрпизом.
Так выглядел один из «абрикосов», предназначенный для корпоративного рынка:
Название к кириллице разумеется отношения не имеет — на экране отнюдь не буква «Ж», а стилизованное «Xi».
Поскольку был найден эмулятор этих интересных машин, решил попробовать это дело собрать и оживить. Однако все оказалось далеко не так просто и процесс написания этой статьи (вместе со сроками) пошел очень сильно не по плану, затянувшись на три месяца экзотических изысканий.
QDAE is a Quick and Dirty Apricot Emulator for Linux, Windows and MacOS X. This version emulates the Apricot F1, Xi and Portable; it may support other F-series and PC-series Apricots as well.
Основная разработка была закончена в далеком 2012 м году, собственно у файла Changelog, в котором находится описание изменений между версиями, дата последней модификации — май 2012 года. И с тех пор проект не развивается, можно сказать заброшен.
Сам эмулятор полностью оправдывает название «Quick & Dirty», поскольку был создан действительно «на коленке», на основе кодовой базы DOS-приложения а стабильность его работы — примерно как у Windows 95 оставляет желать лучшего.
Плюс документация (которой нет), ROM-файлы (которых тоже нет) и сами экзотические машины из далекого прошлого, физического доступа к которым нет и не предвидится.
Но разумеется все это меня не остановило.
Готовая сборка QDAE существует только для Windows, как оказалось в дальнейшем, автор эмулятора создавал эти сборки с помощью кросс-компиляции из-под Linux, причем очень старым компилятором.
Хотя все эти замечательные нюансы всплывут уже потом, скачивая первый раз сборку этого чуда, ни о чем подобном я и не подозревал.
Исходники находятся на личном сайте автора, никаких копий на GitHub обнаружено не было. Поэтому забирать придется оттуда:
Также архив с исходниками присутствует в Windows-версии эмулятора — будет лежать в каталоге установленного приложения. На всякий случай оставлю еще парулинков на сборки, поскольку непонятно как долго еще будет существовать личный сайт автора.
Образы ROM
Первой проблемой с этим эмулятором оказалось полное отсутствие ROM-файлов, необходимых для работы. Сам автор с истинно британским юмором советует «снять дамп с работающей машины»:
For copyright reasons, QDAE is not supplied with any BIOS ROMs or disk images. Accordingly, when you launch QDAE for the first time, it will abort with the message: "Could not open f1.rom". You will need a dump of the F1 ROM (the F10 ROM is not suitable; the F2 ROM may work but has not been tested).
Если у вас есть возможность сгонять на выходные в Лондон, найти там одну из примерно таких сохранившихся машин:
И затем уломать владельца на проведение жестоких экспериментов с его музейным экспонатом — проблемы разумеется нет.
Но я был не в настроении путешествовать и подумал, что будет разумнее поискать эти самые ROM в сети.
простой народ в UK замучен копирайтерами до такой степени, что автор боится выложить загрузочный образ для компьютера из 1980х, произведенного компанией, которой давно не существует.
Представляете как надо было запугать людей? Зато обнаружился и легкий намек на то, как эти самые образы можно получить:
Дальнейшие изыскания показали, что образы вообщем-то в сети есть, причем ихдовольномного. Только с ними есть нюанс:
Файлов ROM оказалось два.
А эмулятору нужен один.
Что это вообще такое и как быть?
Не буду утруждать читателя всей историей изысканий, но мои поиски в итоге привели к этому gist:
Use this script to merge a pair of even+odd / low+high roms into a single file. You'll need to do this for games which have 16-bit CPUs which use 8-bit ROMs. Then, once you've merged each high/low pair, concatenate all the merged pairs into one single file to use in your disassembler.
Приведу код скрипта целиком:
#!/usr/bin/perl # # Merge a pair of hi/low byte roms into a single file # # Usage: merger.pl <low_or_even_byte_rom> <high_or_odd_byte_rom> >outputfile.bin open LO, $ARGV[0] || die $!; open HI, $ARGV[1] || die $!;
Еще на известном Archive.org выложена огромная коллекция образов (~90Гб!), среди которых присутствуют интересные образы дисков и для машин Apricot.
Запуск и работа
При попытке запуска версии для Windows, эмулятор откажется работать, выдав сообщение о том что ROM-файлы не найдены:
ROM-файлы читаются из каталога ~/.qdae/Roms, либо из %USERPROFILE%/Documents/QDAE в Windows.
Однако имена самих файлов зашиты в коде, например для машины «Apricot F1» файл называется f1.rom. Соответственно для того чтобы ROM-файл был найден и загружен эмулятором — недостаточно просто положить его в нужный каталог, нужно еще и соблюсти именование.
Напоминаю:
Без ROM-файлов эмулятор не заработает, совсем.
Как уже было отмечено выше, ROM-файл еще нужно собрать из двух частей, поскольку все доступные в интернете образы разделены на HI и LO части. В качестве примера, покажу весь процесс на ROM-файле для Apricot F1.
Как нетрудно догадаться по адресам сайтов, эти ROM были созданы для более известного и популярного эмулятора Mame, но мы ведь не ищем легких путей, правда?
В архиве будет два файла, которые необходимо соединить в один:
Копируем полученный ROM в домашний каталог с эмулятора:
cp f1.rom ~/.qdae/Roms/
Дальше можно пробовать запускать c использованием образа диска apr00007.dsk:
/opt/own/qdae/bin/qdae ~/Downloads/apr00007.dsk
Будет загружен MS-DOS 2.11 прямиком из 1984 года, так это выглядит:
Сборка
Если вы считаете себя нормальным или хотя-бы психически стабильным — просто скачайте готовую Windows-версию, благо она отлично устанавливается и затем запускается с помощью Wine.
Автор же заморачивался со сборкой и кровавым патчингом этого чудища только ради того чтобыповесить отрубленную башку над камином принципа и высоких достижений. Если вы простой обыватель — вам такие страдания и лишения точно не нужны. Теперь рассказываю как это было.
Получим каталог с набором трешевых исходников на C и C++ и скриптов сборки (autotools разумеется):
cd qdae-0.0.10 ./configure --prefix=/opt/own/qdae
Сборка происходила на Linux Manjaro, ниже будут детали и особенности только по этому дистрибутиву. Эмулятор использует известную библиотеку SDL, причем первую версию, убедитесь что она установлена:
Как видите, я использовал даже не саму 1.х версию а слой совместимости для более современного SDL2
Запускаем сборку командой make и готовимся к первому «боссу». Первая ошибка, которая появляется при сборке на Linux выглядит так:
compress.c: In function ‘comp_open’: compress.c:137:37: error: implicit declaration of function ‘major’ [-Wimplicit-function-declaration] 137 | if (S_ISBLK(st.st_mode) && (major(st.st_rdev) == 2)) return DSK_ERR_NOTME;
Связана она с тем что функции major и minor объявлены устаревшими в заголовках текущей версии ядра Linux:
/* BSD defines `major', `minor', and `makedev' in this header. However, these symbols are likely to collide with user code, so we are going to stop defining them here in an upcoming release. Code that needs these macros should include <sys/sysmacros.h> directly. Code that does not need these macros should #undef them after including this header. */ # define __SYSMACROS_DEPRECATED_INCLUSION # include <sys/sysmacros.h> # undef __SYSMACROS_DEPRECATED_INCLUSION
Для исправления, необходимо добавить использование заголовка sys/sysmacros.h в начало файла LibDsk/lib/compress.c и перезапустить сборку.
Следующая ошибка, также связанная с этой проблемой выглядит так:
drvlinux.c: In function ‘linux_open’: drvlinux.c:182:13: error: implicit declaration of function ‘major’ [-Wimplicit-function-declaration] 182 | if (major(st.st_rdev) != 2) return DSK_ERR_NOTME;
Исправление аналогично предыдущей ошибке — просто добавляем эти строки в начало файла LibDsk/lib/drvlinux.c:
#include <sys/sysmacros.h>
После перезапуска сборки, появится куча ошибок вида:
f1_keyboard.cxx:57:32: error: invalid use of incomplete type ‘struct tm’ 57 | pkt[ 3] = 0x403 | ((ptm->tm_hour % 10) << 4); | ^~
Связаны эти ошибки с изменением структуры заголовков, конкретно — с переносом описания структуры времени из sys/time.h в просто time.h.
Для исправления ситуации, необходимо добавить включение этого заголовка в файле bin/sysdep.h:
#include <time.h>
После исправлений, сборка наконец завершается успешно. Однако собранный эмулятор откажется запускаться из каталога сборки:
Поэтому необходимо выполнить установку:
make install
В каталоге /opt/own/qdae появится сборка эмулятора, бинарник будет находиться в каталоге /opt/own/qdae/bin.
И уже отсюда собранный эмулятор можно наконец запустить.
Так выглядит успешный запуск эмулятора с правильным ROM-файлом, но без каких-либо загрузочных дисков:
Мигающие индикаторы фиска и флоппи - как раз легкий намек на отсутствующий загрузочный диск.
Казалось бы все и вот она — победа, достойный результат многомесячного превозмогания, гугления и заморочек с ROM-файлами.
Увы но нет, дела с этим эмулятором обстояли куда сложнее, чем казалось изначально.
Внимание на экран:
На этом интересном месте происходит зависание эмулятора, отладчика и эмулируемой ОС — проще говоря:
наступает полный и тотальный.. конец всему.
Полный Пэ
Перед вами баг в эмуляторе компьютеров из 1980х от компании, которой больше не существует. Доживших до наших дней, действующих компьютеров Apricot осталось крайне мало, ближайший находится где-то в Лондоне.
Сам эмулятор написан 20 лет назад, с использованием ископаемых технологий тех лет, активная разработка давно прекращена, сайт заброшен а сам автор не отвечает.
Чтобы просто запустить эту йобу, пришлось потратить месяц на поиск и сборку ROM-файлов. Более-менее работает лишь Windows-версия, собранная последний раз в 2012м году.
Для Windows 7.
Мануалов фактически нет, исходный код внутри такой, что одним своим видом может напугать неподготовленного человека.
Даже без знания C/C++.
Ну что, взялись бы за работу по исправлению при таких-то вводных?
Письмо автору
На всякий случай сообщаю, что я не окончательно поехавший (несмотря на все статьи), поэтому первым делом честно попытался написать автору эмулятора:
Greetings Mr. Elliott.
I'm trying to resurrect the QDAE emulator and found a problem that I cannot solve.
I was able to fix the build process on Linux, found and successfully merged ROM files, found working disk images. But when emulator loads any graphical environment (ex. Activity) — emulated OS crashes or reboots.
Same problem persist with all types of emulated machines: right after it goes into graphics mode — emulated OS reboots or crashes.
I’ve tried to use this «server version» of MS DOS, found some disk images without automatic start for graphics. That worked and was more-less stable. But without graphics. Not fun.
Then tried to reduce speed ticks (in source code) — down to 1000, 500 or even 100 — emulation has became much slower, but issue not gone.
Tried to use fake year (1985) instead of calculated from the current timestamp — also didn’t help.
I’m not asking for exact solution, just point to right direction, because issues like that always come from something small or stupid.
There were some minor fixes I did, related to missing headers (due to changes in Linux kernel sources) with date-time functions, but don't think that it could be responsible for described issue.
Как видите, прежде чем писать письмо, было перепробовано много разных вариантов исправления ситуации для такого рода проблем, но ни один не сработал.
Дорога приключений
Собственно при таких раскладах оставалось только два пути:
потратить пару лет жизни (опять) на ковыряние кривых исходников на древнем C++, либо попытаться восстановить сборку Windows-версии, поскольку та по какой-то причине продолжала работать.
Для завершения этой статьи я выбрал второй путь. Так выглядит установка Windows-версии QDAE в Wine:
Кстати на ролике выше используется новый 10й Wine, с режимом WOW64 — т.е одна и та же версия может запускать как 32 так и 64-битные приложения, без всяких отдельных префиксов:
Так выглядит запуск Windows-версии эмулятора в Wine:
ROM-файлы необходимо скопировать в каталог .wine/drive_c/Program\ Files\ \(x86\)/QDAE/Lib/Roms/ :
Изучение
Я решил применить свои «особые навыки» и залезть внутрь Windows-версии эмулятора, использовав PE Explorer, который оказывается весьма неплохо работает под Wine:
Ковыряем один эмулятор с помощью инструментов, запущенных в другом эмуляторе.
Конечно я догадывался, что шансов встретить серьезную защиту в таком ПО не очень много, поэтому не заняло много времени выяснить ряд важных деталей:
сборка Windows-версии осуществлялась кросс-компиляцией из Linux, с помощью MinGW окружения;
использовалась 32-битная версия компилятора и соответственно получился 32-битный бинарник;
использовалась отдельная библиотека ministl (набор заголовков), вместо обычного STL — см. ниже.
Версия MinGW, используемого автором для сборки эмулятора оказалась невероятно древней:
GCC-2.95.2 for Mingw (i386-mingw32) -- Release information =================================================================== Release date: Nov 7, 1999. I'm pleased to announce prebuilt gcc-2.95.2 packages for GNU Mingw (i386-mingw32).
1999 год!
И вот этой ископаемой штукой, автор QDAE делал сборки своего эмулятора аж до 2012 года, причем из-под Linux.
Но это еще не все.
История с ministl
В каждой профессии обязательно есть вещи, о которых не принято говорить в приличном обществе. Обычно это знание спрятано за семью замками и железной дверью, в самом темном углу, дорогу к которому вам так просто не расскажут.
В случае программирования на C++ такой вещью является кастомный STL — «левая» реализация (от Васяна) стандартной библиотеки шаблонов «в переводе Гоблина».
Это самый темный угол C++, кладезь бесконечных и самых феерических багов, король дичи и программного треша, которые только можно сотворить в этом замечательном языке.
О самой возможности замены STL вам врядли расскажут вменяемые программисты, поэтому пишу отдельную статью по этой замечательной теме.
Думаю вы уже догадались, что автор QDAE как раз из таких использовал кастомный ministl при создании сборок своего эмулятора:
Тут должно быть драматическое молчание и МХАТовская пауза — для осознания.
Чиним сборку с ministl
Коль уж мы идем по пути восстановления сборки — придется пытаться собрать эмулятор с этим недоразумением вместо нормального STL.
Для этого необходимо запустить скрипт configure с указанием специального параметра:
./configure --with-ministl
И заново запустить сборку:
make clean make
Разумеется сборка немедленно упадет:
Вы правда думали, что код на C++ из 1996 года соберется в современном окружении?
Хотя конкретно эта ошибка исправляется легко и просто — достаточно заменить устаревший заголовок <iostream.h> на просто <iostream>:
#include <iostream>
Сохраняем изменения в файле ministl/bstring.h и перезапускаем сборку. Но вот дальше.. дальше начинается ад и вьетнамские джунгли:
Хотя за исправление такого треша мне и платят.
Вас ожидает простыня ошибок из самых разных интересных мест, общий смысл которых:
иди своей дорогой сталкер, тебе тут не рады
Как понять, что вас ждут ад и погибель удивительные приключения и сутки тяжелой отладки?Копирайт с датами начала 90х в заголовке исходника на C++:
Copyright (c) 1994-1995 Modena Software Inc.,
Стоит рассказать потомкам, откуда вообще взялся этот bstring.h, вот так выглядит его оргинал из 1996 года. Все дело в том, что на свете есть одна известная и очень старая книжка по C++, которая называется:
STL Tutorial and Reference Guide:C++ Programming with the Standard Template Library
Книга, повторюсь, известная (даже я о ней слышал), думаю кое-кто из читателей держал такую на полке в свое время:
В комплекте с книгой шли примеры исходного кода на C++, одним из которых как раз и был наш bstring.h. Но это все лирика, реалии к сожалению таковы, что сил моих на исправление и переделку под современный C++17 этого древнего шаблона уже не хватило.
Точнее хватить-то хватило (на bstring.h), но обновленная версия ministl сломала весь остальной проект эмулятора, с концами.
Поэтому я его просто.. удалил.
Да, это еще одно тайное знание о заменяемом STL — возможность замещения системных шаблонов по частям.
На самом деле удалить нужно лишь файл string, из которого уже включается bstring.h:
rm ministl/string
Точно также я поступил и с vector.h, где вылезла следующая ошибка на тему новых стандартов и ограничений:
error: ‘void* operator new(size_t, void*)’ may not be declared as static
Объяснить с
Затем с list.h и ошибкой:
h6301.hxx:71:14: error: ‘list’ in namespace ‘std’ does not name a template type 71 | std::list<unsigned char> m_input; | ^~~~
Наконец последняя ошибка, связанная с ministl:
Path.cxx:199:9: error: ‘sort’ was not declared in this scope; did you mean ‘short’? 199 | sort(v.begin(), v.end()); | ^~~~
«Исправил» ее я аналогичным образом — цинично удалив заголовок ministl/algorithm.
Разумеется так делать нельзя и в нормальном проекте за подобные выкрутасы вас скорее всего побьют, возможно даже ногами.
Но и использовать «васянские» STL вместо стандартных — экстрим еще тот.
Со всеми этими правками, костылями и патчами сборка эмулятора наконец успешно завершается.
(бурные аплодисменты)
Но только собранный эмулятор все также не работает, зависая ровно на том же самом месте.
З2 веселых бита
Как мы уже успели выяснить выше, работающая сборка эмулятора под Windows — 32-битная и была создана 32-битным компилятором, поэтому следующий логичный шаг это попытка сборки 32-битной версии.
И скажу сразу:
в современной системе такая сборка — то еще скотство
Нужно будет установить gcc multilib и 32-битные версии библиотек: SDL и всех остальных используемых библиотек, например libxml2. И все зависимости.
Так выглядит набор параметров, передаваемых скрипту configure для сборки и линковки 32-битного приложения в 64-битном окружении:
У нас было 640Кб памяти, CGA-экран, 20-мегабайтовый диск и целых четыре мегагерца тактовой частоты. А еще старые пятидюймовые дискеты на 360кб. Не то чтобы это был необходимый набор для современного разработчика C++, но если уж начали коллекционировать дичь, то сложно остановиться..
Весь сетап целиком.
Проклятая выдача
Наверное все уже в курсе, что социальные сети и поисковые системы постоянно подкручивают ленту выдачи под каждого пользователя на основе его предыдущих запросов и проявленных интересов?
На меня эти алгоритмы тоже начали влиять, но.. особенным образом:
формируя персональную ленту из самой отмороженной компьютерной дичи, которая только есть на свете.
Когда я уже не мог выдерживать накал выдаваемого проклятыми алгоритмами — начал про всю эту дичь писать. На свет стали появляться статьи, испортившие безвозвратно психику, взгляды на жизнь и карьеру многим несчастным.
Если серьезно, то конечно же этот материал появился не на пустом месте и не за один день, это результат довольно долгого изучения матчасти, ковыряния исходников и темных ритуалов из Некрономикона.
Все ради того чтобы в очередной раз показать читателям невозможное, по мнению ИИ и обитателей StackOverflow.
Технический ультрахардкор
Коль уж читаете эту статью — скорее всего и так знаете через какое место как именно программы появляются на свет и какова роль компилятора в этом сложном процессе.
Для простых обывателей поясняю:
чтобы получить тот самый steam.exe, которым вы жадными ручками запускаете любимые игры, его необходимо собрать из исходников.
Сотрудник компании Valve вместо работы над Half-Life 3 запускает компилятор, который собирает из набора файлов с исходниками «финальный билд», который затем упаковывается в инсталлятор и выкладывается на официальный сайт Steam.
Откуда его потом скачивают ушастые простые пользователи.
Теперь представьте:
внезапно настал зомби-апокалипсис и всех программистов, которые занимались разработкой игр в Valve сожрали зомби, после чего процесс сборки, вся документация и тулчейны были утрачены.
C концами.
Все что осталось — несколько старых бекапов на забытых носителях, с трудом извлеченные из.. ээ останков голодного зомби. Из задней части.
Спустя пару сотен лет, вы — представитель жалких остатков человечества, выживших на небольшой колонии с обратной стороны Луны, вновь ступаете на опустевшую Землю в поисках артефактов погибшей цивилизации.
И находите на развалинах бывшего офиса Valve ту самую флешку с исходниками альфа-версии Half-Life 3.
Конечно прогресс в разработке программ к тому времени успел уйти далеко вперед, у вас в ходу на лунной базе теперь какие-нибудь C++-157 и clang-777, с встроенным Rust, тремя слоями виртуализации и сборщиком мусора, работающим через промпты LLM. А про язык C вы узнали лишь из лекции по истории, про исторический период между египетскими пирамидами и вторжением инопланетян.
Встает очевидный вопрос:
как же все-таки насладиться шедевром далеких предков, так и не увидевшим свет в свое время?
Многое можно отдать за запуск этой красоты, даже спустя пару сотен лет после зомби-апокалипсиса:
Нет, это не релизная версия.
Несмотря на весь этот «апокалиптический треш», ситуация сама по себе — более чем реальная:
прямо сейчас эксплуатируются полностью виртуальные системы, собственных средств разработки для которых либо уже нет совсем, либо такая разработка чрезвычайно затруднена.
В первую очередь это мейнфреймы, которые до сих пор живее всех живых, вроде такого красавца от Unisys:
Далеко не только IBM занимается мейнфреймами до сих пор.
Если немного снизить накал технического фетишизма экстрима и обратить взор к современной коммерческой разработке — можно внезапно обнаружить, что фактически вся ее продуктовая часть (там где создается приложение, устанавливаемое у конечного пользователя) работает с обязательной поддержкой устаревшего окружения:
поддержка Windows 7/10, поддержка старых версий Android и iOS, обязательная работа на JRE 1.8+ и так далее и тому подобное.
Разумеется на машинах разработчиков используется современный софт, но собирает он так чтобы конечное приложение без проблем запускалось и работало в устаревшем окружении.
Обратное портирование
Процесс, с помощью которого в окружении 21го века создается нечто работающее на оборудовании из века 20го называется обратным портированием (backporting). И мы уже неоднократно о нем рассказывали, например тут или тут.
Обычно бекпорт создается для окружения с не очень большим устареванием — лет на 5-10 с момента релиза, поскольку на таком промежутке и проходят все основные обновления пользовательского окружения.
В редких случаях (и за отдельную плату) разработчик ПО может согласиться покопаться в чем-то еще более древнем, но уже без гарантий.
Однако то что покажу в этой статье — однозначно выходит за любую границу разумности, проходя даже среди коллег по категории отбитой дичи научной фантастики:
приложение на современном C++, с современными фичами, созданное в современной ОС, которое работает в окружении из 1986 года!
Операционной системой, которую выпустили 40 лет назад выступит известная MS-DOS 3.20. Именно эта версия была выбрана ввиду одной интересной исторической особенности:
Version 3.20 – First retail release (non-OEM); Release date: July 1986
Это первая версия MS-DOS, продаваемая конечным пользователям напрямую от самой Microsoft, с полок магазинов.
До нее Microsoft продавала свою операционную систему только производителям компьютеров, которые включали ее в поставку своих продуктов и под своим собственным брендом:
Наконец показываю, как выглядит компьютер тех лет, для которого мы будем сейчас писать код на современном C++:
Фото современное, таких машин в живом состоянии сохранилось довольно много.
Комната жениха
Для начала, опишу тестовое окружение, которое будет использовано для столь задорной задачи. Три ключевых компонента, необходимых для осуществления задуманного злодейства:
Компилятор C++ DigitalMars, который до сих пор официально поддерживает сборку под DOS;
Думаю уже по одному этому абзацу можно догадаться о накале предстоящей дичи, хотя ряд нюансов все же стоит пояснить.
Во-первых Вена это не только столица Австрии, но еще и небольшой городок на севере США, на 15к жителей, где (внезапно) находится штаб-квартира серьезной софтверной компании, выпускающей эпические компиляторы аж с 1988 года:
In 1988, Zortech was the first C++ compiler to ship for Windows. PC Magazine ran a graphics benchmark and reported that most executables produced by Zortech ran faster than executables produced by Microsoft C 5.1 and by Watcom C 6.5.[3]
Вот так, парни переплюнули официальный компилятор от самого Microsoft, несмотря на весь инсайд и поддержку. Кстати «Zortech» — старое название компилятора (если вдруг будете искать в архивах), продукт по какой-то причине несколько раз переименовывался.
Есть еще один удивительный факт, связанный с этой компанией:
The company gained notice in the software development community for creating the D programming language. D resulted from Bright's frustration with the direction of the C++ language and from his experience implementing it.
Ребята до такой степени угорели по С++, что создали свой собственный язык, «по мотивам»:
resulted from Bright's frustration with the direction of the C++ language
Но вернемся к другим талантам этой замечательной компании — к разработкам для совсем старой школы:
Includes C++ templates, exception handling and rtti.
Most other compilers for 16 bit code were abandoned nearly a decade ago. Digital Mars has a modern compiler for 16 bits.
Все перечисленные выше радости — для официально поддерживаемой сборки под DOS и 16-битных приложений.
Догадываюсь, что современным программистам тяжело воспринимать реалии разработки тех лет и технические ограничения софта из далекого прошлого, поэтому в качестве иллюстрации, покажу таблицу моделей памяти создаваемых приложений:
Сравните это с современными "запускаемыми архивами" с играми, по 100Гб в одном .EXE
Это предельные размеры создаваемого приложения, в случае MS-DOS 3.20 мы будем использовать «s» модель памяти, поэтому размер финальной сборки не должен превышать 64Кб.
Сборка и запуск
Компиляторы C и C++ от DigitalMars изначально были коммерческим продуктом и до сих пор существует коммерческая версия, включающая помимо компиляторов еще и собственную среду разработки (IDDE). Однако не так давно компиляторы стали бесплатным и открытым проектом, с исходниками на Github.
К сожалению проект пока не портируемый — собирается и работает исключительно под Windows.
Тем не менее, поскольку создавали его очень опытные люди — все отлично работает в Wine, что мы и будем использовать для его запуска на FreeBSD. Чтобы снова не раздувать статью — не стал заморачиваться сборкой компилятора из исходников (хотя это не очень сложный процесс), использовав готовую сборку версии 8.5.7.
Инсталлятора тут нет, в архиве сразу готовые бинарники, поэтому распаковываем и запускаем:
Внутри будут дополнительные бинарники, главный из которых это довольно известный EXE2BIN.COM, используемый для генерации COM-файлов из EXE.
С EXE2BIN есть один важный нюанс — он не запустится с помощью Wine, поскольку является DOS-приложением.
Чтобы использовать эту утилиту для создания COM-файлов — необходимо запускать ее с помощью DOSbox:
Теперь переходим к основному эмулятору.
Официальный логотип 86Box
86Box
Достаточно новый проект (разрабатывается с 2016 года), который сейчас активно развивается и позволяет эмулировать огромное множество x86-совместимых систем:
86Box is an IBM PC system emulator that specializes in running old operating systems and software designed for IBM PC systems and compatibles from 1981 through fairly recent system designs based on the PCI bus.
Готовой сборки для FreeBSD пока нет (как и присутствия в портах) и еще год назад были проблемы, требующие ручных правок исходников:
Initially exclusive to Windows, it was ported to Linux in version 3.2 and macOS in version 3.4.
Но на момент написания статьи все поправлено и эмулятор отлично собирается из исходников без каких-либо проблем, а в инструкции по сборке появился раздел про FreeBSD.
Для релизных версий эмулятора — ROM-файлы надо брать в другом месте, со страницы releases. Запускается эмулятор с указанием путей к каталогу с ROM-файлами следующим образом:
./src/86Box --rompath /opt/src/roms
После запуска эмулятора (по прямой аналогии с каким-нибудь VirtualBox) необходимо создать новую виртуальную машину, задав ей вот такие настройки:
Это не единственный возможный сетап эмулируемого оборудования, но максимально приближенный к реалиям 1986 года.
Так выглядела обложка коробочной версии с MS-DOS. Помимо префикса, слово "Microsoft" встречается трижды ;)
MS-DOS
Образы самого MS-DOS достать в сети очень легко, например отсюда. Все они уже давно находятся в публичном пользовании (public domain), поэтому за их использование Microsoft вас не съест засудит.
Более того, даже исходный код некоторых версий MS-DOS был выложен в публичный доступ:
The original sources of MS-DOS 1.25, 2.0, and 4.0 for reference purposes
Коробочная версия поставлялась на 5-дюймовых дискетах, размером в 360Кб, собственно их образы и выложены в сети.
Нам нужен лишь первый:
Этот файл нужно выбрать в меню после запуска эмулятора:
После чего перезагрузить эмулируемую систему.
При запуске пойдет проверка памяти, затем MS-DOS будет просить ввести ей дату и время, достаточно нажать пару раз <Enter> для пропуска:
MS-DOS из 1986 года готов к работе.
Mtools
Разумеется есть проблемы с пробросом данных с хоста в столь старую эмулируемую систему. Существуют несколько возможных решений, но самое простое и очевидное:
с помощью генерации образа floppy-диска на хосте и подключения его на эмулируемой системе, в виртуальный floppy-привод.
Тот самый, с которого мы выше загружали образ MS-DOS.
Для генерации образов флоппи я использовал известный пакет GNU Mtools,
In addition to file access, it supports many FAT-specific features: volume labels, FAT-specific file attributes (hidden, system, ...), "bad block" map maintenance, access to remote floppy drives, Iomega ZIP disk protection, "secure" erase, display of file's on-disk layout, etc.
Пакет довольно известный, поэтому присутствует практически везде, для FreeBSD установить его можно так:
pkg install mtools
Так выглядят те самые пятидюймовые дискеты (5.25").
Как видите все отлично работает в операционной системе 40-летней давности:
Покажите вашему преподу по C++.
Следующим шагом проверил обработку ошибок:
#include <iostream.h> #include <exception>
int main() { try { int age = 15; if (age >= 18) { cout << "Access granted - you are old enough."; } else { throw 505; } } catch (int myNum) { cout << "Access denied - You must be at least 18 years old.\n"; cout << "Error number: " << myNum; } return 0; }
Тут стоит уточнить, что поддержку обработки ошибок надо включать отдельно, ключом -Ae:
dmc -0 -ms -Ae -NV -o+space ex.cpp
Не поверите, но оно тоже работает:
Вот такие дела, конструкция try-catch на языке высокого уровня спокойно работает в MS-DOS образца 1986 года.
Еще больше балета
Разумеется я показал лишь малую часть возможностей компилятора, в первую очередь потому что уже декабрь а статья опять превратилась в простыню не успел закончить историю с STL:
STLport 4.5.3 ported to Digital Mars C++ (requires Digital Mars C++ 8.32 or later)
Это отдельная, весьма своеобразная версия STL, совместимая с DigitalMars, доступная для скачивания в собранном виде (плюс исходники). Но собрана она для целевой платформы Win32, поэтому для сборки под DOS ее готовую версию использовать не получится, надо пересобирать самостоятельно.
Сама возможность такой пересборки под DOS существует, но необходима либо платная версия DigitalMars, которая содержит собственную систему сборки (smake), либо очередной «кровавый патчинг», чтобы собрать STLport вручную.
Не поверите, но еще существует Boost (хоть и очень старый) с поддержкой компилятора DigitalMars:
Boost 1.30.0 for Digital Mars C++
Вот уж где раздолье и настоящий угар: писать под DOS c помощью самой жирной библиотеки для C++ на свете!
Чтобы окончательно добить вашу психику и чувство прекрасного, показываю несколько проектов «обратного портирования» STL — как раз для особых случаев, вроде истории с DigitalMars.
Первый проект:
A recreation of much of the modern C++ standard library in ISO C++98
Тут основная цель это C++11, который DigitalMars поддерживает очень слабо, плюс будут проблемы с Windows-платформой:
Does it work on Windows? Sorry, POSIX mostly. Would love for some Windows devs to help.
Но проект сам по себе весьма интересный и ничего не мешает надергать отсюда необходимых кусков в свою реализацию.
Возвращение на Землю
Несмотря на описанное в статье, дела с компиляторами C/C++ от DigitalMars обстоят несколько печальней чем кажется. Во-первых этот компилятор очень сильно устарел и совместимость со стандартом языка осталась на уровне C++98.
Для более новых версий стандарта есть поддержка лишь отдельных фич и планов по улучшению ситуации я не видел.
Фактически активная разработка остановилась в 2004м году, с тех пор выпускаются лишь мелкие патчи и обновления, поскольку фокус авторов сместился на поддержку языка D.
Во-вторых этот компилятор по прежнему имеет серьезные проблемы с лицензированием:
несмотря на открытие исходного кода, для полноценной сборки требуется закрытый инструментарий.
Так что использовать DigitalMars без цели угара для обычных проектов наверное мало осмысленно, хотя и привнесет определенную толику веселья в тяжелые будни C++ разработки.
Добавлю, что компилятор для наших краев довольно редкий, по крайней мере лично я не встречал проектов, где бы он использовался.
Но для целей кросс‑компиляции под DOS (если вас жизнь заставит) — инструмент более чем интересный.
P.S.
Статья была опубликована на Хабре, оригинал как обычно в нашем блоге, процесс всех этих изысканий и отбитых экспериментов выкладываем в нашем Телеграм канале.
Зато теперь вы знаете, что я собрал этот самый редактор карт DoomEd под NeXT. Из исходников, вот этими самыми руками, да.
Осталось разобраться с текстурами и ресурсами и будет полностью восстановленный процесс разработки оригинального Doom.😍 Кстати Ромеро в своем посте выложил еще и "unreleased soundtrack" - дополнительные мелодии, не вошедшие в оригинальный Doom, с которым рекомендую ознакомиться.
В качестве пруфа.
На скриншоте выше эмулятор NeXT с NeXTSTEP, сетью, средой разработки и собранным редактором карт для Doom - именно той версии, которая использовалась Ромеро для оригинальной разработки.
Собственно запуск оригинального Doom под NeXT, задолго до того как он появится под MS-DOS: