© Иван Рощин, Москва
| ZXNet | : 500:95/462.53 |
| : bestview@mtu-net.ru | |
| WWW | : http://www.ivr.da.ru |
(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) верхней стороны фрагмента относительно верхней границы картинки.
![]() |
Количество элементов в массиве и их значения можно изменять, тем самым задавая новую траекторию движения.
Итак, вот сама программа:
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
|
Другие мои статьи о программировании графических эффектов:
|