┌──────────────────────────────┐
│ │
│ РЕТРО │
│ │
└──────────────────────────────┘
Дж.Хардман, Э.Хьюзон
40 лучших процедур
Продолжение. Начало в ZX РЕВЮ
1997 NN 1-2, 3-4.
6. ДИСПЛЕЙНЫЕ ПРОГРАММЫ
6.1. Слияние картинок
Длина: 21
Количество переменных: 1
Контрольная сумма: 1709
Назначение: эта программа
объединяет картинку, хранящуюся
в ОЗУ, с текущим экраном дис-
плея.
Атрибуты не изменяются.
Переменные:
Имя: screen_store
Длина: 2
Ячейка: 23296
Комментарий: содержит адрес
картинки в ОЗУ.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: нет.
Комментарий: Для объединения
картинок должна быть использова-
на приведенная на листинге прог-
рамма. Однако интересные ре-
зультаты могут быть также полу-
чены заменой OR (HL) на XOR (HL)
или AND (HL).
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,16384 33 0 64
LD DE,(23296) 237 91 0 91
LD BC,6144 1 0 24
NEXT_B LD A,(DE) 26
OR (HL) 182
LD (HL),A 119
INC HL 35
INC DE 19
DEC BC 11
LD A,B 120
OR C 177
JR NZ,NEXT_B 32 246
RET 201
2
Как она работает:
В пару регистров HL загружает-
ся начальный адрес дисплейного
файла, а в пару регистров DE -
его длина. Регистровая пара BC
используется в качестве счетчи-
ка.
В аккумулятор загружается байт
с адресом в DE и выполняется ло-
гическое ИЛИ (OR) этого значе-
ния с байтом дисплейного файла.
Результат затем помещается в об-
ласть дисплея.
HL и DE перемещаются на следу-
ющую позицию, счетчик уменьшает-
ся. Если счетчик не равен 0, то
подпрограмма возвращается назад
для повторения процесса со сле-
дующим байтом.
Программа возвращается в BASIC.
6.2. Инвертирование экрана
Длина: 18
Количество переменных: 0
Контрольная сумма: 1613
Назначение: инвертирует все в
дисплейном файле: если пиксел
включен, он сбрасывается (OFF),
если пиксел выключен, он уста-
навливается.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: нет.
Комментарий: эта программа мо-
жет быть использована для полу-
чения эффекта вспышки. Этот эф-
фект усиливается, если делается
вызов несколько раз и добавляет-
ся звук.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,16384 33 0 64
LD BC,6144 1 0 24
LD D,255 22 255
NEXT_B LD A,D 122
SUB (HL) 150
LD (HL),A 119
INC HL 35
DEC BC 11
LD A,B 120
OR C 177
JR NZ,NEXT_B 32 247
RET 201
2
Как она работает:
В пару регистров HL загружает-
ся адрес дисплейного файла, а в
BC загружается его длина. В
D-регистр помещается значение
255. Всякий раз, когда подпрог-
рамма возвращается к NEXT_B, в
аккумулятор загружается значение
из D-регистра. Этот метод пред-
почтительнее, чем инструкция LD
A,255, т.к. LD A,D выполняется
приблизительно в 2 раза быстрее,
чем инструкция LD A,255. Значе-
ние байта, хранящегося в ячейке
по адресу, указанному в HL, вы-
читается из аккумулятора, а ре-
зультат загружается в тот же са-
мый байт. Таким образом, делает-
ся инвертирование.
HL увеличивается, указывая на
следующий байт, а счетчик BC
уменьшается. Если счетчик не ра-
вен 0, программа возвращается к
NEXT_B. Если счетчик равен 0,
программа возвращается в BASIC.
6.3. Инвертирование символа
вертикально
Длина: 20
Количество переменных: 1
Контрольная сумма: 1757
Назначение: эта программа ин-
вертирует символ вертикально.
Например, стрелка, направленная
вверх, должна стать стрелкой,
направленной вниз, и наоборот.
Переменные:
Имя: chr_start
Длина: 2
Ячейка: 23296
Комментарий: адрес символа в
ОЗУ (ПЗУ).
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: нет.
Комментарий: эта программа по-
лезна в играх, т.к. можно изме-
нять отдельные символы, не за-
трагивая при этом соседние обла-
сти изображения.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,(23296) 42 0 91
LD D,H 84
LD E,L 93
LD B,8 6 8
NEXT_B LD A,(HL) 126
INC HL 35
PUSH AF 245
DJNZ NEXT_B 16 251
LD B,8 6 8
REPL POP AF 241
LD (DE),A 18
INC DE 19
DJNZ REPL 16 251
RET 201
2
Как она работает:
В пару регистров HL загружает-
ся адрес данных символа. Этот же
адрес затем копируется в DE. В
регистр B загружается значение 8
для использования регистра в ка-
честве счетчика.
Для каждого байта в аккумуля-
тор загружается имеющееся в нас-
тоящий момент значение. HL уве-
личивается, указывая на следую-
щий байт, а содержимое аккумуля-
тора помещается на стек. Счет-
чик уменьшается и, если он не
равен 0, подпрограмма возвра-
щается, чтобы повторить процесс
для следующего байта. В регистр
B повторно загружается значение
8, чтобы снова использовать его
в качестве счетчика. Изображе-
ние символа сохранено на стеке.
Процедура REPL возвращает дан-
ные со стека на то же знакомес-
то, но уже в обратном порядке.
Байт за байтом берутся со сте-
ка и через аккумулятор помещают-
ся по адресу, содержащемуся в
DE. DE увеличивается, чтобы ука-
зать на следующий байт, а счет-
чик уменьшается. Если он не ра-
вен 0, программа возвращается к
REPL. В противном случае она
возвращается в BASIC.
6.4.
Длина: 19
Количество переменных: 1
Контрольная сумма: 1621
Назначение: эта программа ин-
вертирует символ горизонтально.
Например, стрелка, направленная
влево, становится стрелкой, нап-
равленной вправо.
Переменные:
Имя: chr_start
Длина: 2
Ячейка: 23296
Комментарий: адрес данных
символа.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: нет.
Комментарий: нет.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,(23296) 42 0 91
LD A,8 62 8
NEXT_B LD B,8 6 8
NEXT_P RR (HL) 203 30
RL C 203 17
DJNZ NEXT_P 16 250
LD (HL),C 113
INC HL 35
DEC A 61
JR NZ,NEXT_B 32 243
RET 201
2
Как она работает:
В пару регистров HL загружает-
ся адрес данных символа, а в ак-
кумулятор загружается количес-
тво байтов, которые должны быть
инвертированы. В регистр B заг-
ружается число битов в каждом
байте - он используется как
счетчик.
Байт с адресом в HL сдвигает-
ся вправо таким образом, что
крайний правый бит копируется во
флаг переноса. C-регистр сдви-
гается влево так, что флаг пере-
носа копируется в крайний пра-
вый бит. Счетчик (B-регистр)
уменьшается.
Если счетчик не равен 0,
происходит переход к NEXT_P для
работы со следующим пикселом.
Инвертированный байт, который
находится в регистре C, поме-
щается в ячейку, из которой он
был взят.
HL увеличивается, указывая на
следующий байт, а аккумулятор
уменьшается. Если аккумулятор не
равен 0, происходит переход к
NEXT_BYTE, в противном случае -
возврат в BASIC.
6.5. Вращение символа
по часовой стрелке
Длина: 42
Количество переменных: 1
Контрольная сумма: 3876
Назначение: эта программа по-
ворачивает символ на 90 граду-
сов по часовой стрелке. Напри-
мер, стрелка, направленная
вверх, становится направленной
вправо.
Переменные:
Имя: chr_start
Длина: 2
Ячейка: 23296
Комментарий: адрес данных
символа.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: нет.
Комментарий: эта программа по-
лезна в играх и для серьезных
целей, например, в графике.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,(23296) 42 0 91
LD E,128 30 128
N_BIT PUSH HL 229
LD C,0 14 0
LD B,1 6 1
NEXT_B LD A,E 123
AND (HL) 166
CP 0 254 0
JR Z,NOT_S 40 3
LD A,C 121
ADD A,B 128
LD C,A 79
NOT_S SLA B 203 32
INC HL 35
JR NZ,NEXT_B 48 242
POP HL 225
PUSH BC 197
SRL E 203 59
JR NC,N_BIT 48 231
LD DE,7 17 7 0
ADD HL,DE 25
LD B,8 6 8
REPL POP DE 209
LD (HL),E 115
DEC HL 43
DJNZ REPL 16 251
RET 201
2
Как она работает:
Символ состоит из группы пик-
селей размером 8х8, каждый из
которых может быть в состоянии
ON (1) или OFF (0). Рассмотрим
любой бит B2 байта B1 на рис.1.
Данные хранятся в ячейке (B2,B1)
в форме:
│ N1 N3 │
│ N2 N4 │
где:
N1 = байт, в который пиксел
(B2,B1) будет вставлен после
вращения.
N2 = бит в N1, в который он
будет вставлен.
N3 = значение, которое пред-
ставляет текущее значение бита.
N4 = значение бита N2. Каждый
байт вращаемого символа будет
сформирован добавлением значе-
ний всех битов N2, которые бу-
дут в новом байте.
┌──────────────────────────────────────────────────────────────┐
│ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 1 │
│ │0 1│0 1│0 1│0 1│0 1│0 1│0 1│0 1│ │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 2 │
│ │1 2│1 2│1 2│1 2│1 2│1 2│1 2│1 2│ │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 3 │
│ │2 4│2 4│2 4│2 4│2 4│2 4│2 4│2 4│ │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 4 │
│ │3 8│3 8│3 8│3 8│3 8│3 8│3 8│3 8│ │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ Байт(B1)│
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 5 │
│ │4 16│4 16│4 16│4 16│4 16│4 16│4 16│4 16│ │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 6 │
│ │5 32│5 32│5 32│5 32│5 32│5 32│5 32│5 32│ │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 7 │
│ │6 64│6 64│6 64│6 64│6 64│6 64│6 64│6 64│ │
│ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
│ │1 128│2 64│3 32│4 16│5 8│6 4│7 2│8 1│ 8 │
│ │7 128│7 128│7 128│7 128│7 128│7 128│7 128│7 128│ │
│ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ │
│ 7 6 5 4 3 2 1 0 Бит(B2) │
│ │
│ Рис.1. Ключ к подпрограмме вращения символа │
└──────────────────────────────────────────────────────────────┘
В HL загружается адрес перво-
го байта символа. В регистр E
загружается значение байта, ко-
торый имеет 7-й бит в состоянии
ON и с 0 по 6-й биты - в OFF,
т.е. 128. HL сохраняется в сте-
ке. В регистр C засылается 0.
Далее в него будут добавляться
данные, давая новое значение для
формируемого байта. В регистр B
загружается значение байта, ну-
левой бит которого включен, а
биты 1-7 - выключены, т.е., это
единица.
В аккумулятор загружается со-
держимое E-регистра (N3). Это
значение перемножается логичес-
ки (AND) с байтом, адрес которо-
го хранится в HL. Если ре-
зультат равен 0, происходит пе-
реход к NOT_S, т.к. пиксел, ад-
ресованный регистром E и регис-
тровой парой HL сброшен (OFF).
Если же он установлен (ON), в
аккумулятор загружается имеющее-
ся значение байта (N1). Регистр
B (N4) добавляется к аккумулято-
ру и это значение загружается в
регистр C. Регистр затем уста-
навливается, чтобы указать на
следующий бит N1. HL увеличи-
вается, указывая на следующий
байт (B1). Если байт N1 не за-
вершен, подпрограмма возвращает-
ся к NEXT_B.
HL восстанавливается из стека,
чтобы снова указать на первый
байт символа. BC сохраняется в
стеке, чтобы запомнить значение
последнего байта для завершения
в C-регистре. E-регистр настраи-
вается на адрес следующего бита
каждого байта. Если вращение не
завершено, происходит переход к
N_BIT.
В DE загружается значение 7, и
это значение добавляется к HL.
Теперь HL указывает на послед-
ний байт данных. В регистр B
загружается число байтов, кото-
рые должны быть взяты из стека.
Для каждого байта новое значение
копируется в E, и это значение
помещается в ячейку с адресом в
HL. HL уменьшается, чтобы ука-
зать на следующий байт, и счет-
чик (B-регистр) уменьшается.
Если счетчик не равен 0, про-
исходит переход к REPL.
Программа возвращается в BASIC.
6.6. Изменение атрибута
Длина: 21
Количество переменных: 2
Контрольная сумма: 1952
Назначение: эта программа из-
меняет значение атрибутов всех
символов экрана на задаваемое,
например, могут быть изменены
цвета всех символов или весь эк-
ран может замигать и т.д.
Переменные:
Имя: data_saved
Длина: 1
Ячейка: 23296
Комментарий: неизменяемые биты
атрибута.
Имя: new_data
Длина: 1
Ячейка: 23297
Комментарий: новые биты, вво-
димые в байт атрибута.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: нет.
Комментарий: отдельные биты
атрибута каждого символа могут
быть изменены с помощью инструк-
ции AND и OR.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,22528 33 0 88
LD BC,768 1 0 3
LD DE,(23296) 237 91 0 91
NEXT_B LD A,(HL) 126
AND E 163
OR D 178
LD (HL),A 119
INC H 35
DEC BC 11
LD A,B 120
OR C 177
JR NZ,NEXT_B 32 246
RET 201
2
Как она работает:
В пару регистров HL загружает-
ся адрес области атрибутов, а в
пару регистров BC - количество
символов на экране. В регистр D
загружается значение new_data, а
в регистр E загружается значе-
ние data_saved.
В аккумулятор загружается байт
с адресом, находящимся в HL, а
биты устанавливаются соответ-
ственно значениям регистров D и
E. Результат помещается обратно
в ячейку в адресом, хранящимся в
HL. HL увеличивается, указывая
на следующий байт, а счетчик BC
уменьшается. Если содержимое BC
на равно 0, программа возвраща-
ется к NEXT_B.
Программа возвращается в BASIC.
6.7. Смена атрибута
Длина: 22
Количество переменных: 2
Контрольная сумма: 1825
Назначение: эта программа ищет
атрибуты с определенным значе-
нием и заменяет каждое найден-
ное вхождение другим значением.
Переменные:
Имя: old_value
Длина: 1
Ячейка: 23296
Комментарий: значение байта,
подлежащего замене.
Имя: new_value
Длина: 1
Ячейка: 23297
Комментарий: значение замещаю-
щего байта.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: нет.
Комментарий: эта программа по-
лезна для выделения областей
текста и графических символов.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,22528 33 0 88
LD BC,768 1 0 3
LD DE,(23296) 237 91 0 91
NEXT_B LD A,(HL) 126
CP E 187
JR NZ,NO_CH 32 1
LD (HL),D 114
N)_CH INC HL 35
DEC BC 11
LD A,B 120
OR C 177
JR NZ,NEXT_B 32 245
RET 201
2
Как она работает:
В пару регистров HL загружает-
ся адрес области атрибутов, а в
BC загружается число символов на
экране. В E-регистр загружается
old_value, а в D-регистр nev_va-
lue. В аккумулятор загружается
байт, адрес которого хранится в
паре HL. Если аккумулятор хранит
значение, которое эквивалентно
содержимому E-регистра, то в
байт с адресом, имеющимся в HL,
помещается содержимое D-регис-
тра. При этом HL увеличивается,
указывая на следующий байт, а
счетчик BC уменьшается. Если BC
не равно 0, происходит переход к
NEXT_B, иначе программа возвра-
щается в BASIC.
6.8. Закрашивание контура
Длина: 263
Количество переменных: 2
Контрольная сумма: 26647
Назначение: эта программа зак-
рашивает область экрана, ограни-
ченную линией пикселей.
Переменные:
Имя: X_coord
Длина: 1
Ячейка: 23296
Комментарий: координата X
стартовой позиции.
Имя: Y_coord
Длина: 1
Ячейка: 23297
Комментарий: координата Y
стартовой позиции.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: если коорди-
ната Y>175 или POINT (X,Y)=1, то
программа тотчас же возвращается
в BASIC.
Комментарий: эта программа не
перемещаемая, ее стартовый ад-
рес - 31955. Когда закрашивает-
ся большая область сложной фор-
мы, нужно большое количество
свободного пространства. Если
это невозможно, может произойти
сбой.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,(23296) 42 0 91
LD A,H 124
CP 176 254 176
RET NC 208
CALL SUBR 205 143*125
AND (HL) 166
CP 0 254 0
RET NZ 192
LD BC,65535 1 255 255
PUSH BC 197
RIGHT LD HL,(23296) 42 0 91
CALL SUBR 205 143*125
AND (HL) 166
CP 0 254 0
JR NZ,LEFT 32 9
LD HL,(23296) 42 0 91
INC L 44
LD (23296),HL 34 0 91
JR NZ,RIGHT 32 236
LEFT LD DE,0 17 0 0
LD HL,(23296) 42 0 91
DEC L 45
LD (23296),HL 34 0 91
PLOT LD HL,(23296) 42 0 91
PUSH HL 229
CALL SUBR 205 143*125
OR (HL) 182
LD (HL),A 119
POP HL 225
LD A,H 124
CP 175 254 175
JR Z,DOWN 40 44
LD A,E 123
CP 0 254 0
JR NZ,RESET 32 16
INC H 36
CALL SUBR 205 143*125
AND (HL) 166
CP 0 254 0
JR NZ,RESET 32 7
LD HL,(23296) 42 0 91
INC H 36
PUSH HL 229
LD E,1 30 1
RESET LD HL,(23296) 42 0 91
LD A,E 123
CP 1 254 1
JR NX,DOWN 32 15
INC H 36
CALL SUBR 205 143*125
AND (HL) 166
CP 0 254 0
JR Z, DOWN 40 6
LD E,0 30 0
JR DOWN 24 2
L_JUMP JR RIGHT 24 167
DOWN LD HL,(23296) 42 0 91
LD A,H 124
CP 0 254 0
JR Z,NEXT_P 40 40
LD A,D 122
CP 0 254 0
JR NZ,REST 32 16
DEC H 37
CALL SUBR 205 143*125
AND (HL) 166
CP 0 254 0
JR NZ,REST 32 7
LD HL,(23296) 42 0 91
DEC H 37
PUSH HL 229
LD D,1 22 1
REST LD A,D 122 1
CP 1 254 1
JR NZ,NEXT_P 32 14
LD HL,(23296) 42 0 91
DEC H 37
CALL SUBR 205 143*125
AND (HL) 166
CP 0 254 0
JR Z,NEXT_P 40 2
LD D,0 22 0
NEXT_P LD HL,(23296) 42 0 91
LD A,L 125
CP 0 254 0
JR Z,RETR 40 12
DEC L 45
LD (23296),HL 34 0 91
CALL SUBR 205 143*125
AND (HL) 166
CP 0 254 0
JR Z,PLOT 40 129
RETR POP HL 225
LD (23296),HL 34 0 91
LD A,255 62 255
CP H 188
JR NZ,L_JUMP 32 177
CP 1 189
JR NZ,L_JUMP 32 174
RET 201
SUBR PUSH BC 197
PUSH DE 213
LD A,175 62 175
SUB H 148
LD H,A 103
PUSH HL 229
AND 7 230 7
ADD A,64 198 64
LD C,A 79
LD A,H 124
RRA 203 31
RRA 203 31
RRA 203 31
AND 31 203 31
LD B,A 71
AND 24 230 24
LD D,A 87
LD A,H 124
AND 192 230 192
LD E,A 95
LD H,C 97
LD A,L 125
RRA 203 31
RRA 203 31
147.
RRA 203 31
AND 31 203 31
LD L,A 111
LD A,E 123
ADD A,B 128
SUB D 146
LD E,A 95
LD D,0 22 0
PUSH HL 229
PUSH DE 213
POP HL 225
ADD HL,HL 41
ADD HL,HL 41
ADD HL,HL 41
ADD HL,HL 41
ADD HL,HL 41
POP DE 209
ADD HL,DE 25
POP DE 209
LD A,E 123
AND 7 230 7
LD B,A 71
LD A,8 62 8
SUB B 144
LD B,A 71
LD A,1 62 1
ROTARE ADD A,A 135
DJNZ ROTARE 16 253
RRA 203 31
POP DE 209
POP BC 193
RET 201
2
Как она работает:
Эта программа вычерчивает го-
ризонтальные линии из смежных
пикселей. Назовем их строчками.
Предел заполнения области строч-
ками ограничен включенными (ON)
пикселями. Каждая строчка запо-
минается с помощью занесения в
стек координат крайнего правого
пикселя этой строчки.
Запускаясь с определенных
координат, программа делает за-
полнение в каждой строчке, отме-
чая позиции каждой из невыпол-
ненных строчек выше или ниже. По
завершении одной строчки послед-
нее значение отмеченных коорди-
нат восстанавливается и для
соответствующей строчки происхо-
дит заполнение. Этот процесс
повторяется до тех пор, пока не
останется незаполненных строчек.
Рис.2 иллюстрирует технику
процесса. Квадраты представляют
пиксели, X обозначает стартовую
позицию в пределах области штри-
ховки, а * обозначает крайние
правые пиксели строчек.
┌───────────────────────────────────────────────┐
│ ┌────╥────╥────╥────╥────╥────╥────╥────┐ │
│ │////║////║////║////║////║////║////║////│ │
│ ╞════╬════╬════╬════╬════╬════╬════╬════╡ │
│ │////║ 0 ║////║ ║ * ║////║////║////│ │
│ ╞════╬════╬════╬════╬════╬════╬════╬════╡ │
│ │////║ 0 ║////║ ║ X ║ ║ ║////│ │
│ ╞════╬════╬════╬════╬════╬════╬════╬════╡ │
│ │////║////║////║ ║ ║ ║ * ║////│ │
│ ╞════╬════╬════╬════╬════╬════╬════╬════╡ │
│ │////║ ║ ║ * ║////║ ║ * ║////│ │
│ ╞════╬════╬════╬════╬════╬════╬════╬════╡ │
│ │////║ ║ * ║////║////║////║ * ║////│ │
│ ╞════╬════╬════╬════╬════╬════╬════╬════╡ │
│ │////║ ║ * ║////║////║////║ * ║////│ │
│ ╞════╬════╬════╬════╬════╬════╬════╬════╡ │
│ │////║////║////║////║////║////║////║////│ │
│ └────╨────╨────╨────╨────╨────╨────╨────┘ │
│ Рис.2. Иллюстрация техники заполнения области │
│ X - стартовая позиция, * - начало строчек, │
│ 0 - оставшаяся незаштрихованная область │
└───────────────────────────────────────────────┘
Программа штрихует горизон-
тальную линию, содержащую стар-
товую позицию, и сохраняет в
стеке позицию начала строчки на
линиях непосредственно выше и
ниже. Далее она штрихует линию
выше, а затем ниже, отмечая в
последнем случае, что еще две
строчки запускаются на следую-
щей нижней строке и т.д. Любая
позиция в пределах области для
штриховки может быть выбрана как
стартовая позиция. Но заметим,
что два пикселя, промаркирован-
ные нулями, нетронуты, т.к. они
отделены от заштриховываемой об-
ласти.
В регистр H загружается Y-ко-
ордината, а в L-регистр - X-ко-
ордината. Если значение Y больше
чем 175, программа возвращается
в BASIC. Процедура SUBR вызыва-
ется, возвращая адрес бита (X,Y)
в память. Если этот бит в состо-
янии ON (включен), подпрограмма
возвращается в BASIC.
Число 65535 помещается в стек,
чтобы отметить первое сохранен-
ное значение. Позднее, когда
число восстанавливается из сте-
ка, оно интерпретируется, как
пара координат. Однако, если
число равно 65535, происходит
возврат в BASIC, т.к. программа
закончена.
В регистр H загружается Y-ко-
ордината, а в регистр L - X-ко-
ордината. Процедура SUBR вызыва-
ется, возвращая в HL адрес бита
(X,Y). Если этот бит установлен
(ON), происходит переход к LEFT.
Иначе X-координата увеличивается
и делается переход к RIGHT, если
X не равен 256.
В процедуре LEFT DE устанавли-
вается в 0. Регистры D и E ис-
пользуются как флаги: D - вниз
(DOWN), E - вверх (UP). X-коор-
дината уменьшается. SUBR вызы-
вается и вычерчивается точка
(X,Y). Если Y-координата равна
175, подпрограмма переходит к
DOWN. Если флаг ВВЕРХ установ-
лен, происходит переход к RESET.
Если бит (X,Y+1) сброшен, значе-
ние X и Y+1 сохраняется в стеке
и флаг ВВЕРХ включается.
В процедуре RESET, если флаг
ВВЕРХ включен, происходит пере-
ход к DOWN. Если бит (X,Y+1)
включен (ON), флаг ВВЕРХ выклю-
чается. В процедуре DOWN, если
Y-координата равна 0, происхо-
дит переход к NEXT_PIXEL. Если
флаг ВНИЗ включен, происходит
переход к REST. Если бит (X,Y-1)
сброшен (OFF), то значения X и
Y-1 сохраняются на стеке и флаг
ВНИЗ включается.
В процедуре REST, если флаг
ВНИЗ выключен, происходит пере-
ход к NEXT_P. Если бит (X,Y-1)
установлен (ON), то флаг ВНИЗ
выключается. В процедуре NEXT_P,
если X-координата равна 0, под-
программа переходит к RETR.
X-координата уменьшается и если
новый бит (X,Y) сброшен (OFF),
происходит переход к PLOT. В
процедуре RETR X- и Y-координа-
ты извлекаются из стека. Если X
и Y равны 255, то - возврат в
BASIC, т.к. заполнение области
завершено. Иначе подпрограмма
возвращается в RIGHT.
Процедура SUBR должна подсчи-
тать адрес бита (X,Y) в памяти.
В BASIC этот адрес будет:
16384 + INT(Z/8) + 256 * (Z - 8
* INT(Z/8)) + 32 * (64 * INT(Z/
64) + INT(Z/8) - 8 * INT(Z/64))
где Z=175-Y.
Пары регистров BC и DE сохра-
няются на стеке. В аккумулятор
засылается число 175, и из этого
значения вычитается Y-коодина-
та. Результат копируется в H-ре-
гистр. Затем HL сохраняется на
стеке. Пять левых битов аккуму-
лятора устанавливаются в 0, а
затем к ним прибавляется 64. Ре-
зультат копируется в C-регистр.
При умножении на 256 получаем:
16384+256*(Z-8*INT(Z/8))
В аккумулятор загружается Z,
это значение делится на 8, ре-
зультат копируется в регистр B.
Этот результат - INT(Z/8). Уста-
новка трех крайних правых битов
в 0 при ротации дает значение
8*INT(Z/64), которое загружает-
ся в D-регистр.
В аккумулятор загружается Z и
6 крайних правых битов выклю-
чается, что дает 64*INT(Z/64).
Это значение загружается в E-ре-
гистр. Значение из C-регистра
копируется в H. В аккумулятор
загружается X-координата, это
значение делится на 8, а ре-
зультат копируется в L.
В аккумулятор затем загружает-
ся значение E-регистра и к нему
прибавляется содержимое B. Зна-
чение D-регистра вычитается и
результат загружается в DE. Это
значение умножается на 32, DE
восстанавливается из стека и
прибавляется к HL. Т.о. HL те-
перь хранит адрес бита (X,Y).
В аккумулятор загружается пер-
воначальное значение X. Установ-
ка пяти левых битов в ноль дает
значение X-8*INT(X/8). В B-ре-
гистр затем загружается 8 минус
значение аккумулятора, чтобы ис-
пользовать его в качестве счет-
чика. Аккумулятор устанавливает-
ся в 1 и это умножается на 2
(B-1) раз.
В этот момент в аккумуляторе
необходимо установить бит, кото-
рый соответствует биту (X,Y) с
адресом в HL. DE и BC затем вос-
станавливаются из стека, и SUBR
выполняет возврат в основную
программу.
6.9. Построение шаблонов
Длина: 196
Количество переменных: 2
Контрольная сумма: 20278
Назначение: эта программа чер-
тит шаблон любого размера на эк-
ране. Под шаблоном понимается
любая, ранее определенная фигура.
Переменные:
Имя: X_start
Длина: 1
Ячейка: 23296
Комментарий: X-координата пер-
вого пикселя.
Имя: Y_start
Длина: 1
Ячейка: 23297
Комментарий: Y-координата пер-
вого пикселя.
Вызов программы:
RANDOMIZE USR адрес
Контроль ошибок: если строко-
вая переменная, хранящая инфор-
мацию по шаблону A$, не сущес-
твует, имеет нулевую длину или
не содержит никакой информации,
программа возвращается непосред-
ственно в BASIC. Это происходит
также в случае, если Y-start
больше, чем 175.
Комментарий: это полезная
программа для хранения фигур в
памяти и быстрого вычерчивания
их на экране.
Использование этой программы:
(I) LET A$ = "информация по
шаблону"
(II) POKE 23296, X-координата
первого пикселя
(III) POKE 23297, Y-координата
первого пикселя
(IV) RANDOMIZE USR адрес
Информация шаблона - это сим-
вол, который имеет следующий
формат:
"0" - поместить точку
"5" - уменьшить X-координату
"6" - уменьшить Y-координату
"7" - увеличить X-координату
"8" - увеличить Y-координату
Любые другие символы игнори-
руются. Программа включает в се-
бя возможность "wrap-round",
т.е., если X-координата выходит
за левую часть экрана, шаблон
появляется справа и т.п.
Чтобы изменить программу для
использования иной строковой пе-
ременной вместо A$, нужно изме-
нить 65* (код буквы A) на код
иного символа.
ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА АССЕМБЛЕР ЧИСЛА ДЛЯ ВВОДА
147.
LD HL,(23627) 42 75 92
NEXT_V LD A,(HL) 126
CP 128 254 128
RET Z 200
BIT 7,A 203 127
JR NZ,FORNXT 32 23
CP 96 254 96
JR NC,NUMBER 48 11
CP 65 254 65*
JR Z,FOUND 40 35
STRING INC HL 35
LD E,(HL) 94
INC HL 35
LD D,(HL) 86
ADD ADD HL,DE 25
JR INCR 24 5
NUMBER INC HL 35
INC HL 35
INC HL 35
INC HL 35
INC HL 35
INCR INC HL 35
JR NEXT_V 24 225
FORNXT CP 224 254 224
JR C,N_BIT 56 5
LD DE,18 17 18 0
JR ADD 24 236
N_BIT BIT 5,A 203 111
JR Z,STRING 40 228
NEXT_B INC HL 35
BIT 7,(HL) 203 126
JR Z,NEXT_B 40 251
JR NUMBER 24 228
FOUND INC HL 35
LD C,(HL) 78
INC HL 35
LD B,(HL) 70
INC HL 35
EX DE,HL 235
LD A,(23297) 58 1 91
CP 176 254 176
RET NC 208
AGAIN LD HL,(23296) 42 0 91
LD A,B 120
OR C 177
RET Z 200
DEC BC 11
LD A,(DE) 26
INC DE 19
CP 48 254 48
JR NZ,NOT_PL 32 78
PUSH BC 197
PUSH DE 213
LD A,175 62 175
SUB H 148
LD H,A 103
PUSH HL 229
AND 7 230 7
ADD A,64 198 64
LD C,A 79
LD A,H 124
147.
RRA 203 31
RRA 203 31
RRA 203 31
AND 31 230 31
LD B,A 71
AND 24 230 24
LD D,A 87
LD A,H 124
AND 192 230 192
LD E,A 95
LD H,C 97
LD A,L 125
RRA 203 31
RRA 203 31
RRA 203 31
AND 31 230 31
LD L,A 111
LD A,E 123
ADD A,B 128
SUB D 146
LD E,A 95
LD D,0 22 0
PUSH HL 229
PUSH DE 213
POP HL 225
ADD HL,HL 41
ADD HL,HL 41
ADD HL,HL 41
ADD HL,HL 41
ADD HL,HL 41
POP DE 209
ADD HL,DE 25
POP DE 209
LD A,E 123
AND 7 230 7
LD B,A 71
LD A,8 62 8
SUB B 144
LD B,A 71
LD A,L 62 1
ROTARE ADD A,A 135
DJNZ ROTARE 16 253
RRA 203 31
POP DE 209
POP BC 193
OR (HL) 182
LD (HL),A 119
HERE JR AGAIN 24 165
NOT_PL CP 53 254 53
JR NZ,DOWN 32 1
DEC 1 45
DOWN CP 54 254 54
JR NZ,UP 32 8
DEC H 37
LD H,A 124
CP 255 254 255
JR NZ,SAVE 32 19
LD H,175 38 175
CP 55 254 55
JR NZ,RIGHT 32 8
INC H 36
LD A,H 124
CP 176 254 176
JR NZ,SAVE 32 7
LD H,0 38 0
RIGHT CP 56 254 56
JR NZ,SAVE 32 1
INC 1 44
SAVE LD (23296),HL 34 0 91
JR HERE 24 215
2
Как она работает:
Для нахождения адреса строко-
вой переменной используется не-
много измененная первая часть
программы "Поиск подстроки".
Длина строковой переменной
загружается в BC, а адрес перво-
го символа A$ загружается в DE.
В аккумуляторе устанавливается
начальное значение Y и, если оно
больше 175, подпрограмма возвра-
щается в BASIC. В H-регистр заг-
ружается Y-координата, а в L -
X-координата. Если значение па-
ры регистров BC равно 0, под-
программа возвращается в BASIC,
т.к. достигнут конец строковой
переменной. BC уменьшается, что-
бы показать, что обрабатывается
следующий символ. Следующий сим-
вол загружается в аккумулятор и
DE увеличивается, указывая на
следующий байт. Если аккумуля-
тор не содержит код 48, происхо-
дит переход к NOT_PL. Точка
(X,Y) вычерчивается, используя
процедуру SUBR из программы
"Закрашивание контура". Затем
программа возвращается назад к
AGAIN.
В процедуре NOT_PL, если акку-
мулятор содержит число 53,
X-координата уменьшается. В про-
цедуре DOWN, если аккумулятор не
содержит число 54, делается пе-
реход к UP. Y-координата умень-
шается, и, если ее значение ста-
новится равным -1, Y-координата
устанавливается на значение 175.
В процедуре UP, если аккумуля-
тор не содержит 55, происходит
переход к RIGHT. Y-координата
увеличивается, и, если она равна
176, то Y-координата устанавли-
вается в 0. В процедуре RIGHT,
если аккумулятор содержит значе-
ние 56, X-координата увеличи-
вается. В процедуре SAVE коорди-
наты X и Y помещаются в память,
а программа делает переход к
HERE.
* * *