Элементарная графика 1993 г.

Практикум по графике в машинных кодах - масштабное увеличение текста. Печать по горизонтали. Масштабное увеличение текста. Печать по вертикали.


                     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



СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Inferno - Авторы журнала.
Шило или мыло - реклама и обьявления.
ZX-Preview - тест: что вы знаете о Speccy?
От авторов - о себе.
Кeвин Mитник: Хaкeр-лeгeндa - Кoгдa я зaдymaл нaпиcaть жизнeoпиcaниe Mитникa и cтaл coбирaть maтeриaлы, я cтoлкнyлcя c oбычнoй прoблemoй любoгo иcтoрикa: иcтoчники прoтивoрeчaт дрyг дрyгy...

В этот день...   23 ноября