__________________________________________
(C) Devil of eTc/Scene'99
Chanks...
В настоящее время в отечественном
demomake'рстве все более и более
популярным становится использование для
вывода графики на экран так называемых
чанков.
Преимущества данной технологии велики,
среди них:
- 16 градаций серого цвета (хотя если
чанки 8*8 то можно использовать и
атрибуты, тогда цветов становиться даже
слишком много:);
- довольно быстрый вывод картинки на
экран (2-3 int'а), при довольно малых
размерах образа экрана (не более 3072 b.);
Однако есть недостаток, который почти
уравновешивает все преимущества:
- значительно падает разрешение экрана
(если чанки 4*4 то очевидно разрешение
экрана будет 64*48 что, мягко говоря,
маловато...);
Пример чанков 4*4 вы можете наблюдать в
таких демках как Refresh, Forever,
5thElement, Goa и многих других.
Для начала рассмотрим, как вывести
готовую анимацию на экран (эффект Вы
можете найти в intro Demo or Die #01). Для
этого надо иметь саму анимацию в таком
формате:
1-byte 2-byte
OOOO OOOO OOOO OOOO . . .
/ \ / \
1-чанк 2-чанк 3-чанк 4-чанк
Т. е. Вы должны так преобразовать
картинку, чтобы в первом байте в старшей
половине находился код первого чанка
(4 bit - 0..15 градаций серого), а в
младшей половине байта код следующего
чанка, и так всю картику. Вслед за ней в
памяти должен располагаться образ второй
картинки, потом третьей и т.д.
Привожу пример программы с подробным
описанием.
ORG 25000
CADR EQU 12 ;SIZE
LEN EQU 15 ;REAL_LEN = (LEN+1)*4
HGT EQU 48
;==================================;
;Кидатель чанков by Devil/eTc/sCeNE;
; MoveR cHanKS 4*4 pIXels ;
;==================================;
CHANKS EQU #F000 ;по этому адресу будет
;находится развернутая
;табл. образов чанков
EI:HALT
CALL INIT_CH ;разворачиваем пол-
;ную табл. чанков
CALL INITCH ;инициализируем
;кидатель чанков
CALL INITTAB ;создаем табл. ад-
;ресов экрана
LD A,CADR ;в А, количество
;кадров анимации
LD LX,A
TWERD
EI
HALT
CALL MOVCH ;вызываем процедуру
;кидания образа экр.
LD A,#7F ;проверяем нажатие
IN A,(#FE) ;пробела и если на-
RRCA ;жат то выход
RET NC
JR TWERD
MOVCH
;Процедура вывода образа экрана
MOVCH1 LD A,LX
DEC A
AND A
JR NZ,MOVCH0
LD A,CADR
LD HL,TABLCH ;в HL, адрес образа
;экрана
MOVCH0 LD LX,A
XOR A
MOVCH2 LD HX,A
LD B,TABLADR[ ;в B, старший байт
;адреса таблицы
;адресов экрана
ADD A,A
LD C,A
LD A,(BC)
LD D,A
INC BC
LD A,(BC)
LD E,A ;в DE, адрес экрана
PUSH DE ;с которого мы будем
;выводить чанки
LD B,CHANKS[ ;в B, старший байт
;адреса таблицы
;всех комбинаций
;чанков
CALL PUTLIN ;рисуем линию из
;(LEN+1)*4 чанков
POP DE
LD A,HX ;проверяем, а не
INC A ;последнюю ли строку
CP HGT ;мы вывели?
JR NZ,MOVCH2
RET
;-----------------------------;
;CREATE DITHER TABLE
;По адресу DTDAT находятся образы чанков,
;продублированные в старшей и младшей
;частях байта.
;пример:
; %1010 1010
; %0100 0100
; %1010 1010
; %0000 0000
;Процедура INIT_CH разворачивает образы
;чанков по адресу #F000 так, чтобы
;получились все #FF комбинаций чанков.
;Младший байт адреса указывает на номер
;чанка, а старший байт на номер байта в
;чанке (всего #0400 байт)
INIT_CH
LD HL,CHANKS
CRDT0 LD A,L:AND #F0
.2 RRCA
LD DE,DTDAT
ADD A,E:LD E,A
ADC A,D:SUB E:LD D,A
LD B,4
CRDT1 LD A,(DE):INC DE
AND #F0
LD (HL),A:INC H
DJNZ CRDT1
LD A,L:AND #0F
.2 RLCA
LD DE,DTDAT+4
ADD A,E:LD E,A
ADC A,D:SUB E:LD D,A
LD B,4
CRDT2 DEC DE:LD A,(DE)
AND #0F
DEC H:OR (HL)
LD (HL),A
DJNZ CRDT2
INC L:JR NZ,CRDT0
RET
DTDAT ;16 COLORS DITHER DATA
DB #00,#00,#00,#00
DB #00,#00,#00,#00
DB #88,#00,#00,#00
DB #88,#00,#22,#00
DB #AA,#00,#22,#00
DB #AA,#00,#AA,#00
DB #AA,#44,#AA,#00
DB #AA,#44,#AA,#11
DB #AA,#55,#AA,#55
DB #AA,#DD,#AA,#77
DB #AA,#77,#AA,#FF
DB #AA,#FF,#AA,#FF
DB #AA,#FF,#BB,#FF
DB #EE,#FF,#BB,#FF
DB #EE,#FF,#FF,#FF
DB #FF,#FF,#FF,#FF
;Спуск на 4 линии по экрану вниз
DOW_DE4 LD A,4
ADD A,D
LD D,A
AND 7
RET NZ
LD A,E
ADD A,32
LD E,A
RET C
LD A,D
SUB 8
LD D,A
RET
;----------------------------
INITTAB LD DE,#4000 ;создаем таблицу
LD HL,TABLADR ;адресов экрана
LD B,48 ;для быстрого рас-
INITT1 LD (HL),D ;чета адреса
INC HL
LD (HL),E
INC HL
CALL DOW_DE4
DJNZ INITT1
RET
;----------------------------
;Процедура создающая кидатель строки
;чанков из кидателя четырех чанков
;(эти самые четыре чанка кидаются в
;экран процедурой PUTLIN)
INITCH LD B,LEN
LD HL,PUTLIN
LD DE,ENDPL
INITC1 PUSH BC
LD BC,ENDPL-PUTLIN
LDIR ;размножаем кусок от
POP BC ;PUTLIN до ENDPL
DJNZ INITC1 ;LEN раз,
LD A,#C9 ;a в конце RET
LD (DE),A
RET
;----------------------------
ORG ($-1)/256*256+256
TABLCH ;грузим анимацию
INCB "ANIM"
ORG ($-1)/256*256+256
TABLADR DS 48*2 ;буфер под табл.
;адресов экрана
;----------------------------
;Здесь все совсем просто:
; В HL - образ экрана
; B - старший байт таблицы
; чанков (т.е. B=#F0)
; DE - адрес в экране
PUTLIN
LD C,(HL) ;берем в C, код чанка
INC HL ;в BC, получаем адрес
;образа чанка
LD A,(BC) ;перекидываем 1-байт
LD (DE),A ;чанка из таблицы в
;экран
INC D ;опускамся вниз по
;экрану
INC B ;переходим к следую-
;шему байту
LD A,(BC):LD (DE),A:INC D,B
;так же 2-байт
LD A,(BC):LD (DE),A:INC D,B
;так же 3-байт
LD A,(BC):LD (DE),A:INC E
;После 4-го байта мы переходим правее по
;экрану, берем код следующего чанка и
;начинаем подниматься вверх.
LD C,(HL)
INC HL
LD A,(BC):LD (DE),A:DEC D,B
LD A,(BC):LD (DE),A:DEC D,B
LD A,(BC):LD (DE),A:DEC D,B
LD A,(BC):LD (DE),A
INC E
ENDPL
Однако мы рассмотрели идеал, т.е. когда
у нас есть в одном байте коды сразу двух,
соседних чанков. Этого можно добиться в
редких случаях (анимация, плазма), чаще мы
имеем один код на один байт. В таком
случае кидатель немного видоизменяется и,
к сожалению, становится значительно
тормозней :(
PUT_LIN
;HL=BUFFER - тот самый буфер, в котором Вы
;формируете изображение перед выводом на
;экран
;HL'=ADDR_SCREEN - адрес в экране
;B=TAB[ - таблица сдвинутых байт на 4 бита
;вправо
;D'=CHANKS[ - старший байт таблицы чанков
LD C,(HL) ;берем код чанка
LD A,(BC) ;по табл. сдвигаем его
;на 4 бита вправо
INC L
LD C,(HL) ;берем код следующего
;чанка
OR C ;получаем в одном байте
;коды двух, соседних
;чанков
;дальше все по вышеописаному алгоритму
INC L
EXX
LD E,A
LD A,(DE)
LD (HL),A
INC H
INC D
LD A,(DE)
LD (HL),A
INC H
INC D
LD A,(DE)
LD (HL),A
INC H
INC D
LD A,(DE)
LD (HL),A
INC L
EXX
LD C,(HL)
LD A,(BC)
INC L
LD C,(HL)
OR C
INC L
EXX
LD E,A
LD A,(DE)
LD (HL),A
DEC H
DEC D
LD A,(DE)
LD (HL),A
DEC H
DEC D
LD A,(DE)
LD (HL),A
DEC H
DEC D
LD A,(DE)
LD (HL),A
INC L
EXX
На этом все. Если что неясно, то вопросы
шлите на адрес 2:4536/100.128@FidoNet to
Sergey Movchan.
__________________________________________