Начинать сегодняшний разговор приходится опять со скандала. Бот что пишет Анатолий Исаев из г. Зеленогорск.
Хочу рассказать Вам один криминальный случай.
ZX-РЕВЮ выписывает в нашей школе только один человек и все "Спектрумовцы" читают журнал по-очвреди. Я почему-то оказываюсь предпоследним. Так вот. Открываю я однажды раздел ЭТЮДЫ и вцжу разливки всяких сортов для экрана, написанные моим одноклас-ником. Ну сначала порадовался за него - все-таки однокласника в самой "Ревюшке" напечатали... А потом смотрю дальше - а там мой CLS с его автографом и копирайтом (он как-то просил у меня CLS для загрузчика)... Я конечно не требую, чтобы вы писали про этот случай, тем более, что теперь мою программу будет рассматривать вся страна. Я рассказал, чтобы вы знали, какие иногда бывают копирайты .
Разыскиваем указанную публикацию . Смотрим... Ну как воспринять упрек? Действительно, в начале статьи нами поставлен копирайт, свидетельствующий о том, что материал взят из письма нашего корреспондента. В самой же указанной процедуре копирайта нет, есть только "нейтральнее" слова автора: "... и еще одна программа очистки экрана...". Корреспондент не утверждает о том, что именно он написал эту процедуру. Так что, tстрого говоря, вроде бы и упрекнуть его не в чем. Но если no-существу, то раз уж вы посылаете нам понравившуюся процедуру своего друга, то почему бы честно не сказать об этом, чтобы избежать двусмысленности. Да и посоветоваться с автором не мешало бы, прежде чем его процедуру посылать - все-таки в одном классе учитесь. А то Вы рискуете быть опозоренным из-за этой двусмысленности на всю страну - доказывайте потом, что Вас неправильно поняли... Мы будем вести жесткую политику по отношению к любителям "въехать б рай на чужом горбу". Кроме "предания позору" мы будем объявлять таким авторам бойкот -их письма никогда не попадут больше на страницы РЕВЮ. Так что, во избежание неприятностей, рекомендуем чесно и четко говорить, Ваша это программа, или откуда она взята.
* * *
Сегодня мы приготовили для Вас очередную порцию маленьких хитростей и секретов программирования. Начнем же с небольшого исследования/ которое прислал Дмитрий Баянов из г.Кемерово.
При работе с графикой Спектру-ма часто возникают проблемы с быстродействием процедур, которые используются при обработке экрана. Для обеспечения плавного перемещения спрайтов по экрану необходимо "освежать" экран, то есть изменять графику на экране не менее 50 раз в секунду (синхронно с прерываниями). При большом количестве движущихся элементов это становится проблематичным, поэтому приходится прибегать к некоторым нестандартным приемам в программировании. О некоторых из этих приемов я и хотел бы поговорить .
1. Для заполнения небольших областей памяти одинаковыми байтами лучшим способом является использование стека (об этом уже говорилось в РЕВЮ).
Ниже приведены две процедуры, выполняющие одно и то же - заполняют первые 32 байта экрана числом 255. Но первая выполняет^это при помощи последовательности команд PUSH HL, а вторая выполняет PUSH HL в цикле. Справа приведено время выполнения команд в тактах процессора Z80.
LD |
(ADDR),SP |
20 |
LD |
SP,16416 |
10 |
LD |
H, 255 |
7 |
LD |
L,H |
4 |
PUSH |
HL |
11 |
PUSH |
HL |
11 |
PUSft |
HL |
11 |
ЭТЮДЫ
|
PUSH |
HL |
11 |
LDI |
16 |
|
PUSH |
HL |
11 |
LDI |
16 ! |
|
PUSH |
HL |
11 |
LDI |
16 |
|
PUSH |
HL |
11 |
LDI |
16 |
|
PUSH |
HL |
11 |
LDI |
16 |
|
PUSH |
HL |
11 |
LDI |
16 |
|
PUSH |
HL |
11 |
LDI |
16 |
|
PUSH |
HL |
11 |
RET |
10 |
|
PUSH |
HL |
11 |
|
|
|
PUSH |
HL |
11 |
Итого: |
190 тактов |
|
PUSH |
HL |
11 |
|
|
|
PUSH |
HL |
11 |
Команде LDIR требуется 21 такт |
|
PUSH |
HL |
11 |
на переброску каждого |
байта, ко- |
|
LD |
SP,(ADDR) |
20 |
манде LDI - 16. Это же касается |
|
RET |
|
10 |
следующих команд: |
LDDR/LDD; |
ADDR |
DEFW |
0 |
|
CPIR/CPI; CPDR/CPD. |
|
|
|
|
|
3. Процедура скроллинга верх- i |
|
|
Итого: |
247 тактов |
ней линии экрана через флаг С |
|
|
|
|
влево. Как правило, делают так: |
б) |
LD |
(ADDR),SP |
20 |
|
|
|
LD |
SP,16416 |
10 |
LD HL,16415 |
10 |
|
LD |
H, 255 |
7 |
LD В,32 |
7 |
|
LD |
L, H |
4 |
OR А |
4 |
|
LD |
B,16 |
7 |
LI RL (HL) |
15x32 |
LI |
PUSH |
HL |
11x16 |
DEC HL |
6x32 |
|
DJNZ |
LI |
13x16 |
DJNZ LI |
13x32 |
|
LD |
SP,(ADDR) |
20 |
RET |
10 |
|
RET |
|
10 |
|
|
ADDR |
DEFW |
0 |
|
Итого: |
1119 тактов |
|
|
Итого: |
: 462 такта |
Быстрее так: |
|
Что |
касается быстродействия, |
LD HL,16415 |
10 |
то преимущества первого способа |
OR A |
4 |
налицо, |
так |
как команда DJNZ за- |
RL (HL) |
15 |
нимает |
при каждом проходе 13 так- |
DEC HL |
6 |
тов. |
|
|
|
RL (HL) |
15 |
2. Часто для изображения гра |
DEC HL |
6 |
фики на |
экране используется ко- |
... . , . |
|
манда LDIR для переброски данных |
комбинация RL |
(HL) |
из ОЗУ |
в дисплейный файл. Приведу |
DEC HL |
два примера |
для переброски 10 |
повторяется 32 |
! раза |
байтов: |
|
|
|
|
|
|
|
|
|
RL (HL) |
15 |
а) |
LD |
HL,40000 |
10 |
DEC HL |
6 |
|
LD |
DE,16384 |
10 |
RL (HL) |
15 |
|
LD |
ВС, 10 |
10 |
RET |
10 |
|
LDIR |
|
21x10 |
|
|
|
RET |
|
10 |
Итого: |
690 тактов |
|
|
Итого: |
250 тактов |
Можно ускорить процедуру еще |
|
|
|
|
быстрее, если вместо |
DEC HL ис- |
б) |
LD |
HL,40000 |
10 |
пользовать DEC L, так |
как на каж- |
|
LD |
DE,16384 |
10 |
дой линии экрана старшие байты |
|
LDI |
|
16 |
адресов всегда одинаковы. Резуль |
|
LDl |
|
16 |
тат, полученный при такой замене: |
|
LDI |
|
16 |
628 тактов. |
|
ЭТЮДЫ
Вывод: Если необходимо достичь максимального быстродействия, то следует, где это возможно, исключать циклы типа DJNZ или DEC ВС • LD А,В . OR С : 3R Z,... однако для этого приходится жертвовать объемом памяти.
* * *
Дмитрий Козлов из Новгорода
сообщает об интересной конструкции, заимствованной из программы ACADEMY (кажется).
CP МАХ ADC А, О
Сколько бы раз этот фрагмент ни выполнялся, содержимое аккумулятора будет увеличиваться на единицу до тех пор, пока не достигнет максимума, после чего дальше не будет увеличиваться. Эта конструкция отличается предельной простотой (всего 4 байта), обычно же в таких случаях используют команды ветвления.
Решить противоположную задачу поможет другая конструкция (тоже 4 байта):
SUB 1
ADC О
Здесь содержимое аккумулятора будет уменьшаться до тех пор, пока не станет равно нулю, дальнейшего уменьшения не последует. Необходимо заметить, что использование DEC А в первой строке не поможет, так как команда DEC не влияет на флаг переноса, значение которого определяет результат
второй команды.
* * ★
Использование команды ADC, результат которой зависит от состояния флага переноса, позволяет найти оригинальные решения и в других ситуациях. Виктор ЗУзле в (возможна ошибка - фамилия неразборчива) из Новгорода приводит свою программу для печати числа в двоичной форме, находящегося в аккумуляторе.
LD В,8 NEXT SLA А PUSH AF LD A,"О" ADC A,0 RST #10 POP AF DJNZ NEXT RET
MUGY из Ив.-Франковской области (Украина) прислал бегущую строку, обладающую несколькими положительными свойствами.
1. Очень короткая программа
2. Очень легко работать с программой Из Бейсика.
3. Можно использовать шрифты шириной 1-8 пикселов.
1 |
|
ORG |
60000 |
2 |
|
LD |
HL,16415 |
3 |
|
LD |
В, 8 |
4 |
LDK |
PUSH |
HL |
5 |
|
INC |
H |
6 |
|
DJNZ |
LDK |
7 |
|
LD |
С, 8 |
8 |
LK |
LD |
В,31 |
9 |
|
POP |
HL |
10 |
LOOP |
RL |
(HL) |
11 |
|
DEC |
HL |
12 |
|
DJNZ |
LOOP |
13 |
|
DEC |
С |
14 |
|
RET |
Z |
15 |
|
SCF |
|
16 |
|
CCF |
|
17 |
|
JR |
LK |
В строке 2 задается адрес, указывающий на правый верхний угол окна со строкой, то есть то место, где будут поярляться символы. В строке 8 в регистре В задается ширина окна в знакоместах (не обязательно 31).
Для повышения скорости работы все адреса записываются на стек, а потом во время работы по одному снимаются со стека.
Длина блока кодов 25 байт:
ЕА60: 21 1F 40 06 08 Е5 24 10 :F1
ЕА68: FC 0Е 08 06 IF Е1 СВ 16 :4В
ЕА70: 2В 10 FB OD С8 37 3F 18 :F3
ЕА78: F2 00 00 00 00 00 00 00 :54
Программа поддержки на Бейсике (поскольку большинство все же на нем работают):
1 GO ТО 10
2 BORDER О: PAPER 0: INK 7: С LEAR 59999: RANDOMIZE USR 15619:
REM : LOAD "begstr2"CODE 60000 10 LET a$="It's from MUGY " 20 FOR a=l TO LEN a$ 30 FOR k = l TO 8
40 RANDOMIZE USR 60000: NEXT k 50 PRINT AT 0,31; INK 0;a$(a): NEXT a
В строке 30 задана ширина используемого шрифта. А в строке 50 после AT задаются координаты, соответствующие адресу во 2 строке Программы на ассемблере.
Тем, кто уже отошел от Бейсика, не составит труда переложить эту программу в машинный код.
|
19 |
|
LD |
HL,#5AFF |
* ★ ★ |
20 |
|
LD |
B, 24 |
|
21 |
МЕТ4 |
PUSH |
BC |
|
22 |
|
LD |
B, 32 |
А теперь ещё несколько работ |
23 |
МЕТЗ |
LD |
(HL),COLOR2 |
наших читателей. |
24 |
|
DEC |
HL |
|
25 |
|
DJNZ |
MET3 |
(С) Владимир Тюков, г.Тула, 1995. |
26 |
|
POP |
BC |
|
27 |
|
HALT |
|
Хочу представить на суд Ваших |
28 |
|
DJNZ |
MET4 |
читателей несколько процедур. |
29 |
|
RET |
|
Первую я назвал "Штора". Она очень проста, однако это не мешает ей эффектно смотреться. Я написал ее поД впечатлением от "му-зыкалки" INSIGHT.
Значения атрибутов C0L0R1 и COLOR2 вначале программы задают режим работы: сверху экрана плавно как бы опускается штора, и все изображение становится с атрибутами COLOR1. В следующее мгновение штора поднимается, и весь экран перекрашивается атрибутом COLOR 2 . Процедура эффектно смотрится с экраном, содержащим текстовую информацию (монохромную) и может применяться, например, при создании адвентюр или программ-тестов, гороскопов, выдающих результат в виде нескольких экранов текста. Если COLOR1 установить равным нулю (PAPRE 0; INK 0), то в строках 15-17 как раз и может быть расположена процедура печати или вывода на экран информации. Эта информация "откроется" при "поднятии" шторы.
1 COLOR1 EQU 8*1+7
2 COLOR2 EQU 8*5+1
3 ORG 50000
4 ENT $
5 LD HL,#5800
6 LD В,24
7 MET2 PUSH BC
8 LD В,32
9.MET1 LD (HL),COLOR1
10 INC HL
11 DJNZ MET1
12 POP BC
13 HALT
14 DJNZ MET2
15 ; Здесь может быть команда
16 ; -переброски в экран моно-
17 ; хромного дисплейного файла
18 ; или процедура печати
Длина |
процедуры |
l = |
35 |
байтов: |
|
C350: |
21 |
00 |
58 |
06 |
18 |
C5 |
06 |
20 |
' 95 |
C358: |
36 |
OF |
23 |
10 |
FB |
CI |
76 |
10 : |
:D5 |
C360 : |
F4 |
21 |
FF |
5A |
06 |
18 |
C5 |
06 |
: 7 A |
C368: |
20 |
36 |
29 |
2B |
10 |
FB |
CI |
76 ; |
: 17 |
C370: |
10 |
F4 |
C9 |
00 |
00 |
00 |
00 |
00 : |
: 00 |
Две следующих программы выполняют эффект, который я назвал "Перелив". Их можно встретить практически в любых загрузчиках к играм и "музыкалках". Приведенную ниже процедуру я вытащил ив музы-калки ТОР 1.
1 |
POS |
EQU |
#5800 |
2 |
LIN |
EQU |
24 |
3 |
COL |
EQU |
32 |
4 |
|
ORG |
50000 |
5 |
|
ENT |
$ |
6 |
|
LD |
HL,POS |
7 |
|
LD |
B,LIN |
8 |
M2 |
PUSH |
ВС |
9 |
|
PUSH |
HL |
10 |
|
LD |
ВС, 32 |
11 |
|
PUSH |
ВС |
12 |
|
LD |
В,COL |
13 |
Ml |
PUSH |
ВС |
14 |
|
LD |
A,(HL) |
15 |
|
INC |
A |
16 |
|
AND |
7 |
17 |
|
LD |
(HL),A |
18 |
|
INC |
HL |
19 |
|
POP |
ВС |
20 |
|
DJNZ |
Ml |
21 |
|
POP |
ВС |
22 |
|
POP |
HL |
23 |
|
ADD |
HL, ВС |
24 |
|
POP |
ВС |
25 |
|
DJNZ |
M2 |
26 |
|
RET |
|
В первой строке задается адрес В файле атрибутов начального знакоместа, с которого начинается окно действия эффекта. Во второй строке - высота (количество строк) окна. В 3 строке - ширина (количество символов) окна.
Длина процедуры = 30 байтов:
С350: 21 00 58 06 18 С5 Е5 01 :55
С358: 20 00 С5 06 20 С5 7Е ЗС :А5
С360: Е6 07 77 23 С1 10 F6 С1 :32
С368: Е1 09 С1 10 Е8 С9 00 00 :97
Использовать процедуру можно например, так. Сначала на экран наносится какое-то сообщение оди^ наковым цветом INK и PAPER. Затем это сообщение выделяется:
10 RANDOMJZE USR 50000: GO ТО 10
можно подставить между этими операторами PAUSE N, или опрос клавиатуры и т.п.
Следующая процедура воспроизводит тот же эффект, но предназначена только для одной строки экрана. Она написана лично мной под впечатлением от предыдущей.
исходные данные задаются в стро-
ках 3 |
И 4. |
|
|
1 |
|
ORG |
50000 |
2 |
|
ENT |
$ |
3 |
|
If) |
HL,#5900 |
4 |
|
LD |
В, 32 |
5 |
МЕТ2 |
LD |
A,(HL) |
6 |
|
INC |
A |
7 |
|
AND |
7 |
8 |
|
OR |
NZ,METl |
9 |
|
INC |
A |
10 |
METl |
LD |
(HL),A |
11 |
|
INC |
HL |
12 |
|
DJNZ |
MET2 |
13 |
|
RET |
|
Длина процедуры = 17 байтов:
С350: 21 00 59 06 20 7Е ЗС Е6 :53 С358: 07 20 01 ЗС 77 23 10 F5 :1Е С360: С9 U0 00 00 00 00 00 00 :ЕС
Владимир пишет также о своем хобби: он добавляет к играм разные усовершенствования - озвучивает, переделывает из 48К в 128К и др., а также предлагает свою помощь (бейсик, ассемблер):
300001, г.Тула, ул.Пролетарская, д.34, кв.41. Тюкову Владимиру Михайловичу.
ЭТЮДЫ
4 LD B,(IX+3) 61 LD Т., A
5 XOR A 62 RET
6 LD (SCHET),A
7 LOOPI PUSH ВС Скорость эффекта можно регули-
8 LD В,(IX+2) ровать, изменяя число HALT'ob
9 HALT (строки 9-10).
10 HALT В своей процедуре я испольsoil LD Е,(IX+0) вал подпрограмму расчета адреса в
12 LD D, (IX+1) экранном файле из ZX-PEBI0-94, N3,
13 LOOP2 PUSH ВС стр.44. Если в Вашей программе
14 CALL ADR уже есть эта подпрограмма, то
15 LD В,4 нужно заменить адрес в команде ее
16 L00P3 PUSH ВС вызора в строке 14 и удалить ее
17 LD А,(SCHET) из листинга (строки 51-62).
18 LD С,А Если же подпрограмма ADR Вам
19 PUSH HL нигде больше не нужна, кроме этой
20 LD В,0 процедуры, то можно ее раскрыть,
21 ADD HL,ВС сделав релоцируемым весь блок и
22 LD (HL),0 укоротив его на 4 байта. Для это-
23 POP HL го нужно вместо строки 14 запи-
24 INC Н сать строки 51-61.
25 PUSH HL Шестнадцатиричные дампы обоих
26 PUSH ВС вариантов (длина соответственно
27 LD С,(1Х+3) 95 и 91 байтов):
28 DEC С
29 ADD HL,ВС С350: DD 21 9С СЗ DD 46 03 AF :45
30 POP ВС С358: 32 9А СЗ С5 DD 46 02 76 :0А
31 SBC HL,ВС С360: 76 DD 5Е 00 DD 56 01 C5 :CD
32 LD (HL),0 C368: CD AO C3 06 04 C5 ЗА 9A :FE
33 POP HL C370: C3 4F E5 06 00 09 36 00 :6F
34 INC H C378: El 24 E5 C5 DD 4E 03 0D :25
35 POP ВС C380: 09 CI ED 42 36 00 El 24 :77
36 DJNZ LOOP3 C388: CI 10 E2 CI 1С 10 D8 CI :84
37 POP ВС C390: ЗА 9A СЗ ЗС 32 9A СЗ 10 :С5
38 INC Е С398: С2 С9 00 00 00 00 18 20 ;1Е
39 DJNZ LOOP2 C3A0: 7В Еб 18 С6 40 67 7В Еб :АА
40 POP ВС СЗА8: 07 OF OF OF 82 6F С9 00 :59
41 LD A,(SCHET)
42 INC А С350: DD 21 А7 СЗ DD 46 03 AF :50
43 LD (SCHET),A C358: 32 A5 C3 C5 DD 46 02 76 :15
44 DJNZ LOOP1 C360: 76 DD 5E 00 DD 56 01 C5 :CD
45 RET C368: 7B E6 18 C6 40 67 7B E6 :72
46 SCHET DEFW 0 C370: 07 OF OF OF 82 6F 06 04 :62
47 DATA DEFB 0 ;Коорд. Y C378: C5 ЗА A5 СЗ 4F E5 06 00 :DC
48 DEFB 0 ;Коорд. X C380: 09 36 00 El 24 E5 C5 DD :0E
49 DEFB 24 ;Высота окна C388: 4E 03 0D 09 CI ED 42 36 :D8
50 DEFB 32 ;Ширина окна C390: 00 El 24 CI 10 E2 CI 1С :E8
51 ADR LD A,E C398: 10 CD CI ЗА A5 СЗ ЗС 32 :09
52 AND #18 C3A0: A5 СЗ 10 B7 C9 00 00 00 :5В
53 ADD A,#40 C3A8: 00 18 20 00 00 00 00 00 :A3
54 LD H, A
56 LD A,E Для большей завершенности эф-
56 AND 7 фекта и универсальности процеду-
57 RRCA ры, ее необходимо дополнить
58 RRCA очисткой атрибутов окна.
59 RRCA
60 ADD A, D * * *