Для начала небольшое теоретическое введение в проблему произвольной раскраски спектрумовских игр вообще и простого обесклэшивания в частности. Как заставить старый спектрумовский код выводить картинку с независимыми цветами для каждой точки? Эта задача распадается на две подзадачи.
Во-первых, для того, чтобы хранить полученную картинку, информации о каждом пикселе нужно больше, то есть нужна дополнительная память и организация в ней данных в новом формате. Формат этот может быть в принципе любым, удовлетворяющим условию "цвет на точку", но лучше выбрать наиболее удобный для развития новых графических возможностей в будущем. Память требуется не только для отображаемого экрана, но и для промежуточных буферов, широко используемых на спектруме.
Во-вторых, как заполнять эту память? Ведь на каждый пиксель теперь нужно информации записывать тоже больше. Если старый код мы не трогаем, то естественно возникает мысль каждому биту в памяти спектрума сопоставить один пиксель в дополнительной памяти и синхронно их пересылать/изменять. По такому приципу работает Spec256 и аналоги. Но проблема в том, что на спектруме информация о
настоящей окраске пикселя вовсе не привязана к биту! Атрибут спрайта может где угодно храниться в памяти и даже вычисляться случайным образом. Того хуже, записью атрибутов настоящая окраска уже отображаемого объекта может измениться неоднократно без каких-либо пересылок пикселей вообще.
Конечно, можно выделить некие два цвета нового формата как спецзначения, чтобы атрибуты на них влияли, как и на спектруме (и как это сделано в EmuZWin). Но проблему это окончательно не решит там, где неизбежно наложение объектов переменной раскраски - они будут портить цвета друг другу. А где решит, может требовать дополнительной работы (например, по полной раскраске фона, чтобы атрибуты спрайтов его не красили). Вот было бы хорошо уметь назначать объекту разные раскраски, на которые атрибутный клэшинг не повлияет!
Но кто сказал, что нужную при записи пикселя дополнительную информацию нужно непременно привязывать жёстко к биту (и
только к биту) графики в zx-памяти? Ведь информацию о цветах объекта нести может фактически что угодно! Атрибут спрайта, прочитанный в определённый момент - из которого можно напрямую извлечь цвета. Чтение с какого-то адреса, однозначно связанного с объектом, где вместо графики любая служебная информация (да хоть координаты или размер); в дополнительной-то памяти мы можем разместить и другую информацию - о цветах. Даже по факту выполнения определённой ветки кода чуть ранее можно назначать те или другие цвета объекту.
То есть нужно вовремя эту дополнительную инфу
запомнить, чтобы позднее (обычно при работе графпроцедуры)
применить с толком.
----------------------------------------------------------------------------------------------------------------
Q. Что такое ZX ULAX?
A. Концепция расширения графических возможностей ZX Spectrum (теоретически - любого компьютера на Z80; однако дополнительные возможности по облегчению адаптации существующего софта запланированы пока что только для Спектрума). Букву X в названии можно понимать как eXtended или eXpanded. По-русски произносится как "юлакс".
Q. Зачем нужно очередное "расширение ZX-графики", когда уже реализованные очень слабо (или вообще никак) не поддерживаются софтом?
A. Вот затем и нужно, чтобы наконец поддерживалось софтом. Как мы считаем, причина слабой поддержки существующих расширений - в сочетании нераспространённости "расширений" и неудобстве (или отсутствии привычки) программирования для них. Сил и времени затрачивать приходится почти столько же, как для написания софта под обычный Спектрум, но при многократно меньшей потенциальной аудитории. Что демотивирует современных ленивых или слишком занятых спектрумистов. В нынешних условиях шансы на поддержку софтом есть лишь у расширения, под которое можно легко и быстро адаптировать софтину для обычного Спектрума, очень незначительными усилиями. В связи с этим ULAX можно в шутку прочитать в два слова "U 'LAX" - как девиз-обещание не слишком напрягать программиста.
Q. Как будет выглядеть физическая реализация?
A. Как внешняя видеокарта на FPGA со своей видеопамятью для ZX-bus либо прошивка самодостаточной системы Spectrum+ULAX для девборды. Первоначально, на этапе разработки и отладки - только лишь второй вариант.
Q. Какие видеорежимы будут в ZX ULAX?
A. Для отображения запланирован лишь один
физический универсальный режим: два переключаемых экрана
50Гц,
PAL-разрешением ~360x288 "квадратных" точек, каждая точка своим цветом из доступного диапазона в двух форматах -
direct color GRB555 или
indirect color ~32k индексов (в эмуляторе сейчас отображается окно 352x256x16). Вероятно, он единственным и останется, учитывая современное применение Спектрума сегодня практически только для ретрогеймерства. Может быть, реализуем возможность локального (для пиксельной строки или даже для отдельного пикселя) удвоения разрешения по горизонтали (ради чёткости текста). Аппаратных спрайтов, слоёв и скроллинга нет и не планируется, их задачи с достаточной скоростью и куда удобнее решит
блиттер.
Q. Но ведь у Спектрума совершенно другой видеорежим, он не будет отображаться юлаксом?
A. Будет, именно "отображаться" картинкой. После сброса при настройках по умолчанию запись байта в адреса экранной памяти Спектрума будет автоматически дублироваться юлаксом как запись 8 пикселей в индексном формате по соответствующим координатам юлакс-экрана (для растра) либо как изменение значений двух определённых индексируемых цветов (для бордюра и атрибутов; "бордюр" в юлаксе - просто область, залитая определённым индексированным цветом). Более того, запись и в любую другую область zx-памяти по умолчанию вызывает запись 8 пикселей по сопоставленному адресу в юлакс-памяти.
Q. Но ведь это то же самое, что происходит в ZX-Poly, EmuZWin и Spec256!
A. Не совсем (или даже "совсем не") то же самое. В упомянутых концепциях организация видеопамяти -
планарная, отдельными битовыми плоскостями, и раскладка растра полностью повторяет раскладку Спектрума. У юлакса организация видеопамяти -
попиксельная (chunky mode) и физическая раскладка растра особого значения не имеет, делается как удобней отображать, так как запись в растр осуществляется через переключаемые
логические раскладки. Более того, и
формат байта данных также можно переключать, например, интерпретировать его не как 8 пикселей двух цветов, а как два пикселя из 16 цветов, или 4 пикселя 4 цветов (причём и пиксели необязательно квадратными могут быть). Что позволит с лёгкостью имитировать различные исторические и новопридуманные "режимы" в рамках одного физического режима и смешивать их с точностью до пикселя, не теряя полученных в другом режиме изображений. Иными словами,
фундаментальное отличие в том, что в концепциях, подобных Spec256, на физическом уровне
простая запись в сложную структуру видеопамяти, а в юлаксе наоборот - физически (но не логически)
сложная запись в простую структуру видеопамяти. Это важно, так как чем проще устройство видеопамяти на физическом уровне, тем проще развивать устройство в дальнейшем, добавляя и развивая дополнительные функции типа отрисовки примитивов, блиттера, разных способов наложений пикселей итп.
Q. Как использовать новые графические возможности?
A. Существует два основных подхода -
явно и
прозрачно, которые можно применять и
совместно. В первом случае
явно переключает режимы записи и рисует графику (блиттером или попиксельно) код основной программы; во втором случае перед загрузкой и запуском чисто спектрумовской программы в память видеокарты загружается специальный "драйвер",
прозрачно выполняющий дополнительные действия синхронно с некоторыми (сопоставленными по адресу) командами Z80. Старый код при этом и "не подозревает", что работают какие-то расширения, и в памяти Спектрума не изменяется ничего.
Q. То есть нужно разобраться в коде, чтобы написать "драйвер"? Разве это не сложнее, чем просто раскрашивать графику, как в Spec256?
A. Практика показывает, что разбор именно графического кода, если и не "проще", то, по крайней мере, занимает времени куда меньше, чем "просто раскрашивание графики" - даже если графика хранится в понятном и удобном для просмотра и редактирования формате, что бывает далеко не всегда. К тому же в разных играх графика разная, а вот код у каждого автора или команды может повторяться без изменений или с небольшими изменениями. Впрочем, с юлаксом доступны
несколько уровней адаптации пропорционально трудозатратам: от простой и быстрой раскраски в общие два цвета всех объектов, рисуемых одной процедурой, до полной попиксельной раскраски вообще всей графики. И хотя дополнительно приходится писать "драйвер", но размер его, как правило, невелик; зато и возможностей больше, чем с подходом Spec256, поскольку команды драйвера, раз уж их приходится задать явно,
не обязаны слепо повторять логику команд Z80 (это, кстати,
второе фундаментальное отличие от подобий Spec256). Что позволяет, например, заблокировать вывод уже ненужных атрибутов раскрашенных спрайтов, чтобы нераскрашенный фон не портили; или выбирать побитовый или попиксельный вариант логической операции; или получить на экране несколько копий спрайта разной окраски...
Q. А чем "явный" подход отличается от поддержки других известных дополнительных графрежимов? Тоже ведь нужно переписывать все процедуры работы с графикой.
A. Все не нужно, а сколько именно переписывать или дополнять - по желанию может изменяться в любых пропорциях. Ведь "режимы" юлакса не физические, а логические, при перенастройке режима записи прошлое изображение не теряется и не искажается. В любом режиме можно будет изменять результат проделанной в других режимах работы, накладывать объекты любым способом и в любом порядке. И блиттер также сможет "вмешаться" в любой момент и также будет обрабатывать те же пиксели.
[свернуть]