Процедуры пропорциональной печати
Так уж бывает, что в одно и то же время оригинальные идеи приходят в головы разным людям. Произошло так и сейчас, когда мы получили практически в одно и то же время два письма: из Белгородской области от Владимира Гоголева и из г. Курган от Александра Скрипко на одну и ту же тему - нестандартные процедуры для печати. Предлагаем их нашим читателям в порядке поступления.
© Владимир Гоголев, г. Шебекино, Белгородская обл., 1994 г.
Я предлагаю программу, которая, по моему мнению поможет людям, пишущим программы с большим количеством текста. Это процедура печати пропорциональным шрифтом. Суть ее заключается в том, что каждый символ в этом шрифте имеет свою ширину, отличную от других и стандартную высоту, равную 8 пикселей. Это дает большие возможности для компактного размещения текста на экране.
Попробуйте, например, напечатать несколько букв "1" стандартным шрифтом. Вы увидите, что в знакоместе, где напечатана эта буква, много свободного места, которое никак не используется. Было бы удобно, чтобы буква "1" занимала на экране окно, размером 3x8 пикселей, а такая буква, как "ш" - окно 6x8 пикселей, что и делает моя программа.
Или обратите внимание на текстовый редактор "Tasword". Все символы в нем имеют размер 4x8 пикселей, и текст, написанный этими символами, очень трудно читать. С помощью моей программы текст можно распечатать символами, которые имеют оптимальную ширину для каждого символа, благодаря чему, текст на экране смотрится очень красиво.
-./0123456789:;<=>?@flBCDEFGHi;iKLMNCiPQ RSTUUUXYZC:t_£abcdefghijiamnopqrstuvwHy2m~® K&'D*+,-./0123456789:;<=>?@flBCDEFGHi;iKLMNCiPQIiSTLIU HXYZ::+_£abcdefghijkLmnopqrstuvwHy3{i:~0 +,-./0123456789:;<=:>?@ABCDEFGHi;iKLMNOPQRSTUUWXYZ ::t_£abcdefghijiamnopqrstuvwHy3{IJ~@ "ХЦУ.ъ:<;>ы,-./ 0123456789:^=>?@flECDEFGHI3KLMNOPQR5TUUWXVZC:t_ £abcdefghijiamnopqrstuvwHy3{IJ~@ !"В$;;5Л)*+,-./0123 456789:^=>?@flECDEFGHI3KLMN0PQPSTUUWXVZ::-t_£^bC defghi.jlUmnopqrstuvwHy:2{II~0 !"B$KS<'0*+,-./01234567 S9:^=>?@flECDEFGHI3KLMN0PQPSTUUWXVZ::-t_£^bCdefgh ijmmnopqrstuvwHy:2{|}~0
RNDINKEYJPIFN POINT SCRE EN$ ATTR AT TAB UAL$ CODE UAL LEN SIN COS TAN AS N ACS ATM LN EXP INT SQR SGN ABS PEEK IN USR STR$ CHRJ NOT BIN OR AND CHOLINE THEN TO STEP DEF F N CAT FORMAT MOUE ERASE OPEN 8CL0SE 8MERGE UERIF V BEEP CIRCLE INK PAPER FLASH BRIGHT INUERSE OUER OUT LPRINT LLIST STOP READ DATA RESTORE NEW BORD ER CONTINUE DIM REM FOR GO TO GO SUB INPUT LOAD L 1ST LET PAUSE NEXT POKE PRINT PLOT RUN SAUE RANDO MIZE IF CLS DRAW CLEAR RETURN COPY
Теперь несколько слов об использовании этой процедуры. Программа полностью релоцируемая, то есть Вы можете загрузить ее под любой адрес и запустить с того же адреса. При первом запуске программа настраивается для работы в этих адресах и переключает каналы. Теперь, если что-нибудь напечатать командой PRINT, то печать будет происходить нестандартным шрифтом. Теперь Вы можете печатать что угодно и где угодно, но Ваша радость будет недолгой. До первого автоматического листинга (при нажатии ENTER, [ВВЕРХ], [ВНИЗ]) или до первого использования команд Бейсика, инициализирующих каналы (RUN, CLEAR, CLS). Чтобы каналы не инициализировались, по команде RUN нужно первой строкой в программе вставить РОКЕ 23739,L : РОКЕ 23740,Н где L -младший байт адреса процедуры печати, Н - старший байт. Адрес процедуры печати равен адресу загрузки плюс 97 (ячейки 23739 и 23740 содержат адрес процедуры вывода для канала экрана и, если кто пользуется периферийными устройствами, пусть вычислит эти адреса для себя сам).
Чтобы каналы не инициализировались по команде CLS, нужно после ее использования делать те же самые РОКЕ, что и для RUN, либо отказаться от ее использования и делать вместо нее PRINT CHR$ 15 (Вы увидите интересный эффект).
Программа кроме символов основного набора печатает ключевые слова Бейсика и следующие управляющие
CHR$ 6 CHR$ 15 CHR$ 13 CHR$ 16
коды:
- как и стандартный перевод позиции печати на середину или начало экрана.
- очистка экрана и установка позиции печати в начальное положение.
- как и стандартный перевод на начало новой строки.
- устанавливает атрибуты в экране с помощью "хитрого" эффекта. Используется перед кодом, содержащим численное значение атрибутов экрана, которые должны быть установлены; может использоваться в команде PRINT INK N.
CHR$ 17 - то же, что и CHR$ 16, только с мгновенной установкой атрибутов; может использоваться как PRINT PAPER N.
CHR$ 20 - как и стандартный (INVERSE N); сохраняется для следующих команд PRINT.
CHR$ 22 - сопровождается двумя параметрами, которые устанавливают позицию печати относительно верхнего левого угла экрана (отсчет ведется не в знакоместах, а в пикселях: 0<y<184, 0<x<255). Может вызываться через PRINT AT y,x;...
Таким образом, печать может быть выполнена с дискретностью позиции в один пиксель. Это демонстрирует рисунок:
О ft .4 c;i=.-7:=:QiT| О ft .-1 н. "7 :=: Q ffl Oft Л1=. i=. "7 ft О i?| " О ft a c; ft "7 ft Q iT]
Oft Л О ft А с: i=. "7 :=: Q i7| Oft .1 cr i=. "7 ftQ m О ft .1 Oft/1 C:i=.T:=:Qi7I Oft Лi=. "7 ft О л гс -jc-i-iiTi1-
О ft .4 =;к7>:й|Г О ft .4i=. "7 ft О i7| -"7 :=:G 0Г Oft.1 RI=.-7:=:Qi7| О ft Л О--:.4 ВД7ЙО0
О ft .4 ^k7:=:QI О ft A c; ft "7 ft Q i7| 0--:.4 Ri=.-7:=:Qi7| Oft Л ^ft "7ft ОСТ Oft .4 ВД7ЙО0 О ft A i=. "7 :=:■!! iTi ■О ft .1
•■=: .-1 :=: Q iTI
- -:/l e:i=. "7 :=:Q iTi ~ ft.-1
Tpft .-1 ^F.-7F:Cih1 1 ■=■ --: .-1 cr i=. "7 :=: О iTi 1 Oft .4 =:i=-7:=:Qi7i ч р'чл «=:i=.t1 :=:-ziiti
V=' -:/l e:i=. "7 :=:Q iTi 1 p ft .-1 t=. 1= "7 :=: Q iTi
Abl -'■-:,i ^ATftam
1 Г"-------
.. ,-7:=:Oi7i
.4 =:i=.-7:=:oi7i
^ ft-7ft am О ": .4 C!b.-7:=:ai7i
IPftи^к7йога ^■j ft .4 ча7 ft a iTi П О ft .1 RF.7 ft Q iTi 1 о ft . 4 i=. -7 ft a m 1 Oft.4 ^fi7ftQffl Xtl pft^i ^ft-7ftam ■L T p ft A ft "7 :=: a m
lf?i
■=, с;к7:::йг Oft Л О ft .-1 PP.7 ft a i7| Oft a Ri=.-7:=:Qi7| Oft Л qfi^ftQffl1" Oft a =:i=.-7:=:Qh4 О ft a i=. "7 :=:■!! iTi ■-Oft.4 О ft А с; н. "7 ft й i7] Oft a
-, -c:,=.-7:=:i=i i7|
Oft a Ri=.-7:=:Oi7|
о ft a -7 ft a or
■| ,h cc о i~i iti
loft.4 =: ft-7 ft am 1234567890
T ft'J hi
О ft .4 RF.7 :=: О Г •OftA О ft .4 =:i=.-7:=:Qi7| О ft a ft ОЙ О ft .4 qfi7ftQQb О ft А с; н. "7 ft й i7] jft.4
Oft.4=:i=.-7:=:Qh О ft a 4fi7ftQffl* ГА"7:=:Gi7] О ft .4 ^к7 :=: О i7|
О ft . 4 "7 ft a 0Г
О ft .4 =:i=.-7:=:Qi7| О ft a ■=■-: .1 qfi7ftQQb Oft.4=:i=-7:=:Qh1
О ft .4
2345678901
В программе использован английский шрифт, но возможно использование пользовательского шрифта. Шрифт в программе находится с адреса, равного адресу загрузки плюс 637. Формат знакогенератора следующий. Блок данных о символе содержит n+1 байт, где n - ширина символа; первый байт этого блока - ширина символа в пределах от 1 до 255. Следующие n байт содержат данные о символе в виде, повернутом на 90°, например, блок данных для символа "1":
=4 -ширина
=66 "1
=0 J
Блоки находятся подряд один за другим от символа с кодом 32 до символа с кодом 127, возможно использование от 128 до 164.
Теперь Бейсик-программа, предназначенная для получения блока кодов предложенной процедуры. После ее запуска с начальной строки в том случае, если Вы при ее наборе допустили ошибку, программа остановится и сообщит номер строки с DATA, в котором допущена ошибка.
1 DATA 4 0000,38
2 DATA "CD52 003B3BE1013 9000 9444D11250019E5D90 625D916000A5F195E235 6E5333315"
3 DATA "2158 98EBA7ED52D1193B3B3B3BEBE1722B7303D910DED9E122BB5CC902 0414 0 93D"
4 DATA "050B031A122 80A04 0B0807 0711050A24 030 90A080817 030D0A12 04 0D130C1115 99"
5 DATA "0 6083A3B9AA7CAF3 98FE052 84 7FE042 855FE032 87 9FE022 80E3C32 3B9A08FEB9E4"
6 DATA "3801AF 323C 9AC 9AF 323B9A0857E6075F3E089332399A3A3C 9A5FA71F371FA71F49"
7 DATA "ABE6F8AB677A07 07 07ABE6C7AB07 07 6F2237 9AC90821005811015801FF0277EDB7"
8 DATA "B 0AF 32 3B 9AC 921002011005801FF02EDB008571E00210058010003 7ABE2 8013407"
9 DATA "230B7 8B12 0F51D2 0ECAF323B9AC908B72 8023E3F32CB99AF323B9AC908FE162 0CB"
10 DATA "0 63E0132 3B9AC9FE0D2 00A2A37 9A7DF61F6FC3F5 99FE0 62 01A2A37 9A7D57E61FA9"
11 DATA "FE1030EA7AE6E0C610 6F22 37 9A3E0832 3 99AC9FE142 00 63E0332 3B9AC9FE0F2 02A"
12 DATA "22 0 60 6C521FF57 0E2 0A7CB2 6CB0 6CB2 62B0D2 0F63E3FBC2 0EEC110E7AF32 3C9AF6"
13 DATA "C37E98FE102 00 63E04 32 3B9AC9FE112 00 63E0532 3B9AC9FE1E2 012113D9A0 632D5"
14 DATA "1AD5C5CD58 98C1D11310F5C9C9FE2 0D8FEA53805D6A5C3100C572A37 9A3A3 99A3C"
15 DATA "47 0E087 8A7CB0E3D2 0FBCD22 9A080D2 0F27AD62 02174 9A2 80 94716007E235F19A3"
16 DATA "10FA7E4F2 3ED5B37 9AEB3A3 99A4 7C5 0 6081AE51F00CB16CD22 9A0810F6E1C105 62"
17 DATA "2 0030 6082C130D2 0E57 8323 99AE50E087 8CB0 63D2 0FBCD22 9A080D2 0F3E17DE690"
18 DATA "1FEE1F2 0173E08323 99A2C7DFEE02 0057CFE50300BA72 0047CC608 672237 9AC997"
19 DATA "2EC02237 9A0 617CD000EC9082 4 3E07A4C02 53EF8A4 67 3E2 085 6FD03E0884 67C9F9" 2 0 DATA "004 0080 6000016500A14 012 07F2 0474F474F4C455 62 05 64C41444 94D4 9522C53 9C"
21 DATA "4 84542454B4 94E4F2 0542E342D32382D323 62C313 93 9342 0003 6000000050000A5"
22 DATA "000000025E0005080 6080 6000 6247E247E24 000 65C54FE5474 000 6C62 610C8C6FB" 2 3 DATA "000 6344A542 050000304 02 00033C42 0003423C000 610543854100004107C1000F9" 2 4 DATA "0380 600005101010100003 60 60000 64 02 0100804 000 63C625A4 63C0004427E4 0F1" 2 5 DATA "000 6645252524C000 624424A4A34 000 6302 8247E2 0000 62E4A4A4A32 000 63C4AD0" 2 6 DATA "4A4A30000 602 0272 0A0 6000 6344A4A4A34 000 60C5252523C000224 000380 64 00ED" 2 7 DATA "04102 844 00052 82 82 82 80004442 810000 604 0252 0A04 00073C425A5 65A1C0005C1" 2 8 DATA "7 814127E00057E4A4A34 00053C424224 000 67E4242241800057E4A4A42 00057E7 0"
2 9 DATA "0A0A02 00053C42 52 34 00057E08087E0004 42 7E42 000522 42 42 3E000 67E081422E1"
30 DATA "4000057E40404000067E0408047E00057E0C307E00053C42423C00057E12120C86"
31 DATA "000 63C4252225C00057E12324C0005444A4A32 000 602 027E02 02 00053E4 04 03E03"
32 DATA "000 61E2 04 02 01E000 67E2 0102 07E000 64224182442 000 60 6087 0080 60005 62524 9"
33 DATA "4A4 600047E4242 0004 0 618 60000442427E000 608047E04 08000 68080808080004 0"
34 DATA "06487C4A424400052054547800057E484830000438444400053048487E00053866"
35 DATA "5454 0800047C0A02 000518A4A47C00057E08087 000044 87A4 000044 0807A0005 69"
3 6 DATA "7E18244 000033E4 0000 67C047 8047 800057C04 047 80005384444380005FC24243C"
37 DATA "180006182424FC8000047C08040005485454200004083E4800053C40403C000630"
38 DATA "0C3040300C00063C4038403C00056C10106C00051CA0A07C00054464544C000419" 3 9 DATA "08764200027E000442760800050402040200077C82 BAAA82 7C007C"
9900 PLOT 100,39: DRAW 0,130: DRAW 76,0: DRAW 0,-24: DRAW 2,0: DRAW 0,-106: DRAW -78, 0
9910 PRINT INVERSE 1;AT 17,13;"PROCEDURE";AT 18,15;"WRITE" 9990 REM (C) GOGOLEV WLADIMIR'94
9993 READ A,S: FOR F=1 TO S
9994 LET Y=0: READ L$: LET L=LEN L$: LET S=0: LET K=2
9995 LET A$=L$(K-1): LET B$=L$(K)
9996 LET C=(CODE A$-4 8-(7*(A$>"@")))*16+CODE B$-4 8-(7*(B$>"@"))
9997 IF K<L THEN POKE A,C: PLOT F*2+100,Y+40: DRAW 0,4: LET Y=Y+4: LET S=S+C: LET K=K+2: LET A= A+1: GO TO 9995
9998 IF S-256*INT (S/256)<>C THEN PRINT FLASH 1; BRIGHT 1,-"ERROR IN LINE ";F+1: STOP
9999 NEXT F: SAVE "PROC" CODE 4E4,1210
Комментарий ИНФОРКОМа. Мы с успехом оттестировали предложенную программу. Даже сделали небольшую демонстрационную Бейсик-программку, которую приводим ниже (фрагменты работы ее Вы видели на рисунках по ходу статьи). Надо
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
отдать должное автору, очень приятно было то, что программа релоцируемая. Профессионально - это и значит -продумано до мелочей. Эффектно работает и программа, формирующая кодовый блок "PROC" CODE. Но на некоторые моменты все же хотим обратить внимание.
Во-первых, нам показалось неудобным подключение приведенной процедуры к потоку #2, то есть к основному потоку экрана. Хотя все то, о чем говорил автор насчет RUN, CLS, CLEAR и т.п. - все это верно. Тем не менее предлагав» альтернативный вариант - подключение процедуры пропорциональной печати к собственному потоку #4, не используемому при обычной работе компьютера. Преимущество в том, что, инициализировав новый поток один раз. Вам больше не надо беспокоиться о том, чтобы случайно не нажать ENTER или подать команду CLS. Поток останется подключенным до тех пор, пока Вы не выключите питание компьютера. Другое преимущество в том, что в программе можно гармонично совмещать как вывод на печать по основному потоку #2 при помощи оператора PRINT, так и вывод на печать при помощи новой процедуры при помощи команды PRINT #4;. И уж конечно не ограничивать себя в использовании операторов CLS, CLEAR и др.
Методика подключения процедуры к новому потоку была подробно изложена в нашей книге "Прикладная графика" (см. Бейсик-программы на стр. 77 и 93 и разбор программы на ассемблере в Приложении 3 на стр. 197-204), поэтому подробно останавливаться на технологии не будем. Все изложенные моменты нашли отражение в демонстрационной Бейсик-программе:
1 GO TO 100
2 CLEAR 39999: LOAD "PROC" CODE 40000 2 0 LET a=USR 4 0000: RANDOMIZE a:
22 POKE 23588,PEEK 23670: POKE 23589,PEEK 23671
24 POKE 23590,196: POKE 23591,21: POKE 23592,83
26 RANDOMIZE (23588-(PEEK 23631+256*PEEK 23632)+1+65536)
28 POKE 23582,PEEK 23670: POKE 23583,PEEK 23671
100 BORDER 0: PAPER 7: INK 0: CLS : INPUT ;: PRINT #4;CHR$ 15;
110 FOR N=1 TO 6: FOR A=32 TO 127: PRINT #4;CHR$ A;: NEXT A: NEXT N
120 PRINT #4;CHR$ 6;CHR$ 6;CHR$ 6;: FOR A=165 TO 255: PRINT #4; CHR$ A;: NEXT A:
PAUSE 100 130 PRINT #4;CHR$ 15;
140 FOR A=0 TO 175 STEP 5: PRINT #4;AT A,A;"1234567890": NEXT A
150 FOR A=0 TO 175 STEP 5: PRINT #4;AT A,75-A; INVERSE 1;"1234567890"; INVERSE 0: NEXT A: PAUSE 100
160 FOR A=0 TO 7: PRINT #4; PAPER (8*A+7-A);: PAUSE 40: NEXT A: PRINT #4; PAPER
(128+64+8+6);: PAUSE 100 170 PRINT #4; PAPER (64+8+7);: PAUSE 100: PAUSE 80: PRINT #4; PAPER 0;: PAUSE 50 180 FOR A=1 TO 7 STEP 2: PRINT #4; INK (8*A+7-A);: PAUSE 30: NEXT A: PAUSE 100 190 GO TO 100
В строке 10 - с нее должен происходить автостарт программы - производится загрузка блока кодов новой процедуры (для примера в адрес 40000). В строке 20 переменной "а".присваивается значение стартового адреса новой процедуры, в данном случае 40097 (кстати, можете выполнить PRINT USR 40000 - и Вы прочитаете этот адрес). Строки 22-28 занимаются инициализацией нового потока #4 и подключением к нему процедуры пропорциональной печати. Все это выполняется один раз при первом старте программы.
Далее происходит переход на основную часть программы - это строки с 100. Проанализируйте внимательно примеры использования новой процедуры, ну а эффекты, происходящие при этом - Вы увидите сами.
Подключение новой процедуры к своему собственному потоку оправдано не только в Бейсике. Эффективно пользоваться этим способом можно и из машинного кода. Только перед подачей команды RST #10 или вызовом подпрограммы, использующей RST #10, необходимо открыть соответствующий канал. Например, процедура печати строки текста может выглядеть так:
3E04 LD А,#04
CD0116 CALL CHAN-OPEN
11.... LD DE,начало строки
01.... LD ВС,длина строки
CD3C20 CALL PR-STRING
C9 RET
Теперь еще об одной проблеме. Вариант процедуры с латинским алфавитом, наверное, мало кого устроит. Первое, что приходит на ум - создать символьный набор для русского шрифта. Но не тут-то было. Ведь каждый символ необходимо вручную "положить" на бок и рассчитать данные для него. Тем не менее, эта проблема вполне под силу самому компьютеру. Символьный набор можно готовить, скажем, при помощи ARTSTUDIO, так, чтобы символы были вплотную "прижаты" к левому краю, при этом несколько вертикальных столбцов справа (в зависимости от конкретного символа) останутся свободными. Затем этот символьный набор "пропускается через специальную программу-утилиту в машинных кодах, которая модифицирует символьный набор в вид, пригодный для процедуры пропорциональной печати. Уверены, что создание такой программы-утилиты вполне под силу нашим читателям.
Как должна работать такая программа? Прежде всего следует отдельно обработать символ "пробел", задав для него некоторую фиксированную ширину. Далее можно приниматься за остальные символы. Сначала программа-утилита все 96 символов поворачивает на 90° вправо. Затем анализирует, сколько столбцов занимает символ (причем отсчет должен вестись с конца, чтобы не было конфликтных ситуаций в тех случаях, когда присутствуют вертикальные "разрывы" - в букве "Ы" или в символе "кавычки"). Первый ненулевой байт, считая от конца, определяет ширину символа. Теперь, когда она известна, это число заносится в память, далее следом перебрасывается соответствующее количество байтов символа. Вот и всё. Повторим это для всех 96 символов и можно выдавать готовый блок кодов для записи.
Желательно дополнить программу-утилиту противоположной процедурой - для декодирования символьного набора в стандартный вид - тогда не понадобится сохранять все "исходные" символьные наборы.
А теперь следующее письмо.
© Александр Скрипко, г. Курган, 1994 г.
Как-то перечитывая вашу книгу "Прикладная графика" (а точнее главу, посвященную нестандартным шрифтам), я задумался: а почему все буквы должны быть фиксированной ширины и высоты (8x8; 5x5; 16x16 и т.д.)? Ведь надпись, сделанная буквами с нефиксированной шириной будет смотреться куда впечатляюще.
Короче, решил попробовать. Как и следовало ожидать, на экране все смотрелось прекрасно, но меня не устраивал один момент. Так как я использовал для хранения ширины символов отдельную таблицу, то при использовании в программе более одного шрифта, количество памяти, занимаемое таблицами ширины и самими шрифтами увеличивалось, и, что важнее, нужен был жесткий контроль за тем, какому шрифту какая таблица соответствует и какой шрифт активен в данный момент.
Решение пришло неожиданно: использовать для хранения таблицы ширины знаков сам символьный набор.
При конструировании шрифтов, обычно, для задания минимального зазора между строками, первый байт оставляют пустым (иногда и восьмой - тоже). Так что, если в восьмой байт символа вписать его ширину, а при печати значение этого байта игнорировать, то, во-первых, никакой дополнительной таблицы не надо; во-вторых, очень легко определить ширину символа по его коду.
Необходимо только помнить, что должен быть свободен левый столбец для фиксированного расстояния между буквами и восьмой байт (нижняя строка) - для кодировки ширины символа. В остальном можно положиться на свой вкус. При недюжинных дизайнерских способностях можно даже эмулировать свой почерк.
Листинг процедуры, выполняющей печать по вышеуказанным принципам выглядит так:
00010 |
CHARS |
EQU |
64600-256 |
|
00020 |
|
ORG |
40000 |
|
00030 |
|
ENT |
|
|
00040 |
START |
LD |
HL,TEXT |
B HL - начало текста. |
00050 |
|
LD |
A, (HL) |
B A - координата X в знакоместах. |
00060 |
|
ADD |
A, A |
Умножим ее на 8, |
00070 |
|
ADD |
A, A |
так как шаг строк |
00080 |
|
ADD |
A, A |
8 пикселов. |
00090 |
|
LD |
B, A |
Так как отсчет координаты точки ве |
00100 |
|
LD |
A, 175 |
дется от левого нижнего угла, то ну |
00110 |
|
SUB |
B |
жно вычесть найденное знач. из 175. |
00120 |
|
LD |
(YPIC),A |
Сохраняем найденную координату X. |
00130 |
|
INC |
HL |
HL указывает на координату Y. |
00140 |
|
LD |
A, (HL) |
B A - коорд. Y в знакоместах. |
00150 |
|
ADD |
A, A |
Умножение на 8. |
00160 |
|
ADD |
A, A |
|
00170 |
|
ADD |
A, A |
|
00180 |
|
LD |
(XP1C),A |
Сохранение ее. |
00190 |
NEXT |
INC |
HL |
HL указывает на начало текста. |
00200 |
|
LD |
A, (HL) |
B A - код первого символа текста. |
00210 |
|
CP |
#FF |
Это не маркер конца? |
00220 |
|
RET |
Z |
Если да, то выход из процедуры. |
00230 |
|
PUSH |
HL Сохранение HL на стеке. |
00240 |
|
LD |
DE,CHARS |
Расчет адреса |
00250 |
|
LD |
H, 0 |
первого |
00260 |
|
LD |
L, A |
байта |
00270 |
|
ADD |
HL, HL |
шаблона |
00280 |
|
ADD |
HL, HL |
символа |
00290 |
|
ADD |
HL, HL |
в символьном |
00300 |
|
ADD |
HL, DE |
наборе. |
00310 |
|
PUSH |
HL |
Запомнили его на стеке. |
00320 |
|
LD |
BC,(XPIC) |
B ВС - координаты левого верхнего пиксела символа. |
00330 |
|
CALL |
NEXTXY |
Подпрограмма вычисления координат |
следующего символа.
Восст. адрес первого байта символа.
Цикл из 7 шагов для сканирования
и побитного копирования семи байтов
шаблона (т.к. в 8-м байте находится
информация о ширине символа).
Сохранение координат.
B A - байт шаблона.
Если равен 0,
то печатать не надо.
Иначе - ротация для определения
необходимости печати точки.
Если бит=0, то обход печати.
Следующий пиксель в линии. Повтор сканирования и печати. Уменьшение счетчика линий. Координаты печати. Если счетчик обнулен, то переход на завершение процедуры. Иначе - переход к печати следующей пиксельной линии символа.
Восстановление адреса символа. Ha печать следующего символа.
NC,OBHOD
AF
HL
ВС
DE
#22E5
DE
ВС
HL
AF
С
L2 E
ВС
Z, KON
DEC В
INC HL
JR L1
KON POP HL
JP NEXT
; Подпрограмма вычисления координат ; левого верхнего угла следующего символа
PUSH
PUSH
LD
INC
DJNZ
LD
LD
LD
INC
DONZ
LD
СР
OR
JR
HL ВС В,7 HL
L3
A, (HL) HL,(XPIC)
B, А
L
L4
A, (XPIC)
L
C, END NZ,NLINE
00770 00780 00790 00800 00810 00820 00830 00840 00850 00860
(XPIC),HL
ВС
HL
ВС С,0
A, В
L,8 L
B, А
LD
POP
POP
RET
POP
LD
LD
LD
SUB
LD
NEXTXY
Адрес первого байта символа. Координаты левого верхнего пиксела. Цикл из 7 повторений. Пропуск 7 байтов.
HL указывает на 8-й байт шаблона. B HL - текущие координаты: в L - Х-коорд., в Н - Y-коорд. Счетчик на А шагов. Увеличение на 1 Х-координаты.
B A - текущая Х-координата. Сравнение с новым значением X. Если новое значение больше старого то переход на "конец". Если меньше (а так может быть только тогда, когда следующее значение X больше 255), то переход для расчета координат на следующей строке. Сохранение новых координат. Восстановление регистров и выход.
Восст. текущие координаты. Х-координата равна нулю. В А - Y-координата. Уменьшаем ее на 8, т.к. отсчет от левого нижнего конца экрана. Возвращаем ее в В.
00360 00370 00380 00390 00400
00410 00420 00430 00440 00450 00460 00470 00480 00490 00500 00510 00520 00530 00540 00550
00560 00570 00580 00590 00600 00610 00620 00630 00640 00650 00660 00670 00680 00690
00700 00710 00720 00730 00740 00750
00760
PUSH
LD
OR
OR
RLA
JR
PUSH
PUSH
PUSH
PUSH
CALL
POP
POP
POP
POP
INC
JR
DEC
POP
OR
00870 |
|
LD |
(XP1C),BC |
Сохранение полученных координат. |
00880 |
|
POP |
HL |
;Bocct. адрес первого байта символа |
00890 |
|
JR |
NEXTXY |
;Повторение для расчета координат. |
00900 |
XPIC |
DEFB |
0 |
;Х-коорд. в пикселах. |
00910 |
YPIC |
DEFB |
0 |
;У-коорд. в пикселах. |
00920 |
TEXT |
DEFB |
10, 15 |
;Координаты в знакоместах X, Y. |
00930 |
|
DEFM |
"DEMO TEXT" |
;Текст сообщения. |
00940 |
|
DEFB |
#FF |
;Маркер конца сообщения. |
Start |
of object |
: # 9C4 0 |
(40000) |
|
Length |
: #008D |
(00141) |
|
Executes |
: # 9C4 0 |
(40000) |
|
Комментарий ИНФОРКОМа.
После набора шестнадцатеричного дампа, сохраните блок кодов:
SAVE "proporc" CODE 40000,141
9C4 0 |
21 |
C1 |
9C |
7E |
87 |
87 |
87 |
47 |
B4 |
9C4 8 |
3E |
AF |
90 |
32 |
C0 |
9C |
23 |
7E |
90 |
9C50 |
87 |
87 |
87 |
32 |
BF |
9C |
23 |
7E |
AF |
9C58 |
FE |
FF |
C8 |
E5 |
11 |
58 |
FB |
26 |
28 |
9C60 |
00 |
6F |
29 |
29 |
29 |
19 |
E5 |
ED |
D1 |
9C68 |
4B |
BF |
9C |
CD |
93 |
9C |
E1 |
1E |
A5 |
9C7 0 |
07 |
C5 |
7E |
B7 |
28 |
11 |
17 |
30 |
8D |
9C7 8 |
0B |
F5 |
E5 |
C5 |
D5 |
CD |
E5 |
22 |
67 |
9C80 |
D1 |
C1 |
E1 |
F1 |
0C |
18 |
EC |
1D |
AD |
9C88 |
C1 |
28 |
04 |
05 |
23 |
18 |
E2 |
E1 |
14 |
9C90 |
C3 |
56 |
9C |
E5 |
C5 |
06 |
07 |
23 |
BB |
9C98 |
10 |
FD |
7E |
2A |
BF |
9C |
47 |
2C |
B7 |
9CA0 |
10 |
FD |
3A |
BF |
9C |
BD |
38 |
02 |
D5 |
9CA8 |
20 |
06 |
22 |
BF |
9C |
C1 |
E1 |
C9 |
52 |
9CB0 |
C1 |
0E |
00 |
78 |
2E |
08 |
95 |
47 |
A5 |
9CB8 |
ED |
43 |
BF |
9C |
E1 |
18 |
D4 |
00 |
AC |
9CC0 |
00 |
0A |
0F |
44 |
45 |
4D |
4F |
20 |
BA |
9CC8 |
54 |
45 |
58 |
54 |
FF |
00 |
00 |
00 |
A8 |
Для демонстрации работы процедуры необходимо сначала подготовить символьный набор. Задача упрощается тем, что формат его - стандартный и можно без проблем сформировать его при помощи все той же
ARTSTUDIO. Фрагмент работы над символьным набором показан на рисунке:
|>| File | Character | Font | Misc. | Menu ■ ■■
. ! . ". ft в.. Я Si.'. С.). х. +.,. -. .. 0.. 1. £.. 3.. 4.. 5.. 6.. 7.. s.. 9..: . ;. =.. >. ?.. Ч. ft. Е.. с.. D„ Е.. F.. g.. К. I. J.. К. L.JI^K. 0..
p.. ft. r. s.. т. и., ц. щ ц. y. г..:. ч :. т. _ £.. ь.. е.. 4. е.. f. э..
К. i. А к.. L. Щ П. О.. Р.. Л Г. 5-.. t. и.. V. Щ Ц. у.. 2.А. . J. ".Щ
Помните, что у каждого символа необходимо оставить свободным левый столбец и нижнюю строку. В ней двоичным кодом указывается ширина символа. Так Вы видите, что ширина символа "L" задана 4, символа "М" - 6, а символа "N" -5 пикселей. Необходимо задать ширину для всех символов (не забудьте про "ПРОБЕЛ"). Теперь сохраните символьный набор обычным порядком. Пусть имя его будет "prop.fnt".
Теперь наберите демонстрационную программку с автостартом со 2-й строки:
1 GO TO 10
2 BORDER 7: PAPER 7: INK 0: CLEAR 3 9999: LOAD "proporc" CODE
3 LOAD "prop.fnt" CODE 64600 10 RANDOMIZE USR 4 0000
В центре экрана Вы увидите фразу: "DEMO TEXT". Но чтобы в полной мере оценить преимущества пропорциональной печати, добейте еще несколько строк в демонстрационную программку:
4 POKE 40129,0: POKE 40130,0: LET a=40129
5 FOR n=1 TO 10: FOR k=32 TO 127
6 POKE a,k: LET a=a+1
7 NEXT Q: NEXT n
8 POKE a,255
Теперь сделайте RUN 4 - будет сформирован массив для распечатки всех символов символьного набора:
MeSKi:-,<)x+-./0i£34S&789:;<=>-?eABCDEFeHIJKLMNOPaF:STLIU WKYZ:Ot_£abcdeH9hijkLmri0P4rstuuwH4Z{IJ'1I) !"ttSx£'Ox-b -..'■0i£3456789:;<=>'?GABCDEFGHIJIj!LMNOPQR5TUUWHYZ[Ot_£a bcdeHshiJkLmnopirstuuwHyz-IIJlI) !"ввк4'()>+-./01£54567® 9:j<=>"?SPlECDEFGHI JHLMH0PQR5TUUUIHYZCx Dt_£abcdeH^hi JKLm
FGHIJKLMNOPQRSTUUWXYZ[Ot_£abcdef9hiJKLmnoP4rstuywK yzilJH) !MeJKi:'()y+-./0i£S4567S9:;-;=>?eflBCDEF6HIJKLMNOP QRSTUUWKYZCOt-fabcdefshiALmnop^rituuwHyztlJ'II) !"SS Ki:'Dy+-./01£34567S9:;<=>?eflBCDEF6HIJHLMHOPaRSTUUI)JWYZi: Ot_£abcdefshiJkLmnoP4ritLiuwH4Ztl}1I) !"ttSx£'()x-b-.^ei£ 3456789:;<=>'?GABCDEFGHIJIj!LMN0PQRSTUUWXYZ[ ]t_£abcdef
^eABCDEFGHIJKLMNOPaRSTUUWKYZCOt-fabcdeHshijkLmriOPi. rstuuwH4Z{|}H) !MttSKi:'Oy+-./01£i4567S9:K=^efiBCDEFGHI JKLMNOPQRSTUUWKYZ[Ot_£abcdef9hiJkLmnoP4rstuuwHyz{l J H) !MttSKi:'Oy+-./01£i4567S9:K=^eflBCDEFGHIJHLMH0PQRiT UUIUXYZC-, :t_£abcdef-3hi JkLmnopirstuuwHyzfl }H)
0 OK J 10:1
Приведенную процедуру также удобнее использовать, подключив к своему собственному потоку. Правда, придется несколько потрудиться для того, чтобы модернизировать ее, введя процедуры обработки управляющих кодов, как это сделал автор предыдущего письма.
* * *
Уважаемые читатели. Сегодня мы представляем большую работу Андрея Кулакова из Самарской области. В некоторых точках она соприкасается с той экспресс-информацией, которую мы давали в прошлом номере РЕВЮ по непосредственному управлению контроллером 1818ВГ93 (письмо Алексея Лязгина из Мурманска). Теперь читатели смогут познакомиться с обширным, систематизированным материалом. Поэтому, не нарушая полноту и стройность изложения, даем этот достойный труд целиком.