О ротаторах
Alone Coder
Наверно, каждый помнит вращающегося
Соника в демо Illusion (1996). Он строится
пикселями 2x2, совершенно честным кодом
типа такого:
ld a,(hl)
[inc/dec h/l]
add a,a
add a,a
add a,(hl)
[inc/dec h/l]
add a,a
add a,a
add a,(hl)
[inc/dec h/l]
add a,a
add a,a
add a,(hl)
[inc/dec h/l]
ld (de),a
inc e
;~83t/byte (260K/экран + 40K копирование)
Инкременты/декременты патчатся. Это
ограничивает возможности зума,но небольшой
зум там есть. Похожая техника вращения
используется в Eye Ache, но уже в мульти─
колоре 4x4.
А что можно сделать в пиксельном разре─
шении?
Можно переписать эту процедуру на пик─
сели, но тогда будет 6 fps, да и адресного
пространства не хватит на картинку во весь
экран.
Можно натягивать текстуру через расста─
новку точек, EOR-fill и сдвиг строк, как в
кубике из Mission Highly Improbable, но
это тоже работает не быстро.
Можно негенерировать повёрнутые байты
от каждого пикселя, как в The Link, но для
этого даже с небольшой картинкой понадоби─
тся больше,чем 128K ОЗУ ( The Link требует
NeoGS ).
Можно,наконец,сделать ротатор с пропус─
ком знакомест. Сначала рендер пропусков по
отдельной карте, оттуда же берём цвет и
номера тайлов. Заранее повёрнутые тайлы
можно просто сдвигать, чтобы не вертеть их
каждый раз. Отдельный тип тайла - прямой
цветопереход, его можно рендерить...
Но такой эффект ещё никто не писал. По─
этому расскажу про более простые эффекты -
rotating chessfield и ротатор цветной кар─
тинки из клеточек такого же размера, как в
rotating chessfield.
1. Rotating chessfield
Этот эффект появился где-то в дебрях
C-64, а на Speccy был реализован в деме
The Board (2011). Идея его в том, что для
каждого конкретного угла поворота есть
всего 8*8 рисунков знакоместа (при разре─
шении U, V в 8 субтекселей), плюс столько
же инверсных копий.
Соответственно,задача делится на подго─
товку знакомест,ротатор и вывод знакомест.
После некоторого перебора вариантов
оказалось,что со знакоместами 8x4 работать
проще (вывод чанков по методу Monster'а,
т. е. цепочкой ret ; U и V кодируются как
младший и старший байты адреса процедуры
вывода чанка).Был ещё вариант 8x2, который
можно было выводить прямо в ротаторе, но
что-то мне в нём не понравилось.
Был сделан простой ротатор 37 t/chunk:
;B,C=#X0, где X=dU,dU+1
;D,E=#X0, где Y=dV,dV+1
;A=U0, A'=V0
;SP=endline
MAPPERLINE
dup 16
push hl
add a,b ;или c (патч)
ld l,a
ex af,af'
add a,d ;или e (патч)
or chout/256 ;там выводилки чанков
ld h,a
push hl
__=$ ;последний проход кончается здесь
add a,d ;или e (патч)
or chout/256 ;там выводилки чанков
ld h,a
ex af,af'
add a,b ;или c (патч)
ld l,a
edup
org __
jp MAPPERLQ
Патч add a,b/c и add a,d/e для такого
ротатора:
;H0=U0
;D0=dU
;B=#80 ;"add a,b"
;C=0
PATCHLINEU
_=MAPPERLINE
dup 16
add hl,de
ld a,b
adc a,c ;0
ld (_+1),a
__=$ ;последний проход кончается здесь
add hl,de
ld a,b
adc a,c ;0
ld (_+14),a
_=_+16
edup
org __
ret
Вывод чанков 8x4:
ld h,a
ld (hl),N
inc h
ld (hl),N
inc h
ld (hl),N
inc h
ld (hl),N
inc l
ret
Чанки,конечно,можно сгенерировать зара─
нее, но в The Board они считались на лету.
Сначала генерировались все нужные скосы по
U и V для текущего угла, а потом они на─
кладывались по XOR во всех 16 комбинациях
(точность U,V - 8 субтекселей):
XORUV
;all upics XOR current vpic
ld bc,upics
_=2
dup 8 ;8 чанков, 8 инверсных копий
dup 4 ;4 строки в чанке
ld a,(bc) ;можно ускорить стеком
xor (hl)
ld e,_
ld (de),a
cpl
ld e,_+#80 ;там инверсная копия
ld (de),a ;чанка
inc c
inc l
_=_+3 ;т.к. чанк - это ld (hl),N:inc h...
edup
_=_+4 ;следующий чанк
org $-1
dec l
dec l
dec l
edup
Генератор скосов был такой:
;U0=(256*upic/16)=upic*16=L*4
;или V0=(256*vpic/16)=vpic*16=L*4
ld a,l
add a,a
add a,a
xor hx ;0/#7f
dup 4
ld b,a
add a,a ;CY=U[7]
;A=U*2 ;или V*2
;C=dU*2 ;или dV*2
;D=teorfrom0/256
;HL=upic ;или vpic
FILLU ;строим рисунок байта
ld a,b
add a,lx ;U0=U0+dV ;или V0=V0-dU
edup
Рисунок байта строится записью перепол─
нений при сложении и потом "горизонтальным
EOR-fill" (который - просто таблица):
;A=U*2 ;или V*2
;C=dU*2 ;или dV*2
;D=teorfrom0/256
;HL=upic ;или vpic
;CY=U[7] ;или V[7]
macro FILLU
dup 8
rl e
add a,c
edup
org $-1
ld a,(de) ;d=teorfrom0/256
ld (hl),a
inc l
endm
2. И как на этом вертеть картинку?
Возьмём за образец дему Mekanix с C-64:
А
Б
В
Г
Д
Е
Ж
З
И
Й
К
Л
М
Н
О
П
Р
С
Т
У
Ф
Х
Ц
Ч
Клетки 2x2,2 цвета. В клетках заполнена
только каждая вторая строчка и каждый вто─
рой пиксель.
Текстура 8(7?)x64. С таким размером
текстуры повторы гарантированы - можно за─
ниматься копипастой кусков экрана, только
они это не делают.
В каждом знакоместе видно максимум 4
текселя,а это всего 16 вариантов. 4 сдвига
по U, 4 по V в 16 вариантах - получается
256 чанков 8x8.
Значит, надо сначала сгенерить 4 знако─
места сдвигов по U, 4 по V, потом 256 чан─
ков по or, xor, and. Вместо половины ри─
сунков можно делать инверсию атрибутов.
Чтобы использовать в этих условиях обы─
чный ротатор,надо хранить в карте клетку с
тремя соседями,итого 4 бита. А значит,надо
4 карты в зависимости от знаков направле─
ния,иначе содержимое клеточек не будет со─
ответствовать.Можно,конечно,менять порядок
клеточек внутри этих четырёх бит за счёт
смены порядка нумерации чанков. Проблема -
от какой из них брать атрибуты.
На C-64 чанки 8x8 аппаратные, а на
Speccy их вывод (даже через строчку) зай─
мёт 62976 тактов:
ld h,a
dup 4
ld (hl),N
inc h
inc h
edup
org $-2
inc l
ret ;17 b
;8 шт.в сегменте (U), 4(texture)*8(V)*256b
:82*768=62976
Однако при выводе чанков можно заливать
пустые знакоместа атрибутом (и не генерить
их графику). Поэтому весь эффект лучше
сразу делать в цвете, а заодно можно и в
1x1, а не через пиксель.
Вывод чанков 8x8 в цвете:
ld (hl),b/c/e/#30 ;attr
ld h,a
dup 8
ld (hl),N
inc h
edup
org $-1
ld h,d
inc l
ret
;28(29) b, 137(140) t
Вывод пустого чанка:
ld (hl),0/#3f ;attr
inc l
ret
Ротатор текстуры:
;addr=%11UUUuu0 VVVVVVvv
ld h,a
ld e,(hl)
inc h
ld d,(hl)
push de
add a,b/c ;du (патч)
or #c0
ld h,a
exa
add a,... ;dv (патч)
---
ld l,a
ld e,(hl)
inc h
ld d,(hl)
push de
add a,... ;dv (патч)
ld l,a
exa
add a,b/c ;du (патч)
or #c0
;59 t/chunk
Этот вариант использован в New Wave 48K
- в этой деме скосы уже не генерировались
на каждом кадре,а брались готовые (загото─
влено 32 поворота). Получилось грубовато,
но зато весь экран за 2 фрейма на 3,5 МГц.
Статистика на картинке "-=rotate" при
32x24:
пустых клеток (с учётом соседей) = 67%
muz = 4000..6000
out = 45000..55000 (вывод чанков и пустых
клеток)
math = 500
xor = 27606 (генерация чанков из готовых
скосов)
patchuv = 2500 (патч add a,N в ротаторе)
ротатор = 47500
итого 133000 +- 6000
Думаю,на основе этой техники можно сде─
лать и другие эффекты, как считаете?
Other articles: