ПАКЕТ ПРОГРАММ ДЛЯ РАБОТЫ С ПЕРИФЕРИЙНЫМ ПРОЦЕССОРОМ ЭВМ ТИПА МС0511 (УКНЦ) U┤K┤G┤R┤A┤P┤H - 1 - СОДЕРЖАНИЕ ВВЕДЕНИЕ ............................................. 3 1. НАЧАЛО РАБОТЫ С ПАКЕТОМ ........................... 4 2. ОПИСАНИЕ ИНТЕРФЕЙСА ПРОГРАММ НА PASCAL С ПАКЕТОМ ┤┤┤UKLOAD (БИБЛИОТЕКА PASINT.OBJ) .................... 6 2.1. Использование процедур библиотеки в программах .. 6 2.2. Система координат ............................... 6 2.3. Цвет в УКНЦ ..................................... 6 2.4. Процедуры библиотеки PASINT.OBJ ................. 7 2.4.1. Графические примитивы ......................... 7 2.4.2. Задание типа линии ............................ 8 2.4.3. Работа со спрайтами ........................... 9 2.4.3.1. Общие замечания ............................. 9 2.4.3.2. Действия со спрайтами ....................... 11 2.4.3.2.1. Простой вывод спрайта ..................... 11 2.4.3.2.2. Задание атрибутов перемещения спрайтов .... 11 2.4.3.2.3. Перемещение спрайта ....................... 12 2.4.3.2.4. Перемещение группы спрайтов ............... 12 2.4.3.2.5. Разрешение/запрет вывода 1-го спрайта ..... 13 2.4.3.3. Программная загрузка и выгрузка спрайтов .... 14 2.4.4. Работа с текстовыми окнами .................... 16 2.4.5. Дополнительные удобства ....................... 16 2.4.5.1. Атрибуты алфавитно-цифрового вывода ......... 17 2.4.5.2. Управление рулоном .......................... 17 2.4.5.3. Вывод в служебные строки .................... 18 2.4.5.4. Межзадачная почта ........................... 18 2.4.5.5. Управление самопроверкой состояния .......... 19 2.4.5.6. Работа со звукогенератором .................. 19 2.4.5.7. Двухоконный режим ........................... 20 2.4.5.8. Нестандартный алфавитно-цифровой вывод ...... 20 2.4.5.9. Идентификация UKLOAD ........................ 21 3. ОПИСАНИЕ ИНТЕРФЕЙСА UKLOAD С ЯЗЫКОМ "СИ" .......... 21 3.1. Построение исполняемой программы ................ 21 3.2. Имена и функции ................................. 22 4. РАБОТА С UKLOAD НА MACRO .......................... 22 4.1. Общие замечания ................................. 22 4.2. Библиотека GLIB.MLB ............................. 22 4.2.1. Отличия от GLIB и PASINT ...................... 22 4.2.2. Дополнительная информация о спрайтах .......... 23 4.2.3. Доступ к системным ресурсам ................... 25 4.2.3.1. Управление таймерами ........................ 25 4.2.3.2. Информация об UKLOAD ........................ 25 4.2.3.3. Словный обмен с ОЗУ ПП ...................... 25 4.2.4. BATCH-средство ................................ 26 5. ПРОГРАММЫ ПОДГОТОВКИ СПРАЙТОВ ..................... 28 5.1. Редактор спрайтов (SPRRED) ...................... 28 5.1.1. Назначение редактора .......................... 28 5.1.2. Запуск редактора .............................. 28 5.1.3. Правила обращения с редактором ................ 28 5.1.4. Терминология редактора ........................ 28 5.1.5. Команды редактора ............................. 29 5.1.6. Префиксные команды ............................ 29 5.2. Конвертер спрайтов (SPRCNV)...................... 30 5.3. Программа загрузки спрайтов (SPRLOA) ............ 31 6. МУЗЫКАЛЬНЫЙ РЕДАКТОР (MUZRED) ..................... 32 - 2 - 7. СИСТЕМНО-НЕЗАВИСИМЫЙ НАБОР ПРОЦЕДУР ОБМЕНА С ПП ┤┤┤(PSERV.OBJ) ....................................... 33 7.1. Запросить участок памяти в ОЗУ┤ПП ............... 34 7.2. Переписать из ОЗУ┤ЦП в ОЗУ┤ПП ................... 34 7.3. Переписать из ОЗУ┤ПП в ОЗУ┤ЦП ................... 34 7.4. Освободить участок памяти в ОЗУ┤ПП .............. 34 7.5. Передать управление программе в ОЗУ┤ПП .......... 34 8. ОПИСАНИЕ ДРАЙВЕРА PP.SYS .......................... 35 9. МОДУЛЬ ЗАГРУЗКИ ФОНТОВ (FNTLOA) ................... 37 ПРИЛОЖЕНИЕ 1. Протокол обмена с UKLOAD ............... 39 ПРИЛОЖЕНИЕ 2. Комплект поставки ...................... 41 - 3 - ВВЕДЕНИЕ Данное программное обеспечение предназначено как для системных программистов, так и для разработчиков прикладных программ, ра- ботающих с ЭВМ МС0511. Программы, входящие в состав пакета обеспечивают следующие функции: -┤богатый набор графических и музыкальных процедур, вызываемых из программ, написанных на языках PASCAL, MACRO, C; -┤работу с окнами; -┤работу со спрайтами (создание, регистрация, загрузка, вывод и управление движением как одиночного спрайта, так и группы не- зависимых спрайтов); -┤вызовы командных строк из программ, написанных на языках PASCAL, MACRO, C; -┤обслуживание стандартных запросов к ПП и выполнение операций с ОЗУ┤ПП; -┤доступ к системным ресурсам; -┤создание и загрузка фонтов (шрифтов) пользователя. Быстрый вывод графики и спрайтов (без обращения к ПЗУ ПП) позво- ляет использовать эти средства для создания мультипликации. В состав пакета программного обеспечения работы с периферийным процессором УКНЦ входят следующие модули: PP┤┤┤┤.SYS┤-┤драйвер обмена с периферийным процессором (ПП); UKLOAD.SAV┤-┤программа вывода аудио и видеоинформации, загружаемая в память (ПП); PASINT.OBJ┤-┤программный интерфейс между про граммами на языке PASCAL и программой UKLOAD; CINT┤┤.OBJ┤-┤программный интерфейс между программами на языке C и программой UKLOAD; PSERV┤.OBJ┤-┤системно-независимый набор процедур обмена с ПП; FNTLOA.SAV┤-┤модуль загрузки фонтов (шрифтов) пользователя; SPRRED.SAV┤-┤редактор спрайтов (создает и редактирует спрайты в формате FTX); SPRCNV.SAV┤-┤конвертер спрайтов из FTX-формата на МАКРО-11; SPRLOA.SAV┤-┤загрузчик спрайтов в память ПП; GLIB┤┤.SAV┤-┤макробиблиотека общения с UKLOAD. - 4 - 1. НАЧАЛО РАБОТЫ С ПАКЕТОМ ~~~~~~~~~~~~~~~~~~~~~~~~~~ Для начала работы с пакетом необходимо запустить программу UKLOAD.SAV командой: R UKLOAD┤┤┤┤┤┤ или RU UKLOAD или RUN DEV:UKLOAD где DEV - имя устройства. В результате резидентная часть программы загружается в ОЗУ┤ПП и начинает работу. После запуска программы могут появиться следующие сообщения: Ukload already loaded! Unload, are you sure? Это значит, что программа уже находится в памят и необходимость пов- торной загрузки сомнительна. Однако, если у Вас есть к тому веские основания, можете ответить удовлетворительно, и загруженная копия программы будет заменена. В противном случае в ОЗУ┤ПП будет загружена новая копия программы. Учтите, что объем ОЗУ┤ПП ограничен, а загрузка новой копии "съест" еще около 15К. Так что при отрицательном ответе возможно возникновение сообщения о невозможности загрузки из-за не- хватки п амяти (см. далее). Wrong version of Ukload! Unload, are you sure? Это значит, что в памяти находится старая версия программы Ukload или любая другая программа, ответившая на запрос версии. Если Вы у верены, что ответ поступил от программы Ukload, то ответьте на этот запрос утвердительно. При этом будет проведена попытка выгрузки загруженной копии программы и загрузки на ее место новой. Однако учтите, что если ответившая программа не является более ранней версией Ukload, то, скорее всего, это приведет к необходимости перезагрузки. При отрица- тельном ответе на этот запрос будет проведена попытка дозагрузки но- вой копии Ukload в ОЗУ┤ПП. Wrong load adress of Ukload. Unloading aborted! New version version loaded! Это значит, что при попытке выгрузить загруженную копию был отмечен недопустимый адрес загрузки старой копии. При этом замена старой копии новой считается недопустимой и загружается новая копия. Такой же смысл имеет сообщение: Wrong length of Ukload! Unloading aborted! New version loaded! Not enough available memory for loading Ukload. Это значит, что свободной части ОЗУ┤ПП не хватает для загрузки Ukload. При возникновении этого сообщения необходимо проанализировать свои действия, и, если не найдется другой возможности, нажать кнопку RESET, либо отказаться от загрузки программы. Запуск в этом случае прошел нормально, однако Вам стоит заду- маться том, что на Вашей ЭВМ ненормально велико время передачи данных по каналу 1 (см. "Руководство системного программиста"). - 5 - Если никаких сообщений на экане не возникло, то запуск прошел нормально. После загрузки программа сразу устанавливает оба сетевых таймера во включенное состояние, устанавливает корректные задержки перехода с дорожки на дорожку для 80-дорожечного дисковода, устанавливает дискретный скроллинг, устанавливает назначения на клавиши К1┤-┤К5 и переносит стандартные вызовы, исполняемые ПЗУ и имеющие коды 240┬8└...260┬8 на коды 140┬8└...160┬8 (см. "Руководство системного программиста"). - 6 - 2. ОПИСАНИЕ ПРОГРАММНОГО ИНТЕРФЕЙСА ДЛЯ ПРОГРАММ, НАПИСАННЫХ НА PASCAL'е, К ПРОГРАММЕ UKLOAD 2.1. Использование процедур библиотеки в программах┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ При написании программ, работающих с графикой необходимо описать используемые Вами графические процедуры как внешние. Например: PROCEDURE INIT;┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤EXTERNAL; PROCEDURE SETCOLOR(COLOR:INTEGER);┤┤┤EXTERNAL; ВНИМАНИЕ!┘ Для корректной работы программ на языке Паскаль необ- ходимо описывать внешние процедуры на том уровне, на котором они используются. Пакет PASINT.OBJ необходимо указывать при компоновке основной программы (команда LINK). Перед запуском Вашей программы необходимо загрузить программу UKLOAD.SAV описанными выше командами. 2.2. Система координат . ~~~~~~~~~~~~~~~~~~~~~~~~ Точка с координатами (0,0) находится в левом верхнем углу экрана. Ось X направлена слева направо, ось Y - сверху вниз. Пределы изменения координат по X - 0▒640, по Y - 0▒260. Необходимо помнить, что пакет не обеспечивает масштабирования и не проверяет корректность задания координат, т.е. все попытки поставить точку за пределы экрана попросту игнорируются и выводится только то, что помещается на экране (т.е. если один конец линии выходит за поле вывода, то лишнее отсекается), без каких-либо сообщений о Вашей ошибке. С помощью процедуры VIEWPORT можно уменьшить поле вывода (объявить "окно"), а процедурой ОFFSET - задать смещение примитивов относительно точки привязки окна. 2.3. Цвет в УКНЦ┘. ~~~~~~~~~~~~~~~~~~ Цвет точки в МС-0511 задается тремя битами. Нулевой бит показы- вает, нужно ли отображать точку в плане 0, первый - в плане 1, вто- рой - в плане 2. Таким образом, диапазон допустимых номеров цветов: 0▒7. Если номер цвета не попадает в этот диапазон , то лишние биты просто отсекаются. - 7 - 2.4. Процедуры библиотеки PASINT.OBJ┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2.4.1. Графические примитивы┘. PROCEDURE INIT; Процедура начальной инициализации графики. Указывается в начале работы с пакетом и служит для проверки корректности номера версии и номера реализации загружаемой части пакета и интерфейса, установки переменных пакета и загружаемой части в исходное состояние: -┤смещение поля вывода┤-┤0; -┤параметры окна┤-┤весь экран; -┤цвет вывода┤-┤7; -┤тип вывода┤-┤0 (см. ниже). PROCEDURE SETCOLOR(COLOR:INTEGER); Установка цвета вывода. Параметр COLOR может принимать восемь зна- чений, а именно от 0 до 7. Значение COLOR по умолчанию┤-┤7. PROCEDURE VIEWPORT(X1,Y1,X2,Y2:INTEGER); Задание поля вывода, у которого X1,Y1 - координаты левого верхнего, а X2,Y2 - правого нижнего углов. Как уже говорилось, поле вывода не получится больше экрана, по умолчанию оно - 640x260. При некорректном задании границ поля вывода оно устанавливается на весь экран. PROCEDURE OFFSET(X,Y:INTEGER); Процедура установки смещения координат левого верхнего угла выво- димого изображения относительно координат окна. По умолчанию смещение отсутствует. PROCEDURE DRAWMODE(MODE:INTEGER); Установка режима вывода изображения. Различается четыре режима вывода: MODE=0┤-┤вывод нормальный, выводимое изображение стирает то, что было на этом месте до этого; MODE=2┤-┤вывод установкой, старое и новое изображение; MODE=4┤-┤вывод сбросом - к изображению применяется логическая опера- ция НЕ-И; MODE=6┤-┤вывод исключением - применяется логическая операция ИСКЛЮЧА- ЮЩЕЕ ИЛИ (сложение по модулю 2). Учтите, что корректность передаваемого типа вывода не проверяется, а лишние биты просто отсекаются. PROCEDURE DOT(X,Y:INTEGER); Поставить на экране точку с координатами (X,Y). - 8 - PROCEDURE FILL(X,Y:INTEGER); Заливка замкнутой области. Точка начала заливки (X,Y) должна ле- жать внутри этой области. При непопадании точки начала заливки в замкнутую область заливается все поле вывода. Если точка начала за- ливки имеет цвет контура или не попадает в поле вывода, то заливка не производится. PROCEDURE CIRCLE(X,Y,R:INTEGER); Прорисовка окружности с центром в точке с координатами X,Y и ра- диусом R. При выходе за границу поля лишнее не рисуется. Если R<2, то R=2. PROCEDURE ARC(X0,Y0,XST,YST,XEND,YEND:INTEGER); Построение части окружности с центром в точке (X0,Y0), начиная с точки (XST,YST) и заканчивая в точке (XEND,YEND), причем построение ведется против часовой стрелки. Учтите, что если точки (XST,YST) и (XEND,YEND) не лежат на дуге окружности с центром в точке (X0,Y0), то прорисовывается окружность, проходящая через точку (XST,YST) с центром в (X0,Y0). PROCEDURE BOX(X1,Y1,X2,Y2:INTEGER); Построение прямоугольника, левая верхняя вершина которого - (X1,Y1), а правая нижняя - (X2,Y2) (хотя такой порядок перечисления вершин, вообще говоря, необязателен). PROCEDURE ZNEWPICTURE(COLOR1,COLOR2:INTEGER); Очистка поля вывода типа "занавес" - сначала слева направо цве- том COLOR1, потом справа налево цветом COLOR2. PROCEDURE CLEARWIND(COLOR:INTEGER); Очистка цветом COLOR текущего поля вывода (окна). Имеет смысл применять эту процедуру для установки цвета фона. PROCEDURE INVERSE; Просто инверсия поля вывода. 2.4.2. Задание типа линии┘. PROCEDURE SETSTYLE(STYLE:INTEGER); PROCEDURE USRSTYLE(WORD1,WORD2:INTEGER); Одним из атрибутов линии является ее тип. Аппарат типа линии, выполненный в данном графпакете несколько расширен по сравнению со стандартом. Указанным типом линии рисуются не только линии, но и дуги, окружности, прямоугольники. Набор стандартных типов линий не ограничивает пользователя. Он волен сочинить любой необходимый ему - 9 - тип. Для того, чтобы понять, как пользоваться этим достаточно удобным инструментом, необходимо понимать, по какому принципу он реализован. Линия любого типа (пунктирная, штрих-пунктирная, точечная и т.д.) состоит из набора повторяющихся последовательностей точек. Например, пунктирная линия строится из элементарного фрагмента, содержащего некоторое количество точек и пропуск. Такие элементарные фрагменты будем называть масками. В данном граф. пакете реализованы 16-точечные (однословные) маски. Стандартный набор включает в себя маски для 12 типов линий: 0┤-┤сплошная; 1┤-┤крупный пунктир (16 точек); 2┤-┤мелкий пунктир (8 точек); 3┤-┤крупный штрих-пунктир (8 точек - пропуск - 2 точки - пропуск); 4┤-┤мелкий штрих-пунктир (4 точки - пропуск - 2 точки - пропуск); 5┤-┤крупная выколотая точка (14 точек - пропуск); 6┤-┤мелкая выколотая точка (6 точек - пропуск); 7┤-┤крупная точеченая (пропуск в 14 точек - 2 точки); 8┤-┤мелкая точечная (пропуск в 6 точек - 2 точки); 9┤-┤через точку (точка - пропуск); 10┤-┤через 2 точки (2 точки - 2 точки пропуска); 11┤-┤через 4 точки (4 точки - 4 точки пропуска). Для переключения на заданный тип линии служит процедура: PROCEDURE SETSTYLE(STYLE:INTEGER); где аргумент STYLE - номер выбранного Вами типа линии. После пере- ключения на выбранный тип линии все линии одинарной толщины и все дуги будут отрисовываться этим типом. Если Вас не удовлетворяет при- веденный выше набор типов линий, Вы всегда можете переключиться на необходимую Вам маску, просто задав ее. Для этого служит процедура: PROCEDURE USRSTYLE(WORD:INTEGER); где аргумент WORD - суть 16 бит маски типа. Таким образом, Вы можете задать фактически любой тип линии, но соблюдайте при этом должную острожность. Например, указав пустую маску типа линии, Вы ее увидите на экране ни одной линии. PROCEDURE DBLINE(X1,Y1,X2,Y2:INTEGER); PROCEDURE LINE(X1,Y1,X2,Y2:INTEGER); Прорисовка прямых линий из точки (X1,Y1) в точку (X2,Y2). Раз- личие только в их толщине - у DBLINE линии толще втрое (для симмет- рии). 2.4.3 Работа со спрайтами┘. 2.4.3.1. Общие замечания┘. Спрайтом будем называть прямоугольную битовую карту, в которой установленные биты соответствуют засвечиваемым точкам, а сброшенные - не засвечиваемым. Спрайт выводится методом вывода XOR во все 3 плана видеопамяти. - 10 - Пример спрайта в формате Ассемблера┴*└: ┤┤┤┤.radix┤2 D1:: ┤┤┤┤┤┤┤.byte┤┤┤1. ┤┤┤┤┤┤┤.byte┤┤┤5. ┤┤┤┤┤┤┤.byte┤┤23.┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000000,00000111,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000000,00001111,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000000,00011011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000000,00110011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000000,01100011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000000,11000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000001,10000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000011,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00000110,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00001100,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00011000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,00110000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,01111111,11111111,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000000,11111111,11111111,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000001,10000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000011,00000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00000110,00000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00001100,00000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00011000,00000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000000,00110000,00000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000111,01100000,00000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00001111,11000000,00000000,00000011,10000000 ┤┤┤┤┤┤┤.byte┤┤00000111,10000000,00000000,00000111,11000000 ┤┤┤┤┤┤┤.even┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ Как видно из примера, спрайты имеют следующий формат: метка:: ┤┤┤┤┤┤┤┤0-й┤байт┤-┤номер┤спрайта; ┤┤┤┤┤┤┤┤1-й┤байт┤-┤размер┤по┤X┤(в┤байтах); ┤┤┤┤┤┤┤┤2-й┤байт┤-┤размер┤по┤Y┤(в┤строчках); далее┤-┤сам┤спрайт.┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ Для подготовки спрайтов может использоваться программа SPRRED.SAV, выдающая созданные спрайты в формате .FTX. Для перекодировки спрайта в формат ассемблера может использоваться про- грамма SPRLOA.SAV или процедура LOADER из пакета PSERV. Если эти средства по какой-либо причине Вас не устраивают, Вы можете вос- пользоваться другими средствами пакета PSERV или драйвера PP.SYS для загрузки спрайтов в ОЗУ ПП. --------------------------------------------------------------------- ┴*└Программисты, не знающие Ассемблера, не пугайтесь! Этот пример приведен только для иллюстрации и Вам, в общем-то, не нужен. - 11 - 2.4.3.2. Действия со спрайтами┘. 2.4.3.2.1. Простой вывод спрайта┘. Это простейшее действие со спрайтом производится по процедуре: PROCEDURE SPROUT(NUMBER,X,Y:INTEGER); где NUMBER - номер выводимого спрайта; X,Y - координаты точки вывода левого верхнего угла спрайта.Если X,Y не попадают в текущее окно вывода, то спрайт просто не выводится. К аналогичному результату приводит указание недопустимого или незарегистрированного номера спрайта. Однако в последнем случае на экране появляется "мусор", т.к. информация, передаваемая после недопустимого номера спрайта игнорируется и, следовательно, остается в терминальной очереди, а впоследствии как-то обрабатывается программами из ПЗУ, поддерживающими работу терминала. Допустимыми считаются номера спрайтов с 1 по 377┬8└. Спрайт с номером 0 зарезервирован под курсор манипулятора "джойстик". 2.4.3.2.2. Задание атрибутов перемещения спрайтов┘. Эта функция выполняется для спрайтов с номерами от 1 до 15. Существуют 2 способа задания атрибутов перемещения: а) задается шаг по X и Y, координаты стартовой точки и задержка перед очередным перемещением. Если шаг больше 100┬8└, то он счи- тается отрицательным и равным (STEP-100┬8└), где STEP - шаг. Здесь и далее этот метод задания атрибутов движения будем назы- вать "формат┤1". Для задания атрибутов движения по формату 1 используется процедура: PROCEDURE SPR1MOVE(NUM,XST,YST,DX,DY,WAIT,NC:INTEGER); где: NUM┤┤┤┤┤-┤номер описываемого спрайта; XST,YST┤-┤координаты стартовой точки; DX,DY┤┤┤-┤шаги по осям X и Y соответственно; WAIT┤┤┤┤-┤задержка после выполнения каждого шага; NC┤┤┤┤┤┤-┤количество выполненных шагов. Координаты точки, в которой окажется Ваш спрайт после пере- мещения, определяется так: X┤=┤XST┤+┤DX┤*┤NC Y┤=┤YST┤+┤DY┤*┤NC б) задаются начальное и конечное положения спрайта, а также задержка перед каждым шагом перемещения. В этом случае по исходным данным вычисляется шаг перемещения по осям. При этом в основу положены следующие принципы: -┤шаг не должен быть больше половины соответствующего размера спрайта; -┤первый шаг делается на границу байта, а затем, по возможности, каж- дый следующий шаг делается также на границу байта; -┤последний шаг делается точно в конечную точку маршрута спрайта. - 12 - Все это делает этот способ задания атрибутов перемещения спрайта (в дальнейшем - просто "формат┤2") наиболее предпочтительным, но не стоит ограничиваться только им. Для задания атрибутов перемещения спрайта по формату 2 предназначена процедура: PROCEDURE SPR2MOVE(NUM,XST,YSX,XEND,YEND,WAIT:INTEGER); где: NUM┤┤┤┤┤┤┤-┤номер описываемого спрайта; XST ,YST┤┤┤-┤координаты начальной точки; XEND,YEND┤-┤координаты конечной точки; WAIT┤┤┤┤┤┤-┤задержка перед очередным шагом. 2.4.3.2.3. Перемещение спрайта┘. Один раз заданные атрибуты перемещения спрайта сохраняются за ним вплоть до поступления следующей команды задания атрибутов перемещения для того же спрайта (эту информацию не очищает даже процедура INIT). Собственно перемещение происходит следующим образом: -┤спрайт выводится в стартовую точку и она принимается за текущее положение спрайта; -┤затем для каждого последующего шага вычисляются координаты нового положения спрайта по координатам его текущего положения. Спрайт выводится по вычисленным координатам, после чего спрайт, выведенный на предыдущем шаге, стирается повторным выводом на прежнее место (напоминаем, что вывод производится операцией XOR). Координаты нового положения спрайта принимаются за текущие. Такая последовательность более или менее исключает "мигание" спрайта при перевыводе. Перемещение спрайта, атрибуты движения которого заданы по формату┤1 производится при помощи процедуры: PROCEDURE SPR1GO(NUMBER:INTEGER) где NUMBER - номер перемещаемого спрайта. Перемещение спрайта, атрибуты движения которого заданы по формату┤2 производится при помощи процедуры: PROCEDURE SPR2GO(NUMBER:INTEGER) где NUMBER - номер перемещаемого спрайта. 2.4.3.2.4. Перемещение группы спрайтов┘. Это самая сложная и мощная функция. Доаольно часто необходимо получить одновременное перемещение группы спрайтов. При этом атрибуты перемещения каждого из спрайтов заданы ранее и независимы друг от друга. Будем называть такую группу спрайтов цепочкой. Для того, чтобы объединить спрайты в цепочку необходимо вызвать процедуру: - 13 - PROCEDURE SETSEQ; После этого перечисляются спрайты, включенные в цепочку. Для этого служит следующая последовательность: SETSEQ;┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ WRITE(CHR(NUM1+40B),CHR(NUM2+40B),..., CHR(40B)); где NUM1, NUM2 - номера включаемых в цепочку спрайтов. Завершается перечисление спрайтов, входящих в цепочку указанием спрайта с номером 0 - CHR(0+40B). После этого можно начать вывод цепочки. Для этого необходимо воспользоваться процедурой: PROCEDURE STRTSEQ; После этого начнется перемещение группы спрайтов. Перемещение будет происходить следующим образом. На каждый тик сетевого таймера производится один шаг для каждого из спрайтов. В цепочку можно включить не более 16┬10└ спрайтов. При попытке включить в цепочку большее количество спрайтов лишние будут просто игнорированы. После каждого вызова STRTSEQ необходимо заново задать цепочку вывода. Для каждого из спрайтов цепочки должны быть заданы атрибуты перемещения по формату┤1. Если для какого-либо спрайта цепочки атрибуты заданы не были, то этот спрайт игнорируется и накопление цепочки прекращается. Хотя в цепочку и можно включать до 16 спрайтов, при большом их количестве эффект распаралеливания будет потерян. 2.4.3.2.5. Разрешение/запрещение вывода первого спрайта при передвижении┘. Для описания этой процедуры следует напомнить, что вывод спрайта осуществляется функцией "ИСКЛЮЧАЮЩЕЕ┤ИЛИ" и если Вы хотите перемещать спрайт с пустого места, то необходимо сначала нарисовать спрайт (эта возможность предусмотрена в пакете), а если спрайт уже нарисован, то этого делать не нужно. Именно для этих целей и написана эта замечательная процедура. После инициализации пакета спрайт по умолчанию перемещается с пустого места, т.е. рисуется первый спрайт. Чтобы перемещать уже нарисованный спрайт, необходимо запретить вывод первого спрайта. Эта процедура называется: PROCEDURE SETFIRST; Чтобы разрешить вывод первого спрайта необходимо снова вызвать эту же процедуру SETFIRST. ПРИМЕЧАНИЕ. Спрайт всегда выводится текущим цветом. Однако не сле- дует воспринимать это слишком буквально. Номер цвета - это 3 бита, представляющие собой фактическую маску для вывода. Установленный бит соответствует разрешению вывода в план видеопамяти, сброшенный - запрету. 0-й бит отвечает за план 0, 1-й - за план 1, 2-й - за план 2. Таким образом, задавая, например, цвет 7, Вы разрешаете вывод во все 3 плана видеопамяти. Однако следствием того, что спрайт выводится по закону XOR является то, что реальный цвет спрайта не всегда соответствует заданному. Действительно, предположим, что текущий цвет вывода - 7 (белый), а текущий цвет фона - 1 (синий). В результате цвет спрайта на экране - 6 (желтый, а никак не белый). Таким образом, реальный цвет спрайта на экране получается по закону: <текущий цвет> XOR <цвет фона>. - 14 - 2.4.3.3. Программная загрузка и выгрузка спрайтов┘. Прежде чем приступить к непосредственному описанию этих процедур, следует отметить, что они входят в соста в пакета PSERV.OBJ и для их использования в Вашей программе необходимо: 1. Скомпоновать пакет PSERV.OBJ с Вашими программными модулями. Мы только напомним, что это делается очень просто, например: .R LINK┤┤ ┤┤┤┤┤┤┤┤*PROG=PROG,SPR,PASCAL,PASINT,PSERV где PROG┤-┤Ваш программный модуль; SPR┤┤-┤Ваш набор спрайтов. 2. Описать эти процедуры как внешние и обратить особое внимание на то, что для корректной работы программ на языке PASCAL необходимо описывать процедуры ├на том уровне, на котором они используются. 3. Описать массив параметров, возвращаемый процедурой LOADER, в который входят размер загруженного спрайта и адрес его загрузки в ОЗУ ПП (эту информацию использует процедура UNLOAD для выгрузки). Описать переменную целого типа, которая будет использоваться в качестве флага повторной загрузки. ПРИМЕР описания: TYPE PARARRAY=OUTPAR ARRAY [0..1] OF INTEGER; VAR OUN1:PARARRAY; (* первый элемент массива-┤┤┤┤┤┤ ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤размер спрайта, второй-┤┤┤┤┤┤ ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤адрес его загрузк и в ОЗУ ПП *) RELOAD:INTEGER; (* флаг повторной загрузки *) 4. Описать адреса, по которым находятся загружаемые спрайты. В PASCAL'е это можно сделать, объявив их процедурами с соответствующими именами (т.е. именами, присвоенными этим спрайтам). Это можно сделать, например так: PROCEDURE SPRNAME; EXTERNAL; где SPRNAME - метка соответствующего спрайта. Пример программы, использующей эти процедуры: PROGRAM TEST; CONST LOAD┤┤┤=┤0; ┤┤┤┤┤┤RELOAD┤=┤1; (* опишем массивы параметров для 3-х спрайтов *) TYPE PARARRAY = OUTPAR ARRAY [0..1] OF INTEGER; VAR OUT1, (* размер и адрес для спрайта номер 1 *) ┤┤┤┤OUT2, (* размер и адрес для спрайта номер 2 *) ┤┤┤┤OUT3:PARARRAY (* размер и адрес для спрайта номер 3 *); ┤┤┤┤SPR_NUM:INTEGER; (* номер спрайта. Напомним, что спрайт ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤и меет свою метку и номер *) ┤┤┤┤┤┤┤(* укажем спрайты, т.е. их адреса *) PROCEDURE S1;┤┤┤EXTERNAL; (* указание адреса спрайта S1┤┤┤*) PROCEDURE S200; EXTERNAL; (* указание адреса спрайта S200 *) PROCEDURE S12;┤┤EXTERNAL; (* указание адреса спрайта S12┤┤*) PROCEDURE D1;┤┤┤EXTERNAL; (* указание адреса спрайта D1┤┤┤*) PROCEDURE D200; EXTERNAL; (* указание адреса спрайта D200 *) PROCEDURE D12;┤┤EXTERNAL; (* указание адреса спрайта D12┤┤* ) ┤┤┤(* опишем процедуры загрузки и выгрузки спрайтов *) - 15 - PROCEDURE LOADER(PROCEDURE SPR;VAR OUTPAR:PARARRAY; ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤FLAG:INTEGER);EXTERNAL; PROCEDURE UNLOAD(VAR OUTPAR:PARARRAY;SPR_NUM:INTEGER);EXTERNAL; BEGIN (* если тот или иной спрайт грузится программой впервые, то необходимо установить флаг загрузки равным 0 *) ┤┤┤┤┤┤┤┤┤┤┤. ┤┤┤┤┤┤┤┤┤┤┤. LOADER(S1,OUT1,LOAD); ┤┤┤┤┤┤┤┤┤┤┤. ┤┤┤┤┤┤┤┤┤┤┤. LOADER(S12,OUT2,LOAD); ┤┤┤┤┤┤┤┤┤┤┤. ┤┤┤┤┤┤┤┤┤┤┤. LOADER(S200,OUT3,LOAD); (* Мы загрузили в качестве спрайта номер┤1 спрайт S1, спрайта номер┤2 - спрайт S12, спрайта номер┤3 - спрайт S200 *) (* После работы программы спрайты необходимо выгружать, иначе ОЗУ ПП постепенно переполнится, и появится сообщение "no room for sprite". Еще более актуальна ситуация, когда Вы хотите сделать много разных картинок с перемещаемыми спрайтами, а таких спрайтов может быть не более 16. Появляется необходимость загружать спрайты с ├теми же номерами┘ и выгружать старые спрайты, но это не спасает, при выгрузке постепенно накапливается некоторая фрагментация и ОЗУ ПП пе реполняется. Есть другая возможность, которая заключается в загрузке спрайта с ├тем же номером┘ на место старого (если его размер меньше или равен размеру старого спрайта). Таким образом число возможных операций загрузки становится не ограниченным. Но следует только отметить, что контроль размера загружаемого спрайта остается на Вашей совести. В ОЗУ ПП спрайт находится в упакованном виде, а именно: -┤в семи младших разрядах каждого байта записано количество непре- рывно повторяющихся единиц или ноликов; -┤в старшем разряде каждого байта ставится единица или нолик в зави- симости от того, что нужно повторять. Исходя из этих соображений можно узнать размер спрайта. *) (* Для такой повторной загрузки ┤┤┤┤┤┤┤┤┤┤устанавливаем флаг равный единице *) LOADER(D1,OUT1,RELOAD);┤┤(* загрузка спрайта D1 ┤┤┤┤┤┤┤┤┤┤.┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤┤┤┤на место спрайта S1 *) ┤┤┤┤┤┤┤┤┤┤. LOADER(D12,OUT2,RELOAD);┤┤(* загрузка спрайта D12 ┤┤┤┤┤┤┤┤┤┤.┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤на место спрайта S12 *) ┤┤┤┤┤┤┤┤┤┤. LOADER(D200,OUT3,RELOAD);┤(* загрузка спрайта D200 ┤┤┤┤┤┤┤┤┤ .┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤на место спрайта S200 *) ┤┤┤┤┤┤┤┤┤┤. (* А теперь выгрузим эти спрайты *) UNLOAD(OUT1,1); (* выгрузка спрайта номер 1 *) UNLOAD(OUT2,2); (* выгрузка спрайта номер 2 *) UNLOAD(OUT3,3); (* выгрузка спрайта номер 3 *) END. - 16 - Спрайты, загруженные процедурой LOADER "готовы к употреблению" сразу же после выполнения данной процедуры. Обращаем Ваше внимание на тот факт, что имя спрайта (его метка) и номер спрайта - это разные вещи, никак между собой не связанные. То есть, метка - это адрес начала спрайта, а номер спрайта - это номер спрайта. 2.4.4. Работа с текстовыми окнами┘. Во всех процедурах работы с текстовыми окнами координаты обо- значают строки (Y) и столбцы (X). Напомним, что максимальное число строк - 24, столбцов - 80. Под "текстовым окном" понимается только ограничение зоны рулона и ничего более. Поэтому, осуществляя ввод или вывод в объявленную зону рулона, Вы обязаны отслеживать окна самостоятельно. Эта часть пакета представляет собой всего-навсего альтернативный набор процедур рулонирования текстовой информации. Все "пакетные" процедуры рулонирования действуют только на те знакоместа, которые попадают в границы окна. Стандартное рулонирование работает как обычно (т.е. со всем экраном). PROCEDURE SETWIND(XSTART,YSTART,NSTR,NCOL:INTEGER); Процедура объявления текстового окна, начиная с позиции XSTART в строке YSTART, размером NCOL столбцов и NSTR строк. В дальнейшем все координаты будут указываться относительно координат начала окна. То есть знакоместо с координатами (0,0) соответствует экранным координатам (XSTART,YSTART). PROCEDURE ROLSTR(NSTR:INTEGER); PROCEDURE RORSTR(NSTR:INTEGER); Процедуры сдвига строки с номером NSTR. Процедура ROLSTR сдвигает строку на одну позицию влево, RORSTR - вправо. PROCEDURE ROLWIND; PROCEDURE RORWIND; Процедуры сдвига всего окна, аналогичны по действию предыдущим. PROCEDURE UPCOL(NCOL:INTEGER); PROCEDURE DOWNCOL(NCOL:INTEGER); Сдвинуть столбец с номером NCOL на одну строку вверх (UPCOL) или на одну строку вниз (DOWNCOL). PROCEDURE UPWIND; PROCEDURE DOWNWIND; То же самое, но со всем окном. 2.4.5. Дополнительные удобства┘. Все нижеописанные процедуры указываются в программе перед оператором WRITE. В конце строки в операторе WRITE необходимо указывать признак окончания строки CTRL/G (код 7). Например: - 17 - UPOUT;┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ WRITE('Hello!',CHR(7)); Этот набор процедур порадобится далеко не каждому пользова- телю. Поэтому перед чтением этого раздела проанализируйте, нужны ли Вам будут нестандартные возможности машины, которые разработчики системного ПЗУ намеренно попытались скрыть от Вас. Мы же посчитали, что скрывать эти возможности от пользователя было бы своего рода формой грабежа. Однако при использовании этих функций необходимо соблюдать известную осторожность. 2.4.5.1. Управление атрибутами алфавитно-цифрового (а/ц) вывода┘. Все эти возможности доступны в той или иной мере в обычном режиме. Однако доступ к ним крайне неудобен. Дело в том, что разработчики системного ПЗУ предусмотрели для их вызова восьмибитные коды команд (все они вызываются одинаково +<код команды>. Подробно все это описано в руководстве по программированию внешних устройств). Поэтому в рамках RT11 эти возможности становятся недоступными. Сразу после загрузки UKLOAD перенастраивает таблицу точек входа таким образом, что все коды, попадающие в интервал от 240┬8└ до 300┬8└ сдвигаются в семибитную область если они используются после символа типа ESC (33 ┬8└). Например, коду команды 33┬8└+241┬8└ будет соответствовать код команды 33┬8└+141┬8└ и т.д. Таким образом, кодовые посылки управления атрибутами а/ц экрана теперь можно выполнять системными средствами RT11. При этом все старые (восьмибитные) коды команд остаются доступными и не меняют своего смысла. /// Примечание: Утверждение о недоступности восьмибитной кодировки в рамках RT11 не совсем верно. При наличии на системном устройстве драйвера TS.SYS такие программные запросы, как ЕМТ 351, ЕМТ 340, ЕМТ 341 приобретают способность работать с восьмибитными кодами (т.е. как коды КОИ-8, так и управляющие последовательности.) Батьков О.А. 2.4.5.2. Управление рулоном┘. По совершенно непонятной причине разработчики системного ПЗУ не сделали пользовательского интерфейса к этим функциям. Для управления режимом рулонирования используется процедура: RULON(PAR:INTEGER); Аргумент PAR принимает значения: 0┤-┤рулон отсутствует; 1┤-┤плавный рулон; 2┤-┤дискретный рулон; При совместном использовании а/ц и графической информации на экране предпочтительным является отсутствие рулона. Тот не очень дально- видный человек, который писал реализацию плавного рулона, видимо хотел увековечить свое творение и по этой причине машина после запуска находится в режиме плавного рулона. Однако этот режим ока- зался неудобным для работы (не очень приятно работать, если руло- - 18 - нирование 3-4-х строк занимает столько же времени, сколько перевывод всего экрана). Поэтому сразу после загрузки UKLOAD устанавливает дискретный рулон. 2.4.5.3. Вывод в служебные строки┘. Эта весьма полезная возможность также оказалась по воле авторов ПЗУ недоступной пользователю. Для вывода в верхнюю и нижню служебные строки используются процедуры: PROCEDURE UPOUT;┤ PROCEDURE DOWNOUT; После использования этих процедур весь вывод переключается в соответствующую служебную строку. Вы, кроме того, можете переключиться в самом начале на латинский шрифт и после этого весь вывод вести в стандартном 8-битном коде. Количество выводимых за один раз байт без учета перевода регистров не должно превышать 80┬10└ (это заведомо больше, чем реально надо, т.к. в служебных строках помещается всего 40┬10└ символов). Следует соблюдать некоторую осторожность при выводе в верхнюю служебную строку, т.к. туда же выводит сообщения программа-диспетчер режимов а/ц терминала и Ваша строка может быть затерта. 2.4.5.4. Межзадачная почта┘. Поскольку ОЗУ ПП сегментировано очень сильно, имеет смысл ис- пользовать резерв памяти для сохранения-восстановления произвольных сообщений. Эта возможность сама по себе довольно удобна, а в среде однозадачных мониторов RT11 (RM ,┤SJ,┤BL) позволяет стандартизировать передачу сообщений между последовательно запускаемыми задачами. Кроме того, при этом весьма ценна возможность передавать-принимать сообщения через канал 0. При этом задача может быть полностью уверена, что принимает сообщение с клавиатуры или передает на терминал. Это аналогично возможности переопределения входных/выходных устройств, которая является одной из базовых для большинства современных ОС. Для перенаправления экранного вывода во внутренний буфер UKLOAD используется процедура: PROCEDURE SAVSTAT(NCHR:INTEGER); где аргумент NCHR - размер сохраняемого сообщения в байтах. Максимальный размер сообщения - 177┬8└ байт. Для перенаправления клавиатурного ввода задачи на ввод из внутреннего буфера UKLOAD служит процедура: FUNCTION RETSTAT:INTEGER; Первый принятый задачей байт - размер сохраненного сообщения. Затем будет принято само сообщение. Эта же возможность может быть использована для организации косвенных командных файлов. Действительно, если сохранить в качестве сообщения командный файл, затем выдать RETSTAT, принять байт-размер сообщения и выйти в монитор, KMON окажется в положении задачи, ввод которой перенаправили на ввод из внутреннего буфера UKLOAD. Соответственно, весь текст командного файла будет приниматься KMON'ом так, как будто он вводится с клавиатуры. - 19 - 2.4.5.5. Управление самопроверкой состояния┘. Для обеспечения нормальной работы пакета управляющей программе приходится постоянно проверять свое состояние и состояние СПЗУ периферийного процессора (от этого зависят алгоритмы работы пакета). Процесс этот достаточно длительный - в среднем - ┴1└/┬3└ эффективного времени работы пакета. Одна ко во многих случаях эту проверку можно и не делать. Фактически, если не происходит обращений к диску или кассете ПЗУ, не изменяется состояние атрибутов а/ц экрана и не происходит рулонирования, состояние управляющей программы можно считать не изменившимся. Чтобы избежать излишних потерь времени, введена группа функций, позволяющая управлять "тщательностью" проверки. Они реализуются следующими процедурами: ONCASHE┤┤┤- установить режим полной проверки; OFFCASHE┤┤-┤частичная проверка (только то, ┤┤┤┤┤┤┤┤┤┤┤┤что "жизненно важно"); RECASHE┤┤┤-┤в режиме частичной проверки произвести ┤┤┤┤┤┤┤┤┤┤┤┤однократный полный просмотр состояния. Не стоит без существенной необходимости пользоваться режимом частичного сканирования, однако, если Вы уверены, что ни одно из вышеперечисленных событий не произойдет, то ничего страшного в этом нет. И даже если произошло одно из событий, меняющих состояние СПЗУ (наиболее частый случай - рулон или изменение атрибутов а/ц экрана), то это еще не повод отказываться от режима OFFCASHE. Достаточно сразу после этого события выполнить оператор RECASHE и соответствие между поведением пакета и состояние программы восстановится. 2.4.5.6. Работа со звукогенератором┘. Одной из отличительных черт ЭВМ┤МС┤0511 является наличие программируемого звукогенератора. Руководствуясь нашими скромными познаниями в музыке, мы написали пользовательский интерфейс к звукогенератору. Мы ориентировались на соотношение между частотами и длительностями нот (поскольку больше ничего не знали). Таким образом, теперь существует возможность воспроизводить полную вторую октаву с помощью звукогенератора УКНЦ. Это можно сделать, восполь- зовавшись процедурой: PROCEDURE MUZIC; Передаваемая после этого на терминал строка произвольной длины рассматривается как последовательность кодов нот. Нота кодируется тремя байтами: 1 - код ноты; 2 - # - диез, любой другой символ - без диеза; 3 - длительность. Допустимыми являются коды нот: без┤диеза┤-┤C,┤D,┤E,┤F,┤G,┤A,┤H,┤1,┤2,┤3,┤4,┤5,┤пробел┤-┤пауза; с┤диезом┤┤-┤C,┤D,┤┤┤┤F,┤G,┤A,┤┤┤┤1,┤2,┤┤┤┤4,┤5,┤пробел┤-┤пауза. Запись нот соответствует стандартной латинской нотации, т.е.: C┤-┤до первой октавы;┤┤ D┤-┤ре первой октавы;┤┤ ┤┤┤┤┤┤┤┤┤┤. ┤┤┤┤┤┤┤┤┤┤. ┤┤┤┤┤┤┤┤┤┤. 5┤-┤соль второй октавы. - 20 - Длительность задается цифрой в интервале 1-5: 1┤-┤целая; 2┤-┤┤┴1└/┬2└┤; 3┤-┤┤┴1└/┬4└┤; 4┤-┤┤┴1└/┬8└┤; 5┤-┤┤┴1└/┬16└; Таким образом, последовательностью операторов: MUZIC;┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ WRITE('C┤1C#1C┤2C#2',CHR(7)); мы ┤последовательно ┤проиграем┤ целые ┤┤до┤ первой┤октавы ┤и ┤до-диез первой ┤октавы,┤ половины┤┤ до ┤первой ┤октавы┤ и┤ до-диез┤первой┤ок- тавы. Текст "музыкальных строк" Вы можете подготовить в музыкальном редакторе Саши Петросяна (музыкальный редактор Mozart), который оказал нам огромную помощь в написании этой части пакета (это был единственный человек среди нас, ко торый знал, что такое нота). Выходные файлы этого редактора - это и есть собственно те строки, которые Вы должны вывести "на экран" после процедуры MUZIC, только не забывайте в конце строки добавлять байт с кодом 7. 2.4.5.7. Двухоконный режим┘. Как оказалось, в экранном ОЗУ УКНЦ достаточно места для орга- низации двух независимых экранов. Эта возможность была использована в пакете. Первое окно - это то окно, которое используется ПЗУ УКНЦ для обычной работы. Второе окно существует независимо и является фактически просто незанятой областью экранного ОЗУ. После загрузки пакета оба окна становятся доступными пользователю, информация в них существует независимо и сохраняется при переключении из окна в окно. Оба окна совершенно равноправны за исключением того, что второе окно может нормально существовать только в режиме 40┬10└ символов в строке. Стандартно вывод идет в первое окно. Для переключения окон используются операторы: WRITE(CHR(27),'N')┤-┤переключение на 1-е окно; WRITE(CHR(27),'O')┤-┤переключение на 2-е окно; 2.4.5.8. Нестандартный а/ц-вывод┘. К сожалению, стандартные подпрограммы вывода символа, содержащиеся в ПЗУ, не удовлетворяют многим требованиям пользователя. Поэтому был написан модуль, осуществляющий вывод а/ц-символа. Символ выводится текущим цветом и текущим типом вывода. Можно устанавливать растяжки и шаг по осям для вывода строки. Введено понятие номера шрифта. Для обслуживания этих функций в пакете введены следующие процедуры: Выбор масштаба по осям: PROCEDURE SCALE(XSCALE,YSCALE:INTEGER); где XSCALE - масштаб по оси X; ┤┤┤┤YSCALE - масштаб по оси Y; Это следует понимать так: если XSCALE=3, то размер символа по оси X будет втрое больше стандартного (33 точки вместо 11). - 21 - Выбор номера шрифта: PROCEDURE SHRIFT(MODE:INTEGER); где MODE - номер (тип) шрифта. Допустимые номера шрифтов лежат в диапазоне 0-15. Соответствие номера шрифта тому, что Вы увидите на экране, лучше всего устанавливать опытным путем. (Довольно тяжело придумать название шрифту, представляющему собой обратный курсив, повернутый на 45▐ влево и зеркально отображенному от оси X. А это отнюдь не самый экзотический шрифт из доступных Вам.) Шрифт с номером 0 - стандартный. Учтите, что используются стандартные фонты, и Вы всегда имеете возможность перезагрузить знакогенератор своими фонтами (см. "Работа с внешними устройствами ЭВМ┤МС-0511"). Вывод строки символов: PROCEDURE OUTSTR(XST,YST,DX,DY:INTEGER); где XST, YST┤-┤координаты начала (левого нижнего угла) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤выводимой строки с точностью до точки; ┤┤┤┤DX, DY┤┤┤- шаг (в точках) между символами; Затем печатаются байты строки. Прием строки завершается по любому байту с кодом меньше 40┬8└, за исключением 11┬8└, 16┬8└ и 17┬8└, на которые возложены их стандартные функции. 2.4.5.9. Идентификация UKLOAD┘. Эта функция позволяет получить номер версии и реализации граф. пакета. FUNCTION ANSREQ:INTEGER; Результат - слово, байты которого имеют следующий смысл: ст. байт - номер версии + 60┬8└; мл. байт - номер реализации + 60┬8└. 3. ОПИСАНИЕ ИНТЕРФЕЙСА UKLOAD С ЯЗЫКОМ "СИ". ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3.1. Построение исполняемой программы┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Для использования возможностей пакета UKLOAD в программе на языке Си необходимо проделать следующее: При создании .SAV файла командная строка компоновщика (LINK) должна выглядеть следующим образом: .R LINK ┤┤┤┤*MYPROG=MYPROG,CGR,C:,C:/B:2000 ┤*^C┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ где: MYPROG┤┤┤-┤имя Вашей Си-программы; ┤┤┤┤┤CGR┤┤┤┤┤┤-┤имя графической библиотеки языка Си (CINT); ┤┤┤┤┤stmod┤┤┤┤-┤имя стартового файла исполняющей системы; ┤┤┤┤┤libname┤┤-┤имя стандартной библиотеки языка Си (CXLIB) - 22 - 3.2. Имена и вызовы функций┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Все функции имеют такие же имена и вызываются точно таким же образом, как это сделано в версии графического интерфейса для языка PASCAL (PASINT.OBJ), поэтому описания функций см. в описании интерфейса для языка PASCAL. 4. РАБОТА С ПАКЕТОМ UKLOAD НА MACRO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4.1. Общие замечания┘. ~~~~~~~~~~~~~~~~~~~~~~ В данный раздел описания пакета UKLOAD включены те функции, которые недоступны программисту, пишущему на PASCAL'е, а также отличия, определяемые собственно языком MACRO. 4.2. Макробиблиоxтека GLIB.MAC . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Перед использованием GLIB посмотрите версию своего транслятора. Если она выше 5.0, то для ссылки на GLIB достаточно вставить в текст директивы: .ENABL┤┤┤MCL┤┤┤ .LIBRA┤┤┤/GLIB/ Если же у Вас более младшая версия, то библиотеку необходимо указывать в командной строке при трансляции. 4.2.1. Различия GLIB и PASINT┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Имена макрокоманд GLIB отличаются от имен процедур, содержащихся в библиотеке PASINT.OBJ, только наличием символа "$" перед именем макрокоманды. Смысл параметров остается тем же. Например: для PASCAL┤┤┤-┤┤┤PROCEDURE SPROUT(NUM,X,Y:INTEGER); для MACRO┤┤┤┤-┤┤┤$SPROUT NUM,X,Y Соответственно, то что верно для PASCAL, верно и для MACRO, за исключением следующего: -┤при работе с цепочкой спрайтов вместо оператора WRITE использу- ются вызовы п/п OUT$BYT: MOV┤┤┤#NUM,R0 CALL┤┤OUT$BYT -┤аргументом макрокоманды $RULON служит одна из определенных в макро- библиотеке констант: $EMPTY┤┤┤==:┤┤┤0┤┤┤┤┤┤┤-┤рулон отсутствует; $PL┤┤┤┤┤┤==:┤┤┤1┤┤┤┤┤┤┤-┤плавный рулон; $QANT┤┤┤┤==:┤┤┤2┤┤┤┤┤┤┤-┤дискретный рулон; -┤для переключения окон существуют макрокоманды: $WIN1┤┤┤┤┤-┤┤┤┤┤переключение на 1-е окно; $WIN2┤┤┤┤┤-┤┤┤┤┤переключение на 2-е окно; - 23 - Пример использования двухоконного режима: ┤┤┤┤┤┤┤.TITLE┤┤12TEST ┤┤┤┤┤┤┤.IDENT┤┤/V01.02/ ┤┤┤┤┤┤┤.ENABL┤┤MCL ┤┤┤┤┤┤┤.MCALL┤┤.PRINT,.EXIT ┤┤┤┤┤┤┤.LIBRA┤┤/SY:GLIB/ START:: ┤┤┤┤┤┤┤BIS┤┤┤┤┤#50100,@#44┤┤┤┤┤┤; без эхо- печати ┤┤┤┤┤┤┤$WIN2┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; переключение на окно 2 ┤┤┤┤┤┤┤.TTYOUT┤#14┤┤┤┤┤┤┤┤┤┤┤┤┤┤; очистка экрана ┤┤┤┤┤┤┤$WIN1┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; переключение на окно 1 ┤┤┤┤┤┤┤MOV┤┤┤┤┤#20,R3┤┤┤┤┤┤┤┤┤┤┤; счетчик повторов - в R3 1$:┤┤┤┤EMT┤┤┤┤┤340┤┤┤┤┤┤┤┤┤┤┤┤┤┤; очистили буфер; ┤┤┤┤┤┤┤BCC┤┤┤┤┤.-2 ┤┤┤┤┤┤┤.TTYIN ┤┤┤┤┤┤┤$WIN2┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; переключаемся на окно 2 ┤┤┤┤┤┤┤.PRINT┤┤#MSG2┤┤┤┤┤┤┤┤┤┤┤┤; печатаем номер окна ┤┤┤┤┤┤┤EMT┤┤┤┤┤340 ┤┤┤┤┤┤┤BCC┤┤┤┤┤.-2 ┤┤┤┤┤┤┤.TTYIN┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; ждем нажатия на что-нибудь ┤┤┤┤┤┤┤$WIN1┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; переключаемся на окно 1 ┤┤┤┤┤┤┤.PRINT┤┤#MSG1┤┤┤┤┤┤┤┤┤┤┤┤; печатаем номер окна ┤┤┤┤┤┤┤SOB┤┤┤┤┤R3,1$ ┤┤┤┤┤┤┤.EXIT .END┤┤START 4.2.2. Дополнительная информация о работе со спрайтами┘. Существует один нюанс, который Вам следует помнить. Внутри UKLOAD работа со спрайтами организована следующим образом. Существуют 2 таблицы, в одной из которых хранятся адреса спрайтов (адрес байта спрайта, в котором записана длина спрайта), а в другой - атрибуты перемещения спрайтов (см. ниже). Номер спрайта нигде не хранится, а является указателем в этих таблицах (фактически - это номер строки таблицы). Зарегистрировать спрайт в этом контексте это значит заполнить поля соответствующей строки второй таблицы. Если Вы пользуетесь процедурой LOADER или программой SPRLOA, то регистрация спрайта происходит автоматически, а номер спрайта берется из 0-го байта служебной инф5ормации, находящейся перед самим спрайтом. Если Вы грузите спрайт в ОЗУ┤ПП любым другим путем, то регистрация, естественно, остается на Вашей совести. Для того, чтобы зарегистрировать спрайт необходимо в этом случае вывести командную последовательность: <33┬8└><115┬8└><номер спрайта+40┬8└><мл.байт адреса><ст.байт адреса> где <мл.байт адреса> - это младший байт слова, содержащего ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤адрес спрайта в ОЗУ ПП; ┤┤┤┤<ст.байт адреса> - это старший байт этого адреса; ┤┤┤┤<номер спрайта>┤┤- это тот номер, которым Вы будете ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤впоследствии идентифицировать этот ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤спрайт. Этот номер, естественно, не обязан совпадать с тем числом, которое находится в 0-м байте служебной информации спрайта. Здесь и далее под адресом спрайта будем подразумевать адрес 1-го байта служебной информации. Учтите однако, что RT11 "режет" 8-й бит при выводе текста на экран по запросам .TTYOUT и .PRINT, поэтому эти запросы не - 24 - могут использоваться для вывода байтов адреса спрайта. В данном случае необходимо использовать только регистровый вывод. Это представляется не слишком удобным, но этот вызов пришлось с охранить для обеспечения совместимости с предыдущими версиями. Кроме того, следует помнить, что UKLOAD использует не сам спрайт, а его "зеркальную" копию. То есть перед загрузкой каждый байт тела спрайта надо "перевернуть" (0-й бит становится 7-м и наоборот. Такая операция проводится с каждым битом байта. Например байт 11001110┬2└ превратится в байт 01110011┬2└). Это было обусловлено тем, что регистры УКНЦ "зеркальные", операция такого переворота крайне проста (16 сдвигов), и, не выполняя ее каждый раз перед выводом, можно добиться существенного повышения быстродействия. Зарегистрировать спрайт проще и быстрее можно, используя макрорасширение: $SPRSET NUMBER,ADDRESS где NUMBER┤┤- номер регистрируемого спрайта; ┤┤┤┤ADDRESS - адрес спрайта в ОЗУ ПП. В данном случае нет необходимости выводить восьмибитный код, т.к. это макрорасширение использует процедуру OUT$WORD из GOUT.OBJ. Эта процедура разбивает слово на 4 части по 4 бита каждая и передает их отдельно, предварительно прибавляя к каждой части 40┬8└. Точно также в данном случае нет необходимости "переворачивать" байты спрайта. Это будет сделано автоматически перед занесением адреса спрайта в таблицу. Необходимо учитывать еще один момент - начало спрайта должно быть выровнено на границу слова. Это вызвано тем, что разработчики ПЗУ по каким-то причинам проигнорировали способность процессора К1801ВМ2 пересылать слово по нечетному адресу. ПРИМЕЧАНИЕ. Аналога процедур LOADER и UNLOAD в макробиблиотеке не существует. Поэтому, если Вы хотите ими воспользоваться, нужно: а) учитывать, что их вызовы "потянут" за собой весь пакет PSERV; б) т.к. встретив описание: PROCEDURE SPRADR;EXTERNAL; PASCAL сгенерит следующий текст: L0:┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤┤┤┤.GLOBL┤┤┤SPRADR ┤┤┤┤┤┤┤JMP┤┤┤┤┤┤SPRADR ┤┤┤┤┤┤┤RETURN┤┤┤┤┤┤┤┤┤ оформить вызов LOADER можно следующим образом: MOV┤┤┤R4,-(SP)┤┤┤┤┤ ┤┤┤; здесь можно поставить команду ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ ; CLR┤┤┤┤-(SP)┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ MOV┤┤┤#L0,-(SP)┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ MOV┤┤┤#OUTPAR,-(SP)┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ MOV┤┤┤RELOAD,-(SP)┤┤┤ ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ CALL┤┤LOADER┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ В случае каких-либо зтаруднений напишите программку на PASCAL, которая будет использовать эти процедуры, странслируйте ее на MACRO с ключами /S и /C и посмотрите полученный текст - увидите то же самое; - 25 - в) вызов процедуры UNLOAD имитируется так: MOV┤┤┤#SPRPAR,-(SP) MOV┤┤┤#SPRNUM,-(SP) CALL┤┤UNLOAD┤┤┤┤┤┤┤ 4.2.3. Доступ к системным ресурсам┘. 4.2.3.1 Управление таймерами┘. При решении задач реального времени часто бывает необходимо "остановить часы" (по терминологии TSX-Plus - "остановить время процесса"). С этой целью были введены функции управления таймерами ПП и ЦП. Эти функции реализуются по макрокоманде: $TIMERS┤STAT где аргумент STAT - константа, определяющая необходимое состояние таймеров .Допустимыми являются следующие значения: 00┬2└┤┤-┤┤оба таймера включены; 10┬2└┤┤-┤┤таймер ЦП включен; 01┬2└┤┤-┤┤таймер ПП включен; 11┬2└┤┤-┤┤оба таймера выключены. 4.2.3.2 Информация об UKLOAD┘. Запрос адреса загрузки и длины UKLOAD выполняется с помощью макрокоманды: $GETLOAD LOAADDR,LENGTH В результате выполнения макрокоманды переменная LOAADDR будет за- полнена адресом загрузки резидентной части UKLOAD, а переменная LENGTH - длиной ее в байтах. 4.2.3.3. Словный обмен с ОЗУ ПП┘. Требования стандартизации заставили нас присоединить эту группу функций к пакету. Суть их состоит в эмуляции системных макроопределений RT11 .GVAL и .PVAL. Базовый адрес - @#0. Приведем без пояснений форматы этих макрокоманд: $PVAL ADDR,ARG┤┤-┤┤записать значение ARG по адресу ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ADDR в ОЗУ ПП; $GVAL ADDR,DST┤┤-┤┤заполнить переменную DST значением ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ по адресу ADDR из ОЗУ ПП.┤┤┤┤┤┤┤┤ - 26 - 4.2.4. BATCH-средство┘. Если возникает необходимость частого выполнения некоторой последовательности (или нескольких последовательностей) команд графики, то мы рекомендуем Вам воспользоваться BATCH-средством. Смысл его в том, что эту последовательность можно выполнить один раз, запоминая во встроенном или собствееном буфере составляющие ее коды. При необходимости снова выполнить эту последовательность достаточно выдать одну команду. При этом до окончания последовательности диспетчер UKLOAD будет брать коды уже не из терминальной очереди, а из этой последовательности, что позволит ускорить работу. Таким образом, BATCH-средство является своеобразным аналогом процедуры. Кроме того, пользователь может без труда написать процедуру, которая перенесет весь терминальный вывод в его буфер (для этого достаточно подменить вызов OUT$BYT в библиотеке GOUT.OBJ и макроопределение $$$ в макробиблиотеке GLIB.MLB. Именно с этой целью и то и другое поставляется в текстах). Затем, используя средства пакета PSERV.OBJ или драйвера PP.SYS или любым другим способом скопировать этот буфер в ОЗУ ПП и в тех случаях, когда скорость становится критичной, перенаправлять весь ввод диспетчера UKLOAD на него. При этом следует учесть, что последовательность команд, созданная таким образом, обязательно должна быть "закрытой" - т.е. заканчиваться вызовом макрорасширения $BAEND. При использовании внутреннего буфера UKLOAD для накопления командной последовательности следует учитывать, что длина этого буфера 1000┬8└ байт, и может возникнуть ситуация переполнения . При этом, при попытке завершить сохранение и "закрыть" последовательность в нижней служебной строке возникнет сообщение "Internal buffer overflow" и все попытки воспользоваться этим буфером будут игнорироваться до то го, как будет выдана команда $INIT (повторная инициализация пакета), либо будет закончено накопление новой последовательности. К сожалению, это единственная возможность сообщить об ошибке, которую авторы нашли более ме нее приемлемой в этой ситуации. Существует и еще одно достаточно общее для таких средств ограничение - в накапливаемой последовательности не должно быть вызовов BATCH-средства за исключением $BAEND, которым можно пользоваться для преждевременного прерывания последовательности команд. Если это не будет учтено, то возникнет рекурсия, на которую данная реализация не рассчитана. Результат в этом случае - необходимость перезагрузки. В ма кробиблиотеке GLIB.MLB имеются следующие вызовы, поддерживающие описанные выше возможности. - $BASAVE BUFFER,LENGTH BUFFER - адрес буфера в ОЗУ ПП; LENGTH - его длина; Этот вызов сообщает диспетчеру UKLOAD, что необходимо начать сохра- нение последовательности команд в пользовательском буфере, находящемся в ОЗУ ПП по адресу BUFFER и имеющему длину LENGTH. Все поступающие команды сохраняются в буфере и отрабатываются. Сохранение продолжается до прихода команды $BACLOSE. Последовательность автоматически "закрывается" командой $BAEND. - 27 - - $BAISAVE Этот вызов сообщает диспетчеру UKLOAD, что необходимо начать сохранение последовательности команд во внутреннем буфере UKLOAD. Буфер имеет длину 1000┬8└ байт и положение его не фиксировано. Поступающие команды отрабатываются. Сохранение продолжается до прихода команды $BACLOSE. Последовательность автоматически "закрывается" командой $BAEND. - $BACLOSE Этот вызов сообщает диспетчеру UKLOAD, что необходимо закончить сохранение командной последовательности и "закрыть" ее командой $BAEND. Если в процессе сохранения командной последовательности было переполнение, то накопление последовательности заканчивается, но "закрытие" ее не произв одится. В нижней служебной строке появляется надпись "buffer overflow". Воспользоваться этой командной последовательностью не удастся. Вызов $BASTART будет игнорироваться до окончания накопления следующей последователь ности, либо вызова $INIT. - $BASTART BUFFER BUFFER - адрес буфера в ОЗУ ПП. Этот вызов перенаправляет весь ввод диспетчера UKLOAD на буфер командной последовательности, находящийся в ОЗУ ПП с адреса BUFFER. Вызов будет игнорирован, если перед этим было переполнение буфера. Обработка командной последовательности закончится при встрече команды $BAEND. - $BAEND Этот вызов сообщает диспетчеру UKLOAD о том, что необходимо переключить ввод на терминальную очередь. Эта команда автоматически подставляется последней в сохраненную последовательность, однако ее можно использовать для преждевременного окончания последовательности. Кроме того, она оказывается очень полезна, если Вы сами формируете командную последовательность, а не пользуетесь для этого стандартными средствами. Пример использования BATCH-средства: ┤┤┤┤┤┤┤.TITLE┤┤┤BATCH_TEST ┤┤┤┤┤┤┤.IDENT┤┤┤/V01.02/ ┤┤┤┤┤┤┤.ENABL┤┤┤MCL ┤┤┤┤┤┤┤.DSABL┤┤┤GBL ┤┤┤┤┤┤┤.LIBRA┤┤┤/SY:GLIB/ START:: ┤┤┤┤┤┤┤BIS┤┤┤┤┤┤#50100,@#44┤┤┤┤;без эхо -печати ┤┤┤┤┤┤┤$INIT┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; инициализация графики ┤┤┤┤┤┤┤$BAISAVE┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; объявляем начало ком.посл. ┤┤┤┤┤┤┤CLR┤┤┤┤┤┤R1┤┤┤┤┤┤┤┤┤┤┤┤┤; будем проводитьлинии ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; с типом от0 ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#15.,R2┤┤┤┤┤┤┤┤; до15┬10└ ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#10.,R3┤┤┤┤┤┤┤┤; координата Y линии = 10┬10└ 1$: ┤┤┤┤┤┤┤$LINSTYLE┤┤R1┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; устанавливаем тип линии ┤┤┤┤┤┤┤$LINE┤┤┤┤#100.,R3,#300.,R3┤┤┤; рисуем линию ┤┤┤┤┤┤┤INC┤┤┤┤┤┤R1┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; увеличиваем номер ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; типа линии - 28 - ┤┤┤┤┤┤┤ADD┤┤┤┤┤┤#10.,R3┤┤┤┤┤┤┤┤┤┤┤┤┤; изменяем ее координаты ┤┤┤┤┤┤┤SOB┤┤┤┤┤┤R1,1$┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; и так 15┬10└раз ┤┤┤┤┤┤┤$BACLOSE┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; конец сохранения послед. ┤┤┤┤┤┤┤.TTYOUT┤┤#14┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; чистим экран ┤┤┤┤┤┤┤EMT┤┤┤┤┤┤340┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤; чистим буфер RT11 ┤┤┤┤┤┤┤BCC┤┤┤┤┤┤.-2 ┤┤┤┤┤┤┤.TTYIN┤ ┤┤┤┤┤┤┤┤┤┤; и ждем нажатия на любую клавишу ┤┤┤┤┤┤┤$BAISTART┤┤┤┤┤┤┤┤┤; запускаем на выполнение сохр. посл. ┤┤┤┤┤┤┤.EXIT┤┤┤┤┤┤┤┤┤┤┤┤┤; и заканчиваем работу .END┤┤START 5. ПРОГРАММЫ ПОДГОТОВКИ СПРАЙТОВ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5.1. Редактор спрайтов SPRRED┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5.1.1. Назначение редактора┘. Редактор SPRRED (далее - просто редактор) предназначен для создания наборов всевозможных картинок с целью использования их (после необходимой обработки) в качестве спрайтов. 5.1.2. Запуск редактора┘. В зависимости от того, где находится редактор, необходимо "сказать" монитору: R SPRRED┤ или RU SPRRED 5.1.3. Правила обращения с редактором┘. Редактор - программа довольно спокойная и терпеливо переносящая Ваши ошибки. Если Вы ошиблись, Вам об этом сообщат, но никаких ре- прессий не последует. Единственное исключение - открытие на запись и чтение одновременно одного и того же файла, и то обидится не ре- дактор, а монитор, а его обижать не следует - очень нервный товарищ с непредсказуемой реакцией. А в остальном редактор выполнит все Ваши желания (в пределах разумного и своих возможностей). 5.1.4. Терминология редактора┘. Редактор позволяет Вам нарисовать что угодно, но не больше 160 точек по горизонтали и 47 точек - поперек. Известно, так же, что на экран можно вывести 24 строки по 80 символов. Поэтому при описании команд мы будем пользоваться следующими понятиями: ┤┤э┤к┤р┤а┤н┤┤┤- это то, что Вы видите на дисплее, о┤к┤н┤о┤┤┤- прямоугольник, ограниченный координатами метки и текущим положением курсора. - 29 - ПРИМЕЧАНИЕ. Если метка Вами не поставлена, то она находится в самом левом и самом верхнем углу картинки (см. ниже). к┤а┤р┤т┤и┤н┤к┤а┤┤┤- массив 160 на 47 точек, который Вы можете разрисовать. В связи с тем, что размеры экрана меньше размеров картинки, экран может по ней "ползать". Это происходит автоматически в тот момент, когда Вы пытаетесь переместить курсор за пределы экрана. Если машина начинает пищать, - Вы дошли до границы картинки и дальше идти некуда. Остается добавить только одно - в редакторе используются т.н. "префиксные" команды, т.е. команды, для выполнения которых необходимо ├последовательно┘ нажать две клавиши - сначала "префикс", а, затем, клавишу команды. Это сделано для облегчения запоминания мнемоники, причем мнемоника всех команд - русская. 5.1.5. Команды редактора┘. ПЕРЕДВИЖЕНИЕ┤КУРСОРА┤-┤нажмите любую из клавиш, управляющих движением курсора (клавиши со стрелками); ПОСТАВИТЬ┤ТОЧКУ┤-┤нажмите клавишу <5> (в этом месте появится символ "#"); УБРАТЬ┤ТОЧКУ┤-┤нажмите <5> еще раз в этом же месте; НАРИСОВАТЬ┤ЛИНИЮ┤-┤нажимайте клавиши <1>, <2>, <3>, <4>, <6>, <7>, <8>, <9> и получайте такие линии, какие нужно. Редактор выводит на экран по методу ИСКЛЮЧАЮЩЕЕ┤ИЛИ, а по сему в точке пересечения двух линий будет стоять символ ".", а не "#". ПОСТАВИТЬ┤МЕТКУ┤-┤нажмите <УСТ>; УДАЛИТЬ┤МЕТКУ┤-┤нажмите <УСТ> еще раз; УДАЛИТЬ┤СООБЩЕНИЕ в служебной строке┤-┤нажмите пробел; ВЫЙТИ┤ИЗ┤РЕДАКТОРА┤-┤нажмите <СТОП>. Если в ответ на заданный Вам во- прос будет введена "Y" (латинская), то Ваши труды не пропадут бесследно; ЗАГРУЗИТЬ┤РЕЗЕРВНЫЙ┤ФАЙЛ┤-┤нажмите <ИСП>; ПОЛУЧИТЬ┤ЭКСТРЕННУЮ┤ПОМОЩЬ┤-┤нажмите <ПОМ>; НАРИСОВАТЬ┤ОКРУЖНОСТЬ┤-┤нажмите <О>; НАРИСОВАТЬ┤ЛИНИЮ┤-┤нажмите <Л>; ЗАПОМНИТЬ┤ОКНО┤В┤БУФЕРЕ┤-┤нажмите <К4>; ВЫВЕСТИ┤СОДЕРЖИМОЕ┤БУФЕРА┤НА┤ЭКРАН┤-┤нажмите <К4> еще раз; Учтите, что команды рисования и занесения в буфер работают при наличии метки. Кроме того, до очистки буфера метка окошка не удаляется. 5.1.6. Префиксные команды┘. Группа команд открытия файла: <К1> - префикс, ┤┤┤┤┤┤┤┤┤<З>┤-┤открыть для записи; ┤┤┤┤┤┤┤┤┤<Ч>┤-┤открыть для чтения; ПРИМЕЧАНИЕ. Редактор может работать только с одним файлом для записи и только одним файлом для чтения. Учтите, что при повторном открытии файла редактор сначала закрывает уже открытый файл, а уже потом спрашивает имя нового. Если Вы передумали открывать файл, нажмите <ВК>. - 30 - Группа команд работы с экраном: <К2> - префикс, ┤┤┤┤┤┤┤┤┤<И>┤-┤инверсия экрана; ┤┤┤┤┤┤┤┤┤<П>┤-┤просмотр в реальном масштабе; ┤┤┤┤┤┤┤┤┤<В>┤-┤вывести экран заново (имеет смысл при каких-либо мелких сбоях на экране). Группа команд работы со спрайтами: <К3> - префикс, ┤┤┤┤┤┤┤┤┤<П>┤-┤поиск спрайта в файле; ┤┤┤┤ ┤┤┤┤<С>┤-┤просмотр содержимого файла; ┤┤┤┤┤┤┤┤┤<З>┤-┤запись спрайта в файл. ПРИМЕЧАНИЕ. Режимы <К2><П> и <К3><С> требуют некоторых начальных условий: 1.┤Наличия машины УКНЦ. 2.┤Наличия в памяти машины программы UKLOAD. В противном случае Вам придется созерцать на экране большую кучу абстрактных символов (т.е. глюков)... Различные очистки: <СБРОС> - префикс, ┤┤┤┤┤┤┤┤┤┤┤┤<К>┤-┤всей картинки; ┤┤┤┤┤┤┤┤┤┤┤┤<О>┤-┤выделенного окна; ┤┤┤┤┤┤┤┤┤┤┤┤<Э>┤-┤текущего экрана; ┤┤┤┤┤┤┤┤┤┤┤┤<Б>┤-┤буфера. Запись в файл производится в текстовом формате FTX, т.е. так: Т┤┤1┤13┤14┤┤┤ ############# ............# ...........#. ..........#.. .........#... ........#.... .......#..... ......#...... .....#....... ....#....... ...#......... ..#.......... .#........... ############# Смысл строки, идущей непосредственно перед спрайтом, прост: <имя спрайта> <номер> <кол-во точек по X> <кол-во строк по Y> Набор спрайтов в этом формате является полуфабрикатом, пригодным для преобразования в любой другой формат. В частности, конвертером SPRCNV Вы можете преобразовать свои спрайты в текст на ассемблере, который, после трансляции совместим, с программой графики на УКНЦ UKLOAD.SAV. Желаем Вам получить громадное удовольствие от использования нашего программного продукта в Ваших целях! 5.2. Конвертер спрайтов SPRCNV┘. Программа SPRCNV.SAV предназначена для преобразования файлов, содержащих информацию (рисунки спрайтов) в FTX-формате, в - 31 - текст на языке Макро-11, с целью их дальнейшего использования в качестве модулей, загружаемых программой SPRLOA.SAV (см. описание программы SPRLOA.SAV). Последовательность команд, приводящая к желаемому результату, следующая: .R SPRCNV В ответ на это появится надпись: Имя файла: После ввода имени файла нужно снова нажать клавишу <ВК> и подождать окончания обработки. Как только Вы вновь окажетесь в мониторе, дайте команды: .MACRO <имя файла><ВК> .LINK/NOBIT/BOT:0 <имя файла>/EXE:<имя файла>.SPR<ВК> Если все прошло нормально - можете себя поздравить: Вы стали счастли- вым обладателем набора спрайтов в SPR-формате, который легко загружается в УКНЦ и может быть использован в Ваш их программах, а если нет - Вы где-то ошиблись. Маленькая тонкость: прежде чем удалить файлы с расширением .FTX и .MAC, убедитесь, что Вы в любой момент можете вспомнить номер любого спрайта в Ваших наборах, иначе Вам придется вспомнить слова кота Базилио: "Плакали наши денежки!". ├5.3. Программа загрузки спрайтов SPRLOA┘. В связи с трудоемкостью процесса загрузки спрайтов в ОЗУ┤ПП и регистрации их в таблицах UKLOAD нами была написана программа автоматической загрузки и регистрации спрайтов. После подготовки спрайтов в FTX-формате (программа SPRRED.SAV) и конвертирования файла спрайтов в формат MACRO-11 (MAC) (программа SPRCNV.SAV) Вам необходимо выполнить следующие действия: 1.Ассемблировать файл спрайтов. Для этого выполните команду: .MACRO FILE.MAC где FILE.MAC - файл, созданный программой SPRCNV.SAV. 2. Получить из объектного кода загрузочный модуль. Для этого выполните команду: .LINK/NOBITMAP/BOTTOM:0 FILE где FILE - объектный модуль, созданный макроассемблером из файла спрайтов . 3. Загрузить спрайты в ОЗУ┤ПП и зарегистрировать их. Для этого Вам необходимо запустить программу SPRLOA.SAV: .R SPRLOA .RU SPRLOA .RUN DEV:SPRLOA в зависимости от того, где находится программа. В ответ на стан- дартное приглашение CSI ("*") Вам надо ввести имя файла спрайтов. После окончания загрузки и регистрации спрайтов на экране опять появится приглашение CSI. Во время работы программы могут выводиться следующие сообщения: SPRLOAD-F-No PP-driver in system Для успешной работы программе необходим драйвер PP.SYS. Это сообщение свидетельствует о том, что на Вашем системном диске этого драйвера нет. Перепишите на системный диск драйвер PP.SYS и инсталлируйте его. - 32 - SPRLOAD-F-Bad fetch:SY:PP.SYS При загрузке драйвера PP.SYS произошла ошибка ввода-вывода. Пере- запишите на системный диск драйвер PP.SYS и перезагрузите систему. SPRLOAD-F-Not enough available memory Слишком мало памяти осталось для работы программы. Проверьте необходимость присутствия в памяти всех резидентных программ. SPRLOAD-E-Invalid device specified В спецификации входного файла было указано недопустимое устройство. Внимательно наберите спецификацию входного файла. SPRLOAD-E-Invalid file name Недопустимый формат спецификации входного файла. Внимательно на- берите спецификацию входного файла. SPRLOAD-E-Invalid option Данный вариант программы не предусматривает приема ключей из командной строки. Вы, вероятно, попытались передать программе некие ключи. Это не имеет смысла, т.к. они не будут обработаны. SPRLOAD-E-File not found Указанный в командной строке файл не найден. Проверьте наличие файла с указанным именем на заданном устройстве. SPRLOAD-E-Read error Ошибка четния входного файла. SPRLOAD-E-Invalid sprite size Достаточно редкая ситуация. Недопустимый размер спрайта (нулевой или слишком большой). Эта ошибка иногда возникает при недостаточно уверенном чтении с диска. Однако, если Вы готовили спрайты своими средствами, то это достаточный повод для анализа корректности Ваших действий. 6. МУЗЫКАЛЬНЫЙ РЕДАКТОР MOZART . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Музыкальный редактор - это программа, предоставляющая пользова- телю максимум удобств при создании, редактировании и прослушивании музыкальных фрагментов. Он может быть в равной мере использован как: -┤инструментальное средство; -┤программа для обучения нотной грамоте; -┤увлекательная игрушка. Музыкальный редактор -┤имеет простой и удобный пользовательский интерфейс; -┤отображает на экране ноты в привычном для музыкантов виде; -┤позволяет прослушивать записанную мелодию; -┤записывает на диск и считывает с него музыкальные файлы (с расширением .MUZ); - 33 - -┤позволяет устанавливать темп игры; -┤имеет встроенную подсказку, которую можно вызвать в любой момент. Музыкальные файлы, подготовленные с помощью данного музыкального редактора, могут быть использованы в программах, написанных на языках программирования MACRO, Си и PASCAL, если, конечно, пользователь имеет в своем распоряжении наш пакет программ общения с периферийным процессором "UKGRAPH". Вход в редактор: RU MUZRED Выход из редактора: <УПР> Команды редактора: стрелки┤┤-┤соответствующее перемещение курсора; <==| (забой)┤-┤удаление ноты слева от курсора; <К1>┤┤┤┤┤┤ ┤┤-┤очистка экрана; <К2><ЦИФРА>┤-┤установка скорости игры: ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤0┤-┤максимальная; ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤5┤-┤минимальная; <ЦИФРА>┤-┤установка длительностей, начиная с текущей ноты; <К4>┤┤┤┤┤┤┤┤-┤чтение музыки из файла: в ответ на запрос "Имя файла на чтение >" наберите имя файла, в котором музыка хра- нится на диске; <К5>┤┤┤┤┤┤┤┤-┤запись музыки в файл: в ответ на запрос "Имя файла на запись >" наберите имя файла, в который Вы хотите записать музыку; <ЦИФРА>┤┤┤┤┤-┤изменение длительности текущей ноты; <ИСП>┤┤┤┤┤┤┤-┤проигрывание всего, что уже есть в памяти; <ПОМ>┤┤┤┤┤┤┤-┤помощь. Длительности нот: 0┤-┤целая; 1┤-┤┴1└/┬2└; 2┤-┤┴1└/┬4└; 3┤-┤┴1└/┬8└; 4┤-┤┴1└/┬16└ Расстановка нот производится нажатием клавиш: ┤C┤U┤┤┤E┤N┤G┤┤┤]┤Z┤┤┤_┤: F┤Y┤W┤A┤P┤R┤O┤L┤D┤V┤\┤.┤ Здесь: -┤в верхней с троке:┤┤┤┤"C"┤-┤соответствует ноте до#; ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤"U"┤-┤ре#,...; ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤":"┤-┤соль# второй октавы; -┤в нижней строке:┤┤┤┤┤┤"F"┤-┤до; ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤"Y"┤-┤ре,...; ┤┤┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤┤┤┤┤┤┤┤┤"."┤-┤соль второй октавы. 7. СИСТЕМНО-НЕЗАВИСИМЫЙ НАБОР ПРОЦЕДУР ОБМЕНА С ПП (PSERV.OBJ). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Кроме процедур LOADER и UNLOAD в пакете PSERV существует набор подпрограмм, который осуществляет выполнение следующих операций с ОЗУ┤ПП: - запросить участок памяти у ПП; - переписать из ОЗУ┤ЦП в ОЗУ┤ПП; - переписать из ОЗУ┤ПП в ОЗУ┤ЦП; - освободить память, запрошенную по п. 1; - передать управление программе в ОЗУ┤ПП. - 34 - Отличительной особенностью пакета PSERV является его полная системная независимость (он будет работать даже при отсутствии операционной системы).Далее приведены описания и примеры обращения к подпрограммам пакета. В примерах используются следующие обозначения: WCNT┤┤┤┤┤-┤размер в словах; ADDRESS┤┤-┤адрес; ADDRCP┤┤┤-┤адрес в ОЗУ┤ЦП; ADDRPP┤┤┤-┤адрес в ОЗУ┤ПП; GOADR┤┤┤┤-┤адрес процедуры, запускаемой в ОЗУ┤ПП. 7.1. .ALLOC - запросить область памяти в ОЗУ┤ПП┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Аргументы: размер запрашиваемой области памяти в стеке. Результат: адрес области - в R0. Вызов:┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#WCNT,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤CALL┤┤.ALLOC 7.2. .FREE - освободить область памяти в ОЗУ┤ПП┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Аргументы: адрес и размер освобождаемой области в стеке. Результат: освобождение области памяти. Вызов:┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#ADDRESS,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#WCNT,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤CALL┤┤.FREE 7.3. .PUT - переписать часть памяти ЦП в память ПП┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Аргументы: адрес в ОЗУ┤ЦП, адрес в ОЗУ┤ ПП, размер - в стеке. Результат: часть памяти ЦП копируется в память ПП. Вызов:┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#ADRCP,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#ADRPP,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#WCNT,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤CALL┤┤.PUT 7.4. .GET - переписать часть памяти ПП в память ЦП┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Аргументы: адрес в ОЗУ┤ПП, адрес в ОЗУ┤ЦП, размер - в стеке. Результат: часть памяти ПП копируется в память ЦП. Вызов:┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#ADRCP,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#ADRPP,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#WCNT,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤CALL┤┤.GET 7.5. .GO - запустить подпрограмму в ОЗУ┤ПП┘. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Аргументы: адрес старта - в стеке. Результат: запуск подпрограммы в ОЗУ┤ПП. Вызов:┤┤┤┤┤┤┤┤┤┤┤┤MOV┤┤┤#GOADDR,-(SP) ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤CALL┤┤.GO - 35 - ПРИМЕЧАНИЕ. Проверка корректности аргументов, передаваемых вышеописанным процедурам пакета не производится, поэтому просим Вас внимательно относиться к передаваемым значениям аргументов. Мало того, не производится проверка и результатов выполнения этих процедур. При запросе адреса участка памяти следует поступать по принципу "проси больше - получишь сколько надо". Больше, в данном случае, - это на одно (всегда ОДНО) слово, и тут никуда не денешься - очередная ошибочка разработчиков. 8. ОПИСАНИЕ ДРАЙВЕРА ОБМЕНА С ПЕРИФЕРИЙНЫМ ПРОЦЕССОРОМ PP.SYS . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Данный драйвер выполняет функции обслуживания стандартных запросов к периферийному процессору: 1. Запросить память у ПП. 2. Переписать из ОЗУ┤ЦП в ОЗУ┤ПП. 3. Переписать из ОЗУ┤ПП в ОЗУ┤ЦП. 4. Освободить память, запрошенную по п. 1. 5. Передать управление программе в ОЗУ┤ПП. Для выполнения этих функций служит .SPFUN с номером 377┬8└. Код выполняемого запроса - нулевое слово в буфере .SPFUN.Перечисленным запросам соответствуют следующие коды: 1 - 04┬8 2 - 02┬8 3 - 01┬8 4 - 10┬8 5 - 20┬8 В целом, структура буфера .SPFUN такова: ┤┤┤┤┤┤┤┤┤+--------------------+┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤0┤┤┤┤!┤┤┤┤┤┤opt.┤code┤┤┤┤┤!┤-┤код┤запроса┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤┤┤┤┤┤+--------------------+┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤1┤┤┤┤!┤┤┤PP┤ram┤address┤┤┤!┤-┤адрес┤в┤ОЗУ┤ПП┤┤┤┤┤┤ ┤┤┤┤┤┤┤┤┤+--------------------+┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤2┤┤┤┤!┤┤┤CP┤ram┤address┤┤┤!┤-┤адрес┤в┤ОЗУ┤ЦП┤┤┤┤┤┤┤ ┤┤┤┤┤┤┤┤┤+--------------------+┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤ ┤┤┤┤3┤┤┤┤!┤┤┤┤Word┤counter┤┤┤┤!┤-┤размер┤области┤памяти ┤┤┤┤┤┤┤┤┤+--------------------+┤┤┤┤┤┤┤┤(в┤словах)┤┤┤┤┤┤ Код запроса должен быть указан всегда. Адрес в ОЗУ┤ПП - для запро- сов 2, 3, 4, 5. Адрес в ОЗУ┤ЦП - для запросов 2, 3. Размер области памяти - для запросов 1, 2, 3, 4. Следует учесть, что при попытке запросить не существующую память происходит остановка ПП. Поэтому не следует пытаться загрузить более 24К. Рекомендуемая последовательность действий для загрузки пользовательского программного обеспечения в ОЗУ┤ПП: -┤освободить участок памяти необходимого размера и зафиксировать адрес, возвращаемый в первом слове буфера .SPFUN; -┤загрузить свою программу в ОЗУ┤ПП с этого адреса; -┤передать управление загруженной программе с этого адреса; -┤по окончании работы освободить запрошенную память. - 36 - Пример исполнения описанной последовательности действий: ┤┤┤┤┤┤┤.TITLE┤┤┤PPTEST ┤┤┤┤┤┤┤.IDENT┤┤┤/240590/ ┤┤┤┤┤┤┤.ENABL┤┤┤MCL ┤┤┤┤┤┤┤.DSABL┤┤┤GBL ┤┤┤┤┤┤┤.MCALL┤┤┤.PRINT,.EXIT PPBLK:┤.RAD50┤┤┤/PP┤┤┤┤┤┤┤┤┤┤/ AREA::┤.BLKW┤┤┤┤15 BUFF::┤.BLKW┤┤┤┤6 NOPP:┤┤.ASCIZ┤┤┤/No┤PP-Driver┤in┤memory/ ┤┤┤.EVEN PTEST:: ┤┤┤┤┤┤┤.SERR┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤ошибки┤обрабатываем┤сами ┤┤┤┤┤┤┤.LOOKUP┤┤#AREA,#0,#PPBLK┤;┤установим┤связь┤с┤драйвером ┤┤┤┤┤┤┤BCC┤┤┤┤┤┤1$┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤удалось┤-┤отлично ┤┤┤┤┤┤┤.PRINT┤┤┤#NOPP┤┤┤┤┤┤┤┤┤┤┤;┤иначе┤сообщение ┤┤┤┤┤┤┤.EXIT┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤и┤закончить 1$: ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#BUFF,R5┤┤┤┤┤┤┤┤;┤R5-указатель┤в┤буфере┤.SPFUN ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#ALO$,@R5┤┤┤┤┤┤┤;┤запрос┤-┤освободить┤память ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#/2,6(R5)┤;┤занесли┤размер ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤памяти ┤┤┤┤┤┤┤.SPFUN┤┤┤#AREA,#0,#377,#BUFF,#4,#0┤┤;┤освободили┤ее ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#PUT$,@R5┤┤┤┤┤┤┤;┤запрос┤-┤записать в┤ОЗУ┤ПП ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#PPSTART,4(R5)┤┤;┤занесли┤адрес┤в┤ОЗУ┤ЦП ┤┤┤┤┤┤┤.SPFUN┤┤┤#AREA,#0,#377,#BUFF,#4,#0┤┤;┤переписали ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#GO$,@R5┤┤┤┤┤┤┤┤;┤запрос┤-┤передать┤управление ┤┤┤┤┤┤┤.SPFUN┤┤┤#AREA,#0,#377,#BUFF,#4,#0┤;┤передали ┤┤┤┤┤┤┤MOV┤┤┤┤┤┤#FRE$,@R5┤┤┤┤┤┤┤;┤запрос┤-┤освободить┤память ┤┤┤┤┤┤┤.SPFUN┤┤┤#AREA,#0,#377,#BUFF,#4,#0┤┤;┤освободили ┤┤┤┤┤┤┤.EXIT PPSTART:: ;┤┤┤┤┤┤┤┤┤... ;┤┤┤┤┤┤┤┤┤... ;┤┤текст┤программы,┤работающей┤в┤ОЗУ┤ПП ;┤┤┤┤┤┤┤┤┤... ;┤┤┤┤┤┤┤┤┤... PPEND:: ┤┤┤┤┤┤┤.END┤┤┤┤┤PTEST Кроме перечисленного драйвер PP.SYS выполняет еще одну важную функцию - корректно выполняет запросы .READx и .WRITx. Выполнение этих запросов приводит соответственно к чтению и записи в ОЗУ┤ПП в соответствии с системными соглашениями. Эта возможность оказалась удобна при отладке программ, работающих в ОЗУ┤ПП и исследовании алгоритмов работы ПЗУ┤ПП (это сейчас, по нашему глубокому убеждению, является загадкой и для их авторов). ПРИМЕЧАНИЕ. Драйвер PP.SYS перед работой с периферийным процессором должен быть обязательно загружен! Используйте запрос .FETCH! - 37 - 9. МОДУЛЬ ЗАГРУЗКИ ФОНТОВ (FNTLOA) . ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Поскольку процесс загрузки фонтов пользователя - достаточно трудоемкая операция, а необходимость ее возникает достаточно часто, нами был написан загрузчик фонтов. Работа с этой программой ведется следующим образом: 1. Готовится файл фонтов в следующем формате: - глобальная метка FNTSTART::; - набор фонтов; - глобальная метка FNTEND::; - псевдокоманда ассемблера .END. Перед каждым фонтом стоит байт с кодом фонта в стандартной 8-битной кодировке. Фонт состоит из 11┬10└ байт - горизонтальных сечений маски символа. Приводим пример типичного файла фонтов: FNTSTART:: ┤┤┤┤┤┤.BYTE┤┤┤┤┤┤101┤┤;┤замена┤латинской┤буквы┤А ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤на┤верхнем┤регистре ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B11110000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B01111000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00111100 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00011110 ┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00001111 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00011110 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00111100 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B01111000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B11110000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B11111111 ┤┤┤┤┤┤.BYTE┤┤┤┤┤┤101!40┤;┤замена┤латинской┤буквы┤А ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤на┤нижнем┤регистре ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B01000000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00100000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00010000 ┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00001000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000100 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000010 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000010 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000100 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00001000. ┤┤┤┤┤.BYTE┤┤┤┤┤┤101!200┤;┤замена┤русской┤буквы┤А ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤на┤верхнем┤регистре ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000010 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000100 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00001000 ┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00010000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00110000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00010000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00001000 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000100 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000010 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B00000001┤┤ - 38 - ┤┤┤┤┤.BYTE┤┤┤┤┤┤101!200!40┤;┤замена┤русской┤буквы┤А ┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤┤;┤на┤нижнем┤регистре ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B11111111 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000100 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B10000001 ┤┤┤┤┤┤┤┤.BYTE┤┤┤┤┤┤^B11111111 FNTEND: ┤┤┤┤┤┤┤┤.END 2. Ассемблировать файл фонтов. Для этого наберите команду: MACRO FILE где FILE - имя файла фонтов. 3. Подкомпоновать файл фонтов к загрузчику. Для этого наберите команду: LINK FNTLOA,FILE,PSERV В результате этих действий Вы получите загрузочный модуль. Если Вы запустите его, то системный набор фонтов будет заменен на тот, который Вы указали в файле фонтов. ПРИМЕЧАНИЕ (для системного программиста).Этой программой не всегда будет удобно пользоваться из прикладного программного обеспечения. (Действительно, запуск задачи, а затем возврат в самого себя, не менее трудоемкая процедура, чем загрузка фонтов.) Поэтому целесообразно пояснить, что делает загрузчик фонтов. В ОЗУ┤ПП с адреса @#14142 расположена таблица адресов фонтов. Адреса расположены в порядке стандартного 8-битного кода. То есть удвоенный 8-битный код символа является смещением от начала таблицы фонтов до адреса соответствующего фонта. Сами фонты расположены в системном ПЗУ, и в ОЗУ не переписываются. Поэтому попытка прописать поверху их своим и фонтами обречена на провал. (Именно это и попытались сделать авторы системного ПЗУ). Вам, таким образом, необходимо переписать фонты в ОЗУ┤ПП и поменять ссылки в таблице фонтов. Так и поступает загрузчик фонтов. Для операций с содержимым ОЗУ┤ПП используется пакет PSERV, который вместе с соответствующим описанием имеется в поставке. - 39 - П Р И Л О Ж Е Н И Я ~~~~~~~~~~~~~~~~~~~ ПРИЛОЖЕНИЕ 1. Протокол обмена с UKLOAD Общение с UKLOAD производится с помощью ESC - последователь- ностей, имеющих следующий вид: <код процедуры><параметр процедуры> (ESC=33┬8└). Значения кодов процедуры следующие: 21┤-┤ зарегистрировать спрайт; 22┤-┤задать перемещение спрайта (формат 1); 23┤-┤задать перемещение спрайта (формат 2); 24┤-┤вывести спрайт; 25┤-┤перемещение спрайта (формат 1); 26┤-┤перемещение спрайта (формат 2); 27┤-┤музыка; 31┤-┤печать в верхней строке; 32┤-┤печать в нижней строке; 40┤-┤отрезок; 41┤-┤текущий цвет вывода; 44┤-┤тип вывода; 46┤-┤перекрасить поле вывода; 47┤-┤поле вывода; 56┤-┤заливка; 57┤-┤точка; 61┤-┤введение смещения; 62┤-┤окружность; 63┤-┤стартовая инициализация; 64┤-┤окончание работы; 64┤-┤задать тип линии; 65┤-┤задать пользовательский тип линии; 66┤-┤линия двойной толщины; 67┤-┤прямоугольник; 70┤-┤занавес; 71┤-┤очистка поля вывода; 73┤-┤вернуть адрес загрузки и длину; 74┤-┤записать в ОЗУ ПП; 75┤-┤прочитать из ОЗУ ПП; 76┤-┤управление таймерами; 77┤-┤тип рулона; 100┤-┤установить текстовое окно; 101┤-┤сдвинуть АЦ-строку влево; 102┤-┤сдвинуть АЦ-строку вправо; 103┤-┤сдвинуть АЦ-окно влево; 104┤-┤сдвинуть АЦ-окно вправо; 105┤-┤сдвинуть столбец вверх; 106┤-┤сдвинуть столбец вниз; 107┤-┤сдвинуть окно вверх; 110┤-┤сдвинуть окно вниз; 115┤-┤вернуть автоответ; 116┤-┤сохранить в буфере; 117┤-┤вернуть содержимое буфера; 121┤-┤включить режим кэширования; 122┤-┤выключить режим кэширования; 123┤-┤перестроить кэш-таблицу; 132┤-┤задать цепочку спрайтов для вывода; 133┤-┤задать масштаб шрифта; 134┤-┤задать наклон шрифта; - 40 - 135┤-┤вывести строку; 136┤-┤вывести заданную цепочку спрайтов; 137┤-┤пользовательский тип шрифта. ┤┤┤┤┤BATCH-процессор: 124┤-┤начать выполнение; 125┤-┤то же, но из внутреннего буфера; 126┤-┤закончить выполнение; 127┤-┤начать сохранение; 130┤-┤то же, но во внутреннем буфере; 131┤-┤закончить сохранение. Параметры процедур и их порядок приведены в описании пакета UKGRAPH. Исключение составляет процедура SPR$OUT, в которой последовательность передачи параметров следующая: X, Y, NUMBER При передаче параметров типа "координаты" необходимо производить распаковку машинного слова в два байта следующим образом: 1-й передаваемый байт = X DIV 64┬10└ + 32┬10└ 2-й передаваемый байт = X MOD 64┬10└ + 32┬10└ Все остальные параметры передаются как один байт, к содержимому кото- рого прибавлено 40┬8└ . - 41 - ПРИЛОЖЕНИЕ 2. ~~~~~~~~~~~~~ Комплект поставки На диске поставки находятся следующие файлы: PP.SYS┘┤┤┤┤┤┤-┤драйвер обмена с периферийным процессором; UKLOAD.SAV┘┤┤-┤программа вывода аудио- и видеоинформации, загружа- емая в память периферийного процессора; PASINT.OBJ┘┤┤-┤программный интерфейс между программами на языке PASCAL и программой UKLOAD; CINT.OBJ┘┤┤┤┤-┤программный интерфейс между программами на языке С и программой UKLOAD; PSERV.OBJ┘┤┤┤-┤системно-независимый набор процедур обмена с ПП; FNTLOA.SAV┘┤┤-┤модуль загрузки фонтов пользователя; SPRRED.SAV┘┤┤-┤редактор спрайтов (создает и редактирует спрайты в формате FT X); SPRCNV.SAV┘┤┤-┤конвертер спрайтов из FTX-формата на MACRO-11; SPRLOA.SAV┘┤┤-┤загрузчик спрайтов в память периферийного процессора; GLIB.MLB┘┤┤┤┤-┤макробиблиотека общения с программой UKLOAD; ZAST.PAS┘┤┤┤┤-┤исходный текст демонстрационной программы; ZAST.SAV┘┤┤┤┤-┤загрузочный модуль демонстрационной программы; ZAST.COM┘┤┤┤┤-┤командный файл для создания демонстрационной программы; SPRDEM.FTX┘┤┤-┤набор спрайтов для демонстрационной программы; GLIB.MAC┘┤┤┤┤-┤исходные тексты макробиблиотеки; GOUT.OBJ┘┤┤┤┤-┤набор процедур ввода-вывода для GLIB; GOUT.MAC┘┤┤┤┤-┤соответствующие исходные тексты.