Сложно ли создать эмулятор ZX Spectrum для SEGA Mega Drive?

Имплантация ZX Spectrum в архитектуру SEGA Mega Drive: хроники инженерных тупиков.

Первоначальный замысел выглядел обманчиво просто: берем картридж с FPGA Altera Cyclone IV (EP4CE15F23C8N), разворачиваем внутри кристалла ядро процессора Z80, подключаем BIOS, настраиваем маппинг портов — и дело в шляпе. Остается лишь наслаждаться классикой вроде Dizzy или Elite.

Вдохновленный этим планом, я взялся за реализацию и уже через три дня получил рабочую основу: логика ядра успешно функционировала, игры запускались, геймпад реагировал, а из колонок доносился звук. Казалось, успех уже в кармане, и я поспешил объявить о триумфе.

Однако эйфория была недолгой. Она испарилась, как только я протестировал отображение атрибутов, а именно знаменитый эффект FLASH (инверсию цветов INK и PAPER). Стоило игре активировать мигание, как изображение превращалось в хаос. Я столкнулся с фундаментальными архитектурными ограничениями видеопроцессора Сеги (SEGA VDP).

Немного визуализации того, как выглядел проект на раннем этапе:

Спустимся с небес на землю. Да, внутри Sega Mega Drive действительно есть свой Z80, но использовать его как основу для ZX Spectrum — затея бесперспективная. У него изолированная шина, специфическая периферия и жесткие тайминги, не имеющие ничего общего с архитектурой Спектрума. Попытка «подружить» их без глубокого контроля сигналов обречена на провал.

Единственный верный путь — полная эмуляция ядра Z80 внутри FPGA, тактируемая от независимого генератора.

Но даже после запуска ядра возникает главная проблема: как согласовать попиксельную графику Спектрума с тайловой структурой видеоконтроллера Сеги.

Пиксели против тайлов: конфликт визуализации.

Спектрум работает по принципу прямого вывода пикселей (bitmap), тогда как Сега оперирует исключительно тайлами (сетками 8 × 8 пикселей). Чтобы адаптировать одно к другому, необходимо преобразовать рабочую область ZX Spectrum в массив уникальных тайлов. Разрешение 256 × 192 пикселя дает нам сетку из 32 × 24 блоков.

Итоговая рабочая область: 32 × 24 = ровно 768 уникальных тайлов.

С бордюром ситуация проще: мы можем не перерисовывать его полностью, а ограничиться одним тайлом, который VDP будет дублировать по всей площади экрана.

План выглядел солидно: обновлять тайлы в видеопамяти SEGA VDP в каждом цикле VBLANK. Но физические возможности шины данных консоли поставили жирный крест на этой идее.

Три аппаратных препятствия, блокирующих эмуляцию.

Практика показала, что пропускная способность шины данных Сеги не справляется с поставленной задачей.

1. Дефицит времени в VBLANK.

Один тайл весит 32 байта, а весь массив из 768 тайлов — это 24 576 байт (24 КБ). В режиме NTSC (60 Гц) обратный ход луча крайне короток, и DMA Сеги успевает передать лишь около 7.3 КБ. Мы отстаем от требуемой скорости более чем в три раза, а попытка растянуть процесс передачи на несколько кадров приводит к катастрофическому tearing (разрыву) изображения.

2. «Пытка бордюром» в HBLANK.

Одинокий тайл бордюра должен динамически менять цвета в каждом HBLANK, чтобы отобразить те самые полосы при загрузке с кассеты. Времени на это у видеопроцессора Сеги критически мало — приходится буквально «гоняться за лучом», обновляя палитру на лету.

3. Проблема оверлея клавиатуры.

Для управления на Спектруме необходим оверлей с виртуальной клавиатурой. Это дополнительные тайлы, требующие места в памяти и времени на отрисовку, что лишь усугубляет и без того критическую нехватку пропускной способности.

Эволюция ошибок:

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

Путь к решению: кастомный видеоконтроллер и звук.

Ключом стало создание собственного модуля ZX_SEGA_VIDEO внутри FPGA. Он взял на себя роль интеллектуального посредника, который «на лету» отслеживает изменения атрибутов в памяти Z80 и генерирует сетку тайлов, отправляя данные в SEGA VDP именно в те такты, когда шина свободна. Кроме того, было добавлено аппаратное ядро YM2149 с алгоритмом стерео-микширования, что позволило добиться чистого звучания без артефактов и клиппинга.

Результат впечатляет: мгновенная загрузка снапшотов, качественный AY-звук и полноценное управление с виртуальной клавиатурой на 16-битной консоли.

Упрощенная архитектура решения:

Финальный штрих: дань уважения кассетным лентам

Добившись мгновенной загрузки образов, я задался вопросом: а как же «ламповое» ожидание? Ведь процесс загрузки с .tzx — это важная часть культуры Спектрума. Без характерных полос на бордюре и специфического цифрового шума картина была бы неполной.

Аппаратный плеер на базе FIFO

Для корректной эмуляции загрузки я реализовал специализированный FIFO-буфер внутри FPGA. Он тактируется от системного генератора, что избавляет от дрожания звука (джиттера) и обеспечивает точную передачу данных с SD-карты.

Теперь выбор за пользователем: либо моментальный старт через .SNA, либо аутентичное погружение в атмосферу 80-х через .TZX. В режиме «кассеты» на бордюре Сеги бегут те самые разноцветные полосы, а из динамиков раздается ностальгический скрежет загрузки данных.

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

На этом всё. Желаю отличного настроения и крепкого здоровья!

 

Источник

Читайте также