Под плоским я понимаю вот что. Всё изображение представляет собой неподвижную матрицу Width x Height (256х192, 384х200, ...), и заполнять его надо программно, сдвигать программно, и всё делать в одной плоскости.
Я понял, что перекладывание всех проблем с размещением спрайтов на плечи программера не приветствуется (но мне кажется, что режим 16c в этом плане вряд ли столь уж прост, тем более что и памяти при этом приходится заполнять в 4 раза больше).
Я немного ещё подумал, и мне пришло в голову, что всё можно упростить кардинально. Итак, 4 байта на описатель кусочка:
XOFF - 1 байт смещения спрайтной линии от левого края экрана (0..255);
PAL+LEN - палитра (3 бита, 0..7) + длина линии (5 бит, 0..31), LEN=0 означает "спрайта нет";
EVEN+FLIP+Addr_hi - начинать со старшего (EVEN=1) или младшего (EVEN=0) пикселя в байте спрайта по адресу Addr, FLIP=1, если пиксели отображать справа налево, Addr_hi - 6 старших бит адреса спрайта.
Addr_lo - 8 младших бит адреса спрайта.
Теперь каждой из 192 линий (из 256 пикселей) соответствует 8 таких 4-байтных описателей, т.е. 32 байта. Размещать спрайты намного проще: достаточно поместить заранее заготовленные адреса/длины/чётности (и поправить FLIP, если надо) - в нужное (по вертикали) место в одной из 8 колонок, указав правильное смещение от левого края экрана. Чем дальше (или ближе, неважно) колонка от начала описателя строки, тем более приоритетен соответствующий (один из восьми) слой, и такой спрайт перекрывает все прочие, если они пересеклись. Такая схема требует быстрого приоритетного выбора пикселя из 8 возможных, и это, наверное, её недостаток. Но, наверное, разруливается как-то. Зато у нас 8 независимых слоёв, не считая заднего плана, 16 независимвых цветов на точку, причём для каждой линии спрайта можно выбрать одну из 8 различных цветовых палитр по 16 цветов. (Кстати, палитру первого слоя, т.е. самой первой колонки можно заодно задействовать и для заднего плана, если больше негде хранить).
В итоге на экране вообще без проблем размещаются 8 спрайтов в ширину, а если какие-то могут двигаться только в одном горизонтальном слое, то нет проблем выполнить совмещение по вертикали, и суммарное число спрайтов легко увеличивается.
Мне кажется, "автомат" здесь вполне можно построить, причём не очень сложный, и для него не нужна какая-то сверх-навороченная альтера, а достаточно простой и не сверхмощной, хоть я и не специалист по фпга. Смысл всего этого такой: памяти требуется всего в 2 раза больше, чем для обычного спековского режима, скорость заполнения получается наверняка больше, чем в случае прямого рисования в экран. А качество графики - совсем другое, чем мы привыкши видеть на спектруме.
Алгоритм должен быть примерно такой (предполагаем, что проблемы считывания таблицы и самих байтов спрайтов как-то решаются, если за раз приходится считывать не более 2 байт из двух спрайтов). На строке -1 считываются данные таблицы для строки 0, на 0й - для строки 1 и т.д. Без буфера тут никак. Дальше, начиная с 0-го пикселя строки, на каждом из 256 пикселей выбирается, что будет рисоваться в качестве пикселя: пиксель первого спрайта, попадающего на этот пиксель экрана, или, если ничего нет, то очередной пиксель заднего плана. Как только найден пиксель спрайта, происходит выборка соответствующего байта (можно сэкономить на обращениях к ОЗУ, и закэшировать байт с парой пикселей, если это принципиально). По окончании каждого пикселя все ненулевые счётчики длины спрайтов во всех 8 описателях уменьшаются, чётность инвертируется, если 0->1, адрес не меняется (при FLIP=0), если 1->0, адрес продвигается вперёд. И так 256 раз.
Про адрес: он стал 14-битным, и получается, что использовать спрайты придётся только из одного непрерывного банка, что может быть не очень удобно, если они все не вмещаются в 16К. Имеет смысл всё-таки разбить адресное пространство на 2 банка по 8192 байта, и младшие адреса 0000-1FFF будут обращаться к одному банку ОЗУ, а старшие - к другому. Порт мог бы иметь вид:
aAAAbBBB, где мленькая буква соответствует биту, который управляет, в какой половине банка идут обращения, младшим или старшим 8К из 16, а большие буквы - задают номер банка ОЗУ, одного из 8.
Про спрайт: к сожалению, ширина линейки спрайта не может быть больше 31 пикселя. Но спрайты пошире легко строятся состыковкой 2х спрайтов.
Если схема слишком сложна для одновременной работы с 8 источниками, число можно сократить до 7 или 6 (хотя это плохо, конечно). Зато программировать такую спрайт-систему очень просто, а качество графики наверняка превысит ямаховское. (И если спрайтов всё-таки не хватает, то ведь и на заднем полане всё ещё можно что-нибудь подрисовать, тоже).
Добавлено через 5 минут
Я прекрасно понимаю, что это малореально было ТОГДА. Хотя бы потому, что своих игрушек в те времена у нас практически (и теоретически) не было (да и сейчас по пальцам). Демки были, а игрушек - не было. Я просто пытаюсь понять, насколько такой спрайт-режим реален СЕЙЧАС, и что конкретно для этого требуется.




Ответить с цитированием