ZX Time #08
30 апреля 2002
  TR-DOS  

Кодерам - частные моменты в работе с TR-DOS (TR-DOS на уровне портов).

<b>Кодерам</b> - частные моменты в работе с TR-DOS (TR-DOS на уровне портов).
Кодерам
────────────────────────────────────────
                                    Nuts

    Частные моменты в работе с TR-DOS
   ───────────────────────────────────

  Итак,  сегодня мы поговорим про работу
с  TR-DOS  на уровне портов. Вопрос этот
уже неоднократно обмусоливался в различ-
ной  прессе,  я  же просто хочу отметить
несколько  моментов, которые упоминались
только  в  малораспротранненых газетах и
журналах:  кто-то  уже  давно пользуется
ими в программах, а кто-то продолжает не
знать.

  В  первую  очередь  речь идет о чтении
пресловутого  порта  #1F  TR-DOS. Кратко
вспомним его назначение.

  Бит 0 - занято, идет выполнение коман-
ды.

  Бит 1  - индексный  импульс (маленькое
отверстие  в дискете находится между оп-
топарой фотодатчика) - "начало дорожки".

  Бит 2  - магнитная головка находится в
исходном положении.

  Бит 3 - ошибка в CRC сектора.

  Бит 4 - ошибка позиционирования.

  Бит 5 -  магнитная головка находится в
рабочем положении.

  Бит 6 - на диске есть наклейка для за-
щиты от записи.

  Как  известно,  стандартная ПЗУ TR-DOS
не  позволяет напрямую читать этот порт.
Поэтому  еще  Ларченко  и Родионов еще в
начале  90-х годов прошлого столетия по-
рылись в этом самом ПЗУ и придумали спо-
соб  косвенного чтения этого порта: если
по  хитрому утановить некоторые регистры
и переменные, то в одной из процедур ПЗУ
совпадут  переходы аккурат на нормальный
RET.

  Способ  этот  был  опубликован в книге
вышеупомянутых: "ZX  SPECTRUM  &  TR-DOS
для  пользователей и организмов"... т.е.
тьфу... ПРОГРАММИСТОВ..." вот. Книга эта
получила  известное  распространение,  а
по  сему и способ тоже. От него плясал и
изестный  и  уважаемый всеми Иван Рощин.
Он   опубликовал  в  различных  источних
большое  количество поправок и коммента-
риев к данному методу. Поэтому произошла
определенная концентрация мыслей на дан-
ном методе.

    Но это же не единственный метод!

  Можно,  например,  решить  проблему  в
лоб:  взять  и прошить в ПЗУ пару-тройку
байтов  чтения  порта.  Развитие  такого
способа произвела, по-моему, фирма МИКРО
АРТ  со  своим АТМ ТУРБО, в ПЗУ которого
такие   байты   были.   Известный  HONEY
COMMANDER,  который бескомпромиссно тре-
бовал  именно  этих байт в ПЗУ, не желая
работать  без  них.  Кроме того, хочется
упомянуть  еще  ELS COMMANDER, (c) 1995,
Электрон  Сервис,  г.Гомель - он тоже не
желал. Оставим в покое этот вопрос, т.к.
существует  куча  версий  ПЗУ со всякими
изменениями - всех не упомнить!

  Другие  методы тоже часто применяются,
но  поскольку  ажиотаж на страницах ЭСМИ
не  утихает - надо  про них еще раз ска-
зать.

  Ниже  приведены  пара  методов,  более
или менее используемых программистами:

  1)  Способ,  выдранный  из  MultiColor
Studio  v2.0, (c)  OHG. Он применяется в
каждой  второй  программе, и даже где-то
опубликован.

  Он основан на том же приеме, что и вы-
шеуказанный, но на другой процедуре ПЗУ:
форматировании диска, а точнее, процеду-
ре  проверки  сектора после форматирова-
ния.  Для этого производится чтение сек-
тора и проверяется содержимое нашего лю-
бимого  порта. Таким образом, эту проце-
дуру  можно  использовать  для  проверки
ошибок при чтении с диска.

  Вот  как  выглядит  используемый кусок
процедуры:

#2099   IN A,(#1F) ;ЧИТАЕМ ПОРТ
        AND A,#7F  ;ВЫДЕЛЯЕМ БИТЫ 0-6
        POP BC     ;ЧТО-ТО  ВОССТАНАВЛИ-
                   ;ВАЕМ СО СТЕКА
        JR Z,#20A6 ;нет ошибок - перехо-
                   ;дим
        LD HL,#5CD6;адрес  переменной  -
                   ;число  плохих секто-
                   ;ров
        INC (HL)   ;увеличиваем его
#20A6   POP HL     ;ЧТО-ТО  ВОССТАНАВЛИ-
                   ;ВАЕМ СО СТЕКА
        LD A,(HL)  ;делаем
        INC HL     ;проверку
        CP 1       ;должна быть 1
        JR NZ,#20A8;иначе  куда-то  пры-
                   ;гаем
        EI         ;а если 1 ->
        RET        ;вертаемся

  Таким  образом, чтобы прочитать значе-
ние порта #1F и проверить, равны ли нулю
его биты 0-6 необходимо:

  1) записать ноль в пременную #5CD6;

  2) положить че нито на стек;

  3)  положить на стек адрес по которому
точно размещается число 1;

  4)  положить на стек адрес продолжения
программы  после того, как она выйдет из
ПЗУ;

  5) положить на стек адрес подпрограммы
#2099;

  6) прыгнуть в ПЗУ на #3D2F

  7)  в продолжении программы (после то-
го, как она выйдет из ПЗУ) проверить пе-
ременную #5CD6: ежель там ноль, то рабо-
тать далее, иначе - обрабатывать ошибку.

  Нижеприведенная  процедурка  реализует
данный алгоритм.

READ1F  LD B,1
        XOR A
        LD (#5CD6),A ;обнуляем
        LD HL,TEMP   ;адрес где 1
        LD (HL),1
        LD DE,#2099
        LD IX,CONTIN
        PUSH IX
        PUSH HL      ;все кладем
        PUSH BC      ;на стек
        JP DOS_DE    ;и прыгаем в ПЗУ
CONTIN  LD A,(#5CD6) ;продолжение
        DI
        OR A         ;проверяем
        JR NZ,DERR ;ошибка !
        ;работаем дальше

TEMP    DB 0;ВРЕМЕННАЯ ПЕРЕМЕННАЯ

DOS_DE  PUSH DE  ;прыгаем в ПЗУ ДОС
        JP #3D2F ;через точку

  Вот и все.

  2)  Cпособ  чтения  порта  при  помощи
процедуры  TR-DOS, находящейся по адресу
#3FE5.  Применяется в извесной программе
RDS  v3.1 (c) RokSoftware. Эта процедура
обычно предназначенна для чтения массива
данных из порта (C), с синхронизацией по
по  битам 6 и 7 (строб и готовность дан-
ных) порта #FF.

  Здесь  же используется не совсем стан-
дартное  обращение, т.к. если сразу сде-
лать  переход  на  эту процедуру, то она
зациклится на опросе этих битов. Поэтому
мы вначале зададим контроллеру дисковода
относительно  длительную  команду, опро-
сим порт и как раз к исполнению этой ко-
манды  и придем на опрос битов. Происхо-
дит это обращение по адресу #3FEC:

#3FEC   INI ;читаем порт (C)
            ;и  кладем  его
            ;содерщимое в (HL)
        JR #3FE5 ;преходим

#3FE5   IN A,(#FF) ;опрашиваем
        AND #C0    ;биты
        JR Z,#3FE5 ;готовности
        RET M      ;вертаемся
                   ;если все прочтено

  Таким  образом  для чтения порта и за-
писи его содержимого по заданному адресу
необходимо:

  1)  Запустить  на  выполнение  команду
дисководу.  Для  этой  цели  обычно  ис-
пользуется команда позиционирования. Де-
ло  в том, что дисковод будет позициони-
роваться на текущую дорожку, т.е. просто
запустится. Это ограничивает возможности
по применению способа: его можно исполь-
зовать  в составе процедуры проверки на-
личия дискеты в дисководе;

  2)  Записать  в регистр C номер порта:
#1F;

  3)  Записать в HL адрес куда будет пи-
саться значение порта;

  4) Неплохо бы и остановить дисковод

  По этому алгоритму работает нижеприве-
денная  процедура  проверки  на  наличие
диска в дисководе.

  Несмотря  на  то, что процедура читает
все  биты порта, данная процедура прове-
ряет только 6-ой бит - наличие защиты от
записи  на  диске.  Эта обьясняется тем,
что  не на всех дисководах работают про-
цедуры,  делающие  подобную  проверку по
наличию индексного импульса (отверстия в
дискете) - похоже  аппаратные реализации
и  временные  характеристики у различных
дисководов  значительно  отличаются друг
от друга.

  Данная  процедура  только  читает этот
бит,  а  сама  процедура проверки должна
ждать 1 в этом бите (когда диск вытаски-
вают),  а  потом 0. Если же диск защищен
от записи, то пока он вставлен, этот бит
всегда будет установлен.

DREADY  LD A,#3C   ;запись в #FF
        CALL TOFF
        LD A,#1F   ;позицианирование на
        CALL TO1F  ;текущую дорожку
        LD A,#D8   ;прерывание опреации
        CALL TO1F
        LD HL,TEMP  ;читаем сюда
        LD C,#1F    ;из порта #1F
        LD DE,#3FEC
        CALL DOS_DE ;читаем
        XOR A      ;сброс контроллера
        CALL TO1F
        LD A,#D8   ;прерывание опреации
        CALL TO1F
        LD A,(TEMP) ;проверяем бит 6
        AND #40
        RET Z      ;сброшен
        LD A,1
        RET        ;установлен

TOFF    LD C,#FF  ;запись в #FF
        JR TOWG
TO1F    LD C,#1F  ;запись в #1F
TOWG    LD IX,#2A53 ;OUT (C),A
DOS_IX  PUSH IX ;переход в ПЗУ
        JP 15663

TEMP    DB 0 ;временная переменная



     Сверхбыстрое позиционирование
               дисковода

  Этот  прием  применяется  очень редко,
хотя  обеспечивает тихое и быстрое пере-
мещение головки дисковода. Практически -
это замена аппаратному турбированию дис-
ковода. Минусом данной продудуры являет-
ся ее несовместимость с некоторыми типа-
ми "медленных  дисководов"  с  червячным
("винтовым")  методом  перемещения голо-
вок.  Собственно  говоря,  эта процедура
используется  в  MultiColor Studio v2.0,
(c)  OHG.  Так  что если эта программа у
вас  не  идет, то винить надо дисковод и
авторов  программы,  не  предусмотревших
настроек процедуры.

  В  общем случае, желательно предусмот-
реть  отключение такого свербыстрого по-
зиционирования,  кроме  того этот способ
можно "подстраховать"     дополнительной
командой   позиционирования  контроллера
дисковода.  Сама же программа использует
команды "Шаг  впред" и "Шаг назад". Ско-
рость  премещения определяется задержкой
между двумя такими командами (желательно
предусмотреть возможность ее регулирова-
ния!).

  Предварительно   необходимо   записать
нужные значения в регистры #7F (дорожка)
и  #FF (статус контроллера). Кроме того,
необходимо  хранить значение текущей до-
рожки (в   переменной  TRACK),  так  как
от  нее отсчитывается число шагов, необ-
ходимых  для перемещения на заданную до-
рожку.  Ее содержимое - логический номер
дорожки (0-166).

  На  входе процедуры, в регистре A дол-
жен  быть  указан  номер  дорожки,  куда
осуществляется премещение.

POSIT   PUSH AF ;запоминаем
        SRL A   ;получаем  физический
        LD C,A  ;номер дорожки
        LD A,(TRACK) ;текущая
        SRL A      ;физическая дорожка
        CP C
        JR Z,POSI_OK ;уже тут
        JR C,POSI_UP ;вперед
        SUB C        ;назад на
        LD B,A       ;В дорожек
        LD A,#78     ;"Шаг назад"
        JR POSITI
POSI_UP LD D,A
        LD A,C
        SUB D        ;назад на
        LD B,A       ;В дорожек
        LD A,#58     ;"Шаг назад"
POSITI  LD (POS_COM),A ;код команды
        CALL PAUSE     ;пауза
POSITIC PUSH BC
        LD DE,#2FC1
        CALL DOS_DE
POS_COM EQU $+1
        LD A,#58     ;код
        LD DE,#2FC3  ;команды
        CALL DOS_DE
        CALL PAUSE   ;ждем немного
        POP BC
        DJNZ POSITIC  ;повторяем
POSI_OK POP AF
        LD (TRACK),A ;новое значение
        RET

TRACK   DB 0 ;текущая дорожка

PAUSE   PUSH BC
        PUSH HL
        LD BC,400  ;задержка
POS1    DEC BC
        LD A,B
        OR C
        JR NZ,POS1
        POP HL
        POP BC
        RET

DOS_DE  PUSH DE  ;прыгаем в ПЗУ ДОС
        JP #3D2F ;через точку


    Сверхбыстрая остановка дисковода
    
  Эта   процедурка   тоже   выдрана   из
MultiColor  Studio  v2.0, (c)  OHG.  Она
также  основана на мухлевании с командой
позиционирования  и  оригинальном чтении
порта  #1F. Для чтения используется про-
цедура по адресу #3EF3:

#3EF3 IN H,(C)    ;чтение порта
#3EF5 IN A,(255)  ;ожидание
      AND 192     ;какого-нибудь сигнала
      JR Z,#3EF5
      EI          ;на случай возврата
      RET M       ;если поступил INTRQ
                  ;то возврат
      DI          ;запрет прерываний
      IN A,(127)  ;чтение байта
      JR #3EF5    ;повтор

  Как видим, содержимое порта остается в
регистре  H,  а  выход осуществляется по
исполнению команды.
  Теперь  сама процедура, обеспечивающая
быструю  отсановку  диска. Надо сказать,
она  конфликтует с некоторыми эмулятора-
ми:  происходит  перемещение  на дорожку
вперед.

STOPDSK PUSH AF
        PUSH HL
        LD A,#40 ;шаг вперед без
        ;инкремента регистра дорожки
        LD DE,#2FC3
        CALL DOS_DE
        LD A,#D8    ;прерывание
        LD DE,#2FC3
        CALL DOS_DE
        LD C,#1F
        LD DE,#3EF3
        CALL DOS_DE
        POP HL
        POP AF
        EI
        RET

                 * * *



Другие статьи номера:

От редактора - DWT отчитывает Павла Павлова за отзыв о газете.

Обзор почты - письма читателей: Виталий Петренко (SLY), Вадим Чумаченко , Nuts, Xmus.

Обзор новья - пресса: Adventurer #13, Lamergy #5-#9, Body #33-#36, Heresy #8, Target #10, DonNews#16. Софт: ACEdit 0.60, Pro Tracker 3.53. Игры: Magic Music Toy 1.02, Открывашка, 3D-Roost, Citadel demo.

Новости и старости - продолжается конкурс <Твоя Игра>, Nuts прекратил работу над коммандером TRouble, Dizzy Game Editor почти готов, Демо версия <Угадай Мелодию> уже готова и т.д.

Мнение - Мысли о системном софте на Спектруме.

Мнение - lzb/j77: "Я и тут молчать не буду!"

Мнение - Абзац: новая печатная газета для Спректрума.

Кодерам - частные моменты в работе с TR-DOS (TR-DOS на уровне портов).

Железяки - схемка: привязка видеосигнала Спектрума к уровню чёрного.

PC и Spectrum - Unreal vs ZX Mak: сравнение двух популярных эмуляторов ZX Spectrum.

PC и Spectrum - обзор PC программ для копирования и конвертации спектрумовских файлов.

О всем про все - "Путь перед рассветом".

И смех, и грех - Письмо в Военно-исторический форум.

Реклама - рекалама и обьявления.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Эказамен - Вам предлагается решить игровой этюд по программе "Deactivators".
Реклама - рекалама и обьявления...
Юмор - Анекдоты.
Железо - Блоки питания.
UFO II - позиции для увеличения техников.

В этот день...   21 ноября