Aspect #08
07 апреля 1998

Программирование - Вывод 64 символов в строке.

<b>Программирование</b> - Вывод 64 символов в строке.
      ЧТОБЫ СТРОКА ВМЕЩАЛА БОЛЬШЕ...

 Наверноe  многие  из  вас  сталкивались с
нехваткой   места   в  строке  для  вывода
информации:  в строке умещалось 32 символа
стандартного  фонта (8*8). No проблемa эта
относительно  легко разрешима. В принципе,
можно  выводить  до  80 символов в строке.
Своеобразными   стандартами,   что  ли,  в
данной  области являются 64 и 42 символа в
строке  (80 символов в строке используются
редко,   т.к.  даже  на  хорошем  мониторе
разобрать         текст         становится
затруднительно).  Итак,  начну, пожалуй, с
64  символов.  При  выводе  в 64 символа в
строке  в  каждый  байт  помещается по два
символа  64-го  фонта(против  одного байта
32-го),  следовательно  символ 64-го фонта
должен иметь размеры 4*8, т.к. в высоту он
такой же как и его 32-ой собрат(фактически
же,  символ  задается  матрицей  3*7, т.к.
справа   и  снизу  должно  быть  свободное
место,   иначе  вместо  текста  мы  увидим
абстрактную  картину).  Можно  задать фонт
стандартно:  один  символ  -  8 байт, т.е.
весь  фонт  (все 256 символов) займет 2048
байт, однако можно уменьшить его размеры в
два раза, если задействовать пустое место.
Тогда  фонт будет выглядеть так: 2 символа
8  байтов,  и фонт займет лишь 1024 байта,
однако  выводить  его будет сложнее. Итак,
прикинем:  надо  вывести  символ на экран,
при  длине  строки  в  64 символа и ужатом
фонте(т.е. фонте в 1024 байта).
 Для этого надо :
  1. Вычислить адрес символа в фонте
  2. Вычислить адрес вывода
  3. Вывести символ

 1.  Адрес  вычисляется  довольно  просто:
делим  код  символа  на два, находим адрес
сдвоенной   матрицы,  далее  проверяем  на
четность   код  символа  (который  был  до
деления) - если четный, то левая половинка
байта, если нечетный - правая.
 2. Адрес вывода берем из таблицы
 3.  Данный  этап целесообразно разбить на
две  части, в зависимости от того, в какую
половинку   байта   на   экране  мы  будем
выводить символ:
 а) Для левой половинки.
 Нечетный  символ  -  никуда  не  двигаем,
берем байт по адресу вывода, объединяем по
логическому "и" (AND  с маской %00001111 -
то  что справа, нам менять не стоит. Берем
байт  из  матрицы  символов, объединяем по
AND с %11110000, объединяем по логическому
"или"  (OR)  с  тем что получили раньше, и
"кладем" на экран.
 Четный  символ - надо объединить по AND с
%00001111,  сдвинуть влево на 4, проделать
то  же  с  байтом адреса вывода, что и для
четного  объединить  по  OR  с  предыдущим
результатом, и "положить" на экран.

 б) Для правой половинки.
 Тоже  что  и для левой, только надо будет
сдвигать  левую часть направо, и маска для
экранной области будет %11110000.

 Ну   вот,  "загрузил"  я  вас  запутанной
теорией,  пора бы ее подкрепить практикой.
В   качестве   примера   будет  процедурка
выводящая 64-ым шрифтом текст.


   0RG   #61A8
   LD   HL,TABLE   ;заполняем таблицу
   LD   DE,0
   LD   B,24
   CALL   ZAPTAB
   LD   HL,TЕXT      ;адрес текста в HL
   LD   BC,0      ;B - Y,C - X координта
            ; в текстовых значениях
WR_64   PUSH   IX      ;он нам еще пригодится
WR_64R   PUSH   BC
   LD   A,B      ;смещение в таблице
   ADD   A,A
   ADD   A,A
   ADD   A,A
   LD   E,A
   LD   D,0
   LD   IX,TABLE   ;находим адрес,  по ко-
            ;торому находится адрес
            ;вывода.
   ADD   IX,DE
   ADD   IX,DE
WR_641   LD   A,(HL)      ;берем символ
   INC   HL
   AND   A      ;ноль - конец текста
   JR   Z,OUTBTEN
   CP   22      ;команда AT
   JR   Z,WR_6471
   CP   #0D      ;перевод строки
   JR   Z,WR_64OL
   CALL   PS_64      ;вывод левой половинки
WR_64N   LD   A,(HL)      ;берем следующий символ
   INC   HL
   AND   A      ;аналогично
   JR   Z,OUTBTEN
   CP   22
   JR   Z,WR_6471
   CP   #0D
   JR   Z,WR_64OL
   CALL   PR_64      ;вывод правой половинки
   INC   C      ;переход к следущему байту
            ;в строке на экране
   JR   WR_641      ;и все по новой
WR_64OL   POP   BC      ;следущая строка
   INC   B
   JR   WR_64R
OUTBTEN   POP   BC      ;конец вывода
   POP   IX
   RET
WR_6471   POP   BC      ;переход к произвольной
            ;позиции вывода
   LD   B,(HL)
   INC   HL
   LD   C,(HL)
   INC   HL
   JR   WR_64R


;ВЫВОД В ЛЕВУЮ ПОЛОВИНКУ БАЙТА
; A - КОД СИМВОЛА
; IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА

PS_64   PUSH   HL      ;то, что нужно - сохраняем
   PUSH   IX
   LD   L,A      ;/2*8=*4
   SRL   L
   LD   H,0
   ADD   HL,HL
   ADD   HL,HL
   ADD   HL,HL
   LD   DE,FONT
   ADD   HL,DE
   EX   DE,HL      ;в DE адрес матрицы символа
   SRL   A      ;проверка на четность
   LD   B,8      ;8 байт выводить
   JR   C,PS_642   ;нечет
   LD   A,(IX)      ;адрес вывода на экран
   LD   H,(IX+1)
   PUSH   BC
   ADD   A,C
   LD   L,A
PS_641   LD   A,(HL)      ;мучаем байт с экрана
   AND   #0F
   LD   C,A
   LD   A,(DE)      ;мучаем выводимый байт
   AND   #F0
   OR   C      ;объединяем их
   LD   (HL),A      ;кладем на экран
   INC   DE
   INC   H
   DJNZ   PS_641      ;повторяем
   POP   BC
   POP   IX
   POP   HL
   RET
PS_642   LD   A,(IX)      ;берем адрес вывода
   LD   H,(IX+1)
   ADD   A,C
   PUSH   BC
   LD   L,A
PS_6422   LD   A,(DE)      ;выделяем правый кусок
   AND   #0F
   RLA         ;двигаем его влево
   RLA
   RLA
   RLA
   LD   C,A
   LD   A,(HL)      ;а здесь все по-старому
   AND   #0F
   OR   C
   LD   (HL),A
   INC   DE
   INC   H
   DJNZ   PS_6422
   POP   BC
   POP   IX
   POP   HL
   RET

;ПРОЦЕДУРА  ВЫВОДА В ПРАВУЮ ПОЛОВИНКУ ЭК-
;РАННОГО БАЙТА
;НА ВХОД В A - КОД СИМВОЛА
;        В IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА

PR_64   PUSH   HL      ;ВСЕ АНАЛОГИЧНО ПРЕДЫУЩЕМУ
            ;СЛУЧАЮ
   PUSH   IX
   PUSH   BC
   LD   L,A
   SRL   L
   LD   H,0
   ADD   HL,HL
   ADD   HL,HL
   ADD   HL,HL
   LD   DE,FONT
   ADD   HL,DE
   EX   DE,HL
   SRL   A
   LD   B,8
   JR   C,PR_642
   LD   A,(IX)
   LD   H,(IX+1)
   ADD   A,C
   LD   L,A
PR_641   LD   A,(HL)      ;байт с экрана будем
   AND   #F0      ;мучать
   LD   C,A
   LD   A,(DE)      ;четный придется двигать
   SRL   A
   SRL   A
   SRL   A
   SRL   A
   OR   C
   LD   (HL),A      ; а дальше все ясно
   INC   DE
   INC   H
   DJNZ   PR_641
   POP   BC
   POP   IX
   POP   HL
   RET
 PR_642   LD   A,(IX)
   LD   H,(IX+1)
   ADD   A,C
   LD   L,A
 PR_6422   LD    A,(HL)      ; тут вроде все ясно
   AND   #F0
   LD   C,A
   LD   A,(DE)
   AND   #0F
   OR   C
   LD   (HL),A
   INC   DE
   INC   H
   DJNZ   PR_6422
   POP   BC
   POP   IX
   POP   HL
   RET

;процедура заполнения таблички
 ZAPTAB   LD   A,D
   LD   C,A
   AND   A
   DUP   3
   RRCA
   EDUP
   AND   #E0
   ADD   A,E
   EX   AF,AF'
   LD   A,C
   AND   #18
   OR   #40
   EX   AF,AF'
   LD   C,A
   EX   AF,AF'
   DUP   8
   LD   (HL),C
   INC   HL
   LD   (HL),A
   INC   A
   INC   HL
   EDUP
   INC   D
   DJNZ   ZAPTAB
   EI
   RET

;выводимый текст
TEXT   DEFB   "ПРИВЕТ ВСЕМ !!!",#0D,#0D
   DEFB   "HELLO TO ALL!!!",0

;здесь будет фонт
FONT   INCBIN   "A:FONT48a.C"

;а здесь таблица адресов
TABLE

 Эта  процедура  вывода  занимает довольно
много  времени,  ее можно заметно ускорить
если    сделать   два   набора   символов:
сдвинутый  влево  и  сдвинутый вправо, при
этом  отпадает  надобность  что-то куда-то
двигать:


   ORG   #61A8
   CALL   RAZPAC      ;превращаем один ужатый
            ;фонт в два разжатых
   LD   HL,TABLE   ;аналогично предыдущему
   LD   DE,0      ;случаю
   LD   B,24
   CALL   ZAPTAB
   LD   HL,TEXT
   LD   BC,0
   LD   IX,TABLE
WR_64   PUSH   IX
WR_64R   PUSH   BC
   LD   E,B
   LD   D,0
   LD   IX,TABLE
   ADD   IX,DE
   ADD   IX,DE
WR_641   LD   A,(HL)
   INC   HL
   AND   A
   JR   Z,OUTBTEN
   CP   22
   JR   Z,WR_6471
   CP   #0D
   JR   Z,WR_64OL
   CALL   PS_64
WR_64N   LD   A,(HL)
   INC   HL
   AND   A
   JR   Z,OUTBTEN
   CP   22
   JR   Z,WR_6471
   CP   #0D
   JR   Z,WR_64OL
   CALL   PR_64
   INC   C
   JR   WR_641
WR_64OL   POP   BC
   LD   A,8
   ADD   A,B
   LD   B,A
   JR   WR_64R
OUTBTEN   POP   BC
   POP   IX
   RET
WR_6471   LD   B,(HL)
   INC   HL
   LD   C,(HL)
   INC   HL
   JR   WR_64R

;ВЫВОД В ЛЕВУЮ ПОЛОВИНКУ БАЙТА
; A - КОД СИМВОЛА
; IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА

PS_64   PUSH   HL
   PUSH   IX
   LD   L,A      ;делить на 2 не надо
   LD   H,0
   ADD   HL,HL
   ADD   HL,HL
   ADD   HL,HL
   LD   DE,FONTL   ;левая половинка -
            ;левый фонт
   ADD   HL,DE
   EX   DE,HL
   LD   A,(IX)
   LD   H,(IX+1)
   PUSH   BC
   ADD   A,C
   LD   L,A
   LD   B,8
PS_641   LD   A,(HL)      ;ловкость рук и никаких
   AND   #0F      ;RRCA
   LD   C,A
   LD   A,(DE)
   OR   C
   LD   (HL),A
   INC   DE
   INC   H
   DJNZ   PS_641
   POP   BC
   POP   IX
   POP   HL
   RET

;ПРОЦЕДУРА  ВЫВОДА В ПРАВУЮ ПОЛОВИНКУ ЭК-
;РАННОГО БАЙТА
;НА ВХОД В A - КОД СИМВОЛА
;        В IX - ТАБЛИЦА АДРЕСОВ ВЫВОДА

PR_64   PUSH   HL
   PUSH   IX
   PUSH   BC
   LD   L,A
   LD   H,0
   ADD   HL,HL
   ADD   HL,HL
   ADD   HL,HL
   LD   DE,FONTR   ;правая половинка -
   ADD   HL,DE      ;правый фонт
   EX   DE,HL
   LD   B,8
   LD   A,(IX)
   LD   H,(IX+1)
   ADD   A,C
   LD   L,A
PR_6422   LD   A,(HL)      ;и ничего не двигаем
   AND   #F0
   LD   C,A
   LD   A,(DE)
   OR   C
   LD   (HL),A
   INC   DE
   INC   H
   DJNZ   PR_6422
   POP   BC
   POP   IX
   POP   HL
   RET

;ПРОЦЕДУРА РАЗЖИМАЮЩАЯ ФОНТ

RAZPAC   LD   HL,FONT1   ;исходный фонт
   LD   DE,FONTL   ;левый фонт
   LD   BC,#8000   ;128 символов в ужатом
   EXX         ;фонте
   LD   HL,FONTR   ;правый фонт
   LD   DE,FONTL+8   ;следующий символ
   LD   BC,FONTR+8   ;следующий символ
   EXX
RAZPAC2   LD   C,8      ;а байт то в символе 8 !
RAZPAC1   LD   A,(HL)      ;начнем-с
   PUSH   AF
   AND   #F0      ;левый символ
   LD   (DE),A
   INC   DE
   EXX
   AND   A      ;двигаем
   DUP   4
   RRCA
   EDUP
   LD   (HL),A      ;в правый фонт
   INC   HL
   POP   AF
   AND   #F      ;правый символ
   LD   (BC),A      ;в след. символ левого
   INC   BC      ;фонта
   DUP   4      ;двигаем
   RLCA
   EDUP
   LD   (DE),A      ; в след. символ правого
   INC   DE      ;фонта
   EXX
   INC   HL
   DEC   C
   JP   NZ,RAZPAC1   ;разжимаем символ
   PUSH   HL
   LD   HL,8      ;переходим к следующему
   ADD   HL,DE      ;символу ужатого фонта
   EX   DE,HL
   POP   HL
   EXX
   LD   HL,8
   ADD   HL,DE
   EX   DE,HL
   LD   HL,8
   PUSH   BC
   AND   A
   ADC   HL,BC
   LD   C,L
   LD   B,H
   POP   HL
   EXX
   DJNZ   RAZPAC2
   RET

;ПРОЦЕДУРА ЗАПОЛНЯЮЩАЯ ТАБЛИЦУ ВЫВОДА

ZAPTAB   LD   A,D
   LD   C,A
   AND   A
   DUP   3
   RRCA
   EDUP
   AND   #E0
   ADD   A,E
   EX   AF,AF'
   LD   A,C
   AND   #18
   OR   #40
   EX   AF,AF'
   LD   C,A
   EX   AF,AF'
   DUP   8
   LD   (HL),C
   INC   HL
   LD   (HL),A
   INC   A
   INC   HL
   EDUP
   INC   D
   DJNZ   ZAPTAB
   EI
   RET
TEXT   DEFB   "ПРИВЕТ ВСЕМ !!!",#0D,#0D
   DEFB   "HELLO TO ALL!!!",0
TABLE
FONT1   INCBIN   "A:FONT48a.C"
   DEFS   1256
FONTL   DEFS   #800
FONTR   DEFS   #800

 Способ,  конечно,  не  экономичный,  зато
быстрый. Ну, с 64-ым фонтом разобрались, а
о 42-ом фонте раскажу в следующий раз.

                            (c)Trusov Ilya






Другие статьи номера:

BBS-Лист - Список Vicomm-совместимых BBS.

STARе - Полное описание игры NewDizzy.

Анонс - Новая модемная игра GAMBIT.

Внимание - Памятка пользователю сети SPbZXNet.

Вот блин - Конец связи? (о повременной оплате телефонных разговоров).

Железо - Что такое "Тестер" и с чем его едят.

Конкурс - Первые эмблемы для FunTop'a.

От авторов - Первоапрельские приколы в номере.

Полигон - О компьютере Sprinter.

Программирование - Вывод 64 символов в строке.

Сетевые новости - MMD v4.00 - тестируется на BBS, закрытие газеты ZXWeek.

Хит-парад - 10-ка лучших игр.

Что такое автомобильный катализатор.

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

Похожие статьи:
Горшырзы - повествование о том, где вы никогда не захотели оказаться, но другие вас там очень хотели бы видеть.
Bytefall - отчёт о посещении.
Warez - презентация игры Abe's Mission ("Миссия Эйба") - конверсия с PC - "Oddworld: Abe's Oddysee".
РАссказ - Послушайте.
Интерфейс - проблема выбора домашнего компьютера: "так ли Amiga Rulez?" (продолжение)

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