┌──────────────────────────────┐
│ │
│ ЧИТАТЕЛЬ - ЧИТАТЕЛЮ │
│ │
└──────────────────────────────┘
(c) Иван Рощин, г.Москва, 1996
TR-DOS:
как не допустить ошибки ?
Вы удивитесь, если узнаете,
сколько программ не распознают
ошибки при работе с диском, не-
правильно распознают их, а также
зависают или сбрасываются при их
возникновении. Разумеется, при
написании собственных программ
таких ситуаций следует избегать,
хотя это не так-то просто. Дело
в том, что корректная обработка
ошибок становится возможной лишь
при работе напрямую с микрокон-
троллером дискового интерфейса,
а это доступно далеко не каждо-
му. Несмотря на это, надежность
программ можно значительно уве-
личить, если использовать наря-
ду с обычными функциями TR-DOS
специальные процедуры для распо-
знавания ошибочных ситуаций.
В этой статье пойдет речь об
одной из самых распространенных
ошибок ввода-вывода - отсутствии
диска в дисководе. Также будет
сказано несколько слов о прямом
программировании ВГ93 и о про-
граммах, контролирующих смену
диска.
Известно, что перед началом
любой дисковой операции, связан-
ной с чтением или записью дан-
ных, необходимо, чтобы диск был
установлен в дисковод и дверца
дисковода была закрыта. Если это
условие не выполняется, програм-
ма (если она грамотно написана)
обычно выдает одно из следующих
сообщений:
- No disk
- Disk not present
- Disk not ready
Специальная процедура для оп-
ределения наличия диска в диско-
воде была бы очень полезной.
Приведу лишь один из возможных
примеров ее использования: если
ваша программа использует интер-
претатор системных функций
TR-DOS и не осуществляет перех-
ват ошибок, то при их возникно-
вении (в частности, при отсут-
ствии диска) может произойти
сброс компьютера (что очень не-
желательно). Но если с помощью
указанной процедуры обнаружить
отсутствие диска еще до вызова
интерпретатора, можно избежать
неприятных последствий (конечно,
если не произойдет какой-нибудь
другой ошибки).
Рассмотрим несколько возмож-
ных способов реализации такой
процедуры:
1) Пробуем прочитать ка-
кой-нибудь сектор (естественно,
не с помощью вызова интерпрета-
тора системных функций, а при
прямом программировании контрол-
лера). Так как считанная инфор-
мация не понадобится, чтение
можно проводить, скажем, в об-
ласть ПЗУ. В случае неудачи счи-
таем, что диска нет.
Недостатки: неудачное считы-
вание сектора еще не значит, что
диск отсутствует. Вполне может
быть, что сектор был записан с
ошибкой или сектора с таким но-
мером вообще нет на дорожке
(т.к. в общем случае формат дис-
ка может быть произвольным).
Достоинства: при работе с
диском фиксированного формата
этот способ вполне подходит.
2) Делаем попытку прочитать
первый встреченный заголовок
сектора. В случае неудачи счи-
таем, что диска нет.
Недостатки: в общем случае
диск может быть и неформатиро-
ванным, при этом ничего прочи-
тать не удастся, и мы получим
неверный результат.
Достоинства: этот способ го-
дится для любого форматированно-
го диска и достаточно прост в
реализации.
3) Используем регистр состоя-
ний микроконтроллера.
Прежде чем говорить о дос-
тоинствах и недостатках этого
метода, вспомним, что такое ре-
гистр состояний и что можно уз-
нать с его помощью.
Регистр состояний отражает
корректность заданной команды, а
также состояния микроконтролле-
ра при ее выполнении. Каждый бит
в нем указывает на определенный
параметр и связан с выполнением
конкретной команды. При выполне-
нии команд восстановления и по-
зиционирования биты системного
регистра имеют следующее назна-
чение:
0 - занято, идет выполнение
команды;
1 - индексный импульс;
2 - магнитная головка находится
в исходном положении;
3 - ошибка в контрольном коде;
4 - ошибка позиционирования;
5 - магнитная головка находится
в рабочем положении;
6 - защита записи;
7 - указывает на готовность дис-
ковода к выполнению команды.
Нас будут интересовать лишь 1
и 6 биты регистра состояний,
поэтому поговорим о них подроб-
нее.
Если посмотреть на дискету,
мы увидим большое отверстие в
центре, а рядом с ним - малень-
кое круглое отверстие в кор-
пусе дискеты и отверстие чуть
меньшего диаметра на самом маг-
нитном диске. Это так называе-
мое индексное отверстие, кото-
рое служит для ориентации маг-
нитной головки дисковода на дис-
кете. Когда отверстия в корпусе
и на самом диске совпадают (а
это происходит при каждом оборо-
те диска), контроллер считает,
что магнитная головка находится
в начале дорожки. Отмечу, что
вероятность случайного совпаде-
ния отверстий составляет пример-
но 3%.
Значение 1-го бита регистра
состояний определяется состоя-
нием индексного отверстия:
┌───────────────────┬────────────────────┐
│ ситуация │ значение 1-го бита │
├───────────────────┼────────────────────┤
│Диска нет │ 1 │
├───────────────────┼────────────────────┤
│Диск есть, │ │
│отверстия в корпусе│ 1 │
│и на самом диске │ │
│совпадают │ │
├───────────────────┼────────────────────┤
│Диск есть, │ │
│отверстия в корпусе│ 0 │
│и на самом диске │ │
│не совпадают │ │
└───────────────────┴────────────────────┘
Шестой бит системного регис-
тра отражает состояние прорези
для защиты записи:
┌───────────────────┬────────────────────┐
│ ситуация │ значение 6-го бита │
├───────────────────┼────────────────────┤
│Диска нет │ 0 │
├───────────────────┼────────────────────┤
│Диск есть, │ │
│прорезь открыта │ 0 │
├───────────────────┼────────────────────┤
│Диск есть, │ │
│прорезь закрыта │ 1 │
└───────────────────┴────────────────────┘
Ясно, что если 1-й бит равен
0 или 6-й бит равен 1, диск при-
сутствует. Но, во-первых, при
наличии диска эти биты могут
принимать, вообще говоря, любые
значения, а во-вторых, совершен-
но неизвестно, закрыта ли двер-
ца дисковода. Как же узнать ее
состояние? Вспомним, что если
она закрыта и двигатель дисково-
да вращается, то будет вра-
щаться и диск. Если же дверца
открыта, диск вращаться не бу-
дет. Ну а как определить, вра-
щается диск или нет, мы уже
знаем - нужно циклически прове-
рять значение первого бита ре-
гистра состояний. При каждом
обороте диска этот бит меняет
свое значение с 0 (отверстие на
корпусе диска не совпадает с от-
верстием на диске) на 1 (отвер-
стия совпадают), и далее - опять
на 0. Если этот бит не будет ме-
нять своего значения - либо в
дисководе нет диска, либо дверца
открыта.
Теперь мы легко можем ука-
зать искомый алгоритм:
- прочитать значение регистра
состояний. Пусть s1 - значение
1-го бита, s2 - значение 6-го
бита.
- пусть s3=1, если диск вра-
щается, и 0, если диск не враща-
ется.
- определить ситуацию по таб-
лице:
s1│s2│s3│ Номер ситуации
──┼──┼──┼────────────────
0│ 0│ 0│ 2
0│ 0│ 1│ 3
0│ 1│ 0│ 2
0│ 1│ 1│ 3
1│ 0│ 0│ 1
1│ 0│ 1│ 3
1│ 1│ 0│ 2
1│ 1│ 1│ 3
Расшифровка номера ситуации:
1 - в дисководе нет диска;
2 - диск есть, но дверца диско-
вода не закрыта;
3 - диск есть и дверца дисковода
закрыта.
Примечание: с вероятностью
примерно 3% ситуация (2) может
быть распознана как ситуация
(1).
Ну что же, осталось только
привести текст процедуры на ас-
семблере:
140.
;***********************************************
;ПРОЦЕДУРА D_READY ОПРЕДЕЛЯЕТ, ВСТАВЛЕН ЛИ
;ДИСК В ДИСКОВОД И ЗАКРЫТА ЛИ ДВЕРЦА ДИСКОВОДА.
;В РЕГИСТРЕ A ВОЗВРАЩАЕТСЯ ЧИСЛО 1,2 ИЛИ 3,
;ОБОЗНАЧАЮЩЕЕ НОМЕР СИТУАЦИИ:
;
; 1 -в дисководе нет диска;
; 2 -диск есть, но дверца дисковода не
; закрыта;
; 3 -диск есть и дверца дисковода закрыта.
;
; Примечание: с вероятностью примерно 3% ситуация (2)
;может быть распознана как ситуация (1).
D_READY XOR A ;УСТАНАВЛИВАЕМ ОДИН И ТОТ ЖЕ
LD C,#3F ;НОМЕР ЦИЛИНДРА
CALL TO_WG93 ;В РЕГИСТРЕ ДОРОЖКИ
LD C,#7F ;И В РЕГИСТРЕ ДАННЫХ.
CALL TO_WG93
LD A,#18 ;ПОЗИЦИОНИРОВАНИЕ. ГОЛОВКА НЕ БУДЕТ
CALL TO_1F ;ДВИГАТЬСЯ, НО ДВИГАТЕЛЬ ВКЛЮЧИТСЯ.
CALL READY ;ЖДЕМ ВЫПОЛНЕНИЯ...
CALL STATUS ;ЧИТАЕМ РЕГИСТР СОСТОЯНИЯ.
LD B,A ;И СОХРАНЯЕМ В РЕГИСТРЕ B.
;ТЕПЕРЬ ЧИТАЕМ РЕГИСТР СОСТОЯНИЯ В ЦИКЛЕ,
;ЧТОБЫ ОПРЕДЕЛИТЬ, ВРАЩАЕТСЯ ЛИ ДИСК.
;ЕСЛИ #300 РАЗ БУДЕТ СЧИТАНО ОДНО И ТО ЖЕ
;ЗНАЧЕНИЕ, ЗНАЧИТ, ДИСК НЕ ВРАЩАЕТСЯ.
;
; ПРИМЕЧАНИЕ: ЧИСЛО #300 ПОДОБРАНО ОПЫТНЫМ ПУТЕМ,
;ИСХОДЯ ИЗ МАКСИМАЛЬНОГО ВРЕМЕНИ РАБОТЫ ЦИКЛА
;(ЭТО ЧУТЬ БОЛЬШЕ ВРЕМЕНИ ОДНОГО ОБОРОТА ДИСКА,
;ИЛИ3 200ms). ЕСЛИ ПРОЦЕССОР РАБОТАЕТ БЫСТРЕЕ ИЛИ
;ДИСК ВРАЩАЕТСЯ МЕДЛЕННЕЕ, ЧИСЛО НУЖНО УВЕЛИЧИТЬ.
LD HL,#300 ;СЧЕТЧИК
LOOP_D PUSH HL
PUSH BC
CALL STATUS
POP BC
POP HL
DEC HL
CP B ;СРАВНИВАЕМ СЧИТАННОЕ И РАНЕЕ ПОЛУЧЕННОЕ ЗНАЧЕНИЯ
LD A,1 ;ФОРМИРУЕМ 0-Й БИТ РЕГИСТРА A
JR NZ,DISK_R ;ЕСЛИ ДИСК КРУТИТСЯ
LD A,H
OR L
JR NZ,LOOP_D ;ПРОДОЛЖАЕМ СЧИТЫВАТЬ ЗНАЧЕНИЕ...
;ФОРМИРУЕМ В РЕГИСТРЕ A БАЙТ С ТАКИМ СОДЕРЖИМЫМ:
;
; БИТ 0: 0-ДИСК НЕ КРУТИТСЯ, 1-КРУТИТСЯ;
; БИТ 1: ТО ЖЕ, ЧТО БЫЛО В 6-М БИТЕ РЕГИСТРА СОСТОЯНИЙ
; БИТ 2: ТО ЖЕ, ЧТО БЫЛО В 1-М БИТЕ РЕГИСТРА СОСТОЯНИЙ
;
;В РЕЗУЛЬТАТЕ В РЕГИСТРЕ A ПОЛУЧАЕМ ЧИСЛО ОТ 0 ДО 7,
;И ДАЛЕЕ ОПРЕДЕЛЯЕМ НОМЕР СИТУАЦИИ ПО ТАБЛИЦЕ.
DISK_R BIT 6,B
JR Z,READY1
SET 1,A
;УСТАНОВЛЕНО ЗНАЧЕНИЕ 1-ГО БИТА.
READY1 BIT 1,B
JR Z,READY2
SET 2,A
;В A ПОЛУЧЕНО НУЖНОЕ ЗНАЧЕНИЕ
READY2 LD (THIS_B+2),A ;МОДИФИЦИРУЕМ КОМАНДУ
;НО СНАЧАЛА ОТКЛЮЧАЕМ ДИСКОВОД:
XOR A ;ЭТИ КОМАНДЫ,
CALL TO_1F ;В ПРИНЦИПЕ,
LD A,#D0 ;МОЖНО
CALL TO_1F ;ВЫБРОСИТЬ.
;ЭТА КОМАНДА СООТВЕТСТВУЕТ LD A,(IX+0)...LD A,(IX+7):
LD IX,TABL
THIS_B LD A,(IX) ;ПОЛУЧИЛИ НОМЕР СИТУАЦИИ
EI
RET
;ТАБЛИЦА ДЛЯ ОПРЕДЕЛЕНИЯ НОМЕРА СИТУАЦИИ:
TABL DB 2,3,2,3,1,3,2,3
;***************************************
;ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ:
TO_1F LD C,#1F
140.
TO_WG93 LD IX,#2A53
JR TO_DOS
READY LD IX,#3EF5
TO_DOS PUSH IX
JP #3D2F
;***************************************
;ПРОЦЕДУРА STATUS ВОЗВРАЩАЕТ СОДЕРЖИМОЕ
;РЕГИСТРА СОСТОЯНИЯ.
;ВХОД: A -СОДЕРЖИМОЕ РЕГИСТРА ДОРОЖКИ,
; B -СОДЕРЖИМОЕ РЕГИСТРА СЕКТОРА,
; КОТОРЫЕ БУДУТ УСТАНОВЛЕНЫ ПОСЛЕ
; ВЫХОДА ИЗ ПРОЦЕДУРЫ.
;ВЫХОД: A -ЗНАЧЕНИЕ, СЧИТАННОЕ ИЗ ПОРТА #1F.
;ПРЕРЫВАНИЯ ПОСЛЕ ВЫХОДА ЗАПРЕЩЕНЫ!
STATUS DI
LD C,#7F ;A=N ЦИЛИНДРА
CALL TO_WG93 ;В РЕГИСТР ДАННЫХ
LD (RG_D+1),A ;ДОРОЖКА
LD A,B
LD (RG_S+1),A ;СЕКТОР
;СОХРАНЯЕМ СОДЕРЖИМОЕ ЯЧЕЕК, КОТОРЫЕ
;МОГУТ БЫТЬ ИСПОРЧЕНЫ:
LD A,(#5D0E)
LD (ST1+1),A
LD A,(#5D0C)
LD (ST2+1),A
LD A,(#5CB6)
LD (ST3+1),A
LD A,(#5D1F)
LD (ST4+1),A
LD A,(#5C3A)
LD (ST5+1),A
LD A,(#5D17)
LD (ST6+1),A
LD HL,(#5D1A)
LD (ST7+1),HL
LD HL,(#5D1C)
LD (ST8+1),HL
LD HL,(#5CF8)
LD (ST9+1),HL
;УСТАНАВЛИВАЕМ СОДЕРЖИМОЕ НЕКОТОРЫХ
;ЯЧЕЕК ДЛЯ ПРАВИЛЬНОЙ РАБОТЫ:
LD A,#FF
LD (#5D0C),A
LD (#5D1F),A
DEC A
LD (#5D0E),A
LD A,#F4
LD (#5CB6),A
LD HL,S_SPEC
LD (#5D1A),HL
LD HL,0
ADD HL,SP
LD DE,-12
ADD HL,DE
LD (#5D1C),HL
LD A,0 ;0 В РЕГИСТР
LD C,#3F ;ДОРОЖКИ
CALL TO_WG93
LD A,#0A ;#A В РЕГИСТР
LD C,#5F ;СЕКТОРА
CALL TO_WG93
LD D,1
LD IX,16179
CALL TO_DOS ;ОПРЕДЕЛИЛИ #1F
;ТЕПЕРЬ ВОССТАНАВЛИВАЕМ СОДЕРЖИМОЕ
;РЕГИСТРОВ ДОРОЖКИ И СЕКТОРА:
RG_D LD A,0
LD C,#3F
CALL TO_WG93
RG_S LD A,0
LD C,#5F
CALL TO_WG93
;ВОССТАНАВЛИВАЕМ РАНЕЕ ЗАПОМНЕННОЕ
;СОДЕРЖИМОЕ ЯЧЕЕК:
ST1 LD A,0
LD (#5D0E),A
ST2 LD A,0
LD (#5D0C),A
ST3 LD A,0
LD (#5CB6),A
ST4 LD A,0
LD (#5D1F),A
ST5 LD A,0
LD (#5C3A),A
ST6 LD A,0
LD (#5D17),A
ST7 LD HL,0
LD (#5D1A),HL
ST8 LD HL,0
LD (#5D1C),HL
ST9 LD HL,0
LD (#5CF8),HL
LD A,B
RET
;СЮДА БУДЕТ ПЕРЕДАНО УПРАВЛЕНИЕ, ЕСЛИ
;0-Й БИТ РЕГИСТРА СОСТОЯНИЙ РАВЕН 1:
S_SPEC POP BC ;СОДЕРЖИМОЕ ПОРТА
LD HL,(#5D1C)
LD DE,12 ;ВОССТАНАВЛИВАЕМ
ADD HL,DE ;УКАЗАТЕЛЬ
LD SP,HL ;СТЕКА
JR RG_D
2 Вам наверняка встречались
программы, контролирующие смену
диска в дисководе (например,
Jemmini Commander). В них прове-
ряются именно указанные выше би-
ты системного регистра (в прин-
ципе, достаточно следить за из-
менением лишь какого-нибудь од-
ного из двух битов). Вот прос-
тейший алгоритм работы такой
программы:
Шаг 1: Прочитать значение регис-
тра состояний. Если пер-
вый бит равен 1, перейти
к шагу 4.
Шаг 2: N="Диск есть".
Шаг 3: Прочитать значение регис-
тра состояний. Если пер-
вый бит равен 0, перейти
к шагу 3.
Шаг 4: N="Диска нет".
Шаг 5: Прочитать значение регис-
тра состояний. Если пер-
вый бит равен 1, перейти
к шагу 5, иначе к шагу 2.
Примечание: программа рабо-
тоспособна при условии, что от-
верстие на самом диске не совпа-
дает с отверстием на корпусе
диска (это связано с использова-
нием 1-го бита регистра состоя-
ний).
Кстати, у такой программы
есть одна особенность, связан-
ная с чтением регистра состоя-
ний. Чтобы прочесть его значе-
ние, нужно, чтобы двигатель дис-
ковода работал. Поэтому ис-
пользуется следующий прием: вы-
полняется команда позиционирова-
ния на дорожку, номер которой
уже записан в регистр дорожки.
При этом головка не будет дви-
гаться, но двигатель дисковода
включится. После окончания вы-
полнения этой команды читается
регистр состояний. Сразу после
этого двигатель выключается,
например, с помощью записи 0 в
порт #FF (или в порт #1F). Меж-
ду двумя последовательными чте-
ниями регистра состояний делает-
ся пауза, обычно 1/50 секунды.
При этом двигатель не успевает
раскрутиться, и лампочка диско-
вода не загорается. Но если вни-
мательно присмотреться, видно,
что лампочка все же чуть-чуть
светится (яркость свечения об-
ратно пропорциональна длине пау-
зы). Так вот, на некоторых дис-
ководах (а именно - на ЕС 5323.
01) было замечено, что при рабо-
те программ, контролирующих сме-
ну диска, лампочка постоянно го-
рит и двигатель работает.
Привожу текст небольшой де-
монстрационной программы, кон-
тролирующей смену диска по вы-
шеуказанному алгоритму. Програм-
ма выводит на экран сообщения
"DISK PRESENT" и "DISK NOT PRE-
SENT". Выход - по нажатию любой
клавиши (когда диск присутству-
ет).
140.
CALL 3435 ;CLS
LD A,2
CALL 5633
M_1 CALL READ_S
BIT 1,A
JR NZ,M_4
M_2 LD A,1
LD (N),A
LD DE,TEXT1
LD BC,23
CALL 8252 ;"DISK PRESENT"
M_3 XOR A
IN A,(254)
AND 31
CP 31
RET NZ ;ЕСЛИ НАЖАТА КЛАВИША, ВЫХОДИМ
CALL READ_S
BIT 1,A
JR Z,M_3
M_4 XOR A
LD (N),A
LD DE,TEXT2
LD BC,23
CALL 8252 ;"DISK NOT PRESENT"
M_5 CALL READ_S
BIT 1,A
JR NZ,M_5
JR M_2
N DB 0 ;1-ЕСТЬ ДИСК, 0-НЕТ.
TEXT1 DB 22,0,0,16,7,17,0,"DISK PRESENT "
TEXT2 DB 22,0,0,16,7,17,0,"DISK NOT PRESENT"
;***************************************
;ПРОЦЕДУРА READ_S ОСУЩЕСТВЛЯЕТ ЧТЕНИЕ
;РЕГИСТРА СОСТОЯНИЙ. ПЕРЕД ЧТЕНИЕМ
;ПРОИЗВОДИТСЯ ВКЛЮЧЕНИЕ ДВИГАТЕЛЯ
;ДИСКОВОДА, А ПОСЛЕ ЧТЕНИЯ -ВЫКЛЮЧЕНИЕ И
;ПАУЗА В3 1/50 СЕКУНДЫ.
READ_S XOR A ;УСТАНАВЛИВАЕМ ОДИН И ТОТ ЖЕ
LD C,#3F ;НОМЕР ЦИЛИНДРА
CALL TO_WG93 ;В РЕГИСТРЕ ДОРОЖКИ
LD C,#7F ;И В РЕГИСТРЕ ДАННЫХ.
CALL TO_WG93
LD A,#18 ;ПОЗИЦИОНИРОВАНИЕ. ГОЛОВКА НЕ БУДЕТ
CALL TO_1F ;ДВИГАТЬСЯ, НО ДВИГАТЕЛЬ ВКЛЮЧИТСЯ.
CALL READY ;ЖДЕМ ВЫПОЛНЕНИЯ...
CALL STATUS ;ЧИТАЕМ РЕГИСТР СОСТОЯНИЯ.
EI ;РАЗРЕШАЕМ РАНЕЕ ЗАПРЕЩЕННЫЕ ПРЕРЫВАНИЯ
PUSH AF
XOR A
CALL TO_1F ;ВЫКЛЮЧАЕМ ДВИГАТЕЛЬ
LD A,#D0
CALL TO_1F
HALT 3 ;ЗАДЕРЖКА 1/50 СЕКУНДЫ
POP AF
RET
;***************************************
;ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ:
TO_1F LD C,#1F
TO_WG93 LD IX,#2A53
JR TO_DOS
READY LD IX,#3EF5
TO_DOS PUSH IX
JP #3D2F
;***************************************
;ПРОЦЕДУРА STATUS ВОЗВРАЩАЕТ СОДЕРЖИМОЕ
;РЕГИСТРА СОСТОЯНИЯ.
;ВХОД: A -СОДЕРЖИМОЕ РЕГИСТРА ДОРОЖКИ,
; B -СОДЕРЖИМОЕ РЕГИСТРА СЕКТОРА,
; КОТОРЫЕ БУДУТ УСТАНОВЛЕНЫ ПОСЛЕ
; ВЫХОДА ИЗ ПРОЦЕДУРЫ.
;ВЫХОД: A -ЗНАЧЕНИЕ, СЧИТАННОЕ ИЗ ПОРТА #1F.
;ПРЕРЫВАНИЯ ПОСЛЕ ВЫХОДА ЗАПРЕЩЕНЫ!
STATUS DI
LD C,#7F ;A=N ЦИЛИНДРА
CALL TO_WG93 ;В РЕГИСТР ДАННЫХ
LD (RG_D+1),A ;ДОРОЖКА
LD A,B
LD (RG_S+1),A ;СЕКТОР
;СОХРАНЯЕМ СОДЕРЖИМОЕ ЯЧЕЕК, КОТОРЫЕ
;МОГУТ БЫТЬ ИСПОРЧЕНЫ:
LD A,(#5D0E)
LD (ST1+1),A
LD A,(#5D0C)
LD (ST2+1),A
LD A,(#5CB6)
LD (ST3+1),A
LD A,(#5D1F)
LD (ST4+1),A
LD A,(#5C3A)
LD (ST5+1),A
LD A,(#5D17)
LD (ST6+1),A
LD HL,(#5D1A)
LD (ST7+1),HL
LD HL,(#5D1C)
LD (ST8+1),HL
LD HL,(#5CF8)
LD (ST9+1),HL
;УСТАНАВЛИВАЕМ СОДЕРЖИМОЕ НЕКОТОРЫХ
;ЯЧЕЕК ДЛЯ ПРАВИЛЬНОЙ РАБОТЫ:
LD A,#FF
LD (#5D0C),A
LD (#5D1F),A
DEC A
LD (#5D0E),A
LD A,#F4
LD (#5CB6),A
LD HL,S_SPEC
LD (#5D1A),HL
LD HL,0
ADD HL,SP
LD DE,-12
ADD HL,DE
LD (#5D1C),HL
LD A,0 ;0 В РЕГИСТР
LD C,#3F ;ДОРОЖКИ
CALL TO_WG93
LD A,#0A ;#A В РЕГИСТР
LD C,#5F ;СЕКТОРА
CALL TO_WG93
LD D,1
LD IX,16179
CALL TO_DOS ;ОПРЕДЕЛИЛИ #1F
;ТЕПЕРЬ ВОССТАНАВЛИВАЕМ СОДЕРЖИМОЕ
;РЕГИСТРОВ ДОРОЖКИ И СЕКТОРА:
RG_D LD A,0
LD C,#3F
CALL TO_WG93
RG_S LD A,0
LD C,#5F
CALL TO_WG93
;ВОССТАНАВЛИВАЕМ РАНЕЕ ЗАПОМНЕННОЕ
;СОДЕРЖИМОЕ ЯЧЕЕК:
ST1 LD A,0
LD (#5D0E),A
ST2 LD A,0
LD (#5D0C),A
ST3 LD A,0
LD (#5CB6),A
ST4 LD A,0
LD (#5D1F),A
ST5 LD A,0
LD (#5C3A),A
ST6 LD A,0
LD (#5D17),A
ST7 LD HL,0
LD (#5D1A),HL
ST8 LD HL,0
LD (#5D1C),HL
ST9 LD HL,0
LD (#5CF8),HL
LD A,B
RET
;СЮДА БУДЕТ ПЕРЕДАНО УПРАВЛЕНИЕ, ЕСЛИ
;0-Й БИТ РЕГИСТРА СОСТОЯНИЙ РАВЕН 1:
S_SPEC POP BC ;СОДЕРЖИМОЕ ПОРТА
LD HL,(#5D1C)
LD DE,12 ;ВОССТАНАВЛИВАЕМ
ADD HL,DE ;УКАЗАТЕЛЬ
LD SP,HL ;СТЕКА
JR RG_D
* * *
2