Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Зачем?
Если Вы — энтузиаст ретро-компьютеров, то мотивационную речь можете смело пропустить и перейти к следующему разделу.
Весь август 2018-го года я и мой 13-летний сын Ivanq потратили на написание демки Good Apple. На фестивале Chaos Constructions наша работа заняла второе место, за что мы получили денежный приз 35 тысяч рублей, который честно поделили поровну. Для ребёнка это неплохой доход, хотя, созданием сайтов он зарабатывал столько же за меньшее время. Очевидно, и я мог потратить своё время с большей экономической выгодой… Но только не август! Надо же когда-то отдыхать от работы. Программировать в своё удовольствие — это роскошь, которую можно позволить себе только в отпуске.
Материальное вознаграждение, конечно, не служит мотивацией, но закрепляет положительные эмоции. Удивительно, что демка для забытого советского компьютера собрала тысячи просмотров на youtube и попала в плейлист с почти сотней тысяч просмотров. Но ещё более удивительно, что в 2018-ом году за неё вручают денежный приз! Возможно, сама невероятность происходящего и порождает такой эмоциональный подъём.
Однако, есть кое-что более важное.
При создании “Good Apple” нам пришлось работать с реальным железом, так как мы использовали возможности компьютера, которые эмуляторы воспроизводят не совсем корректно. Прежде всего, хотелось добиться одинаково устойчивой работы с жёсткими дисками формата IDE и с их современными заменителями в виде Compact Flash.
Именно на этом проекте мой 13-летний сын обрёл бесценный опыт промышленной разработки. Дефектное железо. Хорошее железо, которое ведёт себя не так, как описано в документации. Документация, которая составлена с ошибками. Отсутствие документации по ряду вопросов. Написание собственных тестов для выявления проблем с железом. Выходящие сроки. Тестирование на разных машинах и конфигурациях. Написание собственного кросс-ассемблера (когда стало понятно, что существующие решения тормозят процесс разработки). И, наконец, после короткого празднования успеха — обязательный выпуск финальной версии, исправляющей ряд багов.
На первый взгляд кажется, что подобный опыт можно было получить и с каким-нибудь современным Arduino. По факту же, нам пришлось погрузиться в самые дебри схемотехники. Мы вычисляли число тактов, за которое исполняются инструкции. В разных типах памяти это время отличается. Контроллер памяти и процессор работают на разных частотах, поэтому одинаковые команды могут выполняться разное время даже в памяти одного типа. Длительность исполнения подпрограммы не равна сумме длительностей команд этой подпрограммы. Нам пришлось писать собственные инструменты для тестирования и оптимизации кода на реальном железе.
Закончилось тем, что сын изучал схемотехнику БК 0011 (какие фронты сигналов куда приходят, когда срабатывает RPLY и т.д. — я в этом уже ничего не понимаю). Так он пришёл к идее сделать собственный эмулятор БК, совместимый с реальным железом с точностью до такта, и даже написал ядро… Впрочем, это уже другая история.
Итого, за месяц — от изучения ассемблера до создания собственных средств разработки, от хардварных тестов до готового мультимедийного произведения. Всё это было бы невозможно без главного: Планирование. Пожалуй, наиболее ценный вынесенный урок. Берёшь невозможную задачу. Понимаешь, что столкнёшься с непреодолимыми сложностями. Планируешь. Делаешь. Результат поражает всех настолько, что даже знатоки обвиняют в читерстве (“вы разогнали процессор!”).
Почему не ZX Spectrum?
Опять начну со странного: с финансов. Судя по объявлениям на Avito, в среднем БК 0010 стоит в несколько раз дороже, чем ZX Spectrum. Понятно, что за редкий экземпляр родного Спектрума в идеальном состоянии запросят круглую сумму. Но БК 0011м в полной комплектации всё равно выйдет дороже. Если вообще удастся найти. Цены говорят сами за себя: коллекционная значимость БК 0010 выше. А БК 0011м — и подавно. Иметь такой компьютер дома очень приятно.
Второй аргумент – 16-бит. В БК 0010 нет ничего 8-разрядного. Процессор даже не умеет складывать 8-битные числа, у него нет команды ADDB. 16-битность во всём. Причиной тому – архитектура DEC PDP-11. Многие называют систему команд процессора PDP-11 самой удачной и самой удобной из когда-либо созданных. Конечно, найдутся желающие поспорить с этим утверждением. Но вот один факт: на прошедшем в Яндексе фестивале “Демодуляция” было три семинара, посвящённых архитектурам процессоров, и два из них о PDP-11. Это, действительно, легенда, важнейшая веха в истории вычислительной техники, которая до сих пор продолжает будоражить умы энтузиастов. БК 0010 даёт возможность прикоснуться к этой легенде. И не просто прикоснуться, а разобраться в ней до мельчайших деталей, прочувствовать всю красоту и изящество DEC’овского ассемблера: абсолютно равноправные регистры, восемь методов адресации, линейная память – красота!
Третий довод: для ZX Spectrum написано множество демок. Для БК 0010 — меньше полусотни, считая мелкие 256-байтные и 4-килобайтные. Место на демосцене почти свободно, есть где себя проявить даже начинающему!
И последнее соображение, чисто субъективное. Я наблюдаю за российской демосценой с 1994-го года. Тусовка спектрумистов представляется мне, к сожалению, более токсичной и враждебной. Конечно, есть и прекрасные дружелюбные люди! Испытываю огромное уважение к ним и к их творчеству. Но в целом – вероятно из-за своей массовости – спектрумовская сцена наполнилась конфликтами, выяснением отношений и даже интригами типа name-voting (когда на конкурсах голосуют только за “своих”). В то время как на маленькой БК-шной сцене не ставят вопросов типа “кто круче” и рады каждому новому участнику. Повторю: это моё сугубо личное впечатление, которое вы можете проигнорировать.
Реальное железо
Прошло 20 лет, прежде чем я вернулся к написанию программ для БК. За эти 20 лет многое изменилось. Лично для меня главный сдвиг произошёл в сознании: “Think Different”. Именно этот слоган помещён в заключительные титры нашей демки “Good Apple”.
Раньше мы по 5 минут грузили игры с магнитофона. Затем появились контроллеры дисководов. За ними – жёсткие диски. Потом новодельные реплики контроллеров с Compact Flash на борту. Теперь на ретро-сцене принято эмулировать дисководы флешками… Но постойте, в 2019-ом году у нас есть высококачественный портативный источник звука – iPhone. Так давайте возьмём стандартный аудио-шнур DIN-5 — mini jack (даже перепаивать не придётся) и будем грузить БК с iPhone на высокой скорости.
Я прошёлся трассировкой по ПЗУ, выявил как можно слегка перехитрить алгоритм загрузки с магнитофона и заставить БК читать данные в 4 раза быстрее.
Следующим этапом стало написание микро-загрузчика, который считывал данные в специально разработанном турбо-формате. И загрузчик, и данные помещались друг за другом в единый WAV-файл (конвертер написал Ленар Закиров). БК 0010 считывает и автоматически запускает микро-загрузчик, а тот, в свою очередь, читает остаток данных из файла. Частоты в турбо-формате доходят до 22 КГц, поэтому требования к качеству источника звука высоки. iPhone справляется. Хороший музыкальный плеер тем более. Звуковая карта компьютера тоже.
Затем настала очередь кросс-ассемблера. В него были добавлены опции сохранения программы в WAV (как в стандартном, так и в турбо-формате). Более того, кросс-ассемблер умеет сразу проиграть WAV через звуковую карту. Только представьте, насколько ускорилась разработка! Не нужно возиться с записью образа диска на CF-карту после каждой компиляции. Просто вносишь изменения в код, нажимаешь “Build”, звук льётся в БК и через несколько секунд программа уже запущена на реальном железе. Для приёма звука в стандартном формате достаточно нажать на БК 0011 клавиши L (Load) и Enter (загружать первую встреченную программу). Для передачи звука в турбо-формате нужно предварительно запустить микро-загрузчик (у меня он автоматически запускается с жёсткого диска при включении БК; в любой момент можно выйти в систему, нажав клавишу СТОП).
Подключить БК к телевизору проще всего в монохромном режиме, в обычный композитный AV-вход. Нужно спаять кабель с “тюльпаном” на одном конце и DIN-5 на другом. Монохромный сигнал выходит с 4-го контакта DIN-5 разъёма БК, обозначенного “ТВ”. Земле традиционно соответствует 2-ой контакт DIN-5.
Лично я поклонник монохромных ЭЛТ дисплеев – они обеспчивают чёткость изображения, недостижимую на цветных мониторах с их апертурной решёткой. Но большинство игр и все демки предпочтительней смотреть в цвете. Для этого используют “ТВЦ” выход БК и подключение к телевизору через RGB SCART. Контакты 3, 4, 5 на DIN-5 – соответственно красный, синий, зелёный. Контакт 1 – синхронизация. Контакт 2 – земля. В случае подключения к ЖК-телевизору полезно подать +5 вольт на 16-ый контакт SCART (через резистор 200 Ом или около того). 5 вольт обычно берут с соседнего разъёма “ТВ” (контакт 1).
Можно воспользоваться конвертером SCART-HDMI. Сразу предупрежу, что БК выводит изображение с частотой не 50 кадров в секунду, а 48.83, поэтому вместо плавного скроллинга на ЖК-мониторах будет заметно периодическое подёргивание. Я решил эту проблему заменой 12-мегагерцового кварцевого резонатора БК на 12.288 МГц. Впрочем, подёргивание было заметно только в некоторых демках. Большинство программ на БК не использует синхронизацию с кадровой частотой.
Почему не довольствоваться эмулятором, для чего вообще может понадобиться реальный компьютер? Я обнаружил четыре вещи, которые плохо эмулируются:
- Поведение динамика на высоких частотах.
- Синхронизация изображения и палитр с ходом луча.
- Точное время исполнения команд (важно для музыки через Covox).
- Работа с жёсткими дисками IDE на высоких скоростях.
Если вы не планируете делать ничего из вышеперечисленного, вам вполне хватит эмулятора.
Эмуляция
На MacOS я использую эмулятор BK2010. Он не очень точный, но для большинства задач подходит.
Самый продвинутый на сегодняшний день эмулятор GID работает под Windows. Он также запускается в CrossOver под MacOS и в Wine под Linux. В эмуляторе хороший отладчик, просмотрщик страниц памяти и тому подобное.
Для записи образов дисков на Compact Flash пользуюсь мультиплатформенной утилитой Etcher. Но чаще передаю данные по звуковому каналу.
Средства разработки
Ребята из демогруппы Excess Team подсказали кросс-ассемблер Алексея Морозова. Сперва мы пользовались им, но вскоре Ivanq написал свой собственный – мультиплатформенный, на Python. Он работает медленней, зато гораздо богаче функционально. Тут и поддержка многофайловых проектов, и сложные арифметические выражения, типы данных double word, интеграция с Sublime Text и расширенная поддержка ошибок компиляции, сохранение результата в формате звукового файла, компиляция не только под БК, но и под УКНЦ, и многое другое. Обо всём этом можно почитать в официальной документации.
Кросс-ассемблер называется PDPy11.
Некоторые из ветеранов жалуются, что в PDPy11 не хватает макросов классического DEC’овского макро-ассемблера (Macro-11). Макро-ассемблер – это в некотором смысле другой язык. Он, вероятно, хорош для написания системных программ, но серьёзные игры и демки для БК писали, насколько я знаю, на обычном классическом ассемблере. Иронично: для исходников БК-шных программ принято использовать расширение фала .mac (от “макро”) даже в тех ассемблерах, которые не поддерживают макросы. В любом случае, возможностей PDPy11 хватает для написания программ любого уровня сложности.
Отладчик встроен в эмулятор GID. Он позволяет задать адреса точек останова, в любой момент прерывать или продолжать исполнение программы, смотреть содержимое регистров и памяти, выполнять программу пошагово, изменять содержимое памяти и т.д.
Для конвертации графики в формат БК мы написали онлайн-конвертер. Разрешение БК – 256x256 точек в цветном режиме или 512x256 в монохромном. Картинки большего размера лучше не подавать на вход конвертеру.
Документация
Прекрасное пособие по программированию на ассемблере написал Юрий Зальцман. Об отличиях БК 0011м от БК 0010 написано здесь. Существовала ещё модель БК 0011 (без “м”), но её быстро сняли с производства, признав неудачной.
Несмотря на то, что БК 0011м обладает большими возможностями (цветовые палитры, дополнительные страницы памяти), поначалу я советую программировать под БК 0010 — эта модель проще и понятней. Любая программа, корректно написанная для БК 0010, запустится и на БК 0011м.
Устройство процессора и набор инструкций хорошо описаны в Wikipedia.
Для самых отважных — программирование в кодах.
Hello, world!
Область экранной памяти в БК 0010 начинается с адреса 40000 (левый верхний угол) и заканчивается адресом 77777 (правый нижний угол экрана). Как нетрудно догадаться, в архитектуре PDP-11 используют 8-ричную систему счисления. Но кросс-ассемблер PDPy11 позволяет, конечно, записывать числа также в двоичной, десятичной, шестнадцатиричной системе – поступайте как вам привычней.
Чтобы поставить точку на экране, нужно записать какое-нибудь число в область экранной памяти. Аргументы в DEC’овском ассемблере записываются слева направо: источник, затем приёмник Например:
MOV #100000,@#60040 ; поставить точку в середину экрана
Знак # означает, что аргумент – просто число (а не адрес). Знак @# означает, что аргумент — абсолютный адрес (то есть он не изменится при переносе программы в другое место памяти).
Очистка экрана выглядит так:
MOV #40000,R1 ; начальный адрес
MOV #20000,R0 ; счётчик цикла
1: CLR (R1)+ ; очищаем слово по адресу, после увеличиваем R1
SOB R0,1 ; оператор цикла
Косвенная адресация (R1) использует регистр R1 как указатель адреса. Память в БК адресуется побайтно, но инструкция CLR очищает сразу два соседних байта: сначала 40000 и 40001, на следующем шаге цикла 40002 и 40003, и так далее. Запись (R1)+ означает, что после использования аргумента нужно его увеличить. В данном случае на 2, потому что команда обрабатывает 2 байта. Счётчиком цикла может быть любой регистр. SOB вычитает единицу из регистра и переходит на метку 1. Локальные метки обозначаются цифрами и двоеточием, их область видимости между двумя глобальными метками. Глобальные метки должны начинаться с буквы и также заканчиваться двоеточием.
Инструкцию CLR можно заставить работать с байтами, дописав букву “B”. Тогда CLRB (R1)+ будет увеличивать регистр R1 уже не на 2, а на 1.
MOV #40000,R1
MOV R1,R0 ; теперь счётчик цикла должен быть вдвое больше
1: CLRB (R1)+
SOB R0,1
Можно сделать то же самое короче. Очищаем экран снизу вверх при помощи индексного метода адресации:
MOV #40000,R0
1: CLRB 37777(R0) ; по сути это (37777+R0)
SOB R0,1
Если нужна высокая скорость, то лучше очищать память не побайтно, а сразу словами. Получится вдвое быстрее. Но можно ускориться сверх того: по какой-то причине команда CLR работает медленней, чем MOV. Поэтому:
CLR R2 ; записываем ноль в регистр R2
MOV #40000,R1 ; начальный адрес
MOV #20000,R0 ; счётчик цикла
1: MOV R2,(R1)+ ; очищаем слово по адресу, после увеличиваем R1
SOB R0,1 ; оператор цикла
Теперь, выбрав один из четырёх способов очистки экрана, можно уже ставить точки. В цветном режиме каждой точке соответствуют два бита. В монохромном — один бит. Программного переключения режимов экрана у БК нет. К какому выходу подключил монитор, такое изображение и получил.
Для наглядности запишем цвета точек в двоичной системе счисления:
MOVB #0b00001100,@#50010
MOVB #0b00110000,@#50112
MOVB #0b11000000,@#50313
Цвета в каждой паре битов кодируются так: если установлен только чётный бит — зелёная точка, только нечётный бит — синяя, установлены оба бита — красная, сброшены оба бита — чёрная. Ну а монохромный монитор показывает каждый бит как отдельную точку.
Команда MOVB записывает в экранную память сразу 4 точки, а команда MOV — 8 точек. Если вы не хотите затрагивать соседние точки, используйте команду BIC (Bit Clear) и BIS (Bit Set), например:
BICB #0b00001100,@#50112 ; стереть точку
BISB #0b00000100,@#50112 ; поставить синюю точку
Интересный момент: в тексте мы записываем младшие биты правее старших. А на экране наоборот: точки, соответствующие младшим битам, появляются левее.
Вот, собственно, и всё об устройстве экранной памяти БК 0010.
А что же на счёт вывода текста?
MOV #Text,R1 ; адрес текстовой строки
EMT 20 ; вызов зашитой в ПЗУ процедуры печати текста
HALT ; останов программы
Text: .ASCII “Hello, World!”
.BYTE 0 ; строка должна заканчивать нулевым байтом
Покажите исходники!
Легче всего будет начать, посмотрев исходники готовых демок:
In Your Space — демо для Covox, исходники в архиве.
Good Apple — исходники на GitLab (сложный многофайловый проект).
В 28-ом выпуске журнала Downgrade большая статья про эволюцию алгоритмов трекерной музыки на БК 0010, с фрагментами программ и подробными разъяснениями. Ностальгический рассказ о ранней демосцене впридачу.
EIS — эмулятор инструкций расширенной арифметики с исходниками.
Когда приступать?
Прямо сейчас. Через 4 недели в Казани состоится демопати CAFe 2019. В программе фестиваля есть конкурс БК 0010 — 512 байт. В такой размер уместится от 85 до 256 инструкций – идеально для начинающих. Двух недель вам хватит на то, чтобы разобраться с инструментарием и написать первую простенькую демку. После этого ещё останется неделя-полторы на написание второй, более серьёзной работы.
Дерзайте, вы можете! Телеграм-чат, форум на zx-pk — везде вам помогут. присылайте работы на конкурс, а лучше ещё и приезжайте сами. Scene is alive!