┌───────────────────────────┐ │ ────── СИСТЕМА ────── │ └───────────────────────────┘ (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. Заранее благодарен за все дополнения и исправления. Вам необходимо учесть, что эта статья не претендует на полноту освещения рассматриваемых воп- росов. Если все будет идеально просто и понятно , то вы, доро- гие читатели, разучитесь думать и потеряете тягу к постижению непонятного.