ZX Review #5-6
04 ноября 1997
  TR-DOS  

TR-DOS для начинающих - Продолжение.

┌─────────────────────────────┐
│                             │
│    TR DOS ДЛЯ НАЧИНАЮЩИХ    │
│                             │
└─────────────────────────────┘

(c) В.Сироткин

   Продолжение. Начало см. в ZX
РЕВЮ 1996  NN 1-2, 4-5, 6, 7-8;
ZX РЕВЮ 1997 NN 1-2, 3-4.

  ПРОГРАММИРОВАНИЕ КОНТРОЛЛЕРА

   А теперь  разберем  несколько
конкретных примеров.

   !!! Необходимое  напоминание:
не забудьте, что для разных вер-
сий ТРДОС необходимо  выставлять
свои адреса подпрограмм !!!

   Перед тем, как загрузчик нач-
нет  работать, программа  должна
определить версию ТРДОС и  скор-
ректировать   адреса    вызовов.
Определять версию и  настраивать
загрузчик удобнее всего функцией
ТРДОС C = #13.  Мы пропустим эту
часть программы, так как в главе
'ФУНКЦИИ ТРДОС'  подробно описа-
но, как это сделать.

   Пример 1. Загрузчик файлов
140.
;базовые адреса ПЗУ даны для версии 5.01 *
;в угловых скобках будут указаны адреса для 5.03 *

; головная часть загрузчика

       ORG  ADRESS   ; начальный адрес загрузчика
       DI            ; запретим прерывания
       LD HL,#5800   ; закрасим экран черными атри-
                     ; бутами
                     ; на экране у нас будет буфер
       LD DE,#5801   ; для считывания последнего
                     ; сектора файла, чтобы в ОЗУ
                     ; перенести нужное количество
                     ; байтов,
                     ; а также буфер для считы-
                     ; вания каталога диска
       LD BC,#01FF
       LD (HL),L
       LDIR
;------------------

       CALL  LOAD_CAT ; найти на диске нужный файл
;  и  его атрибуты (подпрограмма возвращает в ре-
;гистре  'D'- номер  Дорожки, в 'E' - номер Секто-
;ра, в 'HL' адрес загрузки в ОЗУ, ; в 'BC'- длину)
;------------------
       PUSH  BC       ; спрятать длину файла
       DEC   B        ; уменьшить длину на 1 сектор
;-------------------

       CALL  LOAD_SEK ; файл  без последних
                      ; 2-х секторов (если 'C'=0,
                      ; то без 1-го последнего)
                      ; загрузить с адреса из 'HL'
;-------------------
       PUSH  HL       ; спрятать последующий адрес
                      ; ОЗУ для оставшихся 2-х,
                      ; (1-го) сектора
       LD HL,#4800    ; адрес буфера для сектора

       LD B,2         ; ДВА сектора
       CALL  LOAD_SEK ; загрузить в адрес #4800 два
                      ; последних сектора
       POP  DE        ; достать адрес ОЗУ для остав-
                      ; шихся секторов/сектора
       POP  BC        ; достать длину всего файла
       LD   B,1       ; один сектор наверняка, и
                      ; остаток длины из 'C'
       LD   HL,#4800  ; перенести из экрана
       LDIR           ; в адрес по 'DE'
       EI             ;
       RET            ; вернуться в программу

;---------------------------
;  подпрограмма считывание каталога и определение
;  атрибутов файла

LOAD_CAT LD DE,0000     ; ноль Дорожка и Сектор
LOAD     PUSH DE        ; спрятать
         LD HL,#4800    ; адрес буфера в ОЗУ для
                        ; сектора
         PUSH HL        ; спрятать
         LD B,1         ; Один сектор
         CALL LOAD_SEK  ; считать сектор номером
                        ; из 'E'
                        ; с НОЛЬ дорожки ; т.е.
                        ; из области КАТАЛОГА диска
         POP HL         ; начало адреса буфера
         LD B,#10       ; счетчик  заголовков (на
                        ; секторе их 16)
CIKL     PUSH HL        ; спрятать адрес начала
         LD DE,FILENAME ; адрес в ОЗУ, где ИМЯ
                        ; файла,
                        ; который  нужно загрузить
         LD C,08        ; счетчик букв имени файла
NAME_F   INC HL         ; пропустим первую букву в
                        ; имени
                        ; файла в считанном ката-
                        ; логе
         LD A,(DE)      ; буква НУЖНОГО имени
         CP (HL)        ; сравним с буквой из ИМЕНИ
                        ; файла считанного с диска
         JR NZ,ZAGOLOW  ; не совпало - переход
         INC DE         ; совпало - следующая буква
                        ; имени
         DEC C          ; уменьшить счетчик букв
                        ; имени
         JR NZ,NAME_F   ; все буквы? - нет - возврат
                        ; на цикл проверки
         POP DE         ; Да, имя и тип файла
                        ; совпали !
         POP DE         ; указатель стека вернем в
                        ; исходное состояние
         INC HL         ; переходим на атрибуты
                        ; файла
         LD  E,(HL)     ; мл.бит АДРЕСА загрузки
                        ; файла
         INC HL
         LD D,(HL)      ; ст.бит АДРЕСА загрузки
         INC HL
         LD C,(HL)      ; мл.бит ДЛИНЫ
         INC HL
         LD B,(HL)      ; ст.бит ДЛИНЫ
         INC HL         ; пропустим байт объем в
                        ; секторах
         INC HL         ;
         LD  A,(HL)     ; Номер первого Сектора
                        ; файла
         INC HL
         LD  H,(HL)     ; Номер Дорожки
         LD  L,A
         EX  DE,HL      ; в HL-адрес загрузки в ОЗУ
                        ; в DE - дорожка / сектор
                        ; в BC - длина згружаемого
                        ; блока
         RET            ; вернемся

;---------------------------
; счетчик заголовков и секторов каталога

ZAGOLOW POP HL          ; вернем адрес текущего
                        ; заголовка
        LD  DE,#0010    ; длина заголовка
        ADD HL,DE       ; перейдем на следующий
                        ; заголовок
        DJNZ CIKL       ; если не весь сектор -
                        ; повторить
        POP DE          ; вернуть и увеличить номер
        INC DE          ; сектора
        BIT 3,E         ; все 7 секторов каталога
        JR Z,LOAD       ; нет - повторить
        JP ERROR        ; да, каталог весь,
                        ; но файлы не обнаружены:
                        ; Переход на обработку
                        ; ошибочной ситуации

;---------------------------
; имя файла для поиска в каталоге

FILENAME  DEFM 'FNAME_0' ; имя файла без 1-й
                         ; буквы
          DEFM 'C'       ; файл тип CODE
;----------------------------

;подпрограмма загрузки с диска

LOAD_SEK  LD IX,#2F1B < #2F65 > ; адрес подпрограм-
                                ; мы в ПЗУ
;'ВОСТАНОВЛЕНИЕ, т.е. переход  на дорожку 0
; адрес является входом в середину процедуры
; #2EF0 < #2F3A > (смотри приложение)

          CALL TRDOS     ; исполнить подпрограмму
                         ; в ПЗУ

TREK      PUSH BC        ; спрячем длину блока
          PUSH           ; и номер дорожки с
                         ; сектором
          LD A,D         ; номер дорожки
          OR A           ; преобразуем в номер
                         ; ЦИЛИНДРА
          RRA            ; и  в СТОРОНУ диска
          LD C,A         ; скопируем номер цилиндра
                         ; в 'C' для работы в ПЗУ
          JR NC,UP_TREK  ; был 'перенос'?,номер был
                         ; четный ?
          LD A,#2C       ; если нечетный -
                         ; готовность 'НИЗ'
          JR FIND_TRK    ; перейти на 'ПОИСК НУЖНОГО
                         ; ТРЕКА'

UP_TREK   LD A,#3C       ; номер четный -
                         ; готовность 'ВЕРХ'

FIND_TRK LD IX,#2F03 < #2F4D > ; адрес в ПЗУ;
                               ; "ПОИСК"

; этот адрес является входом в середину процедуры
; #2EF0 < #2F3A > (смотри приложение к главе)

         CALL TRDOS     ; найти нужный цилиндр и
                        ; прижать к нужной стороне
                        ; диска
          POP DE        ; извлечь номер дорожки,
                        ; сектора
          POP BC        ; и длину блока

N_SECTOR  PUSH BC       ; спрятать
                        ; (здесь уже в процессе
          PUSH DE       ; загрузки будут текущие
                        ; номера
                        ; дорожек и секторов)

          LD IX,#2ED1 < #2F1B > ; загрузить сектор
                                ; с номером
                         ; из 'E', в адрес по 'HL'

          CALL TRDOS     ; исполнить

          POP DE         ; извлечь номер ДОРОЖКИ
                         ; и СЕКТОРА
                         ; уже загруженного
          INC H          ; увеличим адрес буфера
                         ; ОЗУ на 1 сектор,
                         ; т.е. поднимем на 256
          INC E         ; увеличим номер сектора
          BIT 4,E       ; все сектора на дорожке ?

          JR Z, ALL_SEC ; НЕТ- продолжаем загрузку

          LD E,00        ; ДА - обнулим номер
                         ; сектора
          INC D          ; увеличим номер ДОРОЖКИ
          POP BC         ; посмотрим оставшуюся
                         ; длину
          DJNZ TREK      ; уменьшим ее на 256
                         ; (на 1 сектор)
                         ; вернемся, если не все
                         ; загружено

          RET            ; загрузили все что нужно
                         ; выход
;---------------------
ALL_SEK   POP BC         ; посмотрим оставшуюся
                         ; длину
          DJNZ  N_SECTOR ; уменьшим ее на 256
                         ; (на 1 сектор)
                         ; згружаем с дорожки
                         ; дальше, если еще не все

          RET            ; загрузили все что нужно -
                         ; выходим

;---------------------
TRDOS     PUSH IX       ; адрес на исполнение
                        ; процедуры ПЗУ ТРДОС
          JP #3D2F      ; вызвать процедуру косвенно
                        ; по адресу из стека
;----------------------------------------------------
2
   Данная программа не  нуждает-
ся ни в каких системных перемен-
ных и может работать даже в  эк-
ранной области.  Ею можно загру-
жать как головную часть програм-
мы, так и подгружать последующие
уровни. Единственный  недостаток
такого  загрузчика - это то, что
все файлы на диске, в  каталоге,
должны иметь свою РЕАЛЬНУЮ длину
и  адрес  загрузки. Если вам это
почему-то не подходит (например,
вы хотите защитить свои програм-
мы), то, добавив в программу еще
несколько команд и применив  ме-
тод  шифрования  длины  и адреса
файла во время их создания, мож-
но решить и эту проблему. Но это
разговор для отдельной главы.
   Как  мы  видим, большую часть
места в программе занимает поиск
файла на диске и определение его
атрибутов (длины, старта, номера
дорожки и номера сектора).
   Программу  можно  существенно
сократить, если все это  опреде-
лять изначально, когда идет пер-
воначальная загрузка из БЕЙСИКа.
Пока  память  свободна и область
системных  переменных  ТРДОС  не
перекрыта  кодами.  Это  удобнее
сделать  Функциями ДОС, а данные
о файлах передать потом в основ-
ную  программу, сохранив  их  до
поры до времени в свободном мес-
те памяти.

           Пример 2

   Рассмотрим  как раз  тот слу-
чай, когда данные о файле (кото-
рый должен подгружаться как пос-
ледующий уровень  игры  или  как
состояние этой игры)  переданы в
программу во время ее загрузки.
140.
; * загрузчик  *  используем подпрограмму
; ТРДОС #3F00 < #3F0A >
; програма стартует с метки START
; данные о файле лежат в адресах ОЗУ
; Номер сектора и номер дорожки - по адресу
;                                  'ATRIBUT'
; длина файла по адресу  'DLINN'
; адрес загрузки по адресу 'ADR_LO'
;-----------------

ATRIBUT        NOP   ; сюда передать Номер Сектора
               NOP   ; сюда передать Номер Дорожки
DLIN           NOP   ; сюда передать Длину загрузки
               NOP
ADR_LO         NOP   ; сюда передать адрес загрузки
               NOP

;-------подпрограмма вызова процедуры ДОС----------
TRDOS          PUSH IX      ; вызвать подпрограмму
                            ; ТРДОС
               JP #3D2F     ; адресом из 'IX'
;--------------------------------------------------

;............... СТАРТ..............................

START  LD BC,(ATRIBUT)  ; возьмем номера дорожки и
                        ; сектора
       LD HL,(#5CFE)    ; сохраним изменяемые ячейки
       PUSH HL          ; ОЗУ в системной области
       LD HL,(#5D00)
       PUSH HL
       LD HL,(#5C00)
       PUSH HL
       LD A,0           ; в (#5C00) должен быть 0
       LD (#5C00),0
       LD A,C           ; Номер сектора
       LD C,B
       LD (#5CFF),A     ; занести N. сектора
       PUSH BC          ; сохраним N. дорожки

       LD IX,#2EF0 < #2F3A > ; найдем дорожку на
       CALL TRDOS            ; диске

       LD BC,00         ; задержимся
WAIT   DJNZ WAIT        ; и
       DEC C            ; подождем
       JR NZ,WAIT

       POP BC           ; извлечем N. дорожки

       LD IX,#2EF0 < #2F3A > ; так как головка у нас
                     ; вышла на соответствующее место
       CALL TRDOS    ; то дав 'ПОИСК' этой же дорожки
                     ; мы просто прижмем головку к
                     ; диску и раскрутим диск
       LD IX,#3F00 < #3F0A > ; диск крутится, головка
                      ; прижата, теперь -
                      ; команда чтение Сектора
       LD HL,(ADR_LO) ; взять адрес Загрузки и
       LD (#5D00),HL  ; поместить для работы

       CALL TRDOS     ; считать Один Сектор с диска
                      ; в адрес ОЗУ
               ............
               и т. д. ; далее идут коды пересчета
                       ; сколько осталось загружать,
                       ; какие сектора и дорожки.
;-------------------------------------------------
2
   Я  думаю,  продолжение   этой
программы  вы  сможете  дописать
сами (алгоритм  можно  взять  из
предыдущего примера). Не забудь-
те только вернуть при выходе  из
программы со стека все сохранен-
ные значения в область системных
переменных.

   А  теперь  несколько  слов  о
ЗАПИСИ на диск.  Если в вышепри-
веденных примерах вызов  'ЧТЕНИЕ
СЕКТОРА'  заменить на  'ЗАПИСЬ В
СЕКТОР' и  чуть-чуть  переделать
программу, то  у  вас  получится
готовая  подпрограмма  ЗАПИСИ  в
фиксированный файл. (Смотри гла-
ву Функции ТРДОС, пример  сохра-
нения состояния игры 'ЭЛИТА').
   Вы из БЕЙСИКа  создаете  файл
нужной величины для  последующей
записи в него информации из  ра-
ботающей  программы.   Передаете
атрибуты этого  файла  во  время
загрузки в тело программы, где у
вас расположена ваша подпрограм-
ма 'ЗАПИСИ'- и все.
   Это самый легкий способ реше-
ния проблемы. Если же вы  хотите
написать    полную     программу
'СОХРАНЕНИЕ', то правила  записи
файла  на  диск  остаются такими
же, как в главе 'ФУНКЦИИ ТРДОС'.
А той информации, что вы уже по-
черпнули - вполне хватит,  чтобы
сделать  это  вполне  профессио-
нально.

   Теперь, когда мы  узнали, как
записывать - считывать с диска и
как написать подпрограмму, кото-
рая это делает, поговорим о том,
где эту подпрограмму помещать  в
переделываемой программе.
   Немного об этом было  сказано
в главе 'ФУНКЦИИ ТРДОС', но  так
как  мы  уже  вышли  на  уровень
программирования контроллера, то
у нас и  возможностей  появилось
больше.
   Как    встроить     приличный
ПОЛНОЦЕННЫЙ  'загрузчик/сохрани-
тель' в программу,  которая  ис-
пользует ВСЮ ПАМЯТЬ  компьютера,
если к тому  же  не  хочется  из
этой  программы  ничего  выкиды-
вать, а также  не  хочется  пор-
тить экран ??? Выход есть!
   Этот медод может  иметь  мно-
жество различных  вариантов,  но
суть  одна:  в    переделываемой
программе  встраивают  лишь  ма-
ленькую   подпрограмму-загрузчик
(всего лишь несколько байт), ко-
торая  предназначена   сохранять
часть ОЗУ с адреса #5C00 до  ад-
реса, к примеру, #5FFF  (4  сек-
тора  нам,  надеюсь,  хватит)  в
фиксированный  файл,  а  на  это
место загружать из другого  фик-
сированного файла  копию - образ
области  СИСТЕМНЫХ переменных  и
ОСНОВНОЙ  загрузчик,  который  и
будет  выполнять  главную работу
по ЧТЕНИЮ/ЗАПИСИ.
   После окончания работы основ-
ной  загрузчик  должен  передать
управление на ту маленькую  под-
программу,  которая   востановит
сохраненную область ОЗУ из  пер-
вого файла на свое место.
   Это  называется    ОВЕРЛЕЙНОЙ
ЗАГРУЗКОЙ или 'вытаскиванием са-
мого себя за  волосы'.  Вы  рас-
сматриваете  дисковое  простран-
ство как область  дополнительной
памяти с жестко заданными  адре-
сами и перекачиваете в  нее  или
из нее то, что нужно вам на дан-
ный момент.  Поэтапно  это может
выглядеть приблизительно так:

   Создаем командами БЕЙСИКА два
файла типа CODE.

> RANDOMIZE USR 15619:REM:SAVE
  "BUFFER"CODE любой адрес,1024

   Это файл для  сохранения  об-
ласти ОЗУ из  тела  переделывае-
мой программы в процессе ее  ра-
боты.

> RANDOMIZE USR 15619:REM:
  SAVE"SYSBOOT"CODE 23552,1024

   Это файл с образом  системных
переменных и с основной подпрог-
раммой работы с диском.

   Выбираем   в   переделываемой
программе область  для  размеще-
ния вспомогательного  загрузчика
и вписываем его коды на это мес-
то.

   В файле 'SYSBOOT' после копии
всей области системных  перемен-
ных  и  области буфера вписываем
нашу основную подпрограмму рабо-
ты с диском.

   Теперь в процессе старта  пе-
ределываемой программы  мы  дол-
жны передать в область вспомога-
тельного загрузчика всего 4  па-
раметра:

 - номер первого сектора файла
   "BUFFER",
 - номер первой дорожки этого
   файла,
 - номер первого сектора файла
   "SYSBOOT",
 - номер первой дорожки этого
   файла.

   Длину передавать не надо, так
как она известна изначально.

   Во время работы  переделывае-
мой программы, если она  выходит
на процесс загрузки или сохране-
ния, запустится  вспомогательный
загрузчик, который сначала  сох-
ранит область ОЗУ с адреса #5C00
по #5FFF в файле "BUFFER", а за-
тем на это место в ОЗУ  загрузит
из файла "SYSBOOT" копию  облас-
ти  системных    переменных    и
ОСНОВНУЮ подпрограмму  работы  с
диском и передаст ей управление.

   Так как все  системные  пере-
менные и ТРДОС и SOS востановят-
ся, основная подпрограмма  может
работать с  диском  через  любые
ФУНКЦИИ ТРДОС. А это значит, что
у  вас  отпали  все  проблемы  с
поиском нужного файла на диске и
с пересчетом номеров  дорожек  и
секторов - при считывании с дис-
ка, а при записи - проблема  за-
писи информации о файле в  ката-
лог и в 8-й системный сектор!

   Не забудьте, в регистре IY  у
вас должено быть значение #5C3A,
и установлено  прерывание  1.  А
также - переустановите стек, ес-
ли он был  настроен  на  ту  об-
ласть,  которая  сохраняется  на
диске.
   После завершения своей  рабо-
ты основная подпрограмма  должна
передать  управление  опять   во
вспомогательный загрузчик, кото-
рый востановит из файла "BUFFER"
всю область программы, сохранен-
ную на диске, на старое место  в
ОЗУ.
   Единственное неудобство в та-
ком методе -  это  необходимость
иметь  ко  всем  прочим   файлам
программы еще и 2 наших файла.
   Можно отказаться и от файлов,
если поместить буфер  сохранения
и основную подпрограмму работы с
диском в конкретные сектора,  на
конкретной дорожке диска. Напри-
мер, можно использовать  пустую-
щие сектора на НУЛЕВОЙ  дорожке.
Вспомним, что каталог у  нас  на
первых семи секторах,  системный
сектор -  восьмой,  а  остальные
сектора свободны и  системой  не
используются (их использует под-
программа  ПЗУ  ТРДОС  во  время
сохранения МАГИК-файла).
   Если поступить таким образом,
то вы получите программу,  кото-
рая  будет  работать  только  на
этом диске. С одной стороны, это
создаст проблемы  при  копирова-
нии вами этой программы на  дру-
гой диск. Необходимо будет копи-
ровать не толко файлы программы,
но и  сектора  НУЛЕВОЙ  дорожки,
где у вас будет записана  основ-
ная подпрограмма работы  с  дис-
ком.
   А с  другой  стороны,  модуль
работы с  диском, записанный  на
этих секторах,  может  использо-
вать сразу несколько программ, а
сами программы будут защищены от
несанкционированного   копирова-
ния с вашего диска, так как заг-
рузочный модуль на  НУЛЕВОЙ  до-
рожке при попытке 'сдуть' у  вас
программу  останется  нескопиро-
ванным.
   Такой диск можно будет скопи-
ровать только  целиком  ТРЕКОВЫМ
КОПИРОВЩИКОМ.
   А если пойти дальше и  распо-
ложить сектора с нашей  подпрог-
раммой на  специально  размечен-
ной дорожке с номером,  например
161,  о  которой  системе  будет
просто неизвестно, то  полноцен-
но скопировать этот диск не смо-
жет никакой копировщик. Но о за-
щите дисков мы поговорим  немно-
го позднее.

   А сейчас рассмотрим те аспек-
ты программирования контроллера,
которые до сих  пор  упоминались
лишь вскользь.

         ФОРМАТИРОВАНИЕ

   Процесс  форматирования - это
запись  некоторой    специальной
последовательности кодов на выб-
ранный ЦИЛИНДР и сторону  диска.
Наибольшее  число  цилиндров  на
диске зависит  прежде  всего  от
дисковода, так как у одних  дис-
ководов ограничитель хода  голо-
вок стоит на 80, а у  других  он
может стоять на 86 (ограничитель
чисто механический).
   ТРДОС форматирует диск на  80
цилиндров, записывая в  8-м сек-
торе 0 дорожки информацию-сигна-
нализатор - какой  это  диск   и
сколько  свободных  секторов  на
диске.
   Процедура для  форматирования
одной дорожки находится в ПЗУ по
адресу #1FC1 <#1FFD>. Перед этим
головки должны быть выведены  на
нужный цилиндр и прижаты к  вер-
хней (четной) или нижней (нечет-
ной) стороне  диска.  Затем  по-
дается команда 'ЗАПИСЬ ДОРОЖКИ'-
#F4.

   Форматирование     происходит
следующей    последовательностью
байтов  (эти  байты  подаются  в
порт #7F в подпрограмме по адре-
су #2075 <#20B1>).
   Для наглядности приводим таб-
лицу - что подается  для  записи
на диск и  что  записывается  на
диске, так как некоторые байты в
команде 'ЗАПИСЬ ДОРОЖКИ ' интер-

претируются  микросхемой   ВГ93,
как вложенные субкоманды.

               ТАБЛИЦА МАССИВА ДЛЯ ОДНОГО СЕКТОРА

     ┌────────────────────────────────┬───────────────────┐
     │ ЧТО ПОДАЕТСЯ В ПОРТ ДЛЯ ЗАПИСИ │  ЧТО ЗАПИСЫВАЕТСЯ │
     ├────────────────────────────────┴───────────────────┤
     │           10 байтов #4E ( нач. пробел )            │
     ├────────────────────────────────────────────────────┤
     │                  12 байтов  НОЛЕЙ                  │
     ├────────────────────────────────┬───────────────────┤
     │ 3 раза код #F5 (инициализация  │   код #A1, метка  │
     │    счетчика контр.суммы)       │   начало I.A.M    │
     ├────────────────────────────────┴───────────────────┤
     │        код #FE   (адресная индексная метка)        │
     ├────────────────────────────────────────────────────┤
     │                Байт  НОМЕР ДОРОЖКИ                 │
     │ (ВНИМАНИЕ!!!  НОМЕР ДОРОЖКИ на диске ТРДОС записы- │
     │ вает и на ВЕРХНЕЙ и на НИЖНЕЙ стороне диска с ОДИ- │
     │ НАКОВЫМ  номером  - НОМЕРОМ ЦИЛИНДРА. Определение, │
     │ какая  дорожка  из  160  где находится, происходит │
     │ чисто программным путем).                          │
     ├────────────────────────────────────────────────────┤
     │                Байт СТОРОНЫ диска                  │
     │  (ВНИМАНИЕ!!!   ТРДОС  и  верхнюю и нижнюю сторону │
     │ диска метит  байтом  0, определение, какая сторона │
     │ диска принадлежит какой из 160 дорожек, происходит │
     │ чисто программным путем).                          │
     ├────────────────────────────────────────────────────┤
     │       Байт НОМЕР СЕКТОРА ( отсчет с 1 до 16)       │
     ├────────────────────────────────────────────────────┤
     │ Байт РАЗМЕР СЕКТОРА ( в ТРДОС = 1 ,т.е. 256 байт)  │
     ├────────────────────────────────┬───────────────────┤
     │ Байт #F7   (субкоманда -       │    Два байта      │
     │ записать подсчитанную к.сумму) │ конрольной суммы  │
     ├────────────────────────────────┴───────────────────┤
     │        22 байта #4E ( пробел перед данными)        │
     ├────────────────────────────────────────────────────┤
     │                     12 байтов  НОЛЕЙ               │
     ├────────────────────────────────┬───────────────────┤
     │ 3 раза код #F5 (инициализация  │  код #A1, начало  │
     │    счетчика контр.суммы)       │  метки данных     │
     ├────────────────────────────────┴───────────────────┤
     │         код #FB   (адресная метка данных)          │
     ├────────────────────────────────────────────────────┤
     │                       256  НОЛЕЙ                   │
     │                   (это поле данных)                │
     ├────────────────────────────────┬───────────────────┤
     │      Байт #F7   (субкоманда -  │    Два байта      │
     │  записать подсчитанную к.сумму │ контрольной суммы │
     ├────────────────────────────────┴───────────────────┤
     │        50 байтов  #4E ( остаточный пробел)         │
     └────────────────────────────────────────────────────┘

   После того, как все 16 секто-
ров на дорожке размечены, остав-
шееся место дорожки  заполняется
кодом #4E.
   Этот  массив   форматирования
предназначен   для    дисководов
двойной плотности. Для  дисково-
дов одинарной плотности  он  бу-
дет другой.
   Для дисководов двойной  плот-
ности  (режим   Модифицированной
Частотной модуляции ) в  процес-
се  выполнения  команды  "ЗАПИСЬ
ДОРОЖКИ"  микросхема   восприни-
мает и рассматривает как  субко-
манды следующие байты:

байт #F5 - запись кода #A1 и за-
           пуск   счетчика  кон-
           трольной суммы;
байт #F6 - запись кода C2;
байт #F7 - запись   подсчитанной
           контрольной суммы  на
           диск.

   В процессе программирования у
вас может возникнуть желание от-
форматировать отдельные  дорожки
на диске по-другому. Например, в
процессе  создания    защищенных
дисков или для скрытого  загруз-
чика. Нет проблем!
   Вы  можете   отформатировать,
например, 163-ю дорожку на своем
диске  всего  с  одним  сектором
длиною в 1024 байта и с  систем-
ным номером 223, и об  этом  бу-
дет знать только ваша программа,
работающая с этой дорожкой, и вы
сами.
   При попытке кого-либо  друго-
го прочитать вашу секретную  до-
рожку и  сектор,  скорее  всего,
его постигнет неудача,  так  как
этот кто-то не будет знать  сис-
темного  номера  этого  сектора.
Микросхема ВГ93  его  просто  не
найдет на дорожке, не говоря  уж
о попытке прочитать его содержи-
мое.
   (Когда вы прочтете эту  книгу
до конца и затратите  определен-
ные усилия, вы сможете без  тру-
да  копировать  любые   подобные
диски   с    любой    ЛОГИЧЕСКОЙ
ЗАЩИТОЙ).

   Форматирование дорожки  можно
выполнить и  через  другую  под-
программу ТРДОС, а именно  #3FC0
<#3FCA> (см.выше). Сформировав в
области ОЗУ весь массив дорожки,
каким он должен быть  на  диске,
можно одним махом  записать  ин-
формацию из ОЗУ в диск на дорож-
ку, и таким образом отформатиро-
вать ее.
   Посчитаем из таблицы, сколько
байтов в ОЗУ займет у  нас  весь
массив:
   376  байт  -  это  на   одном
секторе и 376*16= 6016  байт  на
всей  дорожке  (плюс    довесок,
приблизительно в 200 байт).
   При  форматировании   дорожки
своими форматами  вы должны учи-
тывать это, и длина всего масси-
ва вашего формата не должна пре-
вышать эту цифру.  Лишняя инфор-
мация просто не запишется на до-
рожку.

   ОПРЕДЕЛЕНИЕ РАЗМЕТКИ ДИСКА

   В некоторых случаях  вам  мо-
жет  потребоваться   определить,
как размечен тот или  иной  диск
(например, для  'вскрытия' защи-
щенных дисков или дисков, разме-
ченных нестандартно).  В системе
команд ВГ93 есть команда:  'ЧТЕ-
НИЕ АДРЕСА', но она предназначе-
на   для  нормально  размеченных
дисков, т.е. без всяких выкрута-
сов.
   С ее помощью можно читать ин-
дексную адресную метку и  ТРДОС-
овских, и MSDOS-овских дисков, и
CP/M дисков, но если вы попытае-
тесь прочитать индексно-адресную
метку на диске, где на одной до-
рожке существуют сектора с  раз-
ной длиной и с номерами, взятыми
с  потолка  - то  вы  прочитаете
метку одного сектора, но узнать,
какие сектора, сколько их и  ка-
кие  у  них  номера, вы  вряд ли
сможете.  Для  этого  существует
'хитрый' способ.
   Вспомним.  У  нас  в  резерве
осталась  команда  ВГ93  'ЧТЕНИЕ
ДОРОЖКИ ЦЕЛИКОМ'. При  этой  ко-
манде микросхема читает с дорож-
ки все: и  метки, и  синхронизи-
рующие  байты, и  данные - в об-
щем, все, все, все. Единственный
недостаток этой  команды  -  это
то, что при чтении информации  с
диска  читаемые байты не строби-
руются. Но это нам не  помешает.
Итак!  Представим, к  вам  попал
диск с подозрительной разметкой.
Выводите  головки  дисковода  на
какую-нибудь дорожку (обычно  на
нулевую ), прижимаете головки  к
поверхности, даете команду 'ЧТЕ-
НИЕ ДОРОЖКИ' и выходите  на под-
программу ТРДОС  #3FDB <#3FE5> -
чтение массива из порта Данных в 
адрес M (HL) (естественно, перед
этим вы  должны  зарезервировать
буфер  для  считываемых  данных,
размером   приблизительно   6300
байта, можно даже на экране).
   Повторите эту процедуру  чте-
ния раза 2-3  подряд  для  более
надежного считывания, т.к.  бай-
ты не сопровождаются  синхросиг-
налом. И вот у вас в буфере ока-
жется массив данных целой дорож-
ки со всеми служебными  метками.
А дальше совсем просто.
   Вспомним, с каких байтов  на-
чинается  I.A.M.  - индексно-ад-
ресная метка. Правильно - с бай-
тов #A1 и #FE (кто не вспомнил -
смотри предыдущую таблицу масси-
ва форматирования).  (Для дисков
с ОДИНАРНОЙ плотностью байт  пе-
ред кодом #FE будет другой  (мо-
жет быть и  00, и #C9, и #FF - в
зависимости от изначального мас-
сива форматирования).
   Находим эти байты в буфере, а
после них, пожалуйста, все  дан-
ные одного сектора: номер дорож-
ки, сторона, номер и длина  сек-
тора. Запомним эти данные в  ка-
ких-нибудь  ячейках  ОЗУ.   Ищем
следующие два байта #A1 и #FE; и
так, пока весь буфер не  кончит-
ся. После этого у  нас  окажутся
на руках все козыри, какой бы ни
был хитроумный формат на  дорож-
ке. Просканировав весь  диск, мы
получим карту формата всех доро-
жек и секторов.  Но  обычно  бы-
вает  достаточно  просканировать
2-4 дорожки.

       Продолжение следует





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

Похожие статьи:
Плюс-минус - о том что такое CB RADIO,об его плюсах и минусах.
Железяки - идея девайса: Эмyляция магнитофона и выcокоcкороcтной поcлeдоватeльный порт.
Scene - беседа Sq, Diver, CJ о судьбе газеты Insanity.

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