ZX Review
#5-6
04 ноября 1997 |
|
Ретро - 40 лучших процедур: Слияние картинок, Вращение символа по часовой стрелке, Инвертирование символов, Изменение атрибута, Закрашивание контура, Построение шаблонов (Дж.Хардман, Э.Хьюзон.).
┌──────────────────────────────┐ │ │ │ РЕТРО │ │ │ └──────────────────────────────┘ Дж.Хардман, Э.Хьюзон 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. * * *
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября