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 * * *
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября