Info Guide #11
05 июля 2015

Code - чанковый эффект: Magnets stretching

     Magnets stretching
Alone Coder 

   Расскажу  про  эффект  в  гритсах  демы
The Board II, основного  названия которого 
я нигде не нашёл, то ли он "стретч", то ли
"магниты". Пусть будут "магниты".



   Идея у него такая:есть две летающих то─
чки  со  своими системами полярных коорди─
нат:U1, V1 и U2, V2 (может быть и U3, V3,
если точек не две, а три); для каждого эк─
ранного пикселя(x,y) находим координаты в
каждой из систем полярных координат, соот─
ветствующие  координаты складываем(U1+U2,
V1+V2), читаем  по ним пиксель из текстуры
и выводим на экран.



   Казалось бы, просто,но обычно на Speccy
этот  эффект  был  очень медленным, даже в
низком  разрешении. А я решил  сделать его
чанками 2x2.

   Дема писалась под ATM Turbo 2+, но пос─
кольку компомашина на том пати была ZX Evo
с  прошивкой  baseconf  (основная прошивка
этого  компьютера-конструктора   реализует 
ATM Turbo 2+  на 14 MHz,наряду с тремя - 
тогда  одной - другими известными моделями 
Спектрума и одной виртуальной под названи─ 
ем "ATM3", которую сейчас разводит Zorel), 
то был стимул даже попытаться сделать этот
эффект фреймовым на компомашине, с обычной
автоподстройкой  демы под скорость машины.
У  меня уже были данные по скорости выпол─
нения команд там: основная идея в том, что
машинный цикл с чтением округляется до чё─
тного такта,если ячейка не считана заранее
в 16-битный буфер; буфер всегда читается с
чётного  адреса  памяти. Но поскольку дли─
тельности  команд  в  таких  "турботактах"
непривычны и нестандартны,буду писать при─
меры  с обычными  тактами и считать, что в
кадре  их примерно 220000 (примерно 100000
на  ATM Turbo 2/2+ @ 7 MHz ). Конечно, это
число зависит от кода, но  в любом случае,
если бы расчёты не сходились, всегда  была
возможность уменьшить окошко.И всегда надо
помнить, что мы пишем под ретромашину,а не
под какую-то прошивку компьютера-конструк─
тора или ещё какой эмулятор с "новыми воз─
можностями" (которые реально  нельзя  под─
ключить к Спектруму). Ибо какой смысл ухо─
дить со Спектрума на липовые "новые возмо─
жности на базе Спектрума", если кругом по─
лно  настоящих платформ с приличными людь─
ми? Смысл только для тех, кому лень писать
под настоящее ретро, а раскрутиться хочет─
ся (они  даже объединяются для восхваления
друг друга и травли тех,кто не любит фейки
и прочее пускание пыли в глаза).

   Напомню, какие  экранные  режимы  у нас
есть  на  ATM Turbo 2/2+ и его современных
реализациях:
 -6912;
 -"EGA" 320x200, 16  цветов  на точку.В
каждом байте 2 пикселя, которые кодируются 
как  атрибуты на 6912. Экран в памяти раз─ 
делён  на 4 слоя по 8000 байт, которые че─ 
редуются через каждые 2 пикселя по горизо─ 
нтали. Внутри  слоя  адрес растёт линейно. 
Слои лежат в разных страницах и половинках 
страниц; 
 -мультиколор  640x200,  hires. Пиксели
лежат в одной странице, атрибуты в другой. 
Причём  как пиксели, так и атрибуты разде─ 
лены на 2 чередующихся слоя каждый; 
 -текстмод 80x25.
   Режимы Timex Sinclair 2068 не поддержа─
ны.

   Первая идея, конечно,была с использова─
нием  чанков и процедуры c2p. Но легко ви─
деть, что  результат  не  достигается даже
близко:  c2p  через pop hl:ldd:ld a,(hl):
ld (bc),a, скажем,  в  окне320x96, займёт 
40*160*48 = 307200 тактов - не  считая са─
мого эффекта, который явно будет не с дву─
мя командами.
   Тем более, зачем нам c2p,если можно вы─
водить  только каждую вторую строчку (про─
межуточные  строчки  отдать под надписи) -
то есть по сути гонять целые байты из тек─
стуры прямо в экран?

   После  этих  рассуждений эффект виделся
таким (на EGA экране):

   Этап 1: складываем  координаты  по двум
таблицам полярных координат: 

ld a,(de):inc e ;U1
add a,(hl):inc l ;U2
push af
:33 t/чанк на одну координату

ld a,(de):inc e ;V1
add a,(hl):inc l ;V2
ld c,N:ld (bc),a
:36 t/чанк на вторую координату

(в сумме 69 t/чанк) 

   Этап 2: читаем  пиксель  из  текстуры и
выводим его на экран: 

pop hl ;координаты в текстуре
ldi ;байт из текстуры пишем в экран
:26 t/чанк

   Процедуры простые, типовые, но...расто─
чительно, не так ли?
   Поэтому я прикинул, можем ли мы объеди─
нить  расчёт  координат и чтение текстуры.
Это получится сделать, если таблица поляр─
ных  координат  для  одной  из точек будет
вбита прямо в процедуру:

pop bc   ;UV1=полярные коорд-ты для точки1
ld hl,NN ;UV2=полярные коорд-ты для точки2
add hl,bc ;адрес в текстуре
set 7,h ;нельзя занять все 64K текстурой!
ldi ;байт из текстуры
:55 t/чанк

   За каждый проход мы выводим только один
слой  экрана из 4, то есть всё время пере─
скакиваем  через 3 чанка (один слой содер─
жит  пиксели0,1,8,9.., второй  -  пиксели
2,3,10,11.., третий - пиксели4,5,12,13.., 
четвёртый...ну,вы поняли).Такие вот хитрые
экраны  на  настоящем ретро - не для ламе─
ров :)

   Легко  видеть, что  попытка выводить на
все  слои  сразу ведёт к проигрышу тактов,
даже если писать так:

ld a,(de):inc e ;U1
add a,(hl):inc l ;U2
ld c,a
ld a,(de):inc e ;V1
add a,(hl):inc l ;V2
ld b,a
ld a,(bc)
ld (NN),a ;чередуем слои
:72 t/чанк -
и это ещё без ограничения адресного прост─
ранства текстуры!

   Перевод  эффекта в мультиколор (2 чанка
в байте) тоже кажется проигрышем:

pop bc ;UV1
ld a,(de):inc e ;U2
add a,c
ld l,a ;U
ld a,(de):inc e ;V2
add a,b
ld h,a ;V
ld c/b,(hl) ;байт из текстуры
1/2*ld a,(bc):ld (NN),a
:65 t/чанк
(без  ограничения  адресного  пространства
текстуры)

   И пока  даже  непонятно, в каких  окнах
памяти  что будет лежать (таблица полярных
координат, текстура,код и две страницы эк─
рана или одна для мультиколора).

   Сидим, грустим.

   Очевидно, нужна смена алгоритма. Какая?
Попробуем  текстуру 16x16  (в одном байте
обе координаты -%VVVVUUUU ):

1/2*pop bc ;UV1 (читаем по 2 записи сразу)
ld a,(de):inc e ;UV2
add a,c/b ;переполнение по мл. координате!
ld l,a ;координаты в текстуре
ld a,(hl)
ld (NN),a ;чередуем слои
:51 t/чанк

   Или для мультиколора:

pop bc ;UV1 (читаем по две записи сразу)
ld a,(de):inc e ;UV2 левая
add a,c ;переполнение по мл. координате!
ld c,a ;координаты в текстуре, левая
ld a,(de):inc e ;UV2 правая
add a,b ;переполнение по мл. координате!
ld l,a ;координаты в текстуре, правая
ld b,N
ld a,(bc) ;%L0LLL0000
or (hl) ;%0R000RRR
ld (NN),a ;чередуем слои
:82 t/2 чанка = 41 t/чанк

   Выигрыш более чем в 2 раза по сравнению
с  первоначальным  вариантом!  Но  в  окне
320x96 пока315000 тактов - никак не лезет 
во фрейм. Можно ли выиграть ещё?
   Можно, и даже существенно!
   Пусть  точки движутся зеркально относи─
тельно центра экрана.Тогда нижняя половина
экрана - копия  верхней с поворотом на 180
градусов. Такой переворот гораздо быстрее,
чем вывод эффекта:

1/2*pop de
ld (hl),d/e:dec l
:16 t/чанк

   Или для мультиколора (тут уже нужна та─
блица переворота байтов):

1/2*pop bc ;b,c!=0
ld l,c/b
ldd
:25 t/2 чанка = 12.5 t/чанк
   С таблицей  оказалось  быстрее, чем без
таблицы :)

   Кроме того,мы можем переворачивать пря─
мо во время вывода!

1/2*pop bc ;UV1 (читаем по 2 записи сразу)
ld a,(de):inc e ;UV2
add a,c/b ;переполнение по мл. координате!
ld l,a ;координаты в текстуре
ld a,(hl)
ld (NN),a ;эффект
ld (NN),a ;отражение
:64 t/2 чанка = 32 t/чанк

   Или для мультиколора:

pop bc ;UV1 (читаем по 2 записи сразу)
ld a,(de):inc e ;UV2, левый чанк
add a,c ;переполнение по мл. координате!
ld c,a ;координаты в текстуре, левый чанк
ld a,(de):inc e ;UV2, правый чанк
add a,b ;переполнение по мл. координате!
ld l,a ;координаты в текстуре, правый чанк
ld b,h
ld a,(bc) ;%L0LLL0000
inc h
or (hl) ;%0R000RRR
ld (NN),a ;эффект
inc b
ld a,(bc) ;%0L000LLL
dec h
or (hl) ;%R0RRR000
ld (NN),a ;отражение
:110 t/4 чанка - 27.5 t/чанк

   Ещё  одна проблема - на стыке эффекта и
отражения может получиться разрыв.В первую
очередь из-за того,что постоянно возникает
переполнение по младшей координате.Его мо─
жно избежать,если текстура будет не16x16,
а16x8. Тогда байты будут%VVVV0UUU, и при
сложении переполнение уйдёт в бит нуля,ко─
торый не будет ни на что влиять.
   Но  есть способ лучше - рисовать чётные
строки эффекта на всю высоту экрана, а не─
чётные  получать отражением. Тогда разрывы
не будут видны.
   Это  позволяет в мультиколоре с тексту─
рой8x8 реализовать ещё более хитрый метод
- чтение из текстуры двух чанков сразу!

pop de
ld a,e
add a,(hl):dec l ;00vvvuuu + 00vvvuuu
                 ; = 0?vvvuuu
ld e,a ;координаты в текстуре, левый чанк
ld a,d
add a,(hl):dec l ;00vvvuuu + 00vvvuuu
                 ; = 0?vvvuuu
ld d,a ;координаты в текстуре, правый чанк
ld a,(de) ;два цвета
exx
ld (bc),a ;эффект
ld l,a ;h=tMIRROR/256
ldi ;отражение ;c!=0
exx
:90 t/4 чанка = 22.5 t/чанк

   Конечно, это в теории. На практике надо
вписаться в окна памяти.
   Экран  и таблица полярных координат пе─
реключаются  (для  каждого  слоя  экрана -
своя таблица).Код и текстура - нет (в этом
коде нет адресов,так что он уже не требует
распихивания по куче страниц). Но с 32-ки─
лобайтной текстурой некуда класть код.
   Поэтому  текстуру придётся ужать в одно
окно (для этого надо добавить and c перед
ld d,a, приc=#3f ). Ещё  одно окно займёт 
экран  (переключаемый). Ещё одно - таблица
полярных  координат (переключаемая). А ос─
тавшееся окно займёт код.
   Таблица полярных координат поместится в
одно  окно, если не будет выравнена по 256
байт, например, с картой224x144. Для это─
гоdec l придётся заменить на dec hl. Есть
способ  заменить только один из них - уга─
даете  как? Правильно, для каждой чётности
X-координаты - своя таблица полярных коор─
динат :)

   Так что  финальный  вариант эффекта та─
кой:

pop de
ld a,e
add a,(hl):dec l ;00vvvuuu + 00vvvuuu
                 ; = 0?vvvuuu
ld e,a ;координаты в текстуре, левый чанк
ld a,d
add a,(hl):dec hl ;0vvv0uuu + 0vvv0uuu
                  ; = ?nnn?nnn
and c ;#3f
ld d,a ;координаты в текстуре, правый чанк
ld a,(de) ;два цвета
exx
ld (bc),a ;эффект
ld l,a ;h=tMIRROR/256
ldi ;отражение ;c!=0
exx
:96 t/4 чанка = 24 t/чанк

   Обвязка:

DRLOOP0
dup wid/4 ;=40
<эффект>
edup
org $-1
ld hl,-40*4+(wid/4)
add hl,bc
ld b,h
ld c,l
ld hl,+40*4-(wid/4)
add hl,de
ex de,hl
ld h,tMIRROR/256
exx
dec b
jp nz,DRLOOP0

   Осталось  написать  генератор  таблиц и
текстур,добавить показ титров и скриптова─
ние, и эффект готов!




Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
MinskZXNet - Aborigen BBS: после коннекта со мной стала безбожно глючить.
Как приручить крысу - бред Чапая.
News - D.J.Crаck ушел в группу Flash inc.

В этот день...   21 ноября