Демо BACK TO THE PET — дневник разработки
В 2022 году я написал и выставил на CAFe 2022 полноформатное демо для редкой в наших краях платформы, одного из древнейших персональных компьютеров — Commodore PET 4032. Монохромный текстовый режим 40×25 без возможности загрузки шрифта, никаких аппаратных скроллов, однобитный бипер на выходе последовательного порта, 32 килобайта ОЗУ, в которые помещается все 4 минуты демо без дозагрузок.
По итогам года демо попало в список The Meteoriks 2023, было номинировано на Best Oldschool Production (лучшее демо для ретро-платформ), где, конечно, не победило, но составило конкуренцию другой работе, в создании которой я также принимал участие, и о чём рассказал на Хабре ранее.
Ещё до начала проекта я решил не делать традиционный 'making of' после релиза, чтобы его написание не затянулось на год — тяжело работать над новыми проектами и одновременно мучительно пытаться вспомнить, что, как и зачем я делал в предыдущем месяцы назад. Вместо этого я в очередной раз попытался вести полноценный дневник разработки, записывая мысли непосредственно в рабочем процессе, от возникновения идеи до результата, и в кои-то веки удалось довести документируемый таким образом проект до завершения.
Записи до 06.09 сделаны по памяти, до того момента я ещё не определился, что и в каком формате буду делать. Осторожно: далее следует плохо структурированное чтиво эпических размеров, в том виде, в котором оно записывалось, без литературной обработки. Для Хабра решил не разбивать на части, но дополнить иллюстрациями.
06.08
Посетил ежегодный местный ретро-геймерский конвент GBX Summer Party. Встретил там коллегу, и он сообщил мне, что в этом году снова будет CAFe в Казани. Призадумался, а не посетить ли его. Ну, а если посещать — то не с пустыми руками, нужно сделать какую-то работу.
13.08
Среди множества заметок о возможных проектах появляется запись идеи реализовать эмулятор PET на внутренних ресурсах ESP8266, без внешней обвязки, для встраивания в клавиатуру. Этой идее несколько месяцев, она периодически приходила в голову до этого.
14.08
У меня накопился с десяток идей для возможных демо, в разных форматах и для разных платформ, включая самую дичь. Часть из них уже была описана в общих чертах. Набросал краткие описания других идей, и попробовал оценить, какую из них можно было бы успеть реализовать за имеющееся время. Точно не помню, но кажется идея демо для PET возникла где-то в этом процессе, изначально её в списке идей не было, видимо в связи с мыслями об эмуляторе PET. Преимущество этой задумки в том, что на создание сложных эффектов нет времени, но на PET их сделать сходу всё равно не получится, за отсутствием графического режима. Значит, можно будет ограничиться относительно простыми псевдографическими эффектами, а основной упор сделать на эстетику платформы. Также есть готовое решение по звуку в виде PeskyTone/PeskySound и плагина для 1tracker, и вообще некоторый относительно недавний опыт — всё это должно позволить уложиться в срок.
15.08
У The 8-bit Guy выходит видео про самодельный корпус для реплики PET. Вероятно это утвердило меня в мысли выбрать именно направление PET.
18.08
Хотя у меня уже есть готовое решение для музыки, оно заточено на минимизацию размера данных в ущерб разнообразию звучания, и процесс сочинения в рамках этой системы относительно трудоёмкий. Хотелось бы иметь возможность использовать для сочинения Reaper — он показал себя очень удобным и экономящим время инструментом в ряде предыдущих проектов, начиная ещё в AONDEMO. Для этого я решил модернизировать мой VSTi плагин PCSPE, а в процессе также решил выделить эту модернизацию в отдельный проект под названием PETCB2. Это то же самое, но с огибающей для формы волны и с другим выходным форматом данных. Изменения были минимальными, и я завершил этот проект за день, включая пример плеера на 6502.
Интерфейс плагина PETCB2
Работа над кодом плеера стала разогревом перед началом работы над демо — я настроил окружение, подготовил конфиг и сборочные файлы, подтянул эмуляторы.
19.08
Написал пакер для выхлопа PETCB2, который позволит сэкономить значительный объём ОЗУ без особых потерь скорости. Демо планируется однозагрузочным, оно должно влезать в 32 килобайта вместе со всеми буферами, потому что PET сразу установил традицию утомительно долгой загрузки на многих компьютерах Commodore. Если на C64 справлялись с этим за счёт кастомных загрузчиков, на PET сделать динамичное демо с подгрузками и непрекращающейся музыкой на нём не представляется возможным, особенно с учётом плохой эмулируемости и недоступности оригинального железа.
На основе кода примера плеера из PETCB2 создал пустой проект для демо. В отличие от многих моих предыдущих проектов, код демо будет писаться полностью вручную на ассемблере, так как производительность PET и объём доступной памяти очень ограничены, компилированный C код тут не прокатит.
21.08
Уже некоторое время набрасывался предварительный список идей для эффектов, новые идеи приходили во время работы, и к этому моменту стало оформляться примерное содержание. Внятного сценария пока нет, работа над ним только начата, но появляется предварительная оценка динамики — порядка трёх минут, чтобы не утомить публику довольно однообразной псевдографикой, и порядка десяти сцен, около 20 секунд на сцену.
Подготовлен тестовый трек такой длительности, чтобы оценить затраты памяти — просто взял трек из AONDEMO, добавил разных форм сигнала для инструментов, экспортировал и упаковал. Получилось 3995 байт.
22.08
Сделал набор символов PETSCII в виде тайлсета для NESST, так как рисовать мне удобнее в нём.
Набор символов и часто используемые символьные элементы для последующего копипаста. Сам редактор моего же авторства предназначен для графики NES, но часто пригождается и для других платформ.
23.08
Начал реализовывать эффект символов Матрицы на ассемблере 6502, и понимаю особенности платформы. Эффекты хочется делать по возможности в 60 FPS, так как они смотрятся значительно интереснее, но на PET с его тактовой частотой 1.0 МГц при 1000 байтах экрана получается порядка 16 тактов на обработку каждого байта экрана за кадр, то есть времени на полную перерисовку экрана впритык. Эффект тормозит.
Прихожу к мысли, что лучше все эффекты прототипировать на C в окружении SDL, и когда алгоритм достаточно оптимизирован, тогда уже переписывать его на ассемблер 6502. Ранее я применял этот подход при создании HEOHDEMO, и он хорошо сработал, это должно сэкономить время. Сделал прототип эффекта Матрицы в таком виде.
24.08
Эффект Матрицы готов и настроен для плавной работы.
05.09
Написал C-прототип задуманного немного ранее эффекта волн на горизонтальных полосках — вариация того, что запомнилось в No Pets Allowed, отладил алгоритм. Начало и конец эффекта, которые представляют собой мини-эффекты, пока отсутствуют. Также нет полного понимания, как именно добиться 60 FPS в этой сцене — только общая идея, но добиться надо.
Сценария всё ещё нет, но список эффектов, которые ближе к практической реализации, постепенно увеличивается. Другие эффекты отпадают после оценки сложности. В частности, была идея эффекта со змейкой, быстро собирающей точки и заполняющей весь экран. После изучения алгоритмов, решающих змейку, выяснилось, что им нужно порядка 60 тысяч шагов для поля 30×30, и настолько эффективный алгоритм реализовать не получится, а заранее просчитанная анимация просто не влезет в ОЗУ.
06.09
Сделал список имён для сцены гритсов, которая пока не придумана, а также список задействованного софта на случай возможных финальных титров.
Задумал простую сцену-филлер с шахматным полем 2×2 символа, где отдельные строки и столбцы будут попиксельно скроллиться относительно других строк и столбцов. Получить в ней 60 FPS должно быть достаточно просто, т.к. нужно просто размножить одни и те же четыре байта из таблицы на две строки или столбца.
Поприкидывал в NESST, выйдет ли сделать ранее задуманную сцену лабиринта — развитие известной в Commodore-кругах простейшей однострочной программы.
Придумал сцену с речевой вставкой, чтобы на экране было некое лицо и оно произносило какую-то фразу. Лицо должно быть в духе страшной рожи из советской аркады Магистраль, а фраза — какой-то слоган Commodore, произносимый речевым синтезатором в духе ранних 80-х. Выбрал известный слоган про Амигу. Прикинул по памяти, и решил, что заморачиваться синтезом из аллофонов нет смысла, трёхсекундная фраза и так должна поместиться в 3–4 килобайта памяти. Перебрал несколько эмуляторов SP0256, Speak&Spell, в итоге нашёл годный VSTSpeek, эмулирующий S.A. M, и что важно, поддерживающий фонетический режим. Сконструировал из фонем фразу, подрезал её нужным образом.
Поискал идеи для рожи с помощью Stable Diffusion, но в итоге пришёл к идее нарисовать сам PET псевдографикой вручную, а лицо представить просто крупными пикселями глаз и рта на экране нарисованного PET. С двух попыток нарисовал этот экран в NESST. Прикинул, как сделать липсинк с технической точки зрения, почитал про раскадровки рта в классической анимации.
Под конец дня подумал, что стоило бы вести дневник разработки. Я уже не раз пытался делать это для разных проектов, но они в итоге не доходили до завершения. С другой стороны, писать making of постфактум довольно утомительно и лень, а детали не задерживаются в памяти, и восстановить процесс прихода к тем или иным решениям иногда уже не получается. Восстановил в памяти и записал предшествующие события.
07.09
Прошло уже некоторое время от начала работ, но на текущий момент фактически готов всего один небольшой эффект. Нет сценария, нет музыки, нет даже названия. Также стало ясно, что для этого проекта эффекты будут идти перед сценарием, то есть буду делать эффекты, которые будут получаться легче, а потом как-то собирать из них демо, вместо того, чтобы запланировать конкретные эффекты и реализовывать их, несмотря на любые затраты времени.
Текущий план действий таков: сосредоточиться на доведении до готовности тех сцен, для которых подготовлено больше всего материала, причём желательно работать над одной сценой за раз, а не над всеми сразу, как это обычно происходит. По готовности нескольких сцен прикинуть намечающийся сценарий — порядок следования готовых элементов; не готовые, но обязательные другие; и возможные новые сцены из списка идей. Тем не менее, обновил файл описания сценария, выписав в него наиболее перспективные эффекты из имеющихся идей. Получилось 15 пунктов, из которых несколько штук — небольшие эффекты для перехода между сцен, а несколько — основные сцены, имеющие свои анимации переходов.
Взялся за голосовую вставку. Вчера подобрал фонетический ввод для VSTSpeek: OHNLIH KAAMOHDOHR PPAEAEAETTT MEYKS IHIHT PAWSIHBLLLLL. Часть с AW звучала некорректно, но начальная гласная мне понравилась больше, и я подрезал итоговый сэмпл для корректного звучания. Тестовый импорт сэмпла я предварительно делал в 1tracker в движке SquatM, новые тесты в BeepFX. Выяснилось, что пропадает звук S и не очень чётко звучат некоторые другие, из-за их смещения относительно нулевого уровня. Пододвинул и сделал громче некоторые места в Wavosaur, и итоговый трёхсекундный сэмпл зазвучал адекватно. Более-менее разборчивый звук получается при размере сэмпла 3.5 килобайт (сжимается apultra до 2.6K), в меньшем качестве теряются свистящие. Высокое качество звука для этой сцены не требуется, главное общий эффект: напомнить, как впечатляли первые голосовые вставки в компьютерных программах. Сделал проигрывание сэмпла, минимальную анимацию рожи и печать фразы снизу во время проигрывания. Фоновая картинка пока не выводится, пока не придумал эффекты для её появления и стирания.
Чтобы уместить все эффекты в имеющейся памяти, нужно сделать их как можно компактнее. Предполагаю задействовать сжатие сцен целиком, вместо со всех их кодом и ресурсами, и распаковку по мере надобности. Сжимать буду apultra. Есть готовый депакер для 6502, но он под другой ассемблер, требуется адаптация. Объём доступной памяти также ограничивает количество эффектов в демо, что с одной стороны неудобно, но с другой позволит удержать объём проекта в рамках приличий, чтобы можно было закончить его вовремя.
08.09
Адаптировал aplib_6502.s к синтаксису CA65. Проверил пока только на картинке с компьютером, но ошибок быть не должно.
Уже некоторое время обдумывал сцену с классическим phong bump mapping. Помимо скорости, основная проблема в том, как отобразить освещение на PET, чтобы это смотрелось интересно. Набросал прототип на C с вариантом, на который делал основную ставку — горизонтальные линии и пиксельные смещения в каждом знакоместе в зависимости от освещённости — результат не смотрится. Возможно, попробую преобразовать эту идею в морфинг выпуклых изображений.
09.09
Провёл эксперимент с прототипом бампа, заменив отображение с линий на распределённые по плотности символы. Смотрится поинтереснее, но SDL-прототип работает на 60 FPS, а на PET хорошо, если получится выжать 30, но скорее будет 20. Для желаемого эффекта нужно обеспечить 256 градаций псевдояркости, тогда как типичная оптимизация для 8-битных платформ подразумевает всего 15 градаций, чтобы уложить основные расчёты в 256-байтную таблицу. В таком виде задача обещает быть сложной, поэтому отложена на потом.
Доделал прототип сцены с волнами, добавил часть с появлением и уезжанием полосок, с быстрым алгоритмом их отрисовки. Теперь требуется переписать её на ассемблер, и похоже, что получить 60 FPS в основной части эффекта будет непросто.
12.09
Продолжение работы после перерыва на выходные. Суммарное количество готовых сцен демо уже некоторое время превышает единицу, но никак не доберётся до уверенной двойки. В связи с этим решил закончить хотя бы сцену с говорящим компьютером.
Для финала этой сцены сделал ещё один микроэффект, гашение экрана псевдояркостью. Вероятно он также пригодится при запуске демо для стирания текущего содержания экрана. Для появления экрана я сначала думал сделать разнонаправленный скролл частей экрана, но это визуально слишком простой эффект. Вместо него решил сделать посимвольную прорисовку картинки. Порядок появления символов я определил вручную, попиксельной анимацией маски в Graphics Gale. Вышло 119 кадров. С помощью очередной вспомогательной программки-конвертера преобразовал анимацию маски в набор данных в формате три байта на символ, адрес и код символа.
Также сделал появление лица на экране несколькими фазами увеличения его из точки в центре до нормального размера.
Для демо пока не написано ни одной ноты музыки. Обычно музыка для демо идёт в начале, а эффекты подгоняются под неё, либо музыка и эффекты делаются одновременно, но на этот раз случай иной, и музыку придётся писать и подгонять под уже готовую визуальную составляющую. Поэтому пока совершенно непонятно, какой она будет. Но ещё с момента оцифровки фразы для сцены говорящего компьютера возникла идея использовать её довольно странно звучащую ритмическую структуру как главный мотив саундтрека. Таким образом, проигрывание фразы в конце демо сыграет роль разрешения музыкальной темы. Пока не уверен, получится ли осуществить эту задумку, но попробовать стоит.
В процессе отладки сцены, после очередного прослушивания фразы, элементы паззла в виде разрозненных идей наконец сложились, и оформилась в общем-то очевидная идея для центральной концепции демо: реклама PET, ретрохайп платформы. Это определило содержание изображений для сцены с морфингом выпуклых фигур, написал её прототип и нашёл более-интересный вариант отображения четырёх картинок с размытием и инверсией выпуклости-впуклости.
Исходные карты высот для сцены с морфингом.
13.09
Дальнейшее обдумывание концепции и вариантов названия. Рабочее название PETDEMO слишком простое, но оно неплохо сочетается с названиями моих предыдущих работ. Учитывая направленность демо, есть вариант PET*HYPE. Разумеется, в голову приходили также различные гэги про PETting, но это слабовато. Вполне однозначно ясно, что хотелось бы в том или ином виде включить PET в название.
Возникла одна довольно спорная идея, которая, впрочем, является давней традицией демосцены, и по прежнему не сдаёт позиций — сделать отсылку к такой глыбе поп-культуры, как фильм Назад в будущее, и назвать демо Back to the PET. Совмещая это с идеей хайпа, подразумевается, что это демо могло бы существовать во времена появления платформы, и служить её рекламой. В минусах неоригинальность подхода, традиционные плюсы — расположение более массового зрителя за счёт узнаваемости, элементы для сценария и цитат в контенте. За неимением лучших концепций пока склоняюсь к этой идее.
Начал реализацию сцены морфинга на ассемблере. Сделал сохранение карт высот в формате RLE (три бита высота, пять бит кол-во повторов) и распаковщик на 6502 — смысл этого в экономии памяти под буфера в момент работы эффекта. Также реализовал прочие необходимые элементы, но пока сцена смотрится очень плохо, особенно сама анимация морфинга. Из-за нехватки скорости я попытался использовать оптимизацию в виде обновления экрана по столбцам, но из-за неё происходит мерцание и диагональные разрывы. Придётся переделать, и возможно ограничиться 30 FPS.
14.09
Разобрался со всеми проблемами эффекта морфинга. К сожалению, его плавность оставляет желать лучшего — 20–30 FPS в зависимости от разницы между изображениями. Для избежания сечения с лучом пришлось разделить отрисовку экрана и цикл морфинга, что автоматически снижает скорость эффекта почти вдвое — и даже так едва-едва хватает тактов, чтобы сечения не происходило, и это ещё без музыки. Конечно, можно было бы получить 60 FPS при наличии лишних 8 килобайт ОЗУ для предварительного просчёта всех кадров, но я хочу уложиться в 32 килобайта на всё демо, и это обещает быть довольно непростым делом. Видимо, придётся смириться с недостаточной плавностью. Тайминг самого демо не должен пострадать из-за неравномерной скорости эффекта, так как смена картинок планируется по маркеру в музыке, на каждый удар.
Для завершения сцены морфинга нужен какой-то эффект стирания экрана. Разъезжание или осыпание полосок было бы слишком банальным, поэтому я решил попробовать сделать дополнительный эффект внутри этой сцены: плавное стирание по форме последнего изображения, сердечка. В процессе также пришла идея сделать это со шлейфом символов меньшей плотности. Реализовал эффект следующим образом: нарисовал покадровую анимацию в разрешении 20×25 (так как она симметрична) в Graphics Gale, написал конвертер, выдающий для каждого кадра набор адресов символов для стирания в каждом кадре. Понадобилась одна маленькая хитрость: так как ширина экрана на PET 40 символов, сделать симметричную зарисовку простыми битовыми манипуляциями не получится. Пришлось отдать 10 старших бит слова на хранение вертикального смещения в буфере (Y*40), и младшие 6 бит на горизонтальное смещение. Таким образом легко посчитать адрес символа в обоих половинах экрана. Итоговый эффект смотрится эффектно, хотя и не совсем в стиле сцены. Оставлю пока так.
На доделку даже такой в общем-то примитивной сцены ушёл целый день. Но хотя бы счётчик готовых сцен перевалил за две единицы.
15.09
Среди первых задумок для демо была идея обыграть классическую однострочную программу на Commodore BASIC, рисующую лабиринт случайным чередованием символов / и \. Решил сделать прототип и посмотреть, работает ли изначальная задумка: пустить несколько лабиринтов разного размера в виде слоёв с разной скоростью прокрутки. Оказалось, что задумка не работает, слои сливаются в кашу, трудно отличимую от стандартного лабиринта. Но прототип подсказал другой вариант: сначала рисуем классический лабиринт, потом более крупный и более детализированный. Попробовал сделать версию с тайлами 4×4 символа.
С появлением новых идей и с пониманием, какие эффекты ближе к практической реализации, обновил и уточнил сценарий. Текущая его версия уже более-менее похожа на правду, она содержит десять сцен разной степени сложности. Также есть восемь возможных дополнительных сцен, которые могут быть включены, если удастся сделать их вовремя. Готовность же кода и контента самого демо пока можно оценить только в 10%. Текущая задача прежняя — довести как можно больше сцен до готовности за минимальное время, чтобы как можно раньше появилось то, из чего можно собрать хоть какое-то демо.
Одна из новых сцен, запланированных в сценарии, изначально предполагала просто показ надписи Personal Electronics Transactor, или очень крупной с быстрым горизонтальным скроллом, или же по одному слову, с какими-то простыми эффектами. В процессе поиска идей я случайно нагуглил несколько обложек журнала Commodore Computer Club, на которых часто изображались прохладно одетые красавицы, и это напомнило мне рекламу в компьютерных журналах 70-х — это часто было изображение женщины, взаимодействующей с компьютером — традиция, продолжившаяся и на демосцене с 80-х до наших дней. Так возникла задумка добавить в сцену с надписью три псевдографические картинки, изображающие женские рекламные образы и эффект печати каждого слова — более разнообразный визуальный контент и лишние голоса от мужской аудитории.
Однако, изобразить в монохромном PETSCII 40×25 символов женскую фигуру крайне непросто, а на достижение уровня мастера в этой области времени нет. У меня есть тайл-матчер в NES Screen Tool, и я потратил несколько часов на попытки получить сколько-либо приличную конверсию. Эксперименты показали, что полутоновые фотографии конвертируются крайне плохо, но карандашно-векторные зарисовки, в частности, получаемые через онлайн-стилизаторы, дают более-менее узнаваемый результат. Они всё равно выглядят очень абстрактно-случайно, что стилистически не бьётся с вручную нарисованной сценой говорящего компьютера и, вероятно, с будущим титульным экраном, и я сильно сомневаюсь, что такое сочетание будет смотреться достаточно органично. Впрочем, выбора всё равно нет, обеспечить хорошую стилистически выдержанную PETSCII-псевдографику я сейчас всё равно не смогу.
Исходник, стилизация перед конверсией, результат конверсии.
16.09
Придумал и сделал другой эффект очистки экрана для начала демо — просто прокрутка вверх, которая первые пять строк сдвигает медленно, а потом по строке за кадр. Это нужно, чтобы не начинать демо сразу с хитроумных символьных манипуляций, и повышать интересность визуала постепенно.
Согласно нынешней моде, попробовал сгенерировать подходящие изображения для сцены с Persona Electronics Transactor нейросетью Stable Diffusion, но у неё плохо получается этот сюжет. Раз уж всё равно придётся брать изображения на стороне, решил взять их из той самой рекламы в старых компьютерных журналах. В качестве эффекта для сцены я решил сделать анимацию вращения крупных заглавных букв и печать полных слов обычными символами — традиционная для демосцены композиция 'женщина и говнолёт'. Казалось бы, примитивно, но в рамках платформы даже анимация вращения уже достаточно непростой эффект — её надо убедительно нарисовать псевдографикой, и как-то утрамбовать в память.
Анимацию буквы я начал рисовать в NESST, там есть очень примитивная система переключения между несколькими картами тайлов в пронумерованных файлах. Первые пробы пера показали оптимальный размер буквы — 11 на 10 символов (13 символов в ширину для анимации граней). Экспериментальным путём выяснилось, что нужно 64 фазы вращения, из которых 32 рисуется вручную, и 32 генерируется таблицей отзеркаливания символов. Одна буква занимает 130 байт, 32 кадра — 4 с небольшим килобайта, и таких букв три, плюс ещё 3 килобайта псевдографических картинок. Это почти половина всей доступной памяти, поэтому однозначно потребуется какое-то дополнительное сжатие, помимо сжатия сцены целиком. Даже не хочется думать о последующей сборке всех сцен демо, геморрой обещает быть знатным.
После первых попыток стало понятно, что нарисовать вручную вращение псевдографикой 'на глаз' в принципе можно, но мелкий джиттер значительно портит впечатление, и я решил прибегнуть к старому трюку: смоделировать математически точное вращение в Blender, а потом воссоздать правильные смещения граней в псевдографической анимации вручную. Фактически я сконвертировал анимацию: смоделировал и отрендерил все три буквы в 3D в точном пиксельном размере, строго по сетке, в ортографической проекции, без шейдинга, с разными цветами граней. Моделирование делал по давно придуманному рецепту: создаётся plane, делается subdiv на количество предполагаемых пикселей, далее лишние полигоны-пиксели удаляются, делается extrude. Задаётся точный размер рендера, устанавливается орто камера сверху точно по центру, её масштаб подгоняется до касания plane краёв прямоугольника камеры. Рендер немного доработал руками в Gale, добавив на торец вертикальные линии таким образом, чтобы соответвовать имеющимся символам псевдографики, перевёл в два цвета, и импортировал в NESST тайл-матчингом к набору PETSCII. Получилась реально сконвертированная 3D анимация на PET.
Подготовка анимации буквы в Blender.
17.09
Определился со способом хранения анимации вращения букв. Все коды символов утрамбовываются в минимальное количество бит — всего 23 символа, значит на один символ хватает 5 бит. Таблица 23-х кодов символов сохраняется, к ней в пару идёт таблица кодов визуально зеркальных символов, для получения программно развёрнутых по горизонтали копий всех кадров. Три оставшиеся бита кодируют 1…8 повторов символа. Стоп-кода нет, так как длина блока данных известна. Буквы кодируются по столбцам. Это позволило утрамбовать 10 килобайт в 3, и они должны неплохо дополнительно сжиматься LZ пакером. Написал конвертер данных, протестировал распаковку в прототипе на SDL. Написал распаковку и вывод анимации для самого PET. Работает на все 60 FPS, что неудивительно.
18.09
Пытаюсь набрать три фоновых картинки для сцены с буквами. К сожалению, результат конверсии в любом случае выглядит сомнительно, а вручную нарисовать не удаётся — как минимум, понадобится много времени. Опробовал ранее возникшую идею обратить эту проблему на пользу сцене — добавить шум к изображению, постоянно обновлять его на экране близкими по плотности пикселей символами. Тогда остаётся общий силуэт, а конкретные детали теряются. Прототип на SDL показал, что обновлять символы можно довольно медленно, а шаг обновления сам по себе даёт интересные визуальные эффекты. Вариант, конечно, тоже так себе, но лучше своей статичной альтернативы.
Посетил второй день Яндекс Демодуляции, где обсудил с несколькими заинтересованными лицами возможность посещения CAFe. В разговорах упоминал о том, что готовлю работу, но не раскрывал никаких деталей. Это напомнило мне, что времени до пати осталось не так уж много, а работы по демо ещё непочатый край.
19.09
Сделал RLE-упаковщик картинок для сцены с буквами, написал скролл картинок и эффект символьного шума на ассемблере для PET. Скроллится только область, в которой есть изображение, поэтому весь эффект работает на 60 FPS.
Набросал алгоритм появления и исчезания слов по буквам в прототипе на SDL. Мне понравилось, как он выглядит при очень небольших значениях максимальной дистанции удаления букв, на 2–3 символа. Хороший вариант для секции с приветствиями.
20.09
Согласно известному принципу 80/20, доделываю те самые рутинные 20 процентов для сцены с буквами, которые растянулись на 80 процентов времени. Сцена в принципе завершена, если не считать сомнительных картинок, и это даёт около трёх завершённых сцен в демо.
21.09
После начальной реализации задуманного в полном объёме, я немного упростил сцену для улучшения динамики: изначально надписи под вращающимися буквами не только посимвольно прилетали, но и улетали, а картинка с женским силуэтом при смене экрана скроллилась обратно в ту же сторону, откуда приехала. Я убрал улетание букв и сделал 60 FPS скролл всех картинок вниз.
Такой эффект перехода между сцен показался мне скучноватым, и я попробовал ещё несколько вариантов. Черезстрочный скролл вниз (сначала одна половина строк, потом другая) работает так же плавно и немного поинтереснее обычного скролла, но всё равно не то. Скролл вниз с одновременным уменьшением плотности пикселей в символах визуально гораздо интереснее, но он не может быть реализован на 60 FPS, и это контрастирует с плавностью в остальных частях сцены. В итоге остановился на варианте скролла по столбцам вверх и вниз, с чередованием через один символ.
Так как сцена состоит из трёх экранов, а для синхронизации с музыкой лучше работают четыре такта, чем три, возникла идея дополнить её ещё одним элементом — показать все три вращающиеся буквы одновременно, уже без фоновой картинки. Однако, скорости работы имеющегося кода не хватает на распаковку трёх букв на скорости 60 FPS. Путём многократного искривления извилин сделал серию оптимизаций в коде распаковки и отрисовки вращающейся буквы, и всё-таки, казалось бы, уложил все три буквы в один кадр. НО только для PAL, то есть в 50 FPS.
Не знаю, по каким причинам, но WinVICE упорно эмулирует только PAL модели, хотя предположительно они были очень редки. Тестирую же я изменения в основном именно в VICE, хотя там и не та модель PET — потому что он не требует набирать вручную RUN при загрузке из PRG-файла и нажимать дополнительные кнопки, и тест можно запустить гораздо быстрее. К тому же у MAME по умолчанию просто гигантское окно, заслоняющее нужные вещи. К сожалению, после теста на NTSC-машине в MAME оказалось, что скорости всё равно не хватило — у PAL-моделей 1000000/50 тактов на кадр, а у NTSC — 1000000/60. При записи дробью разница не так бросается в глаза, но по факту это 20000 против 16666 тактов на кадр, то есть прилично меньше (на 17%). Боюсь, что и в предыдущих сценах с этим будут проблемы. Делать PAL only демо или откатываться до 30 FPS для NTSC не хотелось бы. Пока не знаю, как я буду решать эту проблему. Видимо, придётся как-то урезать осетра.
22.09
Успев расстроиться, взял паузу, а потом сделал ещё один подход к трём буквам. Возникла ещё одна идея для оптимизации, и она выжала недостающие проценты производительности. Правда, теперь немного рвётся экран во время одновременного вращения всех букв, потому что двойной буферизации нет, и буфер под распаковку кадра буквы один, для экономии и памяти и скорости. Но это уже приемлемая шероховатость. Дополнил сцену согласно задумке — прилёт линий, печать надписи. один оборот всех букв одновременно вокруг оси, гашение через уменьшение плотности пикселей в символах. Вопрос подтормаживания остальных элементов этой и других сцен в NTSC ещё предстоит решить.
Решил не делать внутри демо финальные титры, для экономии памяти и структурного разнообразия. Вся информация пойдёт в readme, а краткий кредит я встроил в эффект матрицы — там теперь печатаются надписи, а волны падающих символов их стирают. Наконец-то нашлось подходящее место, чтобы ввернуть пришедшее в голову некоторое время назад словосочетание 'proper demo'. Оно забавно звучит на русском, и этим звучанием иносказательно подразумевает, что попытка выжать из платформы невыжимаемое не очень успешна — такой хулиганский easter egg. Это было очередное небольшое изменение в сценарии, который с предыдущего упоминания уже практически зафинализировался, и получает только такие незначительные дополнения.
Теперь можно сказать, что вполне уверенно готовы четыре сцены из (теперь уже) одиннадцати. Одну сцену из дополнительного списка я решил добавить в обязательном порядке хоть в каком-то виде, чтобы усилить сюжетную линию. Она очень хорошо встаёт в сложившийся сценарий, повышая его связность, тогда как другие идеи из дополнительного списка представляют собой просто рандомные эффекты. В процентах завершённость работы пока всё равно невелика, примерно 20–25. Есть концепция, сценарий, название, часть эффектов и контента. Нет ещё более чем половины сцен, нет музыки и сборки. К вопросу о последней, обдумал запасной план с реализацией подгрузок на вполне вероятный случай невлезания всего демо в одну загрузку. Этот подвешенный вопрос, который прояснится только после завершения всех сцен, отодвигает написание музыки в самый конец очереди задач.
Составил список проблем с торможением и глюками в NTSC. Исправил часть мелких проблем в сцене с вращающимися буками, и заодно изменил чередование столбцов в эффекте убирания экранов на два символа, так смотрится получше.
23.09
Вчера начал понемногу пытаться рисовать титульный экран и графику для сцены таймлайна в начале. За несколько подходов нарисовал различные элементы титульного экрана, которые постепенно собрались в один более-менее приличный вариант, хотя пока и есть сомнения, достаточно ли он крут. Также нужно придумать интересный эффект для его появления, но пока никаких идей на этот счёт не возникло