|
ZX Time
#08
30 апреля 2002 |
|
Кодерам - частные моменты в работе с 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
* * *
Другие статьи номера:
Похожие статьи:
В этот день... 30 октября