TR-DOS для профессионалов и любителей 1993 г.

Значения регистров при входе в TR-DOS - нетрудно заметить, что создатели TR-DOS не придерживаются концепции сэра Синклера о неизменности ПЗУ.


Нетрудно заметить, что создатели TR-DOS не придерживаются концепции сэра Синклера о неизменности ПЗУ, поэтому в различных версиях TR-DOS адреса процедур различны. Желательно обходиться стандартными точками входа (как это делается в большинстве порядочных систем, например, на IBM PC). Если Вы все же используете прямое обращение к ПЗУ, не поленитесь вставить в программу проверку версии DOS, например, при помощи стандартной процедуры #3D13 (см. далее):

LD HL,#0361 ; проверяемый адрес в DOS ПЗУ для v5.01

LD C,#13 ; литера процедуры #3D13 (см. далее)

CALL #3D13 ; перенос 16 байт с адреса в HL в #5CDD

CALL comp ; процедура сравнения 8 байт в #5CDD и в

; строке EXAMPL, если совпадают, флаг Z=0 JP NZ,EXIT ; не совпадают - версия не 5.01 - выход

; или проверка на другую версию ... ... ; продолжение - можно работать с DOS ПЗУ

EXAMPL DEFM 'Ver 5.01' ; последовательность байт, характерная

; для данной версии (любая известная)

Если у Вас нет желания написать подпрограмму сравнения "comp", версии 5.01 и 5.03

можно отличить более простым способом:

LD HL,#026A ; проверяемый адрес в DOS ПЗУ

CALL #01C7 ; возвращает в регистре A байт по (HL)

CP #AA ; в регистре A байт #AA - версия 5.01

JP Z,V5 01

CP #F4 ; в регистре A байт #F4 - версия 5.03

JP Z,V5 03

JP EXIT ; не #AA и не #F4 - неизвестная версия, выход

Однако, весьма вероятно, что с другими версиями DOS данная программа застрянет в #01C7, так и не достигнув "EXIT", поэтому первая проверка более универсальна.

К сожалению, в последнее время стали появляться программы, создатели которых разобрались со своей версией DOS и считают, что она единственная в мире. Запуск таких программ на другом компьютере, как правило, приводит к порче диска.

Наиболее важной для вызова TR-DOS из программы в машинных кодах является точка входа с адресом 15635 (#3D13). Разработчики возложили на данную процедуру функции, которые в серьезных машинах (например, IBM PC) выполняют векторы прерываний системы ввода-вывода. С адреса #3D13 в конечном итоге происходит переход к подпрограмме, которая, в зависимости от кода, содержащегося в регистре C, при помощи таблицы #2842 [10306 dec] (#288C [10380] в v5.03), передает управление соответствующей подпрограмме. Параметры для этих подпрограмм передаются при помощи регистров микропроцессора либо находятся в области системных переменных TR-DOS (например, заголовок файла). Ниже приводятся краткие описания процедур, вызываемых в зависимости от литеры (содержимого регистра C): C=#00 - выполняется команда "Восстановление" ВГ93: головка отводится на нулевую

дорожку и ожидает сигнала INTRQ. Ожидание можно прервать нажатием клавиши BREAK.

C=#01 - инициализация дисковода, заданного в регистре A. Если для указанного номера не инициализирована соответствующая переменная 23802.23805 (= #FF), то она устанавливается равной #08, затем определятся число дорожек и заносится в 23752.23755 (#00-для 40 дорожек, #80-для 80). Затем заданный номер из регистра A заносится в 23798 (временный дисковод), а в 23830 заносится копия системного регистра.

C=#02 - установка головки на дорожку, номер которой задан в регистре A (0.159, т.е. 1-му

треку, и сторонам 0 и 1, соответствуют номера дорожек 0 и 1). C=#03 - установка номера сектора, номер которого задан в регистре A (1.16) - номер

помещается в #5CFF (23807). C=#04 - установка адреса буфера, заданного в регистре HL, в системную переменную #5D00 (23808).

C=#05 - чтение блока секторов: в буфер по адресу HL считывается B секторов, первый из которых имеет номер E на дорожке D (если B=0, считываются только заголовки секторов).

C=#06 - запись блока секторов (параметры аналогичны предыдущей команде): из буфера по адресу HL на диск (дорожка D, сектор E) записывается B секторов.

C=#07 - вывод каталога диска в канал, заданный в регистре A (2-экран, 3-принтер). Номер диска берется из переменной #5CF6 (23798). Необходимо продублировать этот номер в ячейках 23800, 23801. Предварительно выполняется процедура #18.

C=#08 - считывается заголовок файла в область системных переменных по адресу #5CDD-#5CEC. Номер требуемого файла (от 0 до 127, включая и удаленные) задается в регистре A.

C=#09 - запись заголовка файла из системной области на диск, на место файла с номером, указанным в регистре A (переименование).

C=#0A - поиск файла в каталоге по имени и типу, которые заданы в области системных переменных #5CDD-#5CE5; количество проверяемых байтов указывается в переменной 23814 (обычно равное 9). Если файл найден, его номер возвращается в регистре C и ячейках 23838 (#5D1E), 23823 (#5D0F); если нет - в регистре C содержится #FF, 23838 не изменяется, в 23823 - код ошибки #FF.

C=#0B - запись на диск файла типа CODE с адреса HL длиной DE; имя (и тип?) файла

должно находиться в системной области #5CDD-#5CE4. Проверка на наличие такого имени не производится. Предварительно выполняется процедура #18.

C=#0C - запись на диск BASIC-программы; имя файла задается в системной области.

Проверка имени также не производится. В переменной #5CD1 задается номер строки автостарта (младший и старший байт). Иногда, встречается замечание, что если тип не равен "B", файл записывается как "boot"; возможно, для версии 5.03? Предварительно выполняется процедура #18.

C=#0D - выход из TR-DOS (резерв для расширения впоследствии).

C=#0E - загрузка файлов или VERIFY; при этом заголовок и тип должен быть помещен в область #5CDD-#5CE5. При системной переменной 23801 (#5CF9) равной #00 выполняется загрузка, при #FF - проверка. Для загрузки BASIC - программы переменная 23824 (#5D10) должна быть равна #00; если же она равна #FF, то при загрузке новой, старая программа удаляется, но новая не считывается. В зависимости от содержимого регистра A подпрограмма будет работать по-разному:

A=#00 - адрес загрузки и длина берется из каталога;

A=#03 - коды загружаются с адреса HL, длина загружаемого файла определяется значением DE;

A=#FF - коды загружаются с адреса HL, но длина загружаемого файла равна длине записанного на диск.

C=#0F... 11 - выход из TR-DOS (общий адрес для процедур #0D, #0F, #10, #11), (в версиях 5.01 и 5.03 резерв для расширения).

C=#12 - стирается файл, имя и тип которого заданы в #5CDD-#5CE5, причем удаляются все файлы с такими параметрами. В #5D08 сохраняется первый байт имени, которым был заменен на #01; в #5D07 - число удаленных файлов.

C=#13 - перенос информации о файле (16 байт) с адреса в HL, в #5CDD-#5CEC.

C=#14 - перенос информации о файле с #5CDD-#5CEC по адресу в HL.

C=#15 - проверка дорожки, номер которой задан в регистре D. Если обнаружены дефектные сектора, в #5D0F будет помещен код ошибки равный #07, а в системной переменной #5CD6 - число дефектных секторов.

C=#16 - устанавливает текущей сторону диска 0 (верхнюю), например, для предыдущей

процедуры. Изменяет системный регистр #FF (значением из #5D16 маскированным OR #3C, т.е. 00111100). Иначе говоря, загрузка системного регистра значением равным A OR #3C.

C=#17 - устанавливает текущей сторону диска 1 (нижнюю), (значение из #5D16 маскируется AND #6F). Иначе говоря, загрузка системного регистра значением равным A AND #6F.

C=#18 - считывает системный сектор и производит настройку контроллера на тип дискеты.

Таким образом, через процедуру #3D13 можно выполнить практически все необходимые операции с диском, которые могут понадобиться обычной прикладной программе. Только при написании специальных дисковых программ (например, для форматирования) требуется прямое обращение к DOS ПЗУ, однако без крайней необходимости это делать нецелесообразно, так как возникнет проблема совместимости.

В качестве примера приведем часто встречающийся загрузчик для программы-моноблока (все части программы записаны последовательно и объединены с BASICом): LD HL,40000 ; адрес загрузки 1-го блока

LD B, 17 ; число загружаемых секторов для него

CALL DOS ; вызов процедуры загрузки

CALL 4 0000 ; например, декомпрессия экрана

LD HL,24500 ; адрес загрузки 2-го (основного) блока

LD B,115 ; число загружаемых секторов

CALL DOS ;

CALL 24500 ; например, декодирование программы

JP START ; запуск загруженной программы

DOS LD DE, (#5CF4) ; адрес на диске из системной переменной

LD C,5 ; загрузка блока секторов

JP #3D13 ; вызов функции DOS

Загрузчик использует литеру #05 процедуры #3D13, т.е. грузит число секторов, заданное в регистре B, по адресу, заданному в HL (для разных программ, естественно, они будут различны). Чтобы определить адрес на диске, используется системная переменная #5CF4, где после загрузки каждого блока (в т.ч. начальной BASIC-части) находится адрес следующего сектора, дорожки. Таким образом, можно загружать любое число последовательных блоков, причем загрузка происходит значительно быстрее, потому что головка дисковода не ездит на нулевую дорожку за параметрами каждого файла; соответственно, уменьшается износ дискеты. Как правило, блоки записывают сразу после BASIC-загрузчика, и затем при помощи любого "Дискового доктора" исправляют число секторов этого загрузчика на суммарное, а бывшие блоки помечают как удаленные. Кроме прочих преимуществ, программу-моноблок труднее взломать.

Учтите, что если длина блока не кратна длине сектора (256 байт), с последним сектором, после Вашего блока кодов будет загружаться некоторый "мусор". Поэтому, когда требуется загрузить заданное число байтов, нужно пользоваться литерой #0E процедуры #3D13:

LD HL,NAME ; имя 1-го блока

LD C,#13 ; перенос имени из (HL) в область переменных DOS

CALL #3D13 ; вызов функции DOS

XOR A ; адрес и длина блока - из каталога

LD ( #5CF9) , A ; для LOAD

LD C,#0E ; загрузка файла по его имени

CALL #3D13 ;

LD HL,#5CE4 ; последний байт имени файла

INC (HL) ; следующий номер блока

LD HL,ADR2 ; рабочий адрес 2-го блока

XOR A ;

LD (#5CF9),A ;

LD A,#FF ; адрес блока - в HL, длина -

LD C,#0E ; из каталога

CALL #3D13 ;

JP START ; запуск загруженной программы

NAME DEFM "block 01C" ; имя и тип загружаемого файла

В приведенных примерах предполагается, что загружаемые файлы на диске, безусловно, присутствуют. Такой метод можно применять только для загрузки программ. Если же требуется загрузка из прикладной программы, когда имя файла задается пользователем, должна проводиться проверка наличия запрашиваемого файла. Желательно также выполнить настройку на тип диска (так как дискету могли заменить после запуска программы). Это можно выполнить, например, так:

LD C,#18 ; настройки на тип дискеты

CALL #3D13 ; вызов функции DOS

LD HL,NAME ; имя запрашиваемого файла

LD C,#13 ; перенос имени из (HL) в области DOS

CALL #3D13

LD C,#0A ; поиска файла по его имени

CALL #3D13

LD A, C ; в "C''-номер файла в каталоге

INC C

JR Z,EXIT ; если C=#FF, файл не найден - выход

LD C,#08 ; чтение параметров файла в перемененной DOS

CALL #3D13 XOR A

LD ( #5CF9) , A ; для LOAD

LD HL,ADR ; адрес загрузки блока

LD A,#FF ; адрес блока в HL, длина - из каталога

LD C,#0E ; загрузка файла по его имени

CALL #3D13 RET

NAME DEFM "textnameC" ; имя и тип загружаемого файла

КАРТА ПАМЯТИ TR-DOS

При инициализации TR-DOS для нее выделяется 112 байт, соответственно область памяти, начиная с CHANS, сдвигается вверх:

Стандартное начало BASIC-области: 23755 #5CCB

Начало BASIC-области с TR-DOS: 23867 #5D3B

Начало BASIC-области с TR-DOS и интерфейсом 1: 23925 #5D75

Кроме того, во время чтения или записи сектора, между областью переменных DOS и CHANS создается буфер сектора - 257 байт (256 байт данных + контрольный байт). При этом область памяти, начиная с #5D25 (CHANS-1), сдвигается вверх еще на 257 байт, таким образом, что BASIC-область начинается с #5E3C. Если RAMTOP установлен слишком низко, то при вызове команды DOS может быть выдано сообщение "Out of memory", хотя в остальном BASIC работает нормально; это говорит о недостатке памяти для выделения 257-байтного буфера. Выделение буфера необходимо учитывать также при чтении кодов в область BASIC-программы: например, для загрузки в нулевую строку после REM, необходимо указывать адрес не PROG+5, а PROG+5+257, т.е. #5E41.

При переносе кассетных программ на диск, коды в нулевой строке оказываются сдвинуты на 112 байт, что требует соответствующей коррекции адресов. Проще убрать область DOS при помощи процедуры из основного ПЗУ:

LD BC,112 ; величина сдвига

LD HL,23755 ; адрес = стандартному началу BASIC-области

CALL #19E8 ; удаление блока, начиная от HL, длиной BC

Указанная процедура сдвигает всю BASIC-область, корректируя значения системных переменных.

Следует отметить, что 0-я строка с кодами может неправильно обрабатываться DOS, не рекомендуется давать команды CAT, LIST.

Указанный способ выделения буфера перед областью CHANS объясняет странное поведение TR-DOS при обращении к MS-DOS дискете: любое обращение к диску начинается с чтения 8-го сектора во временный буфер, а так как сектор MS-DOS вдвое длиннее, таблица CHANS оказывается затертой - с соответствующими последствиями...

Адрес таблицы канальной информации указывается системной переменной CHANS (по адресу 23631, #5C4F); начало BASIC-программы определяется переменной PROG (см. 23635, #5C53).




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



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

Похожие статьи:
Buy your games from Sintech!
Обозрение - Игровые программы, игры на целый диск, демоверсии игровых программ, электронные газеты, электронные журналы, системные программы, демонстрационные программы.
Железо - как подключить второй дисководо к Спектруму.
Аэробика - хронология российского спектрума: 1995-2002 года (версия от Himik's ZxZ/PoS-WT).
Горячая линия - Внимание! Изменились наши адреса!

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