3.5. Масштабное увеличение текста.
Печать по горизонтали.
Удвоение размеров символов на "Спектруме" имеет в своей
основе очень простые принципы. Представим, что символ помещен
на сетку 8Х8 пикселов. Тогда при переносе его на сетку 16Х16
программа должна найти включенный пиксел и вместо него
напечатать два пиксела по горизонтали и два по вертикали.
Приведенная ниже программа использует этот подход для
того, чтобы изобразить символами двойного размера заданную
символьную строку. Процедура FN d(x,y) выполняет печать текста
по горизонтали символами двойной ширины и двойной высоты. Здесь
x и y задают начальное знакоместо для печати текста.
Процедура FN d(x,y) имеет длину 220 байтов. В конце этой
процедуры отводятся еще несколько байтов для размещения в них
программных переменных. Мы выбрали для этой процедуры начальным
адресом 62200, а память, начиная с адреса 62500 по 62599 выде-
лили в качестве буфера, в котором хранится текст сообщения,
подлежащего печати. Текст хранится здесь в виде последователь-
ности символов и отправляется туда из БЕЙСИКа при посредстве
символьной переменной n$.
10 REM *** Загрузчик машинного кода
20 LET adr=62200: LET long=220: LET z=0
30 FOR i=0 TO long-1: READ a
40 POKE (adr+i),a: LET z=z+a
50 NEXT i
60 LET z=INT (((z/long)-INT (z/long))*long)
70 READ a
80 IF a<>z THEN PRINT "??": STOP
90 REM *** Пример использования процедуры
100 DEF FN d(x,y)=USR 62200
110 BORDER 1: PAPER 6: INK 1: CLS
120 FOR i=0 TO 13
130 DRAW 255,0: DRAW 0,6
140 DRAW -255,0: DRAW 0,6
150 NEXT i
160 DRAW 255,0
170 LET n$="SPECTRUM"
180 GO SUB 230
190 FOR m=1 TO 22 STEP 4
200 RANDOMIZE FN d(x,y)
210 NEXT m
220 PAUSE 0
230 LET t=LEN(n$)
240 LET k=62499
250 FOR i=1 TO t
260 LET n=CODE n$(i)
270 POKE k+i,n
280 NEXT i
290 POKE k+i,13
299 RETURN
300 REM *** Данные для машинного кода
310 DATA 42, 11, 92, 1, 4
320 DATA 0, 9, 86, 1, 8
330 DATA 0, 9, 94, 237, 83
340 DATA 240, 243, 62, 99, 71
350 DATA 33, 36, 244, 34, 244
360 DATA 243, 197, 237, 91, 240
370 DATA 243, 62, 30, 186, 242
380 DATA 37, 243, 22, 0, 28
390 DATA 28, 237, 83, 240, 243
400 DATA 62, 20, 187, 250, 111
410 DATA 243, 42, 244, 243, 126
420 DATA 35, 34, 244, 243, 254
430 DATA 31, 250, 111, 243, 254
440 DATA 144, 242, 111, 243, 214
450 DATA 32, 1, 8, 0, 42
460 DATA 54, 92, 36, 9, 61
470 DATA 32, 252, 34, 242, 243
480 DATA 123, 230, 24, 246, 64
490 DATA 103, 123, 230, 7, 183
500 DATA 31, 31, 31, 31, 130
510 DATA 111, 34, 238, 243, 205
520 DATA 113, 243, 58, 241, 243
530 DATA 60, 60, 50, 241, 243
540 DATA 193, 16, 164, 201, 193
550 DATA 201, 17, 206, 243, 6
560 DATA 32, 62, 0, 18, 19
570 DATA 16, 252, 237, 91, 242
580 DATA 243, 33, 206, 243, 6
590 DATA 8, 197, 26, 1, 2
600 DATA 4, 197, 23, 245, 203
610 DATA 22, 241, 203, 22, 16
620 DATA 247, 35, 193, 13, 32
630 DATA 241, 43, 126, 245, 43
640 DATA 126, 35, 35, 119, 35
650 DATA 241, 119, 35, 19, 193
660 DATA 16, 220, 42, 238, 243
670 DATA 17, 206, 243, 14, 2
680 DATA 229, 6, 8, 26, 119
690 DATA 35, 19, 26, 119, 19
700 DATA 43, 36, 16, 245, 225
710 DATA 62, 32, 133, 111, 48
720 DATA 4, 62, 8, 132, 103
730 DATA 13, 32, 228, 201, 0
740 DATA 0, 0, 0, 0, 0
Дисассемблер программы:
62200 2A0B5C LD HL,(5C0BH) ;См. с.109...111.
62203 010400 LD BC,0004 ;Сдвиг от DEFADD на 4 бай-
62206 09 ADD HL,BC ;та (см. c.109...111).
62207 56 LD D,(HL) ;Координата x.
62208 010800 LD BC,0008 ;Сдвиг от DEFADD еще на 8
62211 09 ADD HL,BC ;байтов (см.c.109...111).
62212 5E LD E,(HL) ;Координата y.
62213 ED53F0F3 LD(COOR_Y),DE ;Переброска параметров y
;и x в адреса 62448,62449
62217 3E63 LD A,63 ;63H=99DEC - количество
;символов в сообщении.
62219 47 LD B,A ;Счетчик символов.
62220 2124F4 LD HL,F424 ;F424H=62500DEC- началь-
;ный адрес сообщения.
62223 22F4F3 LD (POINT),HL ;По адресу 62452 создали
;переменную-указатель на
;адрес печатаемого символа
62226 C5 LOOP_M PUSH BC ;Сохранение счетчика на
;стеке.
62227 ED5BF0F3 LD DE,(COOR_Y) ;Координаты y,x.
62231 3E1E LD A,1E ;Предел по x=31.
62233 BA CP D ;Сравнили x и 31.
62234 F225F3 JP P,SKIP_1 ;Если все O.K. - переход
;на SKIP_1, иначе обнуля-
62237 1600 LD D,00 ;ем x и увеличиваем на 2
62239 1C INC E ;значение y, т.е. перехо-
62240 1C INC E ;дим на новую строку.
62241 ED53F0F3 LD(COOR_Y),DE ;Запоминаем текущую коор-
;динату позиции печати.
62245 3E14 SKIP_1 LD A,14 ;Проверка
62247 BB CP E ;на y < 21.
62248 FA6FF3 JP M,EXIT ;Если y>=21 - выход.
62251 2AF4F3 LD HL,(POINT) ;Адрес символа, подлежа-
;щего печати.
62254 7E LD A,(HL) ;Взяли этот символ,
62255 23 INC HL ;наметили следующий
62256 22F4F3 LD (POINT),HL ;и передвинули указатель.
62259 FE1F CP 1F ;Если код символа меньше
62261 FA6FF3 JP M,EXIT ;32 или больше 143,
62264 FE90 CP 90 ;выполняется выход через
62266 F26FF3 JP P,EXIT ;метку EXIT.
62269 D620 SUB 20 ;Из кода символа вычита-
;ется 32.
62271 010800 LD BC,0008 ;На каждый символ расходу-
;ется 8 байтов.
62274 2A365C LD HL,(5C36) ; = 23606 - адрес систем-
;ной переменной CHARS (см.
;стр.65).
62277 24 INC H ;Теперь HL указывает точно
;на первый символ систем-
;ного набора.
62278 09 LOOP_C ADD HL,BC ;Теперь на второй символ и
;т.д,
62279 3D DEC A ;Когда в аккумуляторе бу-
62280 20FC JR NZ,LOOP_C ;дет 0, HL укажет точно на
;нужный нам символ, равный
;тому, на который в данный
;момент указывает указа-
;тель POINT.
62282 22F2F3 LD (CH_ADD),HL ;Запомнили адрес начала его
;шаблона в ПЗУ компьютера.
62285 7B LD A,E ;¦
62286 E618 AND 18 ;¦ Расчет адреса по
62288 F640 OR 40 ;¦ координатам.
62290 67 LD H,A ;¦
62291 7B LD A,E ;¦
62292 E607 AND 07 ;¦
62294 B7 OR A ;¦
62295 1F RRA ;¦
62296 1F RRA ;¦
62297 1F RRA ;¦
62298 1F RRA ;¦
62299 82 ADD A,D ;¦
62300 6F LD L,A ;¦
62301 22EEF3 LD(ROWCOL),A ;Эта переменная
;содержит адрес в дисплей-
;ном файле, соответствую-
;щий начальной линии изо-
;бражаемого символа.
62304 CD71F3 CALL DOUBL ;Вызов подпрограммы, вы-
;полняющей непосредственно
;печать символов двойной
;ширины и высоты.
62307 3AF1F3 LD A,(COOR_X) ;Увеличиваем на 2
62310 3C INC A ;указатель координаты
62311 3C INC A ;по горизонтали
62312 32F1F3 LD (COOR_X),A ;и запоминаем новую пози
;цию печати.
62315 C1 POP BC ;Восстановили счетчик
;символов.
62316 10A4 DJNZ, LOOP_M ;Если не все символы напе-
;чатаны, возврат.
62318 C9 RET ;Генеральный выход из
;процедуры.
62319 C1 EXIT POP BC ;Перед аварийным выходом
;очищаем стек.
62320 C9 RET ;Аварийный выход, если
;параметр y не в допуске
;или символ - непечатный.
Процедура DOUBLE.
Если до сих пор шли подготовительные операции, то сам ал-
горитм удвоения изображения символа реализован именно в этой
процедуре (мы назвали ее DOUBLE). Основной принцип действия ее
состоит в том, что каждому символу соответствует восьмибайтный
шаблон в ПЗУ - на него указывает пара регистров DE. Строка за
строкой шаблона (байт за байтом) могут быть скопированы в акку-
мулятор. В то же время, в оперативной памяти создается времен-
ный рабочий буфер размером 32 байта для удвоенного символа. На
начало этого буфера указывает регистровая пара HL. Теперь
задача сводится к тому, чтобы бит за битом (пиксел за пикселом)
перенести рисунок из аккумулятора A в буфер (HL), при этом
одному пикселу (биту) в A должны соответствовать два бита в
буфере.
Здесь это сделано оригинальным приемом с помощью операций
RLA и RL (HL). Причем на одну операцию RLA приходятся две
операции RL (HL). Те, кто знакомы с этими операциями по нашей
книге "Первые шаги в машинном коде", знают, что все биты
смещаются влево. При этом старший (седьмой) бит поступает в
флаг C регистра F, а то, что там было перед операцией,
отправляется в нулевой бит. Таким образом, через флаг C
происходит копирование с удвоением из аккумулятора в буфер.
Чтобы во время операции RL (HL) не искажалось содержимое флага
C, принятое из аккумулятора, оно запоминается на стеке PUSH AF
и восстанавливается, когда ротация завершена - POP AF.
Рассмотрим пример:
Флаг C Аккумулятор Буфер
Исходно: 0 10101010 00000000
Шаг 1
RLA 1 01010100 00000000
PUSH AF 1 01010100 00000000
RL (HL) 0 01010100 00000001
POP AF 1 01010100 00000001
RL (HL) 0 01010100 00000011
Шаг 2
RLA 0 10101000 00000011
PUSH AF 0 10101000 00000011
RL (HL) 0 10101000 00000110
POP AF 0 10101000 00000110
RL (HL) 0 10101000 00001100
Шаг 3
RLA 1 01010000 00001100
PUSH AF 1 01010000 00001100
RL (HL) 0 01010000 00011001
POP AF 1 01010000 00011001
RL (HL) 0 01010000 00110011
И так далее ....
Как видите, четырех шагов достаточно, чтобы скопировать
пол-байта шаблона в один байт буфера. Еще четыре шага - и одной
строке шаблона будет соответствовать двухбайтная пара в буфере.
Теперь рассмотрим саму процедуру DOUBLE.
62321 11CEF3 DOUBL LD DE,BUFFER ;Адрес 62414.
62324 0620 LD B,20 ;Счетчик цикла = 32.
62326 3E00 LD A,00 ;
62328 12 LOOP_H LD (DE),A ;Цикл, обнуляющий
62329 13 INC DE ;буфер.
62330 10FC DJNZ FC LOOP_H ;Конец цикла.
62332 ED5BF2F3 LD DE,(CH_ADD) ;DE указывает на шаблон
;текущего печатаемого
;символа.
62336 21CEF3 LD HL,BUFFER ;HL указывает на начало
;буфера.
62339 0608 LD B,08 ;Счетчик по 8.
62341 C5 LOOP_X PUSH BC ;Запомнили его на стеке.
62342 1A LD A,(DE) ;Приняли линию шаблона
;текущего символа.
62343 010204 LD BC,0402 ;Организовали два счетчика
;- на 2 шага в регистре C
;и на 4 шага - в B.
62346 C5 AGAIN PUSH BC ;Запомнили их на стеке.
62347 17 LOOP_S RLA ;Приняли бит аккумулятора
;во флаг C.
62348 F5 PUSH AF ;Запомнили флаг C.
62349 CB16 RL (HL) ;Приняли этот бит из фла-
;га C - в буфер.
62351 F1 POP AF ;Восстановили флаг C
62352 CB16 RL (HL) ;и приняли его еще раз.
62354 10F7 DJNZ LOOP_S ;Возврат в начало цикла,
;пока не сделаем 4 про-
;хода для заполнения од-
;ного байта в буфере.
62356 23 INC HL ;Перешли ко 2-му байту
;буфера.
62357 C1 POP BC ;Вновь в регистре B уста-
;новили счетчик на 4 про-
;хода,
62358 0D DEC C ;но уменьшили счетчик в C.
62359 20F1 JR NZ,AGAIN ;Возврат, если второй байт
;буфера еще не заполнен.
К этому моменту мы как бы удвоили одну строку шаблона по
горизонтали и вместо 8 битов имеем в буфере соответствующие ей
16 битов (2 байта). Но нам надо удвоить эту строку и по
вертикали. Поэтому в третий и четвертый байты буфера заполняем
копией первого и второго.
62361 2B DEC HL ;Возвращаемся ко второму
;байту буфера.
62362 7E LD A,(HL) ;Взяли его в аккумулятор
62363 F5 PUSH AF ;и запомнили на стеке.
62364 2B DEC HL ;Возвращаемся к 1-ому
;байту буфера.
62365 7E LD A,(HL) ;Взяли его в аккумулятор.
62366 23 INC HL ;Переход ко 2-ому байту.
62367 23 INC HL ;Переход к 3-му байту.
62368 77 LD (HL),A ;Копирование 1-го байта
;в третий.
62369 23 INC HL ;Переход к 4-му байту.
62370 F1 POP AF ;Восстановление 2-го
;байта.
62371 77 LD (HL),A ;Копирование его в
;четвертый байт.
Итак, мы скопировали одну строку шаблона символа в четыре
байта буфера. Но у нас есть 8 строк у символа и их тоже надо
так же скопировать.
62372 23 INC HL ;Переход к очередному
;байту буфера.
62373 13 INC DE ;Переход к очередной
;строке шаблона.
62374 C1 POP BC ;Восстановление счет-
;чика строк шаблона.
62375 10DC DJNZ LOOP_X ;Если не все строки еще
;обработаны, то возврат.
Итак, мы скопировали все 8 строк шаблона в 32-байтный бу-
фер. Теперь настало время поместить изображение удвоенного
символа на экран, то есть надо скопировать биты из буфера в
дисплейный файл (с учетом координат позиции печати). Сама эта
операция достаточно тривиальна. Регистровая пара HL является
указателем на адрес в дисплейном файле, пара DE - указывает на
адрес в буфере. Организуется счетчик цикла в C = 2 по рядам
экрана и внутренний в B = 8 по линиям пикселов в ряду. Единст-
венный нюанс - необходимость после печати первого ряда прове-
рить не произошел ли переход через границы текущего сегмента
экрана и соответственно отреагировать изменением содержимого
указателя в HL.
62377 2AEEF3 LD HL,(ROWCOL) ;Адрес в экранном файле.
62380 11CEF3 LD DE,BUFFER ;Адрес буфера.
62383 0E02 LD C,02 ;Счетчик рядов экрана.
62385 E5 LOOP_F PUSH HL
62386 0608 LD B,08 ;Счетчик линий в ряду.
62388 1A LOOP_Y LD A,(DE) ;Переброска линии из
62389 77 LD (HL),A ;буфера на экран (не-
;четной).
62390 23 INC HL ;Сдвиг вправо.
62391 13 INC DE
62392 1A LD A,(DE) ;Переброска четной линии
62393 77 LD (HL),A ;из буфера на экран.
62394 13 INC DE
62395 2B DEC HL ;Сдвиг на знакоместо
;влево.
62396 24 INC H ;Переход к следующей
;линии.
62397 10F5 DJNZ LOOP_Y ;Повтор для 8 пар линий.
62399 E1 POP HL
62400 3E20 LD A,20 ;Переход к следующему
62402 85 ADD A,L ;ряду знакомест
62403 6F LD L,A ;на экране.
62404 3004 JR NC,SKIP_4 ;Проверка не вышли ли
;за границы текщего эк-
;ранного сегмента.
62406 3E08 LD A,08 ;Если да, то переход
62408 84 ADD A,H ;к следующему сегменту
62409 67 LD H,A ;увеличением H на 8.
62410 0D SKIP_4 DEC C
62411 20E4 JR NZ,LOOP_F ;Повтор для 2-х рядов.
62413 C9 RET ;Возврат в вызывающую
процедуру.
62414 BUFFER DEFM
62446 ROWCOL DEFW
62448 COOR_Y DEFB
62449 COOR_X DEFB
62450 CH_ADD DEFW
62452 POINT DEFW
62500 MESSAG DEFL
3.6. Масштабное увеличение текста.
Печать по вертикали.
Эта программа работает примерно так же, как и предыдущая,
но печать сообщения выполняется по вертикали. Точно также
здесь требуется ввести в память компьютера текстовое сообщение,
подлежащее выдаче на экран. Это выполняется в строках 220...290
демонстрационной БЕЙСИК-программы.
Назовем эту программу - FN e (x,y). Здесь x,y - координаты
исходной позиции печати. Длина всей программы - 215 байтов, на-
чальный адрес - 61900.
Поскольку символы имеют удвоенный размер, в высоту экрана
укладываются только 12 символов. Программа не имеет возможнос-
ти переноса текста и, если Вам надо напечатать сообщение более
длинное, то надо ее вызывать несколько раз. Если в Вашем сооб-
щении используется пробел, то вместо него подставьте графичес-
кий символ, находящийся на клавише "8". Демонстрационная прог-
рамма использует в своей работе также и ранее рассмотренную
нами программу FN c (x,y,h,v,c,b,f) для цветового оформления
экрана перед печатью текста.
10 REM *** Загрузчик машинного кода
20 LET adr=61900: LET long=210: LET z=0
30 FOR i=0 TO long-1: READ a
40 POKE (adr+i),a: LET z=z+a
50 NEXT i
60 LET z=INT (((z/long)-INT (z/long))*long)
70 READ a
80 IF a<>z THEN PRINT "??": STOP
90 REM *** Пример использования процедуры
100 DEF FN c(x,y,h,v,c,b,f)=USR 62600
110 DEF FN e(x,y)=USR 61900
120 BORDER 1: PAPER 0: INK 0: CLS
130 LET n$="Spectrum"
140 GO SUB 220
150 LET pap=1
160 FOR k=5 TO 25 STEP 4
170 RANDOMIZE FN c(k-1,2,4,19,pap,0,0)
180 RANDOMIZE FN e(x,3)
190 LET pap=pap+1
200 NEXT k
210 STOP
220 LET m=LEN(n$)
230 LET s=62499
240 FOR k=1 TO m
250 LET n=CODE n$ (k)
260 POKE s+k,n
270 NEXT k
280 POKE s+k,13
290 RETURN
300 REM *** Данные для машинного кода
310 DATA 42, 11, 92, 1, 4
320 DATA 0, 9, 86, 1, 8
330 DATA 0, 9, 94, 237, 83
340 DATA 191, 242, 62, 99, 71
350 DATA 33, 36, 244, 34, 195
360 DATA 242, 197, 237, 91, 191
370 DATA 242, 62, 30, 186, 242
380 DATA 244, 241, 195, 62, 242
390 DATA 62, 20, 187, 250, 62
400 DATA 242, 42, 195, 242, 126
410 DATA 35, 34, 195, 242, 254
420 DATA 31, 250, 62, 242, 254
430 DATA 144, 242, 62, 242, 214
440 DATA 32, 1, 8, 0, 42
450 DATA 54, 92, 36, 9, 61
460 DATA 32, 252, 34, 193, 242
470 DATA 123, 230, 24, 246, 64
480 DATA 103, 123, 230, 7, 183
490 DATA 31, 31, 31, 31, 130
500 DATA 111, 34, 189, 242, 205
510 DATA 64, 242, 58, 191, 242
520 DATA 60, 60, 50, 191, 242
530 DATA 193, 16, 169, 201, 193
540 DATA 201, 17, 157, 242, 6
550 DATA 32, 62, 0, 18, 19
560 DATA 16, 252, 237, 91, 193
570 DATA 242, 33, 157, 242, 6
580 DATA 8, 197, 26, 1, 2
590 DATA 4, 197, 23, 245, 203
600 DATA 22, 241, 203, 22, 16
610 DATA 247, 35, 193, 13, 32
620 DATA 241, 43, 126, 245, 43
630 DATA 126, 35, 35, 119, 35
640 DATA 241, 119, 35, 19, 193
650 DATA 16, 220, 42, 189, 242
660 DATA 17, 157, 242, 14, 2
670 DATA 229, 6, 8, 26, 119
680 DATA 35, 19, 26, 119, 19
690 DATA 43, 36, 16, 245, 225
700 DATA 62, 32, 133, 111, 48
710 DATA 4, 62, 8, 132, 103
720 DATA 13, 32, 228, 201, 0
730 DATA 0, 0, 0, 0, 0
Дисассемблер программы:
61900 2A0B5C LD HL,(5C0BH) ;См. с. 109...111.
61903 010400 LD BC,0004 ;Сдвиг от DEFADD на 4 бай-
61906 09 ADD HL,BC ;та (см. c.109...111).
61907 56 LD D,(HL) ;Координата x.
61908 010800 LD BC,0008 ;Сдвиг от DEFADD еще на 8
61911 09 ADD HL,BC ;байтов (см.c.109...111).
61912 5E LD E,(HL) ;Координата y.
61913 ED53BFF2 LD(COOR_Y),DE ;Переброска параметров y
;и x в адреса 62143,62144
61917 3E63 LD A,63 ;63H=99DEC - размер буфе-
;ра под сообщение.
61919 47 LD B,A ;Счетчик символов.
61920 2124F4 LD HL,BUFFER ;F424H=62500DEC- началь-
;ный адрес буфера сообще-
;ния (используется тот же
;буфер, что и в предыду-
;щей программе).
61923 22C3F2 LD (POINT),HL ;По адресу 62147 создали
;переменную-указатель на
;адрес печатаемого символа
61926 C5 LOOP_M PUSH BC ;Сохранение счетчика на
;стеке.
61927 ED5BBFF2 LD DE,(COOR_Y) ;Координаты y,x.
61931 3E1E LD A,1E ;Предел по x=31.
61933 BA CP D ;Сравнили x и 31.
61934 F2F4F1 JP P,SKIP_1 ;Если все O.K. - переход
;на SKIP_1,
61937 C33EF2 JP EXIT ;иначе - аварийный выход.
61940 3E14 SKIP_1 LD A,14 ;Проверка
61942 BB CP E ;на y < 21.
61943 FA3EF2 JP M,EXIT ;Если y>=21 - выход.
61946 2AC3F2 LD HL,(POINT) ;Адрес символа, подлежа-
;щего печати.
61949 7E LD A,(HL) ;Взяли этот символ,
61950 23 INC HL ;наметили следующий
61951 22C3F2 LD (POINT),HL ;и передвинули указатель.
61954 FE1F CP 1F ;Если код символа меньше
61956 FA3EF2 JP M,EXIT ;32 или больше 143,
61959 FE90 CP 90 ;выполняется выход через
61961 F23EF2 JP P,EXIT ;метку EXIT.
61964 D620 SUB 20 ;Из кода символа вычита-
;ется 32.
61966 010800 LD BC,0008 ;На каждый символ расходу-
;ется 8 байтов.
61969 2A365C LD HL,(5C36) ; = 23606 - адрес систем-
;ной переменной CHARS (см.
;стр. 65).
61972 24 INC H ;Теперь HL указывает точно
;на первый символ набора.
61973 09 LOOP_C ADD HL,BC ;Теперь на второй символ и
;т.д,
61974 3D DEC A ;Когда в аккумуляторе бу-
61975 20FC JR NZ,LOOP_C ;дет 0, HL укажет точно на
;нужный нам символ, равный
;тому, на который в данный
;момент указывает указа-
;тель POINT.
61977 22C1F2 LD (CH_ADD),HL ;Запомнили адрес начала
;его шаблона в ПЗУ компью-
;тера.
61980 7B LD A,E ;¦
61981 E618 AND 18 ;¦ Расчет адреса по
61983 F640 OR 40 ;¦ координатам.
61985 67 LD H,A ;¦
61986 7B LD A,E ;¦
61987 E607 AND 07 ;¦
61989 B7 OR A ;¦
61990 1F RRA ;¦
61991 1F RRA ;¦
61992 1F RRA ;¦
61993 1F RRA ;¦
61994 82 ADD A,D ;¦
61995 6F LD L,A ;¦
61996 22BDF2 LD(ROWCOL),HL ;Переменная по адресу
;62141 несет информацию о
;номере ряда и столбца по-
;зиции печати.
61999 CD40F2 CALL DOUBL ;Вызов подпрограммы, вы-
;полняющей непосредственно
;печать символов двойной
;ширины и высоты.
62002 3ABFF2 LD A,(COOR_Y) ;Увеличиваем на 2
62005 3C INC A ;указатель координаты
62006 3C INC A ;по вертикали
62007 32BFF2 LD (COOR_Y),A ;и запоминаем новую пози-
;цию печати.
62010 C1 POP BC ;Восстановили счетчик.
62011 10A9 DJNZ, LOOP_M ;Если не все символы напе-
;чатаны, возврат.
62013 C9 RET ;Генеральный выход из
;процедуры.
62014 C1 EXIT POP BC ;Перед аварийным выходом
;очищаем стек.
62015 C9 RET ;Аварийный выход, если
;параметр y не в допуске
;или символ - непечатный.
62016 119DF2 DOUBL LD DE,BUFFER ;Адрес 62109.
62019 0620 LD B,20 ;Счетчик цикла = 32.
62021 3E00 LD A,00 ;
62023 12 LOOP_H LD (DE),A ;Цикл, обнуляющий
62024 13 INC DE ;буфер.
62025 10FC DJNZ FC LOOP_H ;Конец цикла.
62027 ED5BC1F2 LD DE,(CH_ADD) ;DE указывает на шаблон
;текущего печатаемого
;символа.
62031 219DF2 LD HL,BUFFER ;HL указывает на начало
;буфера.
62034 0608 LD B,08 ;Счетчик по 8.
62036 C5 LOOP_X PUSH BC ;Запомнили его на стеке.
62037 1A LD A,(DE) ;Приняли линию шаблона
;текущего символа.
62038 010204 LD BC,0402 ;Организовали два счетчика
;- на 2 шага в регистре C
;и на 4 шага - в B.
62041 C5 AGAIN PUSH BC ;Запомнили их на стеке.
62042 17 LOOP_S RLA ;Приняли бит во флаг C.
62043 F5 PUSH AF ;Запомнили флаг C.
62044 CB16 RL (HL) ;Приняли этот бит в буфер.
62046 F1 POP AF ;Восстановили флаг C
62047 CB16 RL (HL) ;и приняли его еще раз.
62049 10F7 DJNZ LOOP_S ;Возврат в начало цикла,
;пока не сделаем 4 про-
;хода для заполнения од-
;ного байта в буфере.
62051 23 INC HL ;Перешли ко 2-му байту
;буфера.
62052 C1 POP BC ;Вновь в регистре B уста-
;новили счетчик на 4 про-
;хода,
62053 0D DEC C ;но уменьшили счетчик в C.
62054 20F1 JR NZ,AGAIN ;Возврат, если второй байт
;буфера еще не заполнен.
62056 2B DEC HL ;Возвращаемся ко второму
;байту буфера.
62057 7E LD A,(HL) ;Взяли его в аккумулятор
62058 F5 PUSH AF ;и запомнили на стеке.
62059 2B DEC HL ;Возвращаемся к 1-ому
;байту буфера.
62060 7E LD A,(HL) ;Взяли его в аккумулятор.
62061 23 INC HL ;Переход ко 2-ому байту.
62062 23 INC HL ;Переход к 3-му байту.
62063 77 LD (HL),A ;Копирование 1-го байта
;в третий.
62064 23 INC HL ;Переход к 4-му байту.
62065 F1 POP AF ;Восстановление 2-го
;байта.
62066 77 LD (HL),A ;Копирование его в
;четвертый байт.
62067 23 INC HL ;Переход к очередному
;байту буфера.
62068 13 INC DE ;Переход к очередной
;строке шаблона.
62069 C1 POP BC ;Восстановление счет-
;чика строк шаблона.
62070 10DC DJNZ LOOP_X ;Если не все строки еще
;обработаны, то возврат.
62072 2ABDF2 LD HL,(ROWCOL) ;Адрес в экранном файле.
62075 119DF2 LD DE,BUFFER ;Адрес буфера.
62078 0E02 LD C,02 ;Счетчик рядов экрана.
62080 E5 LOOP_F PUSH HL
62081 0608 LD B,08 ;Счетчик линий в ряду.
62083 1A LOOP_Y LD A,(DE) ;Переброска линии из
62084 77 LD (HL),A ;буфера на экран.
62085 23 INC HL ;Сдвиг на знакоместо
;вправо.
62086 13 INC DE
62087 1A LD A,(DE) ;Переброска четной линии
62088 77 LD (HL),A ;из буфера на экран.
62089 13 INC DE
62090 2B DEC HL ;Сдвиг на знакоместо
;влево.
62091 24 INC H ;Переход к следующей
;линии.
62092 10F5 DJNZ LOOP_Y ;Повтор для 8 пар линий.
62094 E1 POP HL
62095 3E20 LD A,20 ;Переход к следующему
62097 85 ADD A,L ;ряду знакомест
62098 6F LD L,A ;на экране.
62099 3004 JR NC,SKIP_4 ;Проверка не вышли ли
;за границы сегмента.
62101 3E08 LD A,08 ;Если да, то переход
62103 84 ADD A,H ;к следующему сегменту
62104 67 LD H,A ;увеличением H на 8.
62105 0D SKIP_4 DEC C
62106 20E4 JR NZ,LOOP_F ;Повтор для 2-х рядов.
62108 C9 RET ;Возврат.
62109 BUFFER DEFM
62141 ROWCOL DEFW
62143 COOR_Y DEFB
62144 COOR_X DEFB
62145 CH_ADD DEFW
62147 POINT DEFW
62500 MESSAG DEFL