Примечание 2008г.: BEST-DOS - нескромное рабочее название AltairDOS 3.0x.


        Для тех, кто решит написать программу, использующую особенности
        BEST-DOS, будет полезно это описание.


                      О количестве и качестве.
                      ~~~~~~~~~~~~~~~~~~~~~~~~
        Использование 2-х основных концепций - единого адресного
пространства ОРИОНа и общего для всех программ механизма работы с памятью -
позволили писать программы на качественно другом уровне. Под единым адресным
пространством понимается способ адресации любой ячейки памяти ОРИОНа "длинным"
("межбанковым") адресом, состоящим из 24-х бит (длинные адреса BEST-DOS -
банк(8бит)+адрес(16бит), т.е. возможность адресации более 64к ОЗУ) в
дополнение к стандартной 16 битной адресации процессора (до 64к). Есть
соответствующие низовые процедуры управления данными с параметрами - длинными
адресами (они описаны ниже). Подобная адресация была в АЛЬТАИР-ДОС 1.06 -
там были вектора системы, состоящие из 4-х байт: копия порта 0FBh + копия
порта 0F9h + адрес. Их использование было неудобно, т.к. они не несли смысл
составного адреса, а просто обеспечивали корректную работу системы с прерыва-
ниями и использовались только для векторизирования подпрограмм. 
       В AltairDOS 3.0x напротив, вся память системы имеет сплошное адресное 
поле, адресуемое трехбайтным адресом, единые методы работы с памятью для всех
вновь разрабатываемых программ позволяют им не обращать внимания друг на друга,
выделение и освобождение памяти ведется централизованно (контролируется 
системой), программы лишь уведомляются о успехе (или неуспехе) их операций с
памятью (см. ниже).

                Размещение служебных областей ДОС.
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        С точки зрения стандартной CPM-программы память системы делится на
пользовательскую (TPA) и системную (область связи 0..0FFh, BDOS, BIOS). В
системе BEST-DOS есть еще XTPA (расширенная память ОРИОНа в страницах памяти,
не занятых TPA), к которой можно обращаться при помощи дополнительных ф-ий
BDOS. В CPM 2.2 от DIGITAL RESEARCH и ее плагиате на КОРВЕТЕ (а затем и на
ОРИОНе) начало CCP, BDOS и BIOS были стандартизированы (0C400h, 0CC06h, 0DA00h
соответственно), хотя в каждом фирменном описании написано, что привязываться
к этим адресам некорректно, надо определять начало BDOS и BIOS+3 по ячейкам
6..7 и 1..2 (в области связи) из расчета, что на других релизах CPM высота
BDOS/BIOS может быть другой. Так делают все фирменные программы (чего не
скажешь о многих поделках "советских" любителей). Чтобы обеспечить максимальный
размер TPA в BEST-DOS (в последних релизах он равен 59к при условии, что BIOS
не залезает выше 0EFFFh) начало BDOS и BIOS не определены жестко и отличаются
от релиза к релизу (как и размер CCP), поэтому для настройки используйте
ячейки 6..7 и 1..2 (в области связи).
        Кроме того в дополнение к стандартным векторам ошибок BDOS (которые
представляют собой 4 16-битных адреса для 4-х типов ошибок BDOS и размещаются
по адресу BDOS+3...BDOS+10) в системе BEST-DOS есть дополнительные вектора
(дублирующие основные), размещенные сразу за ними (по адресу BDOS+11..BDOS+22).
Они 24-битовые (стандартные длинные адреса BEST-DOS - банк(8бит)+адрес(16бит)).
Использование длинных адресов позволяет размещать п/п обработки ошибок в
любых доступных страницах (банках) памяти. При возникновении ошибки система
сначала передает управление по дополнительному вектору, а затем по основному.
Правила каскадирования дополнительных векторов ошибок аналогичны межбанковым
векторам системы (см. ниже), следует лишь помнить, что и основные и дополни-
тельные вектора системы восстанавливают свое первоначальное значение при
каждом теплом рестарте системы.


                Размещение дополнительной дисковой информации.
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        Система BEST-DOS имеет имена дисков, юзеров, даты файлов, что конечно
существенно улучшает ее пользовательские качества, но и требует дополнитель-
ного резервирования места на дисках для хранения этой информации. Вся допол-
нительная информация размещается на нулевой дорожке (нумерация - по логичес-
ким номерам дорожек и секторов, как это принято при работе через BIOS), что
не вызывает никаких конфликтов ни с CPM, ни с прикладным ПО.
        Метка диска (Volume label) размещается в секторе 1 со смещением
+20h от начала сектора (сразу за блоком параметров диска) и занимает 16 байт.
(+20h..+2Fh).
        Имена юзеров размещаются в секторах 3..4 (сразу за секторами бут-сек-
тора) и занимают соответственно 256 байт.
        Даты файлов размещаются в секторах 5..10 (сразу за секторами имен
юзеров) и занимают соответственно 768 байт.
        Все эти области имеют свои контрольные суммы и поэтому на дискетах,
сформированных не BEST-DOS не будет найдено ни метки диска, ни имен юзеров,
ни дат файлов.
        Всего система занимает четыре логические дорожки (дор. 0..3, около
18 кб) на дискете формата 5 секторов по 1 кб (5 кб на дорожку).


                        Структура юзеров.
                        ~~~~~~~~~~~~~~~~~
        Как и в CPM 2.2 , система BEST-DOS для обеспечения совместимости имеет
16 юзеров которые с точки зрения стандартных CPM-программ остались совершенно
равноценными. Но в BEST-DOS для обеспечения лучшей структурированности разме-
щения данных на диске введены имена юзеров(16-и символьные) и вложенность
(каждый юзер может быть вложен в любой другой с глубиной вложения до 15).
Юзер 0 (он считается корневым) не имеет имени и на его (имени) месте
размещается информация о вложенности (15 байт) . ССР при вызове команд
USER и INSERT без параметров или при попытке обратиться к юзеру по
несуществующему имени выводит "дерево юзеров" - список имен юзеров, в
котором отступами отображается вложенность юзеров.

Пример "дерева юзеров":
      \                  <- корневой
        USER_1           <- вложен в корневой
        LANGUAGES        <- вложен в корневой
          PASCAL         <- вложен в LANGUAGES
            SOURCE       <- вложен в PASCAL
            COM_FILES    <- вложен в PASCAL
          BASIC
        USER_4
        USER_7
        USER_8
        USER_9
          USER_10
            USER_12
              USER_13    <- глубина вложенности равна четырем
        USER_14
        SYSTEM


                Организация памяти.
                ~~~~~~~~~~~~~~~~~~~
        Ниже представлено распределение памяти для ДОС без драйверов (все ХТРА
считается свободным), хотя это распределение в новых релизах может быть другим,
точно это можно узнать запросив у системы карту памяти (см. ниже):

  Область F000..F3FF - общая для всех банков памяти. По адресу EFFF во всех
  банках находится номер соответствующего банка (маркер банка), необходимый
  для работы подпрограмм, обслуживающих прерывания и для программ и драйверов,
  определяющих номер банка, в каком они работают.

  0:0000..0:3FFF  - экранная плоскость 0
  0:4000..0:DFFF  - свободно (ХТРА)
  0:E000..0:EFFF  - системная область
  В принципе, при необходимости можно использовать и память 0:E000..0:EFFE,
  ячейку EFFF трогать нельзя !!!. Однако при этом возможны конфликты с
  операционной системой.

  1:0000..1:3FFF  - экранная плоскость 0 (цвет)
  1:4000..1:8FFF  - свободно (ХТРА)
  1:9000..1:EFFF  - системная область (основная часть ДОС)

  2:0000..2:DFFF  - системная область (ТРА ДОС)
  2:E000..2:EFFF  - системная область ("виртуальная" ДОС)

      Для всех остальных банков:
  Х:0000..Х:DFFF  - свободно (ХТРА)
  Х:E000..Х:EFFF  - системная область
  Учтите, что системный драйвер консоли не имеет фиксированного рабочего
  адреса и банка, он при своей инициализации резервирует в XTPA 3 сегмента,
  и находится в этих сегментах.

                Планировка области F000..F3FF.

  При использовании любой памяти в системе BEST-DOS необходимо убедиться в том,
что она не занята (по карте памяти). Область F000..F3FF на карте обозначена
как занятая - она занята подпрограммами межбанкового сервиса, векторами
системы, системным стеком и различными буферными областями :
  Область F000..F153 в версии 3.04 ничем не занята.
  Область F153..F1FE используется системой для быстрого трансфера данных
между банками при дисковых операциях, а также стандартным драйвером консоли
при выводе символа на экран.
  2 байта (F1FF.F200) системой не используются и оставлены на случай если
надо будет сформировать еще один вектор прерывания IM2 (системный расположен
на F2FF..F300). Программа , перепрограммирующая регистр I Z80 должна уметь
восстанавливать старое его содержимое.
  В области F201..F2FE находятся подпрограммы межбанкового сервиса. Для
драйверов объявлены следующие входы:
   0F201h - межбанковый LDIR : пересылка блока данных , размер которого задан
            в рег.BC из области с начальным адресом заданным в A+HL (в формате
            банк+адрес) в область с начальным адресом в A'+HL'
   0F204h - межбанковый JMP : передача управления в другой банк на адрес A+HL
   0F207h - межбанковый CALL : передача управления в другой банк на адрес
            A+HL с последующим возвратом командой RET
   0F20Ah - межбанковый RET. Возврат из подпрограммы в другом банке можно
            оcуществить и командой    JP  0F20Ah . Не портит никакие регистры.
   0F20Dh - загрузить в регистр В содержимое ячейки памяти из другого банка по
            адресу  A+HL
   0F20Dh - записать содержимое регистра В в ячейку памяти в другом банке по
            адресу  A+HL
        Драйвера должны пользоваться только этими объявленными входами.
Системные программы, которые хотят считаться классическими должны пользоваться
только объявленными п/п BDOS и BIOS и не лезть в ОЗУ выше BDOS.

   В области F301..F33F находятся системные вектора-дублеры BDOS (0) ,
BIOS (1..15), вектора прерываний (16..17), вектора п/п - обработчиков
стандартных событий от прочих устройств и программа (18..20)
   Структура вектора :   DEFB <номер страницы> DEFW <адрес в странице>

0F301H  вектор BDOS                                             0

0F304H  теплый старт BIOS                                       1
0F307H  состояние клавиатуры                                    2
0F30AH  ввод с клавиатуры                                       3
0F30DH  вывод на дисплей                                        4
0F310H  вывод на принтер                                        5
0F313H  ВЫВОД НА УСТРОЙСТВО ВЫВОДА                              6
0F316H  ВВОД С УСТРОЙСТВА ВВОДА                                 7
0F319H  уст. дорожки 00                                         8
0F31CH  выбор диска                                             9
0F31FH  уст. номера дорожки                                     10
0F322H  уст. номера сектора                                     11
0F325H  уст. адреса буфера обмена                               12
0F328H  чтение сектора                                          13
0F32BH  запись сектора                                          14
0F32EH  состояние принтера                                      15

0F331H  вектор вторичного обработчика прерывания INT 50 Гц      16
0F334H  вектор программного прерывания Монитора3 (ctrl+shf+key) 17

0F337H  вектор пользовательских событий/расширений:             18
        клавиатура, мышь, оконные события и т.п.
0F33AH  резерв                                                  19
0F33DH  резерв                                                  20

        При вызове векторизированной подпрограммы, ДОС сначала делает
межбанковый CALL по значению вектора, соответствующего данной п/п, т.е.
драйвера, каскадирующие этот вектор, отработают до системной подпрограммы.
Первоначально вектора установлены так, чтобы сразу возвращать управление
системе. При подключении драйвера, драйвер должен запомнить старое значение
вектора (оно указывает либо на очередной драйвер, либо на возврат в систему-
это не принципиально) и записать новое значение вектора, указывающее на этот
драйвер. При обращения программы к рассматриваемой подпрограмме ДОС про-
изойдет передача управления на позже всех инсталлировавшийся драйвер . Он,
отработав, передает управление следующему при помощи межбанкового JMP по
значению вектора, которое было до его инсталляции (для этого и запоминается
в теле драйвера старое значение вектора). Так работает вся цепочка драйверов.
При использовании межбанковых подпрограмм портятся регистры A и HL, поэтому
для передачи параметров по цепочке надо использовать регистры BC,DE,A',BC',
DE',HL'. Соответственно драйвера при передаче управления должны должны пере-
давать все регистры кроме A и HL такими, какими они были при входе в драйвер.
Выход из драйвера командой RET или JP 0F20Ah приведет к возвращению управле-
ния ДОС, не давая отработать следующим по цепочке драйверам. Драйвера должны
инсталлироваться используя ф-ию 105d BDOS (это дает автоматическое резерви-
рование памяти, размещение драйвера, устранение конфликтов, возможность
удаления драйвера с освобождением занимаемой им памяти). В конце текста
есть пример простого драйвера.

        В области F340..F3BF находится системный стек.

        Ячейка 0F3F5h - константа цвета, заданная командой COLOR x y  из
CCP или CONFIG.SYS.
        Ячейка 0F3F6h - системные установки . По битам:
    D0 = 0/1 = WIDTH 6/8
    D1 = 0/1 = PROMPT OFF/ON
    D2 = 0/1 = ECHO OFF/ON
    D3 = 0/1 = ф-ия 10 BDOS не имеет/имеет доступ к тимплету
    D4 = 0/1 = LPT F500/F600
    D5 = 0/1 = индикатор занятости драйвера консоли для обработчиков INT 50 Гц
    D6 = 0/1 = нет/есть аппаратные прерывания INT 50Гц (уст. драйвером консоли)
    D7 = 0/1 = бит управления 10 фукцией BDOS (для удобства).
        Ячейка 0F3F7h - опознаватель драйвера консоли .
        Ячейка 0F3F8h - копия порта 0F8h.
        Ячейка 0F3F9h - банк, где расположена TPA системы, для этого релиза
                        ДОС содержит значение 2
        Ячейка 0F3FAh - копия порта 0FAh.
        Ячейка 0F3FBh - копия порта 0FBh.


                Новые функции BDOS.
                ~~~~~~~~~~~~~~~~~~~
        С целью повышения сервисных возможностей системы, к функциям BDOS,
имевшихся в BDOS системы CPM 2.2 добавлены следующие функции:
    1. Ф-ии 29h(41d)..3Ah(58d) - функции дискового интерфейса.
    2. Ф-ии 64h(100d)..73h(115d) - функции менеджера расширенной памяти.
    3. Ф-ии 80h(128d)..0FFh(255d) - функции внешних надстроек BDOS. Они
       системой никак не обрабатываются и результаты их работы системой
       не изменяются. Считается, что драйвера-надстройки BDOS (напр.
       ф-ии графического интерфейса) получают необходимые параметры сидя
       на векторе BDOS (0F301h) и сами формируют выходные результаты.

 F29 - В МАССИВ С АДРЕСОМ В DE В ТЕКУЩЕМ БАНКЕ ВОЗВРАЩ.16 СИМВ.МЕТКА ДИСКА
       ВЫХОД: А=0 ЕСЛИ НОРМАЛЬНО И 0FFh ЕСЛИ НЕТ МЕТКИ
 F2A - ИЗ МАССИВА (ПО DE) НА ДИСК ЗАПИС. 16-И СИМВОЛЬНАЯ МЕТКА ДИСКА
       ВЫХОД: А=0 ЕСЛИ НОРМАЛЬНО И 0FFh ЕСЛИ НЕТ МЕТКИ
 F2B - В МАССИВ (ПО DE) ВОЗВРАЩ. 16 СИМВ. ИМЯ ТЕКУЩЕГО ЮЗЕРА
       ВЫХОД: А=0 ЕСЛИ НОРМАЛЬНО И 0FFh ЕСЛИ У ЮЗЕРОВ НЕТ ИМЕН
 F2C - ТЕКУЩЕМУ ЮЗЕРУ УСТАНАВЛ. НОВОЕ ИМЯ ИЗ МАССИВА (ПО DE) - 16 СИМВ.
       ВЫХОД: А=0 ЕСЛИ НОРМАЛЬНО И 0FFh ЕСЛИ У ЮЗЕРОВ НЕТ ИМЕН
 F2D - УСТАНОВКА ЮЗЕРА ПО ИМЕНИ ИЗ МАССИВА (ПО DE)
       ВЫХОД: А=0 ЕСЛИ НОРМАЛЬНО И 0FFh ЕСЛИ У ЮЗЕРОВ НЕТ ИМЕН ИЛИ НЕТ ЮЗЕРА
       С ТАКИМ ИМЕНЕМ
 F2E - ПОЛУЧИТЬ ИЗ БУФЕРА ТИМПЛЕТА СТРОКУ В МАССИВ (ПО DE).
       ВЫХОД: А=<НОМЕР В БУФЕРЕ ПОЛУЧЕННОЙ СТРОКИ> ИЛИ 0 ЕСЛИ БУФЕР ПУСТ
 F2F - ДОБАВИТЬ СТРОКУ В БУФЕР ТИМПЛЕТА ИЗ МАССИВА (по DE).
 F30 - ПОЛУЧХАЬ ИЗ БУФЕРА ПОДМЕН СТРОКУ В МАССИВ (ПО DE).
       ВЫХОД: А=<НОМЕР В БУФЕРЕ ПОЛУЧЕННОЙ СТРОКИ> ИЛИ 0 ЕСЛИ БУФЕР ПУСТ
 F31 - ДОБАВИТЬ СТРОКУ В БУФЕР ПОДМЕН ИЗ МАССИВА (по DE).
 F32 - ПОЛУЧИТЬ СТРОКУ ИЗ BAT-БУФЕРА В МАССИВ (ПО DE).МАСCИВ СОКРАЩАЕТСЯ
       ВЫХОД: А=0 ЕСЛИ НОРМАЛЬНО И 0FFh ЕСЛИ БУФЕР ПУСТ.
 F33 - ДОБАВИТЬ СТРОКУ В BAT-БУФЕР ИЗ МАССИВА (ПО DE).
 F34 - ПОЛУЧИТЬ ДАТУ И ВРЕМЯ СОЗДАНИЯ ФАЙЛА. ВХОД: DE=ADDR(FCB).
       FCB ЗАПОЛНЯЕТСЯ КАК ПРИ ОТКРЫТИИ ФАЙЛА. ДАТА ВОЗВРАЩАЕТСЯ В
       FCB В БАЙТАХ FCB+16..FCB+20 В HEX ВИДЕ В ФОРМАТЕ:
       FCB+16 - ГОД               FCB+19 - ЧАСЫ
       FCB+17 - МЕСЯЦ             FCB+20 - МИНУТЫ
       FCB+18 - ДЕНЬ
 F35 - УСТАНОВИТЬ ДАТУ СОЗДАНИЯ ФАЙЛА. ВХОД: DE=ADDR(FCB).
       БАЙТЫ  FCB+16..FCB+20  ЗАПОЛНЯЮТСЯ ПО ПРАВИЛАМ Ф.34
 F36 - ПОЛУЧИТЬ СТРОКУ УСТАНОВКИ ДИСКОВ (В МАССИВ ПО DE)
       ЭТА СТРОКА ФОРМИРУЕТСЯ КОМАНДАМИ  ASSIGN  CONFIG'А
 F37 - УСТНОВИТЬ/ПОЛУЧИТЬ PATH-USER . ВХОД: E=(0..0FH)/0FFH
       ВХОД: E=10H..0FEH - ОТКЛЮЧИТЬ  PATH-СЕРВИС
 F38 - ПОЛУЧИТЬ ДАТУ СОЗДАНИЯ ПОСЛЕДНЕГО ИСПОЛЬЗОВАВШЕГОСЯ
       ФАЙЛА. НЕ ТРЕБУЕТ ПРЕДВАРИТЕЛЬНОГО ОТКРЫТИЯ ФАЙЛА.
       ВХОД: DE=ADDR(FCB).
       БАЙТЫ  FCB+16..FCB+20  ВОЗВРАЩАЮТСЯ ПО ПРАВИЛАМ Ф.34
 F39 - УСТАНОВИТЬ ДАТУ СОЗДАНИЯ ПОСЛЕДНЕГО ИСПОЛЬЗОВАВШЕГОСЯ
       ФАЙЛА. ВХОД: DE=ADDR(FCB).
       БАЙТЫ  FCB+16..FCB+20  ЗАПОЛНЯЮТСЯ ПО ПРАВИЛАМ Ф.34
 F3A - ПОЛУЧИТЬ АДРЕС 128б БУФЕРА DMA (БАНК СЧИТАЕТСЯ
       АВТОМАТИЧЕСКИ ПРИ ВЫЗОВЕ ДИСКОВЫХ П/П ЗАПИСИ/ЧТЕНИЯ).

 В функциях F21..F2D,F36, в регистре DE передается/получается указатель
на строку (массив) из 16 байт.

 В функциях F2E..F33 в регистре DE передается/получается указатель на строку,
заполненную в формате ф-ии 10 BDOS:
        Bmax Breal STRING[Breal] , где
   Bmax  - максимальное количество символов в строке STRING  (1 байт)
   Breal - реально считанное кол-во символов в строке STRING (1 байт)
   STRING- значащие символы строки STRING (всего Breal байт).

 Значение 0FFh получаемое в рег.А всегда говорит о неудачном завершении
операции.

           Функциии BDOS-менеджера расширенной памяти.
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Менеджер расширенной памяти оперирует сегментами размером 4096 байт (4к).

  Ф. 100 (64h)
  Установка адреса буфера обмена из DE. Банк (номер 64к страницы памяти) 
  определяется BDOS автоматически.

  Ф. 101 (65h)
  Копирование сегментoв в буфер (установленный Ф.100).
  Вход: D=количество сегментов, E=начальный сегмент.
  Выход: A = 0, если нормально, A = FF если в процессе
         чтения сегментов попался отсутствующий сегмент.

  ф. 102 (66h)
  Запись сегментов из буфера обмена.
  Вход: D=количество сегментов, E=начальный сегмент.
  Выход: A = 0, если нормально, A = FF если в процессе
         записи сегментов попался отсутствующий сегмент.

  Ф. 103 (67h)
  Зарезервировать N последовательных сегментов.
  Вход: D=количество сегментов
        E=начальный сегмент (0FFh если любой)
  Выход: A=начальный сегмент, если резервирование прошло
         нормально, A=FF, если области такого размера нет

  Ф. 104 (68h)
  Oсвободить N последовательных сегментов
  Вход: D=количество сегментов, Е=начальный сегмент
  Выход: A=начальный сегмент, если освобождение прошло
         нормально, A=FF, если была ошибка (освобождение
         системного или отсутствующего ОЗУ)


  Ф. 105 (69h)
  Инсталлировать драйвер пользователя
  Вход: DE = адрес строки - описателя драйвера
  Выход: А=номер драйвера в таблице (1..13), если
         инсталляция прошла удачно  А=FF - иначе
  Формат строки - описателя драйвера (в ТРА):
  +0       - Банк, где располагать драйвер (0FFH-первый под-
             ходящий с конца - по наличию свобод. участка)
  +1..+8   - имя драйвера
  +9..+10  - начальный адрес драйвера в ОЗУ ТРА СРМ(16 бит)
  +11..+12 - длина драйвера (16 бит) (сколько пересылать)
  +13..+14 - адрес п/п захвата векторов (в ОЗУ доп. стр.)
             (для инсталляции).П/п находится в теле драйвера
             и при его инсталляции получает управление. П/п
             переключает вектора на драйвер и может содержать
             перемещающий загрузчик, если драйвер объявлен
             как перемещаемый (грузится на любой адрес). При
             этом в регистре B драйвер получает номер своего
             начального 4к сегмента, а в рег. DE-абсолютный
             адрес данной подпрограммы в странице памяти.
  +15..+16 - адрес п/п уведомления о настройке\удалении (в ОЗУ
             доп. стр.) - обработчик сигналов ОС. Драйвера
             оповещается сигналами, код сигнала передается в
             регистре С (в текущей версии ОС только SIGKILL=9)
             обращением на этот адрес, чтобы драйвер мог в нужный
             момент занять или освободить используемые ресурсы).
             Регистры B, DE  устанавливаются аналогично п\п
             +13..+14 .
  +17..+18 - начальный адрес драйвера (в ОЗУ доп. страницы)
             или 0FFFFh если принять за нач. адрес начала
             первого подходящего сегмента. В этом случае в
             п/п инсталляции встраивается перемещающий
             загрузчик (для пересчета меток) - см. пример.
             В случае перемещаемого драйвера (17..18=FFFF)
             на 13..14 и 15..16 записываются относительные
             адреса от начала первого сегмента драйвера,
             для неперемещаемого (17..18<FFFF)-абсолютные.
  +19      - код, указывающий, что далее идет информация для
             диспетчера программ. В этом случае код = 7Fh
             (127d) - предполагается что этот драйвер - итерактивная
             программа (GUI), которая активируется с клавиатуры
             по программному прерыванию Монитора-3 (ctrl+shift+key).
             При другом значении кода +19 при инсталляции
             драйвера, в массив диспетчера программ ничего
             не заносится, и описатель драйвера на этом
             заканчивается, а сам драйвер активировать из 
             диспетчера программ нельзя (в списке итерактивных 
             программ-резидентов его не будет).
  +20      - код программного прерывания (Монитор3 ctrl+shift+key) по
             которому активируется данная резидентная программа
             с клавиатуры (это актуально для программ с GUI -
             итерактивных). Этот код запоминается в массиве
             диспетчера программ если байт +19 имел
             значение 7Fh (127d).
  +21..+36 - имя резидентной программы, оканчивающаяся нулем.
             Эта строка (не более 16 символов) запоминается
             в массиве диспетчера программ если байт +19
             имел значение 7Fh (127d).


  Ф. 106 (6Ah)
  Удалить драйвер пользователя
  Вход: DE = адрес строки - имени драйвера (8 символов)
  Выход: А=номер удаленного драйвера в таблице (1..13),
         если удаление прошло удачно  А=FF, если драйвера
         с таким именем нет .
  При удалении драйвера автоматически стирается соответств.
  запись в массиве диспетчера программ (если она есть).

  Ф. 107 (6Bh)
  Получить список драйверов
  Выход: в буфер обмена помещается таблица из 0..13
         элементов - заголовков записей о драйвере
         (каждый элемент имеет длину 18 байт)
         A=0..13 - количество этих элементов
  Структура одной записи о драйвере в буфере обмена:
    +0       - начальный сегмент драйвера
    +1..+8   - название драйвера
    +9..+11  - 24-х битовое отображение занимаемых векторов
    +12      - резерв
    +13..14  - адрес п/п инсталляции (захвата векторов)
    +15..+16 - адрес п/п уведомления о удалении
    +17      - длина драйвера (в сегментах)


  Ф. 108 (6Ch)
  Поиск драйвера по имени с метасимволами.
  Вход: DE=адрес строки - имени драйвера (8 символов)
         строка (имя) может содержать знаки '?'
  Выход: А=1..13 и в буфере обмена - запись о драйвере, ^
         если драйвер с таким шаблоном (именем) есть
         А=FF если драйвера с таким шаблоном нет.

  Ф. 109 (6Dh)
  Получить карту памяти
  Выход: в буфер обмена помещается 128-байтовая карта пам.
         Каждый из 256 4-х битовых нибблов отражает
         занятость одного сегмента размером 4096 байт (4к).
         Т.о. 128-байтовая таблица отображает занятость
         1М ОЗУ. Каждый из нибблов(тетрад) значит:
           0         - сегмент свободен
           1..0Dh(13)- сегмент занят драйвером с номером по
                       таблице 1..13 соответственно
           0Eh(14)   - сегмент занят для системных нужд
           0Fh(15)   - сегмент отсутствует или неисправен
         Вообще, в системе с 1Мб памяти располагается 256
         сегментов (каждый размером 4Кб) с номерами соот-
         ветственно от 0..0FFh. Удобно определять физическое
         расположение сегмента, разложив его номер на 2
         ниббла : старший - номер банка (страницы памяти),
         младший - старшие 4 бита 16-битного адреса в
         этом банке. Например, сегмент 3Eh расположен в
         3-м банке с адреса 0E000h по 0EFFFh . Этот сег-
         мент в карте памяти располагается со смещением
         3Eh/2=1Fh, деление без остатка => в старшем ниббле.
         Сегмент с номером 2Dh в карте памяти располагается
         со смещением  2Dh/2=16h, деление с остатком => в
         младшем ниббле.

  Ф. 110 (6Eh)
  Получить информацию о памяти
  Выход: H=размер всего исправного ОЗУ в сегментах
         L=размер свободного ОЗУ в сегментах

  Ф. 111 (6Fh)
  Пересчет физ. адреса в номер сегмента
  Вход: DE = старший байт адреса (D) + банк (E)
        Младший байт адреса считается равным нулю.
  Выход: A = номер сегмента

  Ф. 112 (70h)
  Пересчет номера сегмента в физ. адрес
  Вход: E = номер сегмента
  Выход: HL = старший байт адреса (H) + банк (L)
        Младший байт адреса считается равным нулю.

  Ф. 113 (71h)
  Восстановление карты системного и отсутствующего ОЗУ
  Восстанавливает отметку системного и отсутствующего ОЗУ в
  карте памяти такой, какой она была при старте системы.

  Ф. 114 (72h)
  Поменять местами 2 сегмента в памяти.
  Вход: D,E - номера 2-х меняемых сегментов.
  Содержимое 2-х указанных сегментов меняется местами.
  Без проверки на задание отсутствующего сегмента.

  Ф. 115 (73h)
  Получить массив диспетчера программ.
  Вход: DE - адрес, куда переслать массив.
             Банк считается автоматически.
  Выход: А - количество записей массива
  Каждая запись массива диспетчера программ занимает
  18 байт и состоит из:
     +0      - код драйвера (резидентной программы), к
               которой относится эта запись, т.е. номер
               в списке драйверов (ф. 107d)
     +1      - код программного прерывания, при котором
               активизируется резидентная программа.
     +2..+17 - имя резидентной программы.



 Управляющие коды цветного драйвера консоли (расширение VT52, опознаватель A2h)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      !!!       При старте драйвера есть возможность записать любую
                экранную область в TPA DOS по адресам TPA:4000..B7FF
                в формате команды драйвера 27,'W',3 в цветном режиме.
                Для записи удерживайте клавиши 0..3 при старте драйвера
                до появления надписи о подтверждении записи. !!!

ESC,'4' - включить автоперевод строки
ESC,'5' - выключить автоперевод строки
ESC,'@',byte - byte(1..1fh) - вывод символа с кодом < 20h
07 - BELL
08 и др. курсорные все как в РК-86
09 - горизонтальная табуляция через 8
0A - CLS+HOME
1F - CLS+HOME
1B,'6' - включить инверсный вывод, в цветном режиме при этом цвет фона и сим-
        волов меняются местами.
1B,'7' - выключить инверсный вывод (т.е включить нормальный режим)
1B,':' - включить курсор
1B,';' - выключить курсор
ESC,'N' - возвращает позицию курсора на экране с клавиатуры в виде
          ESC,Y,LN+20h,COL+20h
ESC,'Y',LN,COL - прямое позиционирование курсора
ESC,'E' - CLS (аналог 0C)
ESC,'H' - HOME (без очистки экрана)
ESC,'J' - стирание до конца экрана (включая позицию курсора)
ESC,'K' - стирание до конца строки (вкл-я позицию курсора)
ESC,'L' - вставить строку
ESC,'M' - удалить строку

ESC,'C',MODE - выбор режима работы работы драйвера, реализованы 6 режимов:
        MODE 0 - монохром, палитра 1 (зел./черн.)
        MODE 1 - 4-х цветный режим, палитра 1
        MODE 2 - 16-ти цветный режим (обычный)
        MODE 3 - 16-ти цветный скоростной (т.е без вывода цвета, в расчете,
        что вывод "идет" тем же цветом, что был в этом знакоместе ранее)
        MODE 4 - монохром, палитра 2 (син./желт.)
        MODE 5 - 4-х цветный, палитра 2
   !!!  Если в байте MODE бит D7 установить в 1, то при включении видеорежима
        не будет происходить очистка цветовых атрибутов. !!!

ESC,'Q',BYTE - установить ширину символа (6,8)
ESC,'P',BYTE - установить цвет в цветном режиме:
               в старшем ниббле BYTE передается код цвета фона, в младшем код
               цвета символов.
               В 4-х цветном режиме поддерживаются цвета 0, 1, 2, 4
               коды цветов выбраны так, чтобы обеспечить совместимость с 16-ти
               цветным режимом:
               0 - черный, 1 - голубой, 2 - зеленый, 4 - красный.
               Полная таблица цветов ОРИОНа:
                  Код цвета                 Цвет
                     0        черный              black
                     1        голубой             blue
                     2        зеленый             green
                     3        синий               cyan
                     4        красный             red
                     5        малиновый           magenta
                     6        коричневый          brown
                     7        белый               white
                     8        серый               gray
                     9        светло-голубой      lightblue
                    10        светло-зеленый      lightgreen
                    11        светло-синий        lightcyan
                    12        светло-красный      lightred
                    13        светло-малиновый    lightmagenta
                    14        желтый              yellow
                    15        интенсивно-белый    brightwhite
ESC,'R',BYTE - переключение формы курсора (BYTE= 1-8, толщина курсора)

        Оконные функции (в последующих версиях возможны дополнения).

ESC,'W',0,Y,X,dY,dX - определить окно вывода. X,Y - абсолютные координаты
                      левого верхнего угла окна в символьных позициях.
                      dX,dY - размер окна по X и по Y соответственно. Коорди-
                      ната X и размер по X должны быть кратны 4 в режиме 6x10.
                      Чтобы установить окно размером во весь экран нужно вывес-
                      ти: ESC,'W',0,0,0,25,80.
ESC,'W',1 - получить параметры текущего окна. Возвращает Y,X,dY,dX.
ESC,'W',2 - получить размер окна в байтах. Возвращает мл.байт,ст.байт.
ESC,'W',3,младш,старш,номер_стр. - сохранить содержимое окна по переданному
                                  адресу.
ESC,'W',4,младш,старш,номер_стр. - восстановить содержимое окна.

        Дополнительные управляющие коды драйвера.
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ESC,'D',n - установка задержки ввода с клавиатуры, n = 0..9
esc,'D',0FFh - получить текущую константу задержки

(h,m,s - часы,минуты,секунды в двоичном формате)
(d,m,y - день,месяц,год в двоичном формате)
ESC,'Z' - работа с часами:
 esc,'Z',0 - получение значения часов с клавиатуры в h,m,s
 esc,'Z',1,h,m,s - установка часов в формате h,m,s.
 esc,'Z',2 - получить состояние часов
 esc,'Z',3,byte - установить состояние часов
  состояние часов:
   d0 - 1/0 - разрешен/запрещен вывод времени
   d1 - 1/0 - вывод времени с инверсией/без инверсии
   d2 - 1/0 - полный/сокращенный формат вывода времени
   d3 - 1/0 - 24/12 часовой режим (не реализовано.)
 esc,'Z',4 - получение позиции для вывода времени (2 байта)
 esc,'Z',5,Y,X - установка позиции для вывода времени
(Y,X - 0..24,0..70; начало координат - левый верхний угол)
 esc,'Z',6 - пол. дату в формате d,m,y
 esc,'Z',7,d,m,y - уст. дату в формате d,m,y

ESC,'S',n - управление звуком
 (при нажатии РУС/ЛАТ звук включается).
        n = 0 выключить подзвучку при нажатии клавиш.
        n = 1 включить подзвучку при нажатии клавиш.
        n = 0FFh получить код управления звуком (0-1)

              {  не руководствоваться !
ESC,'F',n - управление фонтами:
(adr,bnk - адрес и банк, где расположен фонт пользователя.)
        n = 0 - включить стандартный фонт 6 бит.
        n = 1 - включить стандартный фонт 8 бит.
 esc,'F',2,adr,bnk - включить фонт пользователя 6 бит.
 esc,'F',3,adr,bnk - включить фонт пользователя 8 бит.
 esc,'F',4 - получить адрес 6-бит фонта с клавиатуры в фор-
             мате adr,bnk.
 esc,'F',5 - получить адрес 8-бит фонта с клавиатуры в фор-
             мате adr,bnk (если системный фонт,то XX:FF:XX).
               }
ESC,'X',n - управление режимом вывода символов на экран.
 n = 0 - установить нормальный режим вывода фонта 6.
 n = 1 - установить нормальный режим вывода фонта 8.
 n = 2 - установить режим наложения символов для фонта 6.
 n = 3 - установить режим наложения символов для фонта 8.
При выводе символов с параметром n = 2 или 3 необходимо
выключать курсор.

ESC,'B' - заполнение атрибутов цвета кодом, ранее установ-
          ленным через код 27,'P',byte

ESC,'I' - установить/получить номер АКТИВНОГО экрана
          (0..2/FF). Все операции драйвера выполняются
          только на АКТИВНОМ экране. На стандартном Орионе
          доступны 3 экрана (0..2) (hex:0,4000h,8000h).

ESC,'V' - установить/получить номер ВИДИМОГО экрана
          (0..2/FF). Одновременно устанавливается цветовой
          режим, ранее установленный на этом экране, если
          он уже был или является текущим АКТИВНЫМ экраном.
          Если экран не включался как АКТИВНЫЙ, то устано-
          вится монохром.

Бит D5 ячейки F3F6 установлен в 1 при вводе ESC - последовательности или при
выводе результатов через клавиатуру. Указывает на невозможность прерывания про-
граммы в данный момент времени.
 ESC,'U',0/1 - получить/восстановить состояние драйвера консоли
Состояние драйвера консоли: 13 байт
byte0:D0,D1 - код цветового режима      (00b-mono/01b-16cfast/10b-4c/11b-16c
              активного экрана
      D2 - инверсия                     (0-нет/1-есть)
      D3 - погашен/видимый курсор       (0-нет/1-есть)
      D4 - шрифт 6/8 бит                (0-6_бит/1-8_бит)
      D5 - наложение для 6 бит          (0-нет/1-есть)
      D6 - наложение для 8 бит          (0-нет/1-есть)
      D7 - auto_CRLF                    (0-нет/1-есть)
byte1,byte2: позиция курсора            (Y+20h/X+20h)
byte3 - форма курсора                   (1..8)
byte4 - код цвета                       (byte)
byte5 - y
byte6 - x  - параметры
byte7 - dy
byte8 - dx
byte9  - номер АКТИВНОГО экрана (D0..D1) (00b..10b)
       - номер ВИДИМОГО экрана  (D2..D3) (00b..10b)
byte10 - видеокод экрана 0  (видеокод - это byte из ESC,'C',byte)
byte11 - видеокод экрана 1
byte12 - видеокод экрана 2
                        ВНИМАНИЕ:

1. ПРИ ИСПОЛЬЗОВАНИИ ЭКРАНОВ 1 И 2 ВО ИЗБЕЖАНИЕ КОНФЛИКТОВ
С ДОС И ДРАЙВЕРАМИ, А ТАК ЖЕ С ДРУГИМИ ПРОГРАММАМИ, ИСПОЛЬ-
ЗУЮЩИМИ XTPA, ПЕРЕД ИСПОЛЬЗОВАНИЕМ ЭКРАННОЙ ПАМЯТИ  ОБЯЗА-
ТЕЛЬНО ЗАРЕЗЕРВИРУЙТЕ ЭТУ ПАМЯТЬ (Ф.103 BDOS) НА ВРЕМЯ РА-
БОТЫ С ЭТИМИ ЭКРАНАМИ, А ПОСЛЕ ЗАВЕРШЕНИЯ РАБОТЫ ОСВОБОДИ-
ТЕ ЭКРАННУЮ ПАМЯТЬ (Ф-ЦИЯ 104 BDOS). ЕСЛИ Ф-ЦИЯ 103 BDOS
ВОЗВРАТИЛА ВАМ ФЛАГ ОШИБКИ, ТО ЭТУ ЭКРАННУЮ ПАМЯТЬ ИСПОЛЬ-
ЗОВАТЬ В ДАННЫЙ МОМЕНТ НЕЛЬЗЯ.

2. ЭКРАН 0 - ЭТО СИСТЕМНЫЙ ЭКРАН, В КАРТЕ ПАМЯТИ ЕГО ОЗУ
ВСЕГДА ОБОЗНАЧЕНО КАК ЗАНЯТОЕ. НЕ РЕЗЕРВИРУЙТЕ И НЕ ОСВО-
БОЖДАЙТЕ ЭТО ЭКРАННОЕ ОЗУ!

3. РАСПРЕДЕЛЕНИЕ ОЗУ:

ЭКРАН 0  -> B0:0000-3FFF, B1:0000-3FFF
СЕГМЕНТЫ 00..03(ГРАФ.), 10H..13H(ЦВЕТ)

ЭКРАН 1  -> B0:4000-7FFF, B1:4000-7FFF
СЕГМЕНТЫ 04..07(ГРАФ.), 14H..17H(ЦВЕТ)

ЭКРАН 2  -> B0:8000-BFFF, B1:8000-BFFF
СЕГМЕНТЫ 08..0BH(ГРАФ.), 18H..1BH(ЦВЕТ)

НА НЕКОТОРЫХ РЕЛИЗАХ СЕГМЕНТЫ 19H,1АH,1BH
МОГУТ БЫТЬ ЗАНЯТЫ И ИСПОЛЬЗОВАТЬ ОБЛАСТЬ ЦВЕТА
ДЛЯ ЭКРАНА 2 В ЭТОМ СЛУЧАЕ НЕЛЬЗЯ (ТОЛЬКО
МОНОХРОМ)


        Пример драйвера в системе Alt-DOS V3.XX
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        .Z80
;
BDOS    equ     5
MARKER  equ     0EFFFh
DRVBANK equ     0FFH            ; инсталляция в любой банк
DRVADDR equ     0FFFFh          ; на любой подходящий адрес
YCONOUT equ     3*4+0F301h
BJMP    equ     0F204h
;
HEADER: db      13,10,'BEEPER V1.0.',13,10,'$'
ERROR:  db      'Out of memory or already installed.',13,10,'$'
BADSYS: db      10,13,'Incorrect DOS version.',13,10,'$'
;
BEGIN:  ld      c,12
        call    BDOS
        exx
        ld      a,h
        cp      0ABh            ; система Alt-DOS V3.XX ?
        ld      c,9
        ld      de,BADSYS
        jp      c,BDOS
        ld      de,HEADER
        call    BDOS
        ld      de,DRVSTR
        ld      c,105
        call    bdos            ; инсталляция драйвера
        ld      de,ERROR
        ld      c,9
        inc     a
        jp      z,BDOS
        ret
;
; +0       - номер банка, где будет располагаться драйвер
; +1..+8   - имя драйвера
; +9..+10  - начальный адрес драйвера в ОЗУ ТРА СРМ(16 бит)
; +11..+12 - длина драйвера (16 бит)
; +13..+14 - адрес п/п инсталляции (напр, для захвата векторов, трансляции кода).
;            Выполняется однократно в ОЗУ доп. страницы непосредственно после
;            посадки драйвера (после перемещения системой кода драйвера в XTPA)
; +15..+16 - адрес п/п УВЕДОМЛЕНИЯ драйвера (обработчик сигналов)
; +17..+18 - начальный адрес драйвера (в ОЗУ доп. страницы)
; +19      - СТОП-код
;
DRVSTR: db      DRVBANK
        db      'Beeper  '
        dw      DBEG
        dw      DEND-DBEG
        dw      INSTALL-OFFSET  ; процедура инсталляции
        dw      SIGNAL-OFFSET   ; процедура обработки сигналов ОС
        dw      DRVADDR
        db      0
;
DBEG:
        .phase  0               ;DRVADDR
OFFSET:
INSTALL:DI
        jr      NEXT
;
HLATTAB:dw      FF0+1,FF1+1,FF2+1,FF3+1,FF4+1,EXLINK+1,0
;
NEXT:   db      3Eh             ; перемещающий загрузчик
INSFLAG:db      0               ; (пересчитывает абсолютно
        or      a               ; заданные адреса)
        jr      nz,EXLINK       ; адреса пересчитываются
        ld      h,b             ; только один раз
        ld      l,0             ; рег.В=начальный сегмент
        add     hl,hl
        add     hl,hl
        add     hl,hl
        add     hl,hl           ; сегмент -> адрес
        ld      b,h
        ld      c,l             ; hl=bc=install
        ld      de,HLATTAB-OFFSET
        add     hl,de           ; hl=hlattab
LINK:   ld      e,(hl)
        inc     hl
        ld      d,(hl)
        inc     hl
        ld      a,e
        or      d
        jr      z,EXLINK
        ex      de,hl
        add     hl,bc
        ex      de,hl           ; de:=de+bc (de+offset)
        ld      a,(de)
        add     a,c
        ld      (de),a
        inc     de
        ld      a,(de)
        adc     a,b
        ld      (de),a
        jr      LINK
EXLINK: ld      hl,INSFLAG      ; запрет повтор. пересчета
        ld      (hl),1
        ld      a,(YCONOUT)     ; захват вектора CONOUT
FF0:    ld      (OLDBANK),a
        ld      a,(MARKER)
        ld      (YCONOUT),a
        ld      hl,(YCONOUT+1)
FF1:    ld      (OLDADDR),hl
FF2:    ld      hl,NEWSUBR
        ld      (YCONOUT+1),hl
        EI
;
SIGNAL: ret        ; вход: reg.c = 9 (SIGKILL)-удаление, или = 1 (SIGHUP)-init
                   ; в данном примере нет необходимости в реакции на сигналы 
;
NEWSUBR:ld      h,4     ; драйвер пищит при выводе символов
LOOP1:  ld      a,c     ; в рег.С передается код символа
        SUB     ' '     ; др. использует только рег. А и HL
        OUT     (0FFh),a
LOOP2:  dec     a
        jr      nz,LOOP2
        dec     h
        jr      nz,LOOP1
FF3:    ld      a,(OLDBANK)
FF4:    ld      hl,(OLDADDR)
        jp      BJMP            ; переход дальше по цепочке
OLDBANK:ds      1
OLDADDR:ds      2
        .dephase
DEND:

        end     BEGIN


