05 июля 2015 |
|
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,наряду с тремя - тогда одной - другими известными моделями Спектрума и одной виртуальной под названи─ ем "ATMЗ", которую сейчас разводит 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) ;%LOLLLOO00 or (hl) ;%0R0OORRR 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) ;%LOLLLOO00 inc h or (hl) ;%0R0OORRR ld (NN),a ;эффект inc b ld a,(bc) ;%0L0OOLLL dec h or (hl) ;%RORRROO0 ld (NN),a ;отражение :110 t/4 чанка - 27.5 t/чанк Ещё одна проблема - на стыке эффекта и отражения может получиться разрыв.В первую очередь из-за того,что постоянно возникает переполнение по младшей координате.Его мо─ жно избежать,если текстура будет не16x16, а16x8. Тогда байты будут%VVVVOUUU, и при сложении переполнение уйдёт в бит нуля,ко─ торый не будет ни на что влиять. Но есть способ лучше - рисовать чётные строки эффекта на всю высоту экрана, а не─ чётные получать отражением. Тогда разрывы не будут видны. Это позволяет в мультиколоре с тексту─ рой8x8 реализовать ещё более хитрый метод - чтение из текстуры двух чанков сразу! pop de ld a,e add a,(hl):dec l ;OOvvvuuu + OOvvvuuu ; = 0?vvvuuu ld e,a ;координаты в текстуре, левый чанк ld a,d add a,(hl):dec l ;OOvvvuuu + OOvvvuuu ; = 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 ;OOvvvuuu + OOvvvuuu ; = 0?vvvuuu ld e,a ;координаты в текстуре, левый чанк ld a,d add a,(hl):dec hl ;OvvvOuuu + OvvvOuuu ; = ?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/чанк Обвязка: DRLOOPO 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,DRLOOPO Осталось написать генератор таблиц и текстур,добавить показ титров и скриптова─ ние, и эффект готов!
Other articles:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Similar articles:
В этот день... 21 November