Помимо всем известной Apple, на свете существовала еще одна «фруктовая» компания, выпускавшая очень популярные компьютеры.
И сейчас мы цинично оживим и запустим эмулятор этих замечательных машин.

Поскольку и сама компания и ее компьютеры и даже их эмулятор (вместе с автором) — с берегов «туманного альбиона», большая часть ссылок в статье ведет в никуда на ресурсы, заблокированные для доступа из РФ, родной РКН к этому никакого отношения не имеет.
Поэтому надеваем монокли, цилиндры и поднимаем тост «За обход блокировок».
Кто бы мне сказал еще десять лет назад, что попасть на фанатский сайт о старых британских компьютерах станет сложнее, чем на официальный сайт Северной Кореи.

Его звали "Apricot"
Изучая материалы из недавнего компьютерного прошлого, в который уж раз убеждаюсь:
за каждой успешной историей в ИТ есть натуральное кладбище из неудач и провалов.
А нынешние и всем известные «лидеры ИТ-индустрии» были отнюдь не первыми в своем деле и часто далеко не самыми инновационными.
Еще у людей короткая память:
вчерашний «лидер рынка» и «король продаж» может легко и просто, а главное — невероятно быстро пропасть с концами из информационного поля.
Невзирая на всю шумиху в прессе, пиар и народную любовь.
Сегодняшняя история как раз про такую компанию:
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».
Так выглядит процесс загрузки Windows 1.0 на настоящем Apricot Xi:
Поскольку был найден эмулятор этих интересных машин, решил попробовать все это дело собрать и оживить.
Однако все оказалось не так просто и процесс написания этой статьи (вместе со сроками) пошел очень сильно не по плану, затянувшись на три месяца экзотических изысканий.
Эмулятор
Эмулятор компьютеров Apricot называется QDAE:
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 обнаружено не было.
Так что забирать придется оттуда:
wget https://www.seasip.info/Unix/QDAE/qdae-0.0.10.tar.gz
Также архив с исходниками присутствует в 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 $!;
$i=0;
while(!(eof(LO) | eof(HI)))
{
$a=getc(LO);
print $a;
$a=getc(HI);
print $a;
}
Тут происходит чтение LO и HI-файлов, переданных в качестве аргументов а затем их побайтовая перекодировка в символы:
getc returns the next character from the input file attached to FILEHANDLE
В этом-то и была главная хитрость, выносившая мне мозг пару недель — надо не просто слить два ROM-файла в один, а еще и перекодировать.
Образы дисков
С дисками все оказалось сильно проще, они неплохо каталогизированы и доступны для скачивания:

Еще на известном 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, но мы ведь не ищем легких путей, правда?
В архиве будет два файла, которые необходимо соединить в один:

Вот так это выглядит:
perl merger.pl lo_f1_1.6.8f hi_f1_1.6.10f > f1.rom
Копируем полученный ROM в домашний каталог с эмулятора:
cp f1.rom ~/.qdae/Roms/
Дальше можно пробовать запускать c использованием образа диска apr00007.dsk:
/opt/own/qdae/bin/qdae ~/Downloads/apr00007.dsk
Будет загружен MS-DOS 2.11 прямиком из 1984 года, так это выглядит:

Сборка
Если вы считаете себя нормальным или хотя-бы психически стабильным — просто скачайте готовую Windows-версию, благо она отлично устанавливается и затем запускается с помощью Wine.
Автор же заморачивался со сборкой и кровавым патчингом этого чудища только ради того чтобы повесить отрубленную башку над камином принципа и высоких достижений. Если вы простой обыватель — вам такие страдания и лишения точно не нужны.
Теперь рассказываю как это было.
Скачав и распаковав архив с исходниками:
wget https://www.seasip.info/Unix/QDAE/qdae-0.0.10.tar.gz
tar xvf ~/Downloads/qdae-0.0.10.tar.gz
получим каталог с набором трешевых исходников на C и C++ и скриптов сборки (autotools разумеется):
cd qdae-0.0.10
./configure --prefix=/opt/own/qdae
Сборка происходила на Linux Manjaro, ниже будут детали и особенности только по этому дистрибутиву.
Эмулятор использует известную библиотеку SDL, причем первую версию, убедитесь что она установлена:

Запускаем сборку командой 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;
Исправление аналогично предыдущей ошибке — просто добавляем:
#include <sys/sysmacros.h>
в начало файла LibDsk/lib/drvlinux.c.
После перезапуска сборки, появится куча ошибок вида:
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
Разумеется сборка немедленно упадет:

Хотя конкретно эта ошибка исправляется легко и просто — достаточно заменить устаревший заголовок <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
By David R. Musser and Atul Saini
Addison-Wesley Professional Computing Series
ISBN 0-201-63398-1 Hardcover 432 pages * 1996
Книга, повторюсь, известная (даже я о ней слышал), думаю кое-кто из читателей держал такую на полке в свое время:

В комплекте с книгой шли примеры исходного кода на 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-битном окружении:
./configure --build=i686-pc-linux-gnu CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32
Если скрипт и проследующая сборка пройдут без ошибок, в каталоге bin появится 32-битный бинарник:

Который наконец заработает как надо.
Результат
Показываю наконец результат всех этих адских мучений:
эмулируемые системы Apricot в действии.
Обратите внимание на даты — многие из читателей имеют отцов, которые младше этих систем;)

Использован образ диска: apr00230.dsk
Описание:
apricot SOFTWARE
*** BETA TEST COPY ***
Date Issued:15/07/85 Return by:29/07/85
F1 (UK)
MSDOS 2.11 BIOS 1.6
Disk One - Activity, Tutor
Disk Two - Diary,Sketch,Async,GWBASIC
1F1U04B Disk 1 of 3

Образ диска: apr00256.dsk
Описание:
APRICOT DEMONSTRATION
PICTURES
BIOS V1.4 JAN 1984

Образ диска: apr00076.dsk
Описание:
24/4/84
PS
PSMATE
SUB-MASTER 211
NOT FOR RELEASE

Образ диска: apr00190.dsk
Описание:
2.6 BOOT PC/XI
WITH LINKWORD
INC MSBASIC
MASTER 61

Образ диска: apr00264.dsk
Описание:
BASIC GAMES, ENCHANTE,
MASON, QUEST MASTER 19
В качестве эпилога:

P.S.
Более вольный оригинал как обычно в нашем блоге, копия на Дзене.
Будут еще статьи по Apricot, поскольку не влезла история с 32-битной сборкой эмулятора на FreeBSD и установкой первых версий Windows.
Следите за анонсами на канале.