Из журнала Demo or Die #2, 1999 (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 и многих других. Для начала рассмотрим, как вывести готовую анимацию на экран (эффектa Вы можете найти в 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.