┌───────────────────────────┐
│ ────── СИСТЕМА ────── │
└───────────────────────────┘
(c) Павел Никитин.
РАБОТА С TR-DOS В АССЕМБЛЕРЕ
----------------------------
В этой статье мы рассмотрим
некоторые приемы использования
функций TR-DOS при программиро-
вании на ассемблере.
1. ФОРМАТИРОВАНИЕ ТРЕКА.
Многие программисты считают
операцию форматирования трека
тайной за семью печатями. Между
тем отформатировать трек произ-
вольным образом не так уж и
сложно. Наберите следующую прог-
рамму в каком-либо ассемблере, и
Вы сами убедитесь в этом:
ORG #EA60 ;Стартовый адрес (60000 в десятичной)
DI ;Запрет прерываний
LD A,#8 ;Загрузка кода комманды ВГ93
CALL ZAGR
LD A,#3C ;Код стороны (равен #3C и #2C
;для соотв. верхней и нижней стороны)
LD C,#00 ;Номер дорожки (в данном случае 0-ой)
CALL SEARCH ;Вызов процедуры поиска трека
CALL FORMAT ;Вызов процедуры форматирования
CALL FORMAT ;(желательно вызывать несколько раз)
EI ;Разрешение прерываний
RET ;Возврат в BASIC
ZAGR LD IX,#2FC3
JP TO_TRDS
SEARCH LD IX,#2F4D ;Адрес в ПЗУ TR-DOS
;процедуры поиска трека
TO_TRDS PUSH IX ;Помещаем в стек адрес процедуры
JP #3D2F ;Переход по стеку в ПЗУ TR-DOS
FORMAT LD HL,FRM_DAT ;Последовательность процедур,
LD BC,#007F ;непосредственно
LD A,#F0 ;производящих
LD IX,#2F57 ;форматирование
PUSH IX
LD IX,#3FCA
PUSH IX
LD IX,#2FC3
JP TO_TRDS
Не надо забывать, что проце-
дура форматирования есть ни что
иное, как запись, только не дан-
ных (ваших программ, массивов и
т.д.), а байтов системной инфор-
мации о данном секторе.
FRM_DAT - список таких бай-
тов, описывающих сектор данного
трека.
FRM_DAT DEFS 50,#4E ;Первый пробел.
DEFS 12,#00
DEFS 03,#F5 ;Запись трех байт #A1
;и инициализация контрольной суммы.
DEFB #FE ;Адресная метка индексных данных,
;т.е. #FE "говорит" ВГ, что дальше
;идут индексные (о треке,секторе и т.д.)
;данные.
DEFB #NN ;Номер дорожки
DEFB #NN ;Номер стороны
DEFB #NN ;Номер сектора
DEFB #NN ;Длина сектора (принимает значения
;0,1,2,3 для соотв. длины в байтах
;128,256,512,1024)
DEFB #F7 ;Запись двух байт контрольной суммы
DEFS 22,#4E ;Второй пробел
DEFS 12,#00
DEFS 03,#F5 ;Инициализация контрольной суммы
DEFB #FB ;(говорит" ВГ, что дальше записаны
;данные, из которых и состоят ваши файлы)
DEFS NNNN,#00 ;Данные (число #NNNN зависит от
;размера сектора - соответственно
;128, 256, 512, 1024 байта)
DEFB #F7 ;Запись двух байт контрольной суммы
DEFS 54,#4E
Для каждого трека вам надо
составить такое количество таб-
лиц FRM_DAT, какое количество
секторов вы хотите получить в
этом треке:
SECTOR1_FRM_DAT 1
SECTOR2_FRM_DAT 2
и т.д.
Но при этом надо помнить,
что на один трек можно прописать
приблизительно (16*256+128) байт
информации.
Далее идет список основных
процедур ПЗУ TR-DOS, используе-
мых при форматировании.
1) При входе регистр А должен
содержать код команды. Процедура
обеспечивает проверку на конец
команды и выполняет задержку.
#2F57 OUT (#1F),A ;Занесение в регистр комманд
;числа 8 из аккумулятора
#2F59 IN A,(#FF) ;Проверка на конец комманды
AND #80
JR Z,#2F59
PUSH BC ;Сохранение BC
CALL #3DFD ;Вызов подпрограммы временной задержки
POP BC ;Восстановление BC
RET ;Возврат из процедуры
2) Заносит в регистр команд ВГ93
число из аккумулятора
#2FC3 OUT (#1F),A
RET
3) Внутренняя процедура
TR-DOS, выполняющяя задержку
#3DFD LD A,#50 ;Два элементарных
#3DFF LD C,#FF ;вложенных цикла,
#3E01 DEC C ;обеспечивающих
JR NZ,#3E01 ;задержку
DEC A
JR NZ,#3DFF
RET
4) При входе регистр А содержит
число для загрузки системного
регистра. Регистр C содержит но-
мер первого трека файла. Проце-
дура обеспечивает занесение но-
мера трека в регистр данных, вы-
полнение команды позиционирова-
ния головок дисковода на нужный
трек, проверку на выполнение ко-
манды и выполнение задержки.
#2F4D OUT (#FF),A ;Загрузка системного регистра
;кодом стороны #3C или #2C
LD A,C ;Перенос числа из регистра C в А
OUT (#7F),A ;Занесение номера трека в регист данных
CALL #3DFD ;Вызов подпрограммы задержки
LD A,18
OUT (#1F),A
#2F59 IN A,(#FF) ;Проверка на конец комманды
AND #80
JR Z,#2F59
PUSH BC ;Сохранение BC
CALL #3DFD ;Вызов подпрограммы задержки
POP BC ;Восстановление BC
RET
5) Процедура, выполняющяя вывод
информации (запись на диск).
#3FCA IN A,(#FF) ;Цикл ожидания
AND #C0
JR Z,#3FCA
RET M
OUTI ;Вывод информации
JR #3FCA
Используя описанную процедуру
форматирования можно поставить
"метку" на диске, если отформа-
тировать трек так: первые 16
секторов стандартно, а один с
номером n>16 размером 128 байт.
При копировании такого диска
трековый копировщик последний
сектор "не заметит" и он скопи-
рован не будет. Трек можно легко
протестировать, читая его стан-
дартной процедурой TR-DOS:
LD B,1 ;Кол-во читаемых секторов.
LD C,5 ;Код команды чтения группы секторов.
LD D,TREK ;Номер трека.
LD E,SECTOR ;Номер сектора.
LD HL,ADDR ;Адрес размещения считанного сектора.
CALL #3D13 ;Групповая точка входа процедур TR-DOS.
RET
2. ДРАЙВЕР ЧТЕНИЯ С ДИСКА, НЕ
ТРЕБУЮЩИЙ НАЛИЧИЯ СИСТЕМНЫХ ПЕ-
РЕМЕННЫХ TR-DOS.
Многие игрушки, особенно мно-
гоуровневые, не всегда хорошо
поддаются дисковизации при ис-
пользовании стандартной процеду-
ры загрузки TR-DOS, т.к. при
этом надо восстанавливать сис-
темные переменные TR-DOS, выде-
лять буфер и т.д.
Ниже приведен драйвер посек-
торного чтения диска, при умелом
использовании которого загрузка
с диска будет выглядеть менее
болезненно для программы, т.к.
драйверу не нужны системные пе-
ременные и дополнительный буфер
для чтения, нет проблемм и с
прерываниями.
Параметры для ввода:
HL - адрес загрузки в памяти;
DE - начальные трек, сектор;
B - количество секторов.
LOADER DI ; Запрет прерываний.
NXTT PUSH BC ; Сохранение BC.
PUSH DE ; --//-- DE.
LD A,D ; Выяснение физического
OR A ; номера трека и стороны.
RRA
LD C,A
LD A,#3C ; #3C - код нулевой стороны.
JR NC,SIDE ; Переход на установку стороны.
LD A,#2C ; #2C - код первой стороны.
SIDE LD IX,#2F4D ; Вызов процедуры установки стороны.
CALL TO_TRDS
POP DE ; Восстановление DE.
POP BC ; --//-- BC.
CONT PUSH BC
PUSH DE
LD IX,#2F1B
CALL TO_TRDS ; Непосредственно чтение сектора.
POP DE
INC H
INC E
BIT 4,E ; Если сектор перевалил за 15-й,
JR Z,NXTS ; то он становится 0-вым, а трек
LD E,#00 ; увеличивается на единицу.
INC D
POP BC
DJNZ NXTT
RET
NXTS POP BC
DJNZ CONT
TO_TRDS PUSH IX ; Вызов процедуры TR-DOS'a
JP #3D2F
ПРИМЕР ИСПОЛЬЗОВАНИЯ:
LD HL,#6000 ;Считывание каталога диска
LD DE,#0000 ;по адресу #6000.
LD B,#9
CALL LOADER
EI
RET
Используя этот драйвер, надо
помнить, что ошибки чтения с
диска не обрабатываются. Если
длина загружаемого блока не
кратна 256, то без специальных
мер будет терятся 1<=n<=255 байт
информации. Байты nn=(256*кол-во
секторов - длина в байтах) будут
испорчены. Их надо сохранить
(актуально для многоблочных
программ)
ПРИМЕР: Будет произведена заг-
рузка #2000 байт с адреса #6000
с сохранением "портящихся" байт
в экранной области.
LD HL,#6000 ; Адрес загрузки
PUSH HL
LD DE,#2000 ; Количество байт
ADD HL,DE
PUSH HL
PUSH DE
LD DE,16384 ; Сохранение
LD BC,256 ; "портящихся"
LDIR ; байт
POP DE
LD A,D ; Расчет
QR A ; количества
JR Z,M1 ; загружаемых
INC D ; секторов
M1 LD B,D
POP DE
POP HL
PUSH DE
LD DE,START_TR_SEC
CALL LOADER ; Вызов загрузчика
POP DE ; Восстановление
LD HL,16384 ; испорченных
LDIR ; байтов
EI
RET
Вы спросите, как можно гру-
зить уровни с диска, не зная их
начальных трека и сектора? Для
этого надо выделить основной
(главный) блок, обработать его и
после него записать один за дру-
гим уровни:
main block
level1
level2
level3
и т.д.
После этой процедуры дайте
команду MOVE, чтобы файлы распо-
лагались друг за другом не
только в каталоге, и чтобы между
ними не было посторонней инфор-
мации. Составьте таблицу разме-
ров (в секторах) всех уровней.
После загрузки main_blok запиши-
те последний трек/сектор. Затем,
выбирая уровень, берите из таб-
лицы длины и прибавляйте к пос-
ледним треку/сектору, вычисляя
начальные трек/сектор нужного
уровня.
В этом вам поможет следующая
процедура, которая по начальным
треку/сектору вернет трек/сектор
с пропуском в #nn секторов.
DE - нач. трек/сектор.
A - кол-во пропускаемых секторов.
По выходу в DE новые трек/сектор.
LD B,#10 ; Количество секторов в треке.
ADD A,E ; Пропустить от начала трека.
M1 CCF
SUB B ; Сдвинуться на трек.
JR C,M2 ; Все ?
INC D ; Нет, увеличить номер трека.
JR M1
M2 ADD A,B
LD E,A ; Новый начальный сектор.
RET
3. ОСОБЕННОСТИ РАБОТЫ КНОПКИ
MAGIC.
Еще одна мелочь, которая Вам
может пригодиться - это защита
от MAGIC'а. Ниже мы рассмотрим
три элементарных варианта защи-
ты.
а) При нажатии кнопки MAGIC пор-
тятся две ячейки, где хранятся
данные опроса клавиатуры
(LAST_KEY). Вы их сможете без
труда протестировать.
б) Если поместить стек в экран
(SP <= #4038), то при сохранении
регистров стек "залезет" в ПЗУ и
на этом работа MAGIC'а закончит-
ся.
в) "RESET" ВГ93:
CALL RESET
EI
RET
RESET LD HL,#1FF3
XOR A
PUSH HL
DI
JP #3D2F
Использовать этот прием необ-
ходимо после всех загрузок, т.к.
если ВГ93 не восстановить, то
читать она не будет.
P. Заранее благодарен за все
дополнения и исправления. Вам
необходимо учесть, что эта
статья не претендует на полноту
освещения рассматриваемых воп-
росов. Если все будет идеально
просто и понятно , то вы, доро-
гие читатели, разучитесь думать
и потеряете тягу к постижению
непонятного.