it-history
November 30

17 мгновений осени: оживляем эмулятор Psion/EPOC32 

Очередная статья про ужасы разработки и оживление древностей. В этот раз на стол к некроманту попал некогда популярный наладонник Psion, а точнее его ОС — EPOC.

Статья

Как-то я наткнулся на одну интересную статью:

In which I build WindEmu, an emulator for the Psion Series 5mx (a PDA from 1999 running EPOC - the OS that would become Symbian), over the course of just over a week, without access to the actual hardware. Yet another cursed project.

Тут автор разумеется цинично п#здит, по всей видимости набивая себе цену, поскольку один объем кода на C++ в проекте минимум на полгода работы. Без учета начальной подготовки и исследований.

Хотя разумеется дело ваше кому верить — дедушке-автору, который все это написал или дедушке-мне, который это смог собрать и запустить на FreeBSD спустя 5 лет после выкладки исходников.

Про «5 лет после релиза» стоит рассказать отдельно:

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

Девайс

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

Вот так оно выглядело вживую:

Еще одна интересная цитата из оригинальной статьи:

For the Series 5 (there was no 4), Psion moved to ARM chips and built a new version of EPOC - sometimes called EPOC32 - as a full rewrite using object-oriented C++. This is the OS that would end up evolving into Symbian OS, known for appearing on world-famous devices like, uh... the Nokia 9210 Communicator and the N-Gage. What a fate.

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

Сборка

Забираем исходники эмулятора:

git clone https://github.com/Treeki/WindEmu.git

Проект реализован на QT, сборка работает как с QT6 так и с QT5.

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

Сначала собирается ключевая библиотека WindCore:

cd WindCore && qmake6 && make

Я все это делал по старой джедайской традиции на FreeBSD, но точно такие же шаги сборки (за одним исключением см. ниже) будут актуальны для всех остальных ОС, на которые успели портировать QT5 или QT6.

Cборка происходила с помощью Clang 18, попытка собрать с помощью gcc не удалась, несмотря на видимую поддержку.

При попытке сборки WindCore появятся ошибки:

./arm710.h:120:22: error: no template named 'function' in namespace 'std'
  120 |         void setLogger(std::function<void(const char *)> newLogger) { logger = newLogger; }
      |        

и:

./arm710.h:126:7: error: no template named 'function' in namespace 'std'
  126 |         std::function<void(const char *)> logger;     

Происходит это из-за пропущенного заголовка functional, который необходимо добавить в arm710.h:

#include <functional>

Если сборка прошла успешно, в каталоге с исходниками будет файл libWindCore.a Следующей стадией собирается интерфейс эмулятора:

cd WindQt && qmake6 && make

При сборке возникает ошибка:

mainwindow.cpp:212:20: error: conversion from 'uint8_t' (aka 'unsigned char') to 'QChar' is ambiguous
  212 |                                 outLine.append(byte);

которая достаточно легко исправляется путем оборачивания в QChar:

outLine.append(QChar(byte));

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

pdascreenwindow.cpp:135:2: error: "Unsupported platform (for now! fix me in pdascreenwindow.cpp)"
  135 | #error "Unsupported platform (for now! fix me in pdascreenwindow.cpp)"

Думаю не нужно напоминать, что сборка происходит на FreeBSD, само существование которой регулярно ставится под сомнение, не то что поддержка сборки для нее ;)

Для исправления просто комментируем строку с проверкой:

//#error "Unsupported platform (for now! fix me in pdascreenwindow.cpp)"

и чуть ниже исправляем неверную сигнатуру функции resolveKey, про которую автор видимо забыл:

static EpocKey resolveKey(int key, int vk) {
..

Добавляем второй аргумент int vk, чтобы сигнатура функции совпадала с версией выше, используемой для MacOS.

Очевидно что при сборке на MacOS данная ошибка возникать не будет.

Если сборка прошла успешно, в каталоге WindQt появится готовый бинарник WindQt.

Запускаем:

./WindQt

эмулятор попросит выбрать ROM-файл, с которым ввиду старости EPOC32 и патентных ограничений есть проблемы.

Я поступил просто и цинично — вытащил готовый ROM из веб-версии эмулятора:

Файл называется WindEmu.data, размером в 10Мб, прямая ссылка для скачивания тут.

Этот файл необходимо сохранить на диск и открыть собранным выше эмулятором.

Ну и наслаждаться этим древним чудом техники:

Среда разработки

Если вы круты как обрыв имеете весь инструментарий для разработки на Qt, включая QtCreator, то можно собрать и запустить эмулятор целиком из среды разработки:

Основной файл проекта WindEmu.pro находится в корне каталога.