ЧИТАТЕЛЬ - ЧИТАТЕЛЮ
Печать крупноформатных изображений
Уважаемая редакция!
Мы являемся давними читателями Вашего журнала и поклонниками ZX Spectrum. И вот, читая № 4 за 1995 г., натолкнулись на идею, которой пользуемся уже длительное время (статья
IN |
A,(#7B) |
RLA |
|
JR |
NC,PRINT |
CALL |
#1F54 |
JR |
C,WAIT |
RST |
8 |
DEFB |
20 |
OUT |
( #7B) ,A |
OUT |
(#FB),A |
RET |
|
А.Беседина в "Форуме"). Выносим на Ваш суд её развитие. Полагаем, что предложенная программа окажется весьма полезной для многих любителей, занимающихся "железом". Но прежде отвечаем на вопрос А. Беседина.
На четырёх квадратах внизу (режим Scrapbook) указана привязка окна выбранного элемента к курсору, который будет "таскать" его по экрану. Если учесть, что квадратик курсора не может выходить за левую, правую и нижнюю границы экрана, становится ясным назначение 4-х вариантов. Это имеет значение, когда окно впечатывается вплотную к какой-либо границе экрана. При неправильном выборе часть окна может выйти за границу, и соответствующий кусок изображения будет потерян. А развитие идеи простое: ART STUDIO-128 исключительно удобна для рисования принципиальных схем. В режиме Scrapbook легко создаются изображения стандартных элементов, которые затем используются в работе. На экране стандартным способом рисуются конкретные элементы схем (с указанием нумерации выводов и пр.). Выбранные элементы поочередно помещаются в окно и включаются в спрайтовый набор функцией INSERT режима Scrapbook. Далее изготовленный набор спрайтов сохраняется на диске. Работа выполняется один раз и надолго. Таких файлов - наборов может
быть несколько: логические микросхемы, аналоговые элементы, узлы функциональных схем и т.д. Имея такие наборы рисование электрических схем выполняется весьма быстро.
И вот тут встает вторая, но не менее важная задача: а если схема большая и в один экран не помещается? Выход прост - разбить всё поле схемы на набор экранов, как картинку в детских кубиках. А для вывода на принтер использовать предлагаемую ниже программу. Итак, схема разбивается на участки, назовём их, например, f$_nm, где n-номер экрану по Y, a m- по X, как показано рис. 1:
ft 11 |
ft_12 |
f$_13 |
f$ 14 |
Ось X |
ft 21 |
f$ 22 |
ft 23 |
ft 24 |
Ось Y |
|
Рис. 1
Индексная нумерация удобней, чтобы не запутаться в именах файлов при распечатке. Программа распечатает все изображения, состыковав их без зазора как по горизонтали, так и по вертикали. Изображение печатается повернутым на 90 градусов, и вот почему. Экранные байты информации в знакоместах расположены горизонтально, а на принтер нужно выдавать "вертикальный" байт: 7-е биты всех 8 линий знакоместа, затем 6-е и т. д. Повернув все изображение на 90 градусов выдаем на принтер байты из нужных файлов, загруженных в RAM, рассчитав лишь их адреса. Сначала печатаются экраны f$_11, f$_21..., затем f$_12, f$_22... и т.д. Таким образом на печать выводится вертикальный столб первого знакоместа строки по всем n экранам, затем второй, и т.д. до последнего. После этого в RAM загружаются следующие n экранов. Разумеется, каретка принтера печатает, как и положено, слева направо.
Максимальный размер изображения по вертикали (относительно экранов) ограничен размером каретки принтера. Размер по горизонтали ограничен только размером листа бумаги. Например, на стандартном листе умещается формат 2x3 экранов (т.е. 6). Для принтеров с широкой кареткой соответственно больше.
Данная программа удобна и в других ситуациях. Например, для распечатки в виде единого массива серии записанных на диск страниц журнала SPECTROFON. Да мало ли для чего.
Текст загрузчика программы приведен в Листинге 1 и кодовый блок в Листинге 2. BASIC -часть особых пояснений не требует. В строке 70 вводится число экранов по горизонтали, а в строке 80 - по вертикали. В индексной нумерации экранов (файлов) первым подразумевается
ЧИТАТЕЛЬ - ЧИТАТЕЛЮ
номер по Y сверху вниз, а вторым - по X слева направо. Вывод каждой строки на принтер происходит в два этапа. Сначала формируется полная строка в буфере с адреса 61000, а затем она непосредственно выводится ни принтер. Вывод байтов сразу на принтер часто приводил к зависаниям последнего. Буфер устранил недостаток.
В программе используется драйвер принтера (PRINTR) для интерфейса ZX LPRINT III. В случае использования интерфейса на базе порта КР580ВВ55 следует изменить строки 980-990, 1750-1880 и добавить 992-995. Изменения отражены в Листинге 3.
Тем, у кого нет 128К RAM, можно работать с обычной версией ART STUDIO, набирая элементы по знакоместам, поработав с Font Editor меню TEXT. И ещё один полезный совет. Для стыковки соседних изображений удобно использовать тот же режим Scrap-book, оформив приграничную область, как элемент и поместив его на RAM-DISK. Но тут есть ограничения: размер такого элемента не может превышать 18 знакомест (большие куски у нас обрезаются). Иначе говоря, имеем аналог функции "Insert Window" из ARTIST 2.
В качестве примера распечатки (но не более того) направляем Вам схему программатора. Поле схемы состоит из 3x3 экранов, а площадь листа использована ещё не полностью. Ещё большие форматы уже просто неудобны практически. (ИФК: присланную схему мы опубликовать не можем из-за огромного размера, но можете нам поверить - она впечатляет!).
Теперь несколько слов на другую тему. На страницах журнала уже неоднократно писалось о том, что некоторые программы из-за некорректного опроса Kempston-Joystic не идут на машинах, где он не реализован. Один из примеров - ZX Word 2.1. После опроса порта IN A,(#1F) поочередно анализируются биты аккумулятора и при установке первого опрошенного активизируется соответствующая подпрограмма. Если Kempston не реализован, из порта считывается байт #FF, и раздражение вам гарантировано. Один из способов лечения такой. Каким-нибудь монитором (например ADM 7.08) найти команду IN A,(#1F) в листинге. Она занимает два байта, которые следует заменить на: XOR A - NOP. Программа воспримет такую замену, как наличие Kempston в неактивном состоянии. Если же программа хорошо защищена, придётся попотеть, снимая защиту (что ещё при этом получится?) или отказаться от неё вовсе.
Листинг 1
10 CLEAR 29500
15 BORDER 1: PAPER 1: INK 6: CLS
20 RANDOMIZE USR 15619: REM: LOAD "prin1" CODE
30 CLS: PRINT #0;"Insert disk with screen": PAUSE 0
40 RANDOMIZE USR 15619: REM: CAT
50 LET addr=31000
60 POKE 29996,addr-256*(INT(addr/256)): POKE 29997,INT(addr/256)
70 INPUT "Number of screen X-? ";x
80 INPUT "Number of screen Y-? ";y: POKE 29995,у
90 RANDOMIZE USR 30000
100 FOR j=1 TO x
110 LET addr=31000
120 FOR i=1 TO у
130 GO SUB 300: PRINT AT 21,0;" Name of Y=";i;" to X=";j;" screen-?":
PAUSE 20: INPUT N$ 132 IF N$="" THEN GO SUB 300: PRINT INK 2; PAPER 4; FLASH 1; AT
21,0;"lnput BAD !": PAUSE 0: GO TO 130 140 LET err=USR 15619: REM: LOAD N$ CODE addr,6144
142 IF err<>0 THEN GO SUB 300: PRINT INK 3; PAPER 4; AT 21,0;" File
not found ": PAUSE 0: GO TO 130 150 LET addr=addr+614 4 160 NEXT i
170 RANDOMIZE USR 30003
180 NEXT j
190 CLS: PRINT AT 21,0; INK 3; PAPER 4; FLASH 1;"All printed" 2 00 PAUSE 0: GO TO 3 0
300 PRINT INK 1; PAPER 1; AT 21,0;" "
310 RETURN
9998 RANDOMIZE USR 15 619: REM: ERASE "V_PRINT"
9999 RANDOMIZE USR 15 619: REM: SAVE "V_PRINT" Для сохранения модуля на диске дать команду GO TO 9998
Листинг 2 (для кодового блока "prin1")
10 ;+--------------------------------------------------------------+
Программа распечатки поворотом
ORG 29993
BUF
BUF1
Y
START NUMBER
20 22 25 27 30 40 50 60 70 80 90
графических изображений единым блоком с на 90 градусов =$erg &Со= 1994
;Адрес, буфера для вывода на принтер ;Адрес текущей ячейки буфера ;Число экранов по Y ; Адрес хранения экранов ;Число пикселей в n экранах по ;вертикали.
100 ;-----
110 INIT
12 0 ;-----
130 140
150 L5 160 170 180 190 200 210 220 230 240 250 260
27 0 ;-----
280 PVERT
290
300
310
320
330 L4 340
350 360 370 380
DI
XOR
CALL
CALL
CALL
I NC
СР
JR
CALL
EI
RET
A
INITGR
PVERT
CRLF
A 32
NZ, L5 CLRAM
ВС AF
A, (Y
B, A AF MASS
P1ST
L4
ВС
;Инициализация принтера
B A - номер позиции столбца (0-31) 3апись в буфер команды принтера "графический режим одинарной плотности" Вывод в буфер вертикального столбца для n экранов
Выдача на принтер всей строки буфера и кодов #^-#0А
Переход наследующий столбец ;TEST на последний столбец
; Очистка RAM
;B A - номер позиции столбца ;B B - число экранов по Y
; Вычисление адреса нижнего байта столбца ; для каждой позиции знакоместа оче-;редного экрана
;Запись в буфер столбца одного экрана
390 |
|
|
|
|
400 |
MASS |
PUSH |
ВС |
|
410 |
|
PUSH |
DE |
|
420 |
|
LD |
DE,6144 |
;Число байт в одном экране |
430 |
|
LD |
HL,(START) |
|
440 |
|
DEC |
B |
|
450 |
|
JR |
Z , M1 |
|
460 |
L6 |
ADD |
HL,DE |
/Суммируем экраны без нижнего |
470 |
|
DJNZ |
L6 |
|
480 |
M1 |
LD |
DE,6112 |
;Смещение нижнего байта 0 позиции для |
490 |
|
|
|
; нижнего экрана |
500 |
|
ADD |
HL, DE |
|
510 |
|
LD |
D, 0 |
|
520 |
|
LD |
E, A |
|
530 |
|
ADD |
HL, DE |
/Добавляем к адресу нижнего байта сме^ |
540 |
|
|
|
; щение на номер позиции столбца |
550 |
|
POP |
DE |
|
560 |
|
POP |
ВС |
|
570 |
|
RET |
|
|
580 |
|
|
|
|
|
|
|
|
590 |
P1ST |
PUSH |
DE |
|
600 |
|
PUSH |
ВС |
|
610 |
|
LD |
DE,2048 |
/Число байт в вертикальном столбце ;сегмента |
620 |
|
LD |
B, 3 |
; Число сегментов в экране |
630 |
|
PUSH |
HL |
/Адрес нижнего байта столбца экрана |
640 |
L3 |
CALL |
P1SSEG |
/Вывод в буфер байтов столбца сегмент |
650 |
|
SBC |
HL, DE |
/Переход на следующий сегмент |
660 |
|
DJNZ |
L3 |
|
670 |
|
POP |
HL |
|
680 |
|
POP |
ВС |
|
690 |
|
POP |
DE |
|
700 |
|
RET |
|
|
710 |
|
|
|
|
|
|
|
|
720 |
DP1SSEG |
PUSH |
DE |
|
730 |
|
PUSH |
ВС |
|
740 |
|
LD |
DE,32 |
/Число знакомест в строке экрана |
750 |
|
LD |
В, 8 |
/Число знакомест в столбце сегмента |
760 |
|
PUSH |
HL |
/Адрес нижнего байта столбца сегмента |
770 |
L2 |
CALL |
P1ZN |
/Вывод в буфер байтов знакоместа |
780 |
|
SBC |
HL, DE |
/Переход на знакоместо выше |
790 |
|
DJNZ |
L2 |
|
800 |
|
POP |
HL |
/ Восстановление адреса нижнего байта |
810 |
|
POP |
ВС |
|
820 |
|
POP |
DE |
|
830 |
|
RET |
|
|
840 |
|
|
|
|
|
|
|
|
850 |
P1ZN |
PUSH |
ВС |
|
860 |
|
LD |
В, 8 |
/ Число линий в знакоместе |
870 |
|
PUSH |
HL |
/ Адрес нижнего байта знакоместа |
880 |
|
PUSH |
AF |
|
890 |
L1 |
LD |
A,(HL) |
|
900 |
CALL |
W_BUF |
;3апись байта в буфер |
910 |
DEC |
H |
; Переход на линию выше |
920 |
DJNZ |
L1 |
|
930 |
POP |
AF |
|
940 |
POP |
HL |
; Восстановление адреса |
950 |
POP |
ВС |
|
960 |
RET |
|
|
97 0 ;===========
980 MNITPR XOR
Остановка strobe=1
Выдача на принтер команды Интервал 12/216
(27-51-12) (для принтеров без автоматического перевода строки значение интервала должно быть не 12, а больше)
; Число экранов по Y ; Число байт в столбце экрана
1020 1030 1040 1050 1060 1070 1080 1090 1100 1110 1120 1130 1140 1150 1160 1170 1180 1190 1200 1210 1220 1230 1240 1250 1260 1270 1280 1290 1300 1310 1320 1330 1340 1350 1360 1370 1380
A, 51 PRINTR A, 12 PRINTR
A, (Y)
B, A DE,192 HL, 0 HL,DE L9
(NUMBER)
LD
CALL LD
CALL
LD
LD
LD
LD
ADD
DJNZ
LD
RET
HL ; Число байт столбце для n экранов
Число байт в столбце для n экранов :Число байт в столбце для n экранов мл.
Число байт в столбце для n экранов ст
и регистра IX перед формированием
; Инициализация ячейки BUF1 ; очередной строки в буфере CLBUF PUSH HL
LD
HL,BUF
INITGR
LD |
(BUF1),HL |
POP |
HL |
LD |
IX, 0 |
RET |
|
PUSH |
AF |
PUSH |
HL |
CALL |
CLBUF |
LD |
A, #1B |
CALL |
W_BUF |
LD |
A, #4B |
CALL |
W_BUF |
LD |
HL,NUMBER |
LD |
A,(HL) |
CALL |
W_BUF |
I NC |
HL |
LD |
A,(HL) |
CALL |
W_BUF |
POP |
HL |
POP |
AF |
Инициализация буфера
|
|
|
|
1390 |
|
RET |
|
|
1400 |
|
|
|
|
|
|
|
|
1410 |
CRLF |
PUSH |
AF |
|
1420 |
|
CALL |
PRIZBF |
|
1430 |
|
LD |
A, 13 |
|
1440 |
|
CALL |
PRINTR |
|
1450 |
|
LD |
A, 10 |
|
1460 |
|
CALL |
PRINTR |
|
1470 |
|
POP |
AF |
|
1480 |
|
RET |
|
|
1490 |
|
|
|
|
|
|
|
|
1500 |
|
|
|
/IX - счётчик длины буфера |
1510 |
W BUF |
PUSH |
HL |
|
1520 |
|
LD |
HL,(BUF1) |
|
1530 |
|
LD |
(HL),A |
|
1540 |
|
INC |
HL |
|
1550 |
|
INC |
IX |
|
1560 |
|
LD |
(BUF1),HL |
|
1570 |
|
POP |
HL |
|
1580 |
|
RET |
|
|
1590 |
|
|
|
|
/ |
|
|
|
1600 |
,• Вывод |
строки |
из буфера в |
принтер до признака: IX=0 |
1610 |
PRIZBF |
LD |
HL,BUF |
|
1620 |
|
PUSH |
DE |
|
1630 |
NZN |
LD |
A,(HL) |
|
1640 |
|
CALL |
PRINTR |
|
1650 |
|
INC |
HL |
|
1660 |
|
DEC |
IX |
|
1670 |
|
PUSH |
IX |
|
1680 |
|
POP |
DE |
|
1690 |
|
LD |
A, D |
/При DE=0 весь буфер выведен |
1700 |
|
OR |
E |
|
1710 |
|
JR |
NZ,NZN |
|
1720 |
|
POP |
DE |
|
1730 |
|
CALL |
CLBUF |
/ Подготовка к записи следующей строки |
1740 |
|
RET |
|
|
1750 |
|
|
|
|
/ |
|
|
|
1760 |
/ Драйвер принтера для ZX |
LPRINT III |
1770 |
PRINTR |
PUSH |
AF |
|
1780 |
PR1 |
IN |
A,(#7B) |
/Опрос готовности принтера |
1790 |
|
BIT |
7,A |
|
1800 |
|
JR |
NZ,PR1 |
/BUSY=1 |
1810 |
|
POP |
AF |
|
1820 |
|
OUT |
(#FB),A |
/Вывод байта информации, strobe=1 |
1830 |
|
NOP |
|
|
1840 |
|
OUT |
(#7В),А |
/Выдача strobe=0 |
1850 |
|
NOP |
|
|
1860 |
|
OUT |
(#FB),A |
/strobe=1 |
1870 |
|
RET |
|
|
1880 |
|
|
|
|
|
|
|
Листинг 3 |
Для интерфейса принтера на базе порта КР580ВВ55 с адресами портов #3F, #5F, #7F и опросом BUSY по шине D7
97 0 ;====================
980 INITPR LD А, #98
;Значение управляющего слова для /программирования ВВ55
990 |
OUT |
(#7A) , A |
/Вывод управляющего слова |
992 |
LD |
A, 01 |
|
995 |
OUT |
(#5F) , A |
/Установка strobe=1 |
1750 |
|
|
|
; |
|
|
1760 |
/Драйвер принтера для |
КР580ВВ55 |
1770 |
PRINTR PUSH |
AF |
|
1775 |
OUT |
(#3F) , A |
/Вывод в порт байта информации |
1780 |
PR1 IN |
A,(#5F) |
/Опрос готовности принтера |
1790 |
BIT |
7, А |
/Контроль BUSY производится по |
1800 |
JR |
NZ,PR1 |
/BUSY=1 |
1810 |
XOR |
А |
|
1820 |
OUT |
(#5F) , A |
/Выдача strobe=0 |
18З0 |
NOP |
|
|
1840 |
INC |
A |
|
1860 |
OUT |
(#5F) , A |
,• strobe=1 |
1865 |
POP |
AF |
|
1870 |
RET |
|
|
7 биту
18 8 0 ;=============================================================
P.S. Недавно пришлось столкнуться с такой проблемой. Имеются принтеры (упрощенные, отечественного производства), которые работают только с Основной кодовой таблицей ГОСТа, к тому же там отсутствуют элементы псевдографики. Современные текстовые редакторы типа ZX-WORD различных версий используют таблицу с альтернативной кодировкой.
Предлагаемый драйвер печати производит перекодировку знаков кириллицы при выводе на принтер. Драйвер рассчитан на использование интерфейса с КР580ВВ55, но его несложно модифицировать для ZX-LPRINT.
10 |
|
ORG |
#5В00 |
|
20 |
|
JR |
INIT |
/Инициализация интерфейса |
30 |
|
NOP |
|
|
40 |
|
JR |
PRINT |
/Печать знака |
50 |
|
|
|
|
|
|
|
|
60 |
INIT |
LD |
А,#98 |
|
70 |
|
OUT |
( #7 F) , A |
/ Вывод управляющего слова в ВВ55 |
80 |
|
LD |
А,1 |
|
90 |
|
OUT |
(#5F) , A |
/Установка strobe=1 |
100 |
|
RET |
|
|
110 |
|
|
|
|
|
|
|
|
120 |
PRINT |
CP |
#80 |
|
130 |
|
JR |
C, PR Z |
/ Для знаков 1 половины таблицы ASCII |
140 |
|
CP |
#E0 |
|
150 |
|
JR |
NC,PR Z |
/Для знаков "р-я" |
160 |
|
CP |
#B0 |
|
170 |
|
JR |
SDWIG |
/Для знаков "А-п" |
180 |
|
LD |
A, #20 |
/Замена псевдографики пробелом |
190 |
PR Z |
OUT |
(#3F),A |
/ Вывод байта информации в порт |
200 |
PRINT1 |
CALL |
#1F54 |
/Тест на BREAK |
210 |
|
JR |
NC,PRINTQ |
/Если BREAK нажата |
220 |
|
IN |
A, (#5F) |
|
230 BIT 7,A /Проверка готовности принтера
240 JR NZ,PRINT1 /При BUSY=1
250 XOR A
260 OUT (#5F),A /Вывод strobe=0
270 INC A
280 NOP
290 OUT (#5F),A /Вывод strobe=1
300 SCF /Установка CY=1
310 CCF /Сброс CY при нормальном завершении
320 RET
33 0 /=============================================================
340 PRINTQ SCF /Установка CY=1 - признак ненормального
/завершения
350 RET
3 60 /=============================================================
370 SDWIG ADD A,#30 /Увеличение кода знаков "А-п" на 48
38 0 JR PR Z /Печать знака