Д.Ю. Усенков
РЕАЛИЗАЦИЯ МНОГОЦВЕТНОЙ ЗАКРАСКИ НА БЕЙСИКЕ
(по следам одной старой ошибки)
В журнале «Информатика и образование» №2 за 1989 г. была опубликована программа для реализации 16-цветной закраски с помощью оператора Бейсика PAINT (автор - С. Зильберштейн). Кратко напомню, о чём шёл разговор. Предлагалось с помощью опубликованной программы в кодах модифицировать Бейсик таким образом, чтобы иметь возможность закрашивать замкнутые области (с помощью PAINT) произвольно выбранным цветом из 16 возможных (из них четыре стандартных), где добавочные цвета задаются пользователем с помощью оператора описания DEF С<номер цвета>=(хххх, хххх, хххх, хххх), где "хххх” - числа, кодирующие цвет.
К сожалению, в опубликованной программе оказались ошибки. Их поиск и устранение сильно усложнились из-за того, что коды были приведены в десятичном формате и отсутствовала контрольная сумма.
Сегодня среди пользователей БК уже имеется аналогичная программа в составе комплекта FBASIC, но она менее удобна - цвет приходится задавать байтами с помощью операторов РОКЕ перед каждым вызовом PAINT, что более сложно и удлиняет программу.
Всё вышесказанное побудило произвести подробный анализ, исправление ошибок и доработку старого варианта программы. И теперь вашему вниманию предлагается программа, позволяющая выполнять всё, что было обещано в упомянутом втором номере «Информатики и образования».
Ниже приводится листинг в кодах (с указанием контрольной суммы) и исходный текст на ассемблере в формате М18. Ассемблерный листинг не только поможет снизить вероятность ошибок при наборе на БК, но и даст возможность при желании легко перекомпилировать программу с другого начального адреса, задать другое количество цветов в палитре и т.д. Кроме того, весьма полезно рассмотреть ассемблер-текст поподробнее «в обучающих целях», так как он является хорошей иллюстрацией некоторых приёмов работы Бейсик-транслятора и способов вмешательства в процесс компиляции.
«Постановка задачи программисту» или «немного о возможностях программы»
Прежде чем писать программу, программист чётко формулирует для себя «техническое задание» - определяет все необходимые операции, которые должна обеспечивать программа. В нашем случае эта задача была поставлена в журнале «Информатика и образование» №2 за 1989 г., но не решена.
Итак, наша программа должна обеспечивать:
- Заливку с помощью PAINT неким дополнительным цветом (грамотнее было бы говорить о цвете и фактуре закраски), заданным пользователем. При этом пользователь задаёт вид элементарного «макро-пиксела», состоящего из 4*4 точек.
- Возможность указания номера, выбранного для закраски дополнительного цвета непосредственно в операторе PAINT, как обычно указывается стандартный цвет заливки. При этом программа должна обеспечивать распознавание номеров стандартных цветов (от 0 до 4) и нестандартных (от 5 до 15). Если задан стандартный цвет, заливка должна производиться как обычно.
- Возможность задания цвета и фактуры для любого нестандартного «цвета» палитры с помощью оператора DEF С<номер>=(хххх, хххх, хххх, хххх), где «хххх» - числа из 4 цифр, определяющие четыре строки «макро-пиксела»:
макро-пиксел запись оператора
DEF C<n> = (1111, 1212, 3322, 4344)
┌─────┬─────┬─────┬─────┐ │ │ │ │
│1 │1 │1 │1 │ │ │ │ │
│ │ │ │ ├───┘ │ │ │
├─────┼─────┼─────┼─────┤ │ │ │
│1 │2 │1 │2 │ │ │ │
│ │ │ │ ├─────────┘ │ │
├─────┼─────┼─────┼─────┤ │ │
│3 │3 │2 │2 │ │ │
│ │ │ │ ├───────────────┘ │
├─────┼─────┼─────┼─────┤ │
│4 │3 │4 │4 │ │
│ │ │ │ ├─────────────────────┘
└─────┴─────┴─────┴─────┘
(цифры 1...4 обозначают общепринятые номера цветов точек, т.е. 1-красный, 2-зелёный, 3-синий, 4-чёрный)
Исходя из этого видно, что алгоритм нашей программы должен включать в себя как минимум три части: алгоритм закраски, алгоритм перехвата и обработки ошибки при задании нестандартного номера цвета в PAINT и алгоритм перехвата синтаксической ошибки при трансляции не предусмотренного в Бейсике оператора DEF С...
Отдельно рассмотрим одну из этих частей - алгоритм многоцветной закраски. Остальные части достаточно хорошо просматриваются при анализе листинга программы на Ассемблере.
Алгоритм многоцветной закраски
Проще всего получить новый цвет, загружая в служебные ячейки Монитора (@#212 - фон, @#214 - передний план) вместо стандартных байтов, кодирующих цвета (177777 - красный, 125252 - зелёный, 52525 - синий, 0 - чёрный), свои значения, кодирующие нужный цвет. Подробно об этом было рассказано в журнале «Вычислительная техника и её применение» № 12 за 1990 г., с. 31. Однако простая подстановка имеет существенный недостаток: получаемый при заливке цвет оказывается всегда «в вертикальную полоску».
В программе GRAF3 применён более совершенный алгоритм: для первой телевизионной строки используется «основной» байт, для второй - тот же байт предварительно проворачивается влево и только затем заносится в ячейку @#214, для третьей строки - ещё раз влево и т.д. Но и у этого алгоритма свой недостаток: он хорошо реализует простые «смесевые» цвета (темно-красный, тёмно-зелёный, тёмно-синий, жёлтый, фиолетовый и голубой, то есть состоящие из «сетки» точек двух каких-нибудь стандартных цветов), а также «гладкие» стандартные цвета. Но вот попытка задать «белый» цвет (смесь трёх цветов) или задать более редкое расположение точек одного цвета по отношению к другому (например, на три черные точки одна зелёная) оканчивается неудачей: проступает явная «полосатость» получаемой закраски либо производится простая «заштриховка» наклонными линиями.
Мы же применим алгоритм ещё более совершенный, и в то же самое время простой. Пусть пользователь сам задаёт четыре отдельных байта для закраски. Тогда можно будет при желании сделать и «сетку», и «штриховку», и сложную фактуру. А наша программа будет всего лишь подставлять в ячейку @#214 один из этих байтов в соответствии с координатой Y требуемой точки, то есть для нулевой строки - первый байт из четырёх, для первой строки - второй, для второй - третий, для третьей - четвёртый, для четвертой - снова первый и т.д.
Итак, новая программа должна перехватывать ЕМТ 30 и ЕМТ 32, определять, относятся ли эти функции к реализации оператора PAINT (ведь нам не нужно менять цвета для LINE, PSET и т.д.), вычислять по значению хранящейся в R2 координаты Y адрес байта в палитре, где записаны по 4 байта на каждый цвет, заносить выбранный байт в ячейку @#214 и после установки точки или линии не забывать восстановить старый цвет рисования. Проще всего это реализовать так: сохраним в стеке значение R2, выделим из него три младших бита - останется число от 0 до 3, прибавим это число к хранящемуся в ячейке @#300 (она используется только при операциях обмена с магнитофоном и мы можем использовать её как буфер) адресу первого байта палитры, соответствующего указанному ранее номеру цвета, занесём байт в ячейку @#214, сохранив предварительно в стеке старое значение из этой ячейки, восстановим истинное значение R2 и отработаем ЕМТ 30 или ЕМТ 32, а затем восстановим из стека старое значение ячейки цвета.
Именно так и сделано в программе. Мы можем увидеть это в первой части листинга, «посвящённой» ЕМТ-перехвату.
Программа начинается с ЕМТ-драйвера. Мы перехватываем на него ЕМТ-прерывание и по сохранённому в стеке адресу возврата определяем точное место, откуда был вызван ЕМТ (из PAINTa, из LINE или откуда-нибудь ещё). Для такой работы полезно иметь ассемблеровский листинг Бейсик-транслятора. (Этот листинг, а также листинг Монитора БК-0010 редакция планирует опубликовать в одном из выпусков приложения к ИНФО - «Персональный компьютер БК-0010 - БК-0011М».)
Если «пойманный» ЕМТ не тот, который нам нужен, производим переход на стандартный драйвер обработки ЕМТов по адресу 100112.
Кстати, нет нужды делать отдельные реализации замены цвета для ЕМТ 30 и ЕМТ 32. В нашей программе производится определение (опять-таки по адресу, с которого был вызван ЕМТ) типа функции (ЕМТ30 или ЕМТ32) и нужный машинный код заносится непосредственно «в тело» самой программы, а затем, после замены цвета, выполняется.
Далее, нам нужно производить перехват ошибок Бейсика. Для этого мы пишем свой драйвер TRAP-прерываний. И первая же строка нашей программы, первое же действие, производимое при любом ЕМТ-прерывании - занесение нового значения адреса обработки прерываний TRAP. Ну а в самом драйвере TRAP мы производим аналогичным способом (по адресам вызова) анализ TRAP-функций, чтобы выделить среди всех возможных вызовов сообщений об ошибках, а также (не следует об этом забывать) вызовов TRAP-подпрограмм самого Бейсика нужные нам ошибку цвета в PAINT и ошибку синтаксиса в DEF. Остальные TRAPы перенаправляем на стандартную обработку.
Если посмотрим на ассемблеровский листинг, то увидим три анализируемых случая TRAP. Во-первых, мы перехватываем первый же служебный TRAP при компиляции оператора PAINT. Это не ошибка, а признак «для нас»: пора вставить в шитый код адрес маленькой самодельной подпрограммки, которая при работе уже откомпилированной Бейсик-программы будет производить исходное обнуление буферной ячейки @#300 перед каждым оператором PAINT (зачем - обсудим позже).
Во-вторых, отлавливается сообщение об ошибке, когда при работе откомпилированной Бейсик-программы БК «замечает», что PAINT задан номер цвета более 4. Теперь нам нужно «сделать вид», что ошибки не было. Мы прежде всего определяем «оставшийся» в R0 после компиляции заданный нами нестандартный номер цвета и вычисляем по нему адрес первого байта из четырёх отведённых для этого цвета в палитре. Записываем адрес в ячейку @#300. Заменяем «условно» цвет закраски на текущий (О), чтобы Бейсик «больше не ругался», и «как ни в чём не бывало» продолжаем работу, переходя к следующему шитому коду. (Разумеется, уже произведена «нормализация» стека, то есть с помощью команды CMP (R6)+,(R6)+ удалены занесённые туда при вызове TRAP четыре байта.)
Затем, уже при постановке точек и линий, ЕМТ-перехватчик заменит «условный» цвет заливки на заданный нами через значение ячейки @#300. Заметим, что если мы задали в PAINT стандартный номер цвета от 0 до 4, то этой ошибки не возникнет, ячейка @#300 останется обнуленной, как это сделала подпрограммка, рассмотренная нами «во-первых», а при отработке ЕМТ наша программа не будет заменять цвет закраски, а просто выведет точку или линию заданным стандартным цветом. Таким образом реализовано одно из дополнительных условий задачи - если цвет стандартный закраска производится как обычно.
И в-третьих, отлавливаем ошибку при компиляции DEF. Точно так же нормализуем стек, а затем выполняем вместо вильнюсского транслятора его работу, то есть сами компилируем наш оператор DEF С<n>=... .
Для этого вначале убираем лишние пробелы между «DEF» и «С» с помощью служебной функции TRAP112. Проверяем, совпадает ли текущий символ исходного текста на Бейсике с символом «С» (латинское заглавное). При компиляции регистр R3 содержит адрес текущего байта исходного текста и мы это используем Если текущий символ не «С», значит, мы действительно ошиблись в Бейсик-программе, и мы генерируем запоздалое TRAP2. Если не ошиблись, продолжаем. Снова убираем незначащие пробелы (если они есть) между «С» и номером цвета с помощью TRAP112. Вызываем подпрограмму, считывающую записанное в десятичной форме в исходном тексте число - номер цвета в палитре и заносим номер в R5 Подпрограмма чтения номера (NUM) сама следит и за синтаксисом (чтобы номер не содержал нецифровых символов), и за значением номера (не менее 5 и не более 15), выдавая в некорректном случае «ОШИБКУ 2». Вновь вызываем TRAP112 для ликвидации пробелов перед знаком равенства и проверяем, действительно ли это знак равенства.
Теперь с помощью другой служебной функции TRAP127 производим поиск открывающей скобки (TRAP127 пропускает пробелы в исходном тексте и возвращает в R3 адрес первого непробельного байта после найденной открывающей скобки). И с помощью подпрограммы PPR анализируем четыре записанных через запятую числа. Сначала первое, мы «на нём стоим». Потом вызываем спецфункцию TRAP126, которая выводит нас аналогично TRAP127 на первый непробельный байт после запятой, и снова вызываем подпрограмму PPR для второго числа. Сделав так четыре раза для четырёх чисел, вызываем TRAP130, которая, аналогично двум предыдущим спецфункциям, возвращает адрес после закрывающей скобки и, наконец, с помощью TRAP106, отсекающей попутно комментарии, переходим на следующую строку исходного Бейсик-текста. И вот теперь возвращаемся в стандартный компилятор.
Как работает подпрограмма PPR, думаю, не стоит разбирать подробно. Это можно сделать и самостоятельно по ассемблер-тексту.
И в качестве своеобразного «резюме» повторим ещё раз сведения об используемых при компиляции регистрах процессора и служебных TRAP-подпрограммах.
ПРИ КОМПИЛЯЦИИ ИСПОЛЬЗУЮТСЯ:
- Регистры:
R3 - адрес текущего байта исходного текста Бейсик-программы (указатель на текущий байт);
R1 - адрес текущей ячейки для записи шитого кода.
- Служебные TRAP-функции:
TRAP 112 - тестирует текущий байт исходного текста и, если это пробел, смещает указатель «вправо», пока не встретит непробельный символ. Таким образом, при компиляции реализуется пропуск незначащих пробелов;
TRAP 127 - аналогичным образом пропускает пробелы, а затем проверяет: если очередной, непробельный символ - открывающая скобка ("("), снова пропускает пробелы после скобки и возвращает в R3 адрес первого непробельного символа в скобках. Если не скобка, генерируется ОШИБКА 2;
TRAP 126 - аналог предыдущей функции, «натасканный» на запятую (",");
TRAP 130 - аналог двух предыдущих по отношению к закрывающей скобке (")");
TRAP 106 - пропускает все байты исходного текста, пока не встретится код 12 - код конца строки. Возвращает в R3 адрес первого байта следующей строки и используется как «завершающий аккорд» при компиляции каждой из строк Бейсик- программы. Кстати, отсекает дополнительные комментарии;
TRAP с номерами менее 100 генерируют текст «ОШИБКА n», где n - номер ошибки, равный номеру TRAP-функции. В Бейсик-трансляторе задействованы не все номера ошибок из возможных, так что при желании вы можете предусмотреть в своих программах свои номера сообщений об ошибках. Нужно только подать TRAP<номер>, а остальное Бейсик сделает сам.
Правила работы с программой
Программа в машинных кодах 16PAIN.BIN должна быть считана в Бейсик с адреса &037300 с помощью оператора BLOAD. Предварительно нужно выполнить оператор CLEAR ,&О37300. Перед компиляцией (то есть ДО ввода команды RUN!) нужно занести адрес начала программы (в нашем случае 37300) в ячейку @#30 оператором POKE &О30,&О<нач.адрес>, набранным в непосредственном режиме. После этого Бейсик-программа запускается на выполнение как обычно.
В Бейсик-программе допустимы операторы:
DEF С<номер> = (хххх, хххх, хххх, хххх) - задание цвета, <номер> - от 5 до 15;
PAINT (X, Y),<номер>,<цвет границы> - закраска внутри контура, <номер> - от 0 до 15, <цвет границы> - от 0 до 4.
Желающие могут перекомпилировать ассемблерный текст в системе типа М18, заменив начальный адрес программы на требуемый (программа неперемещаема). При этом можно также расширить размер палитры, для чего в помеченных звёздочками строках нужно изменить значения констант:
#460 заменить на большее, увеличивая на 4 для каждого добавляемого цвета (при этом уменьшается «действующий» объём стека, и вы тем самым уменьшаете возможности Бейсик-программы);
#17 заменить на новый максимально допустимый номер цвета в палитре.
;
; Драйвер многоцветной графики для оператора PAINT Вильнюсского
;Бейсика (исправленный вариант программы из «ИНФО» №2 за 1989г)
; -------------------------- SCREW(c) -------------------------
;
; Усенков ДЮ. МОСКВА 1992
;
;==============================================================
; Новый EMT-драйвер:
%EMT: MOV #%TRAP,@#34 ; Новый вектор TRAP
; Проверка: откуда вызван ЕМТ?
CMP @R6,#126264 ; ЕМТ30 реализации PAINT?
BNE I1 ;
I2: MOV #104030,KOMMD ; ДА!
BR I3 ;
I1: CMP @R6,#126310 ; ЕМТ30 также из PAINT?
BEQ I2 ; ДА-переход, нет- проверка:
CMP @R6,#126320 ; ЕМТ32 из реализации PAINT?
BNE A1 ;
MOV #104032,KOMMD ;
I3: MOV @#214,-(R6) ; Старый цвет закраски - в стек
TST @#300 ; Цвет закраски-стандартный?
BEQ KOMMD ; ДА-сразу на вывод точки/линии
MOV R2,-(R6) ; НЕТ-формируем цвет закраски:
CMP R6,#460 ; * ; Не затер ли стек палитру цветов?
BHI I4 ; НЕТ-формируем цвет
MOV 2(R6),@#214 ; ДА-восстановим старый цвет за-
TRAP 7 ; краски и выводим "ОШИБКУ 7"
I4: BIC #177774,R2 ; Формируем цвет заливки по коор-
ADD @#300,R2 ; динате Y и номеру цвета из ячейки
MOVB @R2,@#214 ; @#300
MOV (R6)+,R2 ; Восстанавливаем значение Y
KOMMD: EMT 30 ; Рисуем точку/линию
MOV (R6)+,@#214 ; Восстанавливаем цвет закраски.
RTI ; Выход из ЕМТ
A1: JMP @#100112 ; Для других ЕМТ-на стандартный
; драйвер
ERR: JMP @#146404 ; Стандартный драйвер TRAP
; Новый драйвер TRAP:
%TRAP: CMP 4(R6),#145230 ; Компиляция PAINT?
BNE A2 ;
MOV #X1V,(R1)+ ; ДА-заносим в шитый код свой код
BR ERR ; и продолжаем трансляцию
X1V: CLR @#300 ; Подпрограмма предварительного
JMP @(R4)+ ; обнуления номера цвета
A2: CMP @R6,#125172 ; Ошибка при отработке PAINT: не-
; стандартный номер цвета?
BNE A3 ;
CMP (R6)+,(R6)+ ; ДА-нормализуем стек,
SUB #5,R0 ; вычисляем по номеру заданного в
ASL R0 ; PAINT цвета номер в палитре, по-
ASL R0 ; мещаем его в ячейку @#300, для
ADD #400,R0 ; ’’маскировки” ошибки назначаем
MOV R0,@#300 ; цвет, равный 0, и возвращаемся
CLR @R6 ; в программу отработки PAINT
JMP @(R4)+ ;
A3: CMP @R6,#145566 ; Ошибка при компиляции DEF Сп=..?
BNE ERR ; НЕТ - на стандартный драйвер
CMP (R6)+,(R6)+ ; ДА-нормализуем стек,
TRAP 112 ; убираем лишние пробелы,
CMPB (R3)+,'C' ; это наш DEF С?
BNE SYERR ; Нет-ошибка 2
TRAP 112 ; убираем лишние пробелы после "С",
JSR R7,NUM ; считываем номер цвета
BR B ;
SYERR: TRAP 2 ; выход на сообщение об ошибке
B: TRAP 112 ; убираем лишние пробелы перед
CMPB (R3)+,'=' ; дальше идет код "="?
BNE SYERR ; НЕТ-ошибка 2
TRAP 127 ; ищем открывающую скобку
SUB #5,R5 ; формируем адрес ячеек палитры
ASL R5 ; для данного цвета
ASL R5 ;
ADD #400,R5 ;
MOV #3,-(R6) ; Формируем составляющие байты
A: JSR R7,PPR ; п/пр чтения очередного числа
TRAP 126 ; ищем запятую
DEC @R6 ;
BGT A ;
TST (R6)+ ;
JSR R7,PPR ; последнее число
TRAP 130 ; поиск закрывающей скобки
TRAP 106 ; выход на следующую строку Бейсик
; программы
RTS R7 ; выход на продолжение компиляции
;
PPR: CLR -(R6) ; Подпрограмма формирования байтов:
MOV #4,R2 ;
AA: ASR @R6 ; загружает очередное 4-цифровое
ASR @R6 ; число из списка и формирует по
MOVB (R3)+,R4 ; нему байт для палитры
SUB #64,R4 ;
NEG R4 ;
CMP R4,#3 ;
BHI SYERR ;
SWAB R4 ;
ASR R4 ;
ASR R4 ;
BIS R4,@R6 ;
SOB R2,AA ;
MOV (R6)+,R4 ;
MOVB R4,(R5)+ ; Готовый байт заносим в палитру
RTS R7 ;
; ; Подпрограмма чтения цвета:
NUM: MOV R0,-(R6) ;
CLR R5 ;
1: CMPB @R3,'0' ; заносит в R5 номер цвета, за-
BLO 2 ; данного в описании DEF С<номер>
CMPB @R3,'9' ;
BHI 2 ;
ASL R5 ;
MOV R5,R0 ;
ASL R5 ;
ASL R5 ;
ADD R0,R5 ;
MOVB (R3)+,R0 ;
SUB '0',R0 ;
BIC #177400,R0 ;
ADD R0,R5 ;
BR 1 ;
2: CMP R5,#5 ;
BLO 3 ;
CMP R5,#17 ; * ; Ограничение кол-ва цветов
BHI 3 ;
MOV (R6)+,R0 ;
RTS R7 ;
; ;
3: TRAP 2 ; Ошибочный номер цвета
;
;--------------------------------------------------------------
Кодовый листинг программы 16PAIN.BIN
НАЧ. АДРЕС : 037300 ДЛИНА : 000500
|
012737 |
037436 |
000034 |
021627 |
126264 |
001004 |
012767 |
104030 |
|
000074 |
000411 |
021627 |
126310 |
001771 |
021627 |
26320 |
001033 |
|
012767 |
104032 |
000050 |
013746 |
000214 |
005737 |
000300 |
001417 |
|
010246 |
020627 |
000460 |
101004 |
016637 |
000002 |
000214 |
104407 |
|
042702 |
177774 |
063702 |
000300 |
111237 |
000214 |
012602 |
104030 |
|
012637 |
000214 |
000002 |
000137 |
100112 |
000137 |
146404 |
026627 |
|
000004 |
145230 |
001006 |
012721 |
037454 |
000767 |
005037 |
000300 |
|
000134 |
021627 |
125172 |
001013 |
022626 |
162700 |
000005 |
006300 |
|
006300 |
062700 |
000400 |
010037 |
000300 |
005016 |
000134 |
021627 |
|
145566 |
001343 |
022626 |
104512 |
122327 |
000103 |
001004 |
104512 |
|
004767 |
000134 |
000401 |
104402 |
104512 |
122327 |
000075 |
001373 |
|
104527 |
162705 |
000005 |
006305 |
006305 |
062705 |
000400 |
012746 |
|
000003 |
004767 |
000022 |
104526 |
005316 |
003373 |
005726 |
004767 |
|
000006 |
104530 |
104506 |
000207 |
005046 |
012702 |
000004 |
006216 |
|
006216 |
112304 |
162704 |
000064 |
005404 |
020427 |
000003 |
101333 |
|
000304 |
006204 |
006204 |
050416 |
077216 |
012604 |
110425 |
000207 |
|
010046 |
005005 |
121327 |
000060 |
103417 |
121327 |
000071 |
101014 |
|
006305 |
010500 |
006305 |
006305 |
060005 |
112300 |
162700 |
000060 |
|
042700 |
177400 |
060005 |
000756 |
020527 |
000005 |
103405 |
020527 |
|
000017 |
101002 |
012600 |
000207 |
104402 |
000000 |
000000 |
000000 |
КОНТРОЛЬНАЯ СУММА: 011047
И.А. Сапегин
О ПРИРУЧЕНИИ КЛАВИШИ "СТОП"...
В ИНФО №2 за 1992 г. была напечатана статья Д. Якошвили "Обработка прерываний по клавише СТОП средствами Бейсика". Способ определения адреса начала "шитого кода" строки, предложенный автором, имеет несколько недостатков. Во-первых, он очень трудоёмкий. Во-вторых, даже при небольшом изменении программы приходится проводить всю работу заново.
Я предлагаю программу, свободную от этих недостатков:
1 FOR I=РЕЕК(1044)+4 ТО 16384 STEP 6 2 IF ABS(65536*(SGN(PEEK(I))-1))/2+PEEK(I)=<A> THEN POKE 514,PEEK(I-4) ELSE 7 3 POKE 512,5572 4 POKE 516,92 5 POKE 4,512 6 GOTO 10 7 NEXT I 10 REM ...ВАША ПРОГРАММА...
Во второй строке <А> - это номер строки в вашей программе, куда нужно перейти при нажатии клавиши СТОП.
При запуске программа сама определит адрес начала "шитого кода” нужной строки. Для этого используется таблица номеров строк, адрес начала которой записан в ячейке 1044 (здесь и далее все адреса десятичные). В этой таблице для каждой строки записано три параметра: адрес начала "шитого кода” строки, адрес начала её исходного текста и номер.
Моя программа последовательно просматривает все номера строк в этой таблице и, найдя требуемый, записывает адрес начала ’’шитого кода", соответствующего нужной строке, в ячейку 514.
Подпрограмма в машинных кодах, расположенная в памяти с адреса 512 и заносимая туда строками 3 и 4, работает так, как написано в статье Д. Якошвили.
ОТ РЕДАКЦИИ
Письмо И.А. Сапегина продолжает начатую в прежних публикациях тему о "приручении" клавиши СТОП в Бейсике. Предлагаемая им программа позволяет "подвешивать" клавишу СТОП на нужную строку полностью автоматически, не производя при этом длительных и запутанных ручных расчётов и поисков, описанных в статье Д. Якошвили.
Хотелось бы добавить к сказанному автором следующее. Во-первых, в программе не предусмотрен контроль за существованием строк, и, если в качестве <А> вы зададите номер несуществующей строки, реакция БК будет, мягко говоря, непредсказуемой. Во-вторых, если ваша программа не изменяет искусственно при своей работе шитый код и содержимое ячейки @#4, то после выхода из программы в диалоговый режим по оператору STOP или END нажатие на клавишу СТОП по-прежнему вызывает переход на заданную Бейсик-строку. Таким образом данный эффект даёт возможность повторного запуска Бейсик-программы, заменяя собой команду RUN <номер строки> или GOTO <номер строки>.
Р. Аскеров
ЕСЛИ НЕТ ПРИНТЕРА...
... и вам нужна копия с экрана БК, и не одна - как быть? Если у вас есть фотоаппарат и вы можете подключить свой компьютер к телевизору с размером экрана по диагонали 50-60 см, то нет проблем!
После длительных экспериментов в Брянском клубе пользователей БК разработана методика съёмок с экрана ТВ. Использовался дальномерный фотоаппарат ФЭД5В и черно-белый телевизор КАСКАД-230 с диагональю 59 см. Аппарат устанавливается на штативе (впрочем, снимать можно и «с рук», жертвуя при этом чёткостью) на расстоянии 1 м от экрана, видоискатель наводится на точку, отстоящую на 13 см от верхней кромки экрана и на 23 см от левой. На шкалах фотоаппарата устанавливаются значения выдержки 1/30, диафрагмы 2.8, дальности 1 м. Спуск затвора можно производить как через фототросик, так и непосредственным нажатием на кнопку.
На негативах изображение получается чётким, во весь кадр, и в дальнейшем может быть увеличено в любое количество раз и переведено на фотобумагу. К сожалению, при использовании некоторых видов плёнки изображение может оказаться слегка неравномерным по яркости из-за особенностей телевизионного экрана.
ПРИМЕЧАНИЕ РЕДАКТОРА
Данный совет полезен не только пользователям БК, но и всем, кто работает с домашними ПЭВМ, тем более что многие «самодельные» компьютеры вообще не рассчитаны на подключение принтера. Практическая ценность предложенного Брянским клубом пользователей БК совета значительно повышается и за счёт того, что в нём приведены готовые рекомендации при пересъёмке изображения на экране с помощью фотоаппарата с видоискателем, а работать таким фотоаппаратом в подобных случаях намного сложнее, чем зеркальной фотокамерой.
Следует также сказать, что и на профессиональных персональных компьютерах в составе графических станций, оснащённых принтерами и графопостроителями, также используется фотографическая пересъёмка изображения на экране с помощью специализированных фотокамер. Подробнее об этом можно узнать из книги «Компьютер обретает разум» (М.: Мир, 1990, с. 138).
Однако справедливости ради следует заметить, что предлагаемая идея использования фотоаппарата для получения копии экрана на БК не нова. О ней, в частности, говорилось на страницах журнала «Наука и жизнь» (1986, №10, с. 113, заметка читателя И. Львова из Москвы). В «Науке и жизни» предлагалось производить пересъёмку с экрана зеркальной фотокамерой «Зенит» со штатива в затемнённой комнате (для устранения бликов на экране) Объектив «Волна-9», плёнка 32 или 65 ед. ГОСТ. Диафрагма 5.6 - 8 с выдержкой 3 - 4 с для 32 ед или 1 - 2 с для 65 ед. (выдержка отрабатывается вручную). Проявитель стандартный, время проявления - указанное на коробочке с плёнкой.