(Некоторые перспективы параллельных пересылок)
Размышляя на тему реализации "внутренних" ldir-ов, я подумал: что, собственно, происходит
в разных ситуациях при таких пересылках? Например, ldi из ОЗУ в видеопамять - сначала байт
читается из обычной страницы ОЗУ, потом записывается в перехватываемую страницу - и
одновременно в видеопамять через логическую операцию с регистрами-защелками. И наоборот,
для ldi из видеопамяти в ОЗУ сначала в защелки читаются байты, потом они суммируются
какой-то логической операцией и полученный байт через процессор отправляется в ОЗУ.
А при "внутреннем" ldi (то есть когда обращение к обоим адресам источник/приемник
перехватывается видеокартой) что произойдет? То и другое - читаются байты, суммируются,
полученный байт процессором отправляется в ОЗУ - и одновременно обратно в видеопамять.
То есть во все слои попадают одинаковые байты, что очень плохо. Очевидно, что от проца
требуются только адреса приемника и источника, а данные не нужны - и если байт данных при
записи проигнорировать, то в адрес-приемник в видеопамяти попадет содержимое защелок,
полученное перед эти при чтении, то есть произойдет параллельная пересылка, чего мы и
добивались!
Спрашивается, как понять, когда игнорировать данные при записи, а когда нет? Не делать
же анализатор кода на видеокарте с отловом нужных команд... ;) Можно поступить так:
если сразу после попытки чтения происходит попытка записи (то есть между ними не было
выборки новой команды - сигнал M1 не появлялся), тогда игнорируем. А если после выборки
сразу идет запись, тогда безусловно пишем, что на шине.
Понятно, что такой ldi годится только для параллельного копирования данных в видеопамяти,
то есть прежде всего для "побайтных" прокруток изображения. Вот если бы можно было делать
такие пересылки с учетом логических операций! А для этого нужно просто ввести "второй
комплект" регистров-защелок (то есть теперь имеем отдельные для чтения и для записи) и
распараллелить схему выполнения логических операций. А заодно дать возможность отдельно
выбирать базовые 16K страницы видеопамяти для чтения и записи. То есть запись происходит
так: байт, поступивший от проца, распределяется по Ч-защелкам, одновременно заполняются
данными из видеопамяти З-защелки, выполняются логические операции и результат из З-защелок
записывается обратно в видеопамять. А вот при выполнении "внутреннего" ldi прочитанные из
видеопамяти байты сначала попадут в Ч-защелки, суммируются "на выход" (результат отдается
процу) и остаются в Ч-защелках. Теперь, когда придет запрос на запись, Ч-защелки
байтом, поступившим по шине, не заполняются, а сразу производятся логические
операции с заполненными из адреса записи З-защелками и собственно запись в видеопамять.
Добавить к этому возможность записи "со сдвигом" и "зеркальной" записи, как раньше.
(Некоторые перспективы параллельных пересылок)
Какой отсюда вывод? А такой, что спрайты можно теперь хранить прямо в видеопамяти,
и выводить на любой фон со скоростью, сопоставимой со скоростью работы обычной спековской
графики - и это все в 64 цветах! Причем маску можно (нужно!) хранить в обычном ОЗУ, что
сэкономит место в видеопамяти под сами спрайты. Даже если в APA-режиме используются все
четыре базовых страницы (два переключаемых задних и два передних плана), все равно в
каждой странице остается 6*4K, что с учетом масок в обычном ОЗУ составит эквивалент 16-32К
обычной спековской графики. Да еще и в неотображаемых (отсекаемых бордюром) областях
можно чего-нибудь хранить. Плюс менее важные спрайты/тайлы можно по-прежнему печатать из
ОЗУ за несколько проходов.
Процедура вывода "спрайта" в APA-режиме будет выглядеть примерно так:
out... ; (установка базовых страниц чтения и записи видеопамяти)
out... ; (вывод по AND во все плоскости)
ld hl,^маска ; в неперехватываемых адресах
ld de,^экран ; в видеопамяти (базовая страница для записи)
push de
ЦИКЛ
- ld a,e
- call "цепочка ldi"
- ld e,a
- inc d
ПОВТОРИТЬ
pop de
ld hl,^спрайт ; в видеопамяти (базовая страница для чтения)
out... ; (вывод по OR во все плоскости)
ЦИКЛ
- ld a,e
- call "цепочка ldi"
- ld e,a
- inc d
ПОВТОРИТЬ
out... ; (восстановили базовые страницы, если нужно)
Можно попытаться еще "упихать" все это в один цикл (с некоторыми аппаратными
доработками), но не уверен, что получим существенное ускорение.