© Иван Рощин, Москва
| ZXNet | : 500:95/462.53 |
| : bestview@mtu-net.ru | |
| WWW | : http://www.ivr.da.ru |
Предлагаю вашему вниманию драйвер
экрана небольшую процедуру на ассемблере (211 байтов), вызываемую
по прерываниям
Вот пример программы, использующей драйвер для
реализации простейшего эффекта: по экрану движутся три цветные полосы.
Обратите особое внимание на то, как программируется этот эффект, а также на
длину программы всего 217 байтов (без драйвера).
ORG #6000
;Основная программа:
N EQU 37 ;Размер по вертикали в знакоместах.
LD HL,#5800 ;Установка
LD DE,#5801 ;атрибутов
LD BC,#2FF ;(не обязательно).
LD (HL),L
LDIR
;Рисуем сетку (необходимо для multicolor'а):
LD HL,#4000
LP1 XOR A
BIT 0,H
JR NZ,NE_FF
CPL
NE_FF LD (HL),A
INC HL
LD A,H
CP #58
JR NZ,LP1
;Инициализация эффекта:
CALL E_INIT
;Чтобы вызывать драйвер по прерываниям,
;формируем таблицу, например, с адреса
;#FEFE:
LD HL,#FE00
LD B,0
LOOPT LD (HL),#62
INC HL
DJNZ LOOPT
LD (HL),#62
LD A,#FE
LD I,A
IM 2
LOOP_M HALT
CALL EFFECT
IN A,(254) ;что-то нажато?
CPL
AND %00011111
JR Z,LOOP_M ;если нет
IM 1
RET ;выход из программы
;---------------------------------------
;Реализация эффекта "цветные полосы":
;Точка входа для инициализации:
E_INIT LD HL,DATA+40
LD DE,DATA+41
LD BC,300
LD (HL),0
LDIR
LD HL,DATA
LD DE,DATA+1
LD BC,39
LD (HL),7
LDIR
RET
;Точка входа для вызова раз в прерывание:
EFFECT LD HL,(A_BEG)
LD B,1
LD A,(A_WAY)
CALL MOVE
LD (A_WAY),A
LD (A_BEG),HL
LD HL,(B_BEG)
LD B,2
LD A,(B_WAY)
CALL MOVE
CALL MOVE
LD (B_WAY),A
LD (B_BEG),HL
LD HL,(C_BEG)
LD B,4
LD A,(C_WAY)
CALL MOVE
CALL MOVE
CALL MOVE
LD (C_WAY),A
LD (C_BEG),HL
RET
;Процедура MOVE сдвигает полосу:
MOVE AND A
JR NZ,MOVE_D
;Сдвиг вверх:
LD A,H
OR L
JR Z,MOVE_D
MOVE_UP DEC HL
PUSH HL
LD DE,DATA
ADD HL,DE
LD A,(HL)
OR B
LD (HL),A
LD DE,40
ADD HL,DE
LD A,(HL)
XOR B
LD (HL),A
POP HL
XOR A
RET
;Сдвиг вниз:
MOVE_D LD DE,297-40
AND A
SBC HL,DE
PUSH AF
ADD HL,DE
POP AF
JR Z,MOVE_UP
PUSH HL
LD DE,DATA
ADD HL,DE
LD A,(HL)
XOR B
LD (HL),A
LD DE,40
ADD HL,DE
LD A,(HL)
OR B
LD (HL),A
POP HL
INC HL
LD A,1
RET
A_BEG DW 0 ;координаты
B_BEG DW 0 ;полос
C_BEG DW 0
A_WAY DB 0 ;направление
B_WAY DB 0 ;движения
C_WAY DB 0
;---------------------------------------
ORG #6262
;=======================================
;Драйвер экрана:
DI
PUSH AF ;Сохраняем значения
PUSH BC ;используемых
PUSH DE ;регистров.
PUSH HL
PUSH IX
PUSH IY
LD (M122+1),SP
;Задержка, пока луч не дойдет до верхней строки:
LD D,H ;WAIT
LD E,L ;WAIT
LD BC,171 ;WAIT
LDIR ;WAIT
LD IX,DATA+1 ;адрес таблицы
LD HL,#5720 ;текущий адрес атрибутов
LD BC,3 ;B - всегда 0, C - счетчик.
LD A,(DATA) ;цвет первой строки
LD YL,A ;запомнили цвет
LD DE,#20
;Луч в начале очередной строки:
M3 LD SP,HL
SBC HL,DE
LD A,YL
OUT (254),A
LD A,(IX+1)
LD YL,A
AND A
RLCA
RLCA
RLCA
OR (IX)
LD D,A
LD A,H
CP #58
JR C,NO_ATR
CP #5B
JR NC,NO_ATR2
;Половина строки уже прорисована,
;и атрибуты можно сменить.
LD E,D
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
;16 байтов заполнены, луч в начале
;следующей строки:
LD A,D
AND 7
OUT (254),A
LD A,C
;Меняем оставшиеся атрибуты:
LD C,#20 ;BC=#20
ADD HL,BC
LD SP,HL
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
PUSH DE
LD C,A
INC XL
LD A,0 ;WAIT
NEXT_L LD DE,#10
INC IX
DEC C
JR NZ,M10
LD C,4
ADD HL,DE
JR M3
M10 SBC HL,DE
JP M3
;Сюда попадаем, если текущая строка
;целиком относится к бордюру:
NO_ATR LD A,0 ;WAIT
LD A,0 ;WAIT
;Проверка по значению HL: не пора ли
;выйти из прерывания?
NO_ATR2 LD DE,#5720+((N-1)*#20)
AND A
SBC HL,DE
JR NC,M122
ADD HL,DE
LD DE,(0) ;WAIT
LD DE,(0) ;WAIT
NOP ;WAIT
LD A,(IX)
OUT (254),A
LD A,(IX) ;WAIT
LD A,(IX) ;WAIT
LD A,(IX) ;WAIT
LD A,(IX) ;WAIT
INC DE ;WAIT
LD DE,#20
ADD HL,DE
INC XL
JR NEXT_L
;Выход из прерывания:
M122 LD SP,0
POP IY ;восстанавливаем
POP IX ;значения регистров
POP HL
POP DE
POP BC
XOR A
OUT (254),A
POP AF
EI
RET
;=======================================
ORG #7001
;---------------------------------------
;Массив данных для multicolor'а:
DATA DS 320
Несколько замечаний по поводу программы:
При работе драйвера программист может считать, что
видеопамять это массив данных, расположенный по адресу DATA и
занимающий столько байтов, сколько строк multicolor'а он хочет видеть на
экране. Значение каждого байта этого массива число от 0 до 7,
определяющее цвет соответствующей строки экрана. Если массив не изменяется,
Вертикальный размер multicolor'а в знакоместах
определяется значением переменной N. Это значение может быть не любым, а лишь
в границах
|
|
Чтобы подстроить значение задержки в драйвере, найдите команды, помеченные «WAIT», в самом начале драйвера. Вы увидите такой фрагмент:
LD D,H ;WAIT
LD E,L ;WAIT
LD BC,171 ;WAIT
LDIR ;WAIT
Добиться наилучшего качества изображения можно, изменяя загружаемое в BC число или добавляя NOP'ы (или и то, и другое). Следить за результатом внесённых изменений удобно, если при каждом запуске программы на экране появляется неподвижная картинка с разноцветными линиями. Для этого нужно убрать строки CALL E_INIT и CALL EFFECT, а вместо строки DATA DS 320 поместить такие строки:
DATA DB 7,0,4,0,4,0,4,0
DB 4,0,4,0,4,0,4,0
DB 4,0,4,0,4,0,4,0
DB 4,0,4,0,4,0,4,0
DB 4,0,4,0,4,0,4,0
DB 4,0,4,0,4,0,4,0
DB 4,0,4,0,4,0,4,0
DB 4,0,4,0,4,0,4,7
DB 0,1,2,3,4,5,6,7
DB 4,0,4,0,4,0,4,0
.......................
При использовании драйвера в своих программах лучше
синхронизироваться с прерываниями командой HALT. Это связано с тем, что если в
момент прерывания процессор будет занят выполнением более длинной команды,
драйвер позже начнет свою работу, и картинка может сместиться.
Если вы всё же решили программировать
Дополнение: графические эффекты, получаемые
с помощью описанного в статье драйвера, вы можете увидеть
в моём demo «Ray».
|
Другие мои статьи о программировании графических эффектов:
|