Страница Ивана Рощина > Статьи >

© Иван Рощин, Москва

ZXNet: 500:95/462.53
E-mail: bestview@mtu-net.ru
WWW: http://www.ivr.da.ru

Улучшенный эффект из demo «Art Vision»

(Adventurer #8)
Дата последнего редактирования: 11.12.2003.

Если вы видели demo «Art Vision», то помните, что в последней части там движется атрибутная надпись «intel outside». Так как надпись атрибутная, то и перемещается она с дискретностью 8 пикселов (1 знакоместо), что выглядит не очень красиво. Я написал программу, которая, по существу, реализует тот же самый полноэкранный, «укладывающийся в прерывание» эффект, но теперь перемещение — попиксельное, что выглядит несравнимо лучше. Программа снабжена подробными комментариями, так что разобраться в ней не составит большого труда.

Если вы захотите посмотреть, как выглядел этот эффект в оригинале, — просто уберите из программы две строки, помеченные «*».

Картинка размером 64x64 знакоместа взята из demo «Art Vision» и находится в массиве PICTURE. Каждое знакоместо кодируется одним битом, таким образом, вся картинка занимает 512 байтов.

Траектория движения задаётся с помощью массива CRDS, который содержит 100 элементов следующего вида:

1 байт — смещение (в знакоместах) левой стороны фрагмента относительно левой границы картинки (см. рис. 1).

1 байт — смещение (в пикселах, по модулю 8) левой стороны фрагмента относительно левой границы картинки.

1 байт — смещение (в знакоместах) верхней стороны фрагмента относительно верхней границы картинки.

1 байт — смещение (в пикселах, по модулю 8) верхней стороны фрагмента относительно верхней границы картинки.

Рис. 1

Количество элементов в массиве и их значения можно изменять, тем самым задавая новую траекторию движения.

Итак, вот сама программа:

        CALL    MAKEADR  ;Подготовка...
        CALL    UNPACK
        CALL    CLS

M1      LD      IX,CRDS  ;Адрес таблицы.
        LD      D,100    ;Кол-во координат
                         ;в таблице.
M2      LD      BC,4
        LD      A,(IX)   ;Берём
        LD      (XATR),A ;координаты
        LD      A,(IX+1) ;выводимого окна.
        LD      (XPIX),A ;*
        LD      A,(IX+2)
        LD      (YATR),A
        LD      A,(IX+3)
        LD      (YPIX),A ;*

        ADD     IX,BC    ;Увелич. адрес.
        PUSH    IX
        PUSH    DE
        CALL    OUTSCR   ;Вывод на экран.
        POP     DE
        POP     IX

        XOR     A
        IN      A,(254)
        CPL
        AND     31       ;Если что-то
        RET     NZ       ;нажато, выходим.

        DEC     D        ;Продолжаем...
        JR      NZ,M2
        JR      M1

;***************************************
;Проц. OUTSCR выводит на экран фрагмент
;картинки.
;Вход: XATR, XPIX - смещение левой
;стороны фрагмента относительно
;левой границы картинки (XATR*8+XPIX
;пикселов);
;YATR, YPIX - смещение верхней стороны
;фрагмента относительно верхней границы
;картинки.

OUTSCR  DI
        LD      (TO_Q+1),SP ;Сохранили SP.
        LD      SP,TAB_SCR

;SP указывает на начало таблицы адресов
;строк экрана. При каждом выполнении
;команды POP со стека снимается адрес
;очередной строки.

        LD      A,(XPIX)
        ADD     A,A
        ADD     A,A
        ADD     A,A
        ADD     A,A
        ADD     A,#80
        LD      H,A
        LD      L,0
        LD      A,(YATR)
        LD      D,A
        LD      E,0
        SRL     D
        RR      E
        SRL     D
        RR      E
        ADD     HL,DE
        LD      D,0
        LD      A,(XATR)
        LD      E,A
        ADD     HL,DE

        POP     DE            ;#4000
        LD      BC,-#10
        EX      DE,HL
        ADD     HL,BC
        EX      DE,HL
        LD      (LP4+1),DE

;HL указывает на строку изображения,
;DE - на адрес в видеопамяти, куда
;нужно переслать эту строку
;(в данном случае это самая верхняя
;строка экрана, с адресом #4000).

        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI

;Пересылаем оставшиеся (7-YPIX) строки:

        LD      (HL_S1+1),HL

        LD      A,(YPIX)
        LD      B,A
        LD      A,7
        SUB     B
        JP      Z,SCRH

LP4     LD      HL,0
        POP     DE
        LD      BC,-#10
        EX      DE,HL
        ADD     HL,BC
        EX      DE,HL
        LD      (LP4+1),DE
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        DEC     A
        JP      NZ,LP4

;Теперь ещё 23 раза пересылаем по 8 строк.

SCRH    LD      YL,23  ;Счётчик.
HL_S1   LD      HL,0   ;Адрес очередной
        LD      BC,#40 ;пересылаемой
        ADD     HL,BC  ;строки.
        LD      (HL_S1+1),HL

;Подготавливаем адреса для переброски:

        EX      DE,HL   ;Сохранили HL.
        LD      C,#10
        POP     HL      ;Куда пересылать.
        LD      (SP_0+1),HL
        ADD     HL,BC
        LD      (SP_01+1),HL
        POP     HL      ;На строку ниже.
        LD      (SP_1+1),HL
        ADD     HL,BC
        LD      (SP_11+1),HL
        POP     HL      ;На строку ниже.
        LD      (SP_2+1),HL
        ADD     HL,BC
        LD      (SP_21+1),HL
        POP     HL      ;На строку ниже.
        LD      (SP_3+1),HL
        ADD     HL,BC
        LD      (SP_31+1),HL
        POP     HL      ;На строку ниже.
        LD      (SP_4+1),HL
        ADD     HL,BC
        LD      (SP_41+1),HL
        POP     HL      ;На строку ниже.
        LD      (SP_5+1),HL
        ADD     HL,BC
        LD      (SP_51+1),HL
        POP     HL      ;На строку ниже.
        LD      (SP_6+1),HL
        ADD     HL,BC
        LD      (SP_61+1),HL
        POP     HL      ;На строку ниже.
        LD      (SP_7+1),HL
        ADD     HL,BC
        LD      (SP_71+1),HL
        LD      (PUT_SP+1),SP ;Сохр. SP.

        EX      DE,HL   ;Восстановили HL.
        LD      BC,-#20
        ADD     HL,BC
        LD      SP,HL
        POP     AF      ;Взяли первые
        POP     BC      ;16 байтов
        POP     DE      ;пересылаемой
        POP     HL      ;строки.
        EXX
        POP     BC
        POP     DE
        POP     HL
        POP     IX
        LD      (TWO+1),SP

SP_0    LD      SP,0    ;Записываем их
        PUSH    IX      ;на экран
        PUSH    HL      ;в 8 соседних
        PUSH    DE      ;строк.
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_1    LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_2    LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_3    LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_4    LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_5    LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_6    LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_7    LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX

TWO     LD      SP,0
        POP     AF      ;Взяли вторые
        POP     BC      ;16 байтов
        POP     DE      ;пересылаемой
        POP     HL      ;строки.
        EXX
        POP     BC
        POP     DE
        POP     HL
        POP     IX

SP_01   LD      SP,0
        PUSH    IX      ;Записываем...
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_11   LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_21   LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_31   LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_41   LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_51   LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_61   LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX
SP_71   LD      SP,0
        PUSH    IX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX
        PUSH    HL
        PUSH    DE
        PUSH    BC
        PUSH    AF
        EXX

PUT_SP  LD      SP,0    ;Восст. SP.
        DEC     YL      ;Уменьшаем счётчик.
        LD      A,YL
        AND     A
        JP      Z,END_ML ;Вывели 23 строки.

;После того, как вывели 12 строк, ждём
;прерывания. Это нужно для синхронизации
;с ходом луча. Когда луч рисует верхнюю
;часть экрана, программа выводит
;изображение в нижнюю часть, и наоборот.

        CP      12
        JP      NZ,HL_S1
        LD      HL,0
        ADD     HL,SP
        LD      SP,(TO_Q+1)
        PUSH    IY
        LD      IY,#5C3A
        EI
        HALT
        DI
        POP     IY
        LD      SP,HL
        JP      HL_S1

;Если YPIX<>0, нужно вывести последние
;строки в самом низу экрана:

END_ML  LD      A,(YPIX)
        AND     A
        JP      Z,TO_Q

        LD      HL,(HL_S1+1)
        LD      BC,#20
        ADD     HL,BC
        POP     DE
        LD      BC,-#10
        EX      DE,HL
        ADD     HL,BC
        EX      DE,HL
        LD      (LP5+1),DE
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI

;Пересылаем оставшиеся строки:

        LD      A,(YPIX)
        DEC     A
        JP      Z,TO_Q
        LD      B,A

LP5     LD      HL,0
        POP     DE
        LD      BC,-#10
        EX      DE,HL
        ADD     HL,BC
        EX      DE,HL
        LD      (LP5+1),DE
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        LDI:LDI:LDI:LDI:LDI:LDI:LDI:LDI
        DEC     A
        JP      NZ,LP5

TO_Q    LD      SP,0     ;Восстановили SP.
        LD      IY,#5C3A ;Восстановили IY.
        EI
        RET     ;Выход из процедуры.

;***************************************
;Проц. MAKEADR создаёт таблицу с
;адресами всех 192 строк экрана,
;в которой каждый адрес увеличен на #10.
;Адрес таблицы - TAB_SCR.

MAKEADR LD      HL,TAB_SCR
        LD      DE,#4010
        LD      B,192

LP_MAKE LD      (HL),E
        INC     HL
        LD      (HL),D
        INC     HL
        CALL    DOWN_DE
        DJNZ    LP_MAKE
        RET

DOWN_DE INC     D
        LD      A,D
        AND     7
        RET     NZ
        LD      A,E
        SUB     #E0
        LD      E,A
        RET     NC
        LD      A,D
        SUB     8
        LD      D,A
        RET

;***************************************
;Проц. UNPACK распаковывает картинку
;по адресу PICTURE на #8000-#FFFF.

UNPACK  LD      HL,#8000
        LD      DE,PICTURE
LP_UP1  LD      B,8
        LD      A,(DE)
LP_UP2  RLA
        LD      C,#FF
        JR      C,TO_MEM
        LD      C,0
TO_MEM  LD      (HL),C
        INC     HL
        DJNZ    LP_UP2
        INC     DE
        LD      A,H
        CP      #90
        JR      NZ,LP_UP1

        LD      HL,#8FFF
        LD      DE,#9FFF
        AND     A
        PUSH    AF

LP_UP3  POP     AF
        LD      A,(HL)
        RLA
        PUSH    AF
        LD      (DE),A
        DEC     HL
        DEC     DE
        LD      A,L
        CP      #FF
        JR      NZ,LP_UP3
        LD      A,H
        AND     #0F
        CP      #0F
        JR      NZ,LP_UP3
        LD      BC,#2000
        ADD     HL,BC
        EX      DE,HL
        ADD     HL,BC
        EX      DE,HL
        LD      A,D
        CP      #0F
        JR      NZ,LP_UP3
        POP     AF
        RET

;***************************************
;Проц. CLS устанавливает атрибуты:

CLS     LD      HL,#5800
        LD      (HL),5
        LD      DE,#5801
        LD      BC,#2FF
        LDIR
        RET

;****************************************
;Картинка #40х#40 = #1000 битов = #200
;байтов.

PICTURE DB #00,#00,#00,#00,#7F,#F0,#00,#00
        DB #00,#00,#00,#1F,#FF,#FF,#80,#00
        DB #00,#00,#00,#7F,#FF,#FF,#E0,#00
        DB #00,#00,#03,#FF,#FF,#FF,#FC,#00
        DB #00,#00,#1F,#FF,#FF,#FF,#FE,#00
        DB #00,#00,#3F,#FF,#FF,#FF,#FE,#00
        DB #00,#00,#FF,#FE,#1F,#FF,#FC,#00
        DB #00,#01,#FF,#F0,#03,#FF,#FC,#00
        DB #00,#07,#FF,#00,#00,#1F,#F8,#00
        DB #00,#0F,#F8,#00,#00,#0F,#F8,#00
        DB #00,#1F,#C0,#00,#00,#C1,#F0,#00
        DB #00,#3F,#00,#18,#00,#E0,#70,#00
        DB #00,#7E,#00,#18,#01,#E0,#20,#00
        DB #00,#F0,#00,#18,#01,#E0,#00,#00
        DB #01,#F0,#01,#FF,#81,#C0,#04,#00
        DB #03,#E7,#03,#FF,#31,#C0,#0E,#00
        DB #03,#C7,#00,#1C,#79,#C0,#0F,#00
        DB #07,#87,#00,#18,#F9,#C0,#0F,#80
        DB #0F,#00,#5E,#19,#99,#C0,#1F,#C0
        DB #0F,#0E,#7E,#19,#99,#C0,#1F,#C0
        DB #1E,#0E,#67,#39,#B1,#C0,#3F,#F0
        DB #1C,#0E,#67,#31,#B1,#C0,#3F,#F0
        DB #1C,#0C,#67,#33,#E1,#C0,#0F,#F8
        DB #38,#0C,#67,#33,#C1,#C0,#07,#F8
        DB #30,#1C,#67,#33,#89,#C0,#03,#F8
        DB #30,#18,#67,#31,#99,#80,#01,#FC
        DB #30,#18,#67,#31,#99,#80,#00,#FC
        DB #60,#18,#07,#31,#F1,#80,#E0,#7C
        DB #60,#18,#03,#30,#E1,#80,#E0,#7E
        DB #60,#00,#00,#30,#00,#00,#E0,#3E
        DB #E0,#00,#00,#00,#00,#00,#E0,#3E
        DB #E0,#00,#00,#00,#00,#00,#E0,#1E
        DB #C0,#00,#00,#18,#00,#E0,#E0,#1E
        DB #C0,#00,#00,#18,#00,#E0,#E0,#0F
        DB #C0,#00,#00,#7E,#08,#00,#E0,#8F
        DB #C0,#00,#00,#FE,#38,#00,#E3,#CF
        DB #C0,#00,#00,#FC,#78,#00,#E7,#CF
        DB #E0,#00,#00,#19,#E0,#E3,#E4,#CF
        DB #60,#00,#03,#1B,#C0,#E7,#E4,#C7
        DB #60,#3E,#63,#9B,#80,#CF,#EC,#C7
        DB #60,#3E,#63,#9B,#C0,#DE,#EF,#C7
        DB #60,#66,#63,#99,#F8,#D8,#EF,#87
        DB #60,#E7,#63,#98,#7C,#D8,#EE,#07
        DB #30,#C7,#63,#98,#1C,#D8,#EC,#46
        DB #30,#C7,#63,#98,#0C,#D8,#EC,#CE
        DB #30,#C7,#63,#98,#1C,#DE,#ED,#CE
        DB #30,#C7,#67,#98,#78,#CF,#E7,#8E
        DB #18,#C7,#67,#99,#F1,#CF,#E7,#8C
        DB #1C,#C7,#7F,#99,#C1,#C0,#60,#0C
        DB #0E,#C6,#7D,#80,#00,#00,#00,#38
        DB #0E,#66,#19,#80,#00,#00,#00,#38
        DB #03,#3C,#00,#00,#00,#00,#00,#70
        DB #03,#80,#00,#00,#00,#00,#00,#70
        DB #01,#C0,#00,#00,#00,#00,#00,#C0
        DB #00,#E0,#00,#00,#00,#00,#03,#80
        DB #00,#70,#00,#00,#00,#00,#07,#80
        DB #00,#38,#00,#00,#00,#00,#0E,#00
        DB #00,#1E,#00,#00,#00,#00,#1C,#00
        DB #00,#0F,#C0,#00,#00,#00,#F8,#00
        DB #00,#07,#F0,#00,#00,#01,#F0,#00
        DB #00,#00,#7F,#80,#00,#7F,#80,#00
        DB #00,#00,#0F,#FF,#FF,#FC,#00,#00
        DB #00,#00,#01,#FF,#FF,#F0,#00,#00
        DB #00,#00,#00,#03,#F0,#00,#00,#00

;***************************************
;Координаты движения:

CRDS    DB #0E,#07,#00,#00,#0D,#07,#00,#01
        DB #0D,#00,#00,#02,#0C,#00,#00,#05
        DB #0B,#00,#00,#07,#0A,#00,#01,#03
        DB #09,#01,#01,#07,#08,#02,#02,#03
        DB #07,#03,#03,#00,#06,#04,#03,#06
        DB #05,#06,#04,#04,#05,#00,#05,#03
        DB #04,#02,#06,#02,#03,#05,#07,#02
        DB #03,#00,#08,#01,#02,#03,#09,#02
        DB #01,#07,#0A,#02,#01,#04,#0B,#03
        DB #01,#00,#0C,#05,#00,#06,#0D,#06
        DB #00,#04,#0F,#00,#00,#02,#10,#02
        DB #00,#01,#11,#03,#00,#00,#12,#05
        DB #00,#00,#14,#00,#00,#00,#15,#02
        DB #00,#01,#16,#04,#00,#02,#17,#05
        DB #00,#04,#18,#07,#00,#06,#1A,#01
        DB #01,#00,#1B,#02,#01,#04,#1C,#04
        DB #01,#07,#1D,#05,#02,#03,#1E,#05
        DB #03,#00,#1F,#06,#03,#05,#20,#05
        DB #04,#02,#21,#05,#05,#00,#22,#04
        DB #05,#06,#23,#03,#06,#04,#24,#01
        DB #07,#03,#24,#07,#08,#02,#25,#04
        DB #09,#01,#26,#00,#0A,#00,#26,#04
        DB #0B,#00,#27,#00,#0C,#00,#27,#02
        DB #0D,#00,#27,#05,#0D,#07,#27,#06
        DB #0E,#07,#27,#07,#10,#00,#28,#00
        DB #11,#00,#27,#07,#12,#00,#27,#06
        DB #12,#07,#27,#05,#13,#07,#27,#02
        DB #14,#07,#27,#00,#15,#07,#26,#04
        DB #16,#06,#26,#00,#17,#05,#25,#04
        DB #18,#04,#24,#07,#19,#03,#24,#01
        DB #1A,#01,#23,#03,#1A,#07,#22,#04
        DB #1B,#05,#21,#05,#1C,#02,#20,#05
        DB #1C,#07,#1F,#06,#1D,#04,#1E,#05
        DB #1E,#00,#1D,#05,#1E,#03,#1C,#04
        DB #1E,#07,#1B,#02,#1F,#01,#1A,#01
        DB #1F,#03,#18,#07,#1F,#05,#17,#05
        DB #1F,#06,#16,#04,#1F,#07,#15,#02
        DB #20,#00,#14,#00,#1F,#07,#12,#05
        DB #1F,#06,#11,#03,#1F,#05,#10,#02
        DB #1F,#03,#0F,#00,#1F,#01,#0D,#06
        DB #1E,#07,#0C,#05,#1E,#03,#0B,#03
        DB #1E,#00,#0A,#02,#1D,#04,#09,#02
        DB #1C,#07,#08,#01,#1C,#02,#07,#02
        DB #1B,#05,#06,#02,#1A,#07,#05,#03
        DB #1A,#01,#04,#04,#19,#03,#03,#06
        DB #18,#04,#03,#00,#17,#05,#02,#03
        DB #16,#06,#01,#07,#15,#07,#01,#03
        DB #14,#07,#00,#07,#13,#07,#00,#05
        DB #12,#07,#00,#02,#12,#00,#00,#01
        DB #11,#00,#00,#00,#10,#00,#00,#00

XATR    DB  0
YATR    DB  0
XPIX    DB  0
YPIX    DB  0

TAB_SCR DS  192*2

Другие мои статьи о программировании графических эффектов:

1. 

«Драйвер экрана для компьютера „Пентагон-128“». «ZX-Ревю» 3—4/1997.

2. 

«Два графических эффекта». «ZX-Ревю» 3—4/1997.

3. 

«Графический эффект „цветные полосы“». «ZX-Ревю» 7—10/1997.

4. 

«Несколько графических эффектов». «ZX-Ревю» 11—12/1997.

5. 

«Графический эффект „iris“». ZX Format #8, Adventurer #8.

6. 

«Оптимизация на примере intro „Start“». «Радиомир. Ваш компьютер» 7—10/2001.

Страница Ивана Рощина > Статьи >