Не так давно мне в руки попался CD-аддон для 16-битной консоли Sega Mega Drive, знаменитый своими FMV-играми. И в процессе изучения игровой библиотеки и системы у меня возник вопрос: а насколько сложно было бы сделать собственный видеодиск, проиграть на консоли собственное видео? И вот что у меня получилось...

Вместо тысячи слов - работающий скрипт, пускай и с рядом оговорок, о которых ниже: https://github.com/Newbilius/SegaCD_VideoCD_Converter
Демонстрация работы и качество получаемого видео:
Скрипт конвертирует видео в формат Cinepack с учётом требований системы, и потом собирает образ диска для Sega CD / Mega CD с этим видео и плеером. Образ можно либо загрузить в эмуляторе игровой консоли, либо записать на болванку и запустить на консоли уже реальной. Никакой защиты от запуска сапописных дисков у консоли нет, а региональная защита не проблема, т.к. скрипт по запросу может собрать образ под любой регион.
Если захотите попробовать запустить это же видео на эмуляторе или на консоли, чтоб проверить его реальность — образы дисков под все регионы лежат тут: https://github.com/Newbilius/SegaCD_VideoCD_Converter/tree/main/examples
Как оно работает
Нюанс тут в том, что скрипт я именно что собрал из готовых частей: под капотом он использует пачку других утилит и скриптов, большая часть из которых была написана на Perl человеком с никнеймом Bgvanbur ещё в 2011 году. Ссылки на все оригинальны скрипты, естественно, указаны там же в репозитории! И главной проблемой в сборке было то, что оригинальные скрипты поставлялись "как есть", без документации и описания необходимых зависимостей и окружения.
Некоторые скрипты я доработал сам, некоторые через LLM-ки портированы на Python для увеличения скорости работы, т.к. тратить почти час на конвертирование 3-минутного видео — то ещё развлечение. В итоге процесс работы основного скрипта выглядит так:
1) Выдираем из исходного видео аудио-дорожку с помощью ffmpeg, конвертируем её в 8-битный монофонический WAV-файл с частотой 16276 Гц. Частота выглядит странно, но как я понял, это завязано на проприетарную библиотеку, которая требует именно такой частоты
2) Разбиваем видео-файл на кадры с помощью всё того же ffmpeg, каждый кадр сжимаем до разрешения 256x192 пикселя и экспортируем в формат PNG. На этом же шаге решаем, сколько у нас будет кадров в секунду в финальном видео. По моему опыту в таком разрешении стабильно работает лишь 7-8 кадров в секунду. Большая частота кадров рано или поздно приводит к заиканию звука и пропуску или повтору кадров, в общем - видео начинает визуально дёргаться. При этом я видел примеры видео на SegaCD с 15-кадрами в секунду в том же разрешении без заиканий! Но у себя воспроизвести такой опыт я не смог. Ну и разрешение это не минимальное для системы, можно было бы сжать и сильнее — но использованный плеер не умеет растягивать видео меньшего разрешения на весь экран, так что если уменьшить размер — большая часть экрана останется пустой.
3) Снижаем количество цветов до 15, используя один из доступных алгоритмов дизеринга (Римерсма, Флойда-Стейнберга, упорядоченный 2x2 / 4x2 / 4x4) или без такового. Вообще, Sega Mega Drive умеет отображать на экране до 4 палитр одновременно, по 16 цветов в каждой, но в трёх палитрах один из цветов обязан быть прозрачным, так что гипотетически мы можем выжать 61 цвет на экране (15x3 + 16). И формат файлов для данного плеера умеет использовать сразу 4 палитры! Но настроить всё так чтоб оно работало я не смог.
4) Каждый кадр пережимается под формат видеосистемы Mega Drive: разбивается на тайлы и карты тайлов для экрана, плюс для каждого кадра генерируется файл с уникальной палитрой. Из-за того, что уменьшение количества цветов на 3 шаге делалось для каждого кадра индивидуально, изображение может местами мигать из-за выбора разных палитр в соседних кадрах. И это в целом характерная проблема для видео на Sega CD / Mega CD, можно сказать "часть стиля". И данную проблему определённо можно победить алгоритмически, но я так далеко не копал.
5) Файлы видео и аудио-дорожка собираются в контейнер для проигрывателя.
6) Ну и собственно далее идёт сборка образа диска с видео-контентом и вшиванием загрузчика под выбранный регион. Первый ключевой момент для процесса — ассемблерный файл SP.ASM, который инициализирует нужный режим экрана, выделяет место в памяти и передаёт управление библиотеке-плееру. Ну а сам плеер находится в файлах MAINPLAY.BIN и SUBPLAY.BIN, как я понял, это уже скомпилированные в бинари проприетарные библиотеки, написанные то ли компанией SEGA, то ли их подрядчиками или авторами кодека. Плеер там является демонстрационным и не даёт никакого управления над процессом: ни перемотки, ни возможности поставить на паузу там нет. Из непривычного лично для меня - в функцию проигрывания передаётся НОМЕР СЕКТОРА на диске. Файловая система и именами файлов и директориями? Пффф, это слишком скучно и высокоуровнево)))
Просьба о помощи
Как вы уже увидели по предыдущим шагам, данное решение далеко от идеала. Отсутствие возможность управлять проигрывателем, только одна палитра для каждого кадра... Но это всё мелочи.
Ключевая беда — видео может быть длиной не более 3 минут 40 секунд, примерно в этом месте видео зависает, и на фоне последнего загруженного кадра по кругу повторяется последний аудио-фрагмент. Похоже на переполнение какого-то счётчика в плеере, но найти причину я не смог — не хватило квалификации. Точно могу сказать разве что то, что использование единой палитры для всех кадров видео ситуацию не решает, т.е. переполняется не оно. Но может быть именно у вас получится доработать проект и решить эту проблему?)
Все исходники, включая ссылки на все использованные материалы, исследование того же Bgvanbur, разные бинарные версии библиотеки плеера и прочее также собраны в репозитории:
https://github.com/Newbilius/SegaCD_VideoCD_Converter/tree/main/sources_of_information
P.S. У меня есть аналогичный проект для первой Sony PlayStation, но там подобных проблем нет и на диск влезает целых 32 минуты видео :)

