;Дизассемблер ide_tune.com от 11.9.1999
ORG #5DC0
LD C,#A0 ;неизвестно
для чего это
NOP
JR BEGIN
EXT DEFM "blk" ;расширение
для потенциального драйвера
DEFM "UnCo" ;вектор Unicolor
DEFB 8 ;8
цветов
L5DCD DEFW #0106
L5DCF DEFW #0738
L5DD1 DEFW #0102
L5DD3 DEFW #0105
;Работаем с драйвером на диске. Надо загрузить кусок
драйвера в память. На имя драйвера указывает HL. Путь к файлу уже открыт рестартом #43
DISK LD C,#34 ;открываем
файл по имени в HL
RST #10
RET C ;на выходе в HL описатель файла
LD BC,8 ;+8 - расширение
ADD HL,BC
;Проверка на расширение файла blk
LD DE,EXT ;расширение blk
LD B,3 ;3 символа
DISK1 LD A,(DE)
CP (HL) ;сравниваем
JR NZ,NOIDE ;не
совпало, выходим с сообщением, что указанный файл не является
;IDE-драйвером
INC HL
INC DE
DJNZ DISK1 ;пока не проверим все 3 символа
;Загружаем кусок драйвера на виртуальный диск
LD DE,0 ;блок 0 драйвера
LD C,#2D ;читаем
на виртуальный диск в памяти
RST #10
RET C
EXX ;HL-адрес прочитанного блока в памяти
JR VERIF ;переход на проверку
принадлежности драйвера к IDE-драйверам
;Анализируем командную строку на наличие ключа и имени
драйвера
BEGIN LD C,#43
RST #10
RET C
JR Z,BEGIN1 ;что-то
нашли (ключ или путь с именем драйвера)
LD A,77 ;если ни ключа ни имени драйвера
нет, то
SCF ;выходим
с ошибкой 77
RET NZ
BEGIN1 OR A
JR Z,BEGIN2 ;нашли
имя драйвера
LD (BEGIN3+1),A ;нашли ключ
JR BEGIN ;проверяем дальше, после
ключа должно быть имя драйвера
BEGIN2 EXX ;в
HL имя драйвера
BEGIN3 LD A,0 ;проверка,
имя драйвера было само по
OR A ;себе или после ключа
JR Z,DISK ;само
по себе, значит работаем с драйвером на диске
;Работаем с драйвером в памяти (после ключа). Запускаем
поиск драйвера в памяти по имени
LD BC,#0851 ;8 символов
LD A,#F8 ;поиск
с канала #F8
RST #10
RET C ;если нет такого драйвера, то
выход
EXX ;HL-тело канала драйвера
INC HL ;по смещению +4 лежит
адрес загрузки
INC HL ;драйвера
INC HL
INC HL ;+4 от начала канала
LD E,(HL)
INC HL
LD D,(HL)
EX DE,HL ;HL-адрес загрузки драйвера
;Проверяем драйвер с начальным адресом в HL на принадлежность к IDE-драйверу
VERIF LD BC,9 ;+9
от начала - регистр состояния DRCSR
ADD HL,BC
LD A,(HL)
AND #7F ;бит 7 регистра игнорируем
CP 4 ;должно
быть 4 - не TR-DOS драйвер
JR NZ,NOIDE ;если
не так, то выход с ошибкой
INC HL
INC HL
INC HL ;+12
номер версии TR-DOS
LD A,(HL)
CP #FC ;должен быть #FC
JR NZ,NOIDE ;ошибка
INC HL
INC HL ;+14 - адрес буфера
драйвера
LD A,(HL) ;должно
быть #0000
INC HL
OR (HL)
JR Z,MOVE ;если
так, то драйвер опознан
;Текущий драйвер не является IDE-драйвером, о чем и сообщаем пользователю
NOIDE LD HL,(L5DD1) ;переносим цвета из вектора Unicolor
LD (ERR_W+4),HL ;в вектор окна с сообщением
об ошибке
LD IX,ERR_W ;выводим окно
XOR A
LD C,#61
RST #10
LD C,#66 ;печатаем сообщение об ошибке
RST #10
LD C,8 ;ждем отпускания клавиши,
если она
RST #10 ;была
нажата
DEC C ;ждем нажатия любой клавиши
RST #10
;Выход из программы
QUIT XOR A
LD C,#F4
RET
;Переносим кусок драйвера, который будем изменять, в память
MOVE INC HL ;со
смещения +16 от начала драйвера
LD (SAVE_M+1),HL ;с этого места потом будем
сохранять
LD DE,BUFER ;переносим
в буфер
LD BC,22 ;22 байта
LDIR
;Делаем идентификацию винчестера
LD HL,I_BUF ;выделяем буфер
для идентификационного блока (256 байт)
CALL IDENT ;идентификация
JR NC,INFO ;если
прошла успешно, то переход к выводу окна с информацией о винте
;Идентификация по каким-то причинам не прошла, выдаем
сообщение об ошибке, но работа программы продолжается, это не фатальная ошибка
LD HL,0 ;задаем позицию печати
сообщения 0,0
LD C,#0C
RST #10
LD HL,N_PORT ;печатаем строку с
сообщением, что порты
LD C,#6C ;винчестера
не удалось прочитать
RST #10
JR MENU ;переходим сразу к меню без
вывода окна с информацией о винте
;Выводим окно с информацией о винчестере Для этого берем
информацию из идентификационного блока и переносим ее в текст окна
INFO LD DE,(I_BUF+7) ;кол-во головок
LD HL,L61C7 ;место в тексте
окна
CALL TRANS ;переводим в строку символов
LD DE,(I_BUF+13) ;количество секторов
LD HL,L61D0
CALL TRANS
LD HL,(I_BUF+2) ;количество
цилиндров
LD E,H ;переводим
число в строку символов
LD D,L
LD HL,L61D9
XOR A
CALL TRANS1
LD HL,I_BUF+20 ;серийный номер
винчестера
LD DE,L61DE
LD BC,10
LDIR
INC DE
LD HL,I_BUF+46 ;микропрограммное
изменение
LD C,8
LDIR
INC DE
LD B,42 ;номер модели. Тут ошибка!
Длина блока
INFO0 LD A,(HL) ;не 42
байта, а 40!!!
INC HL ;Переносим, пока не
встретится байт 0
CP #20
JR C,INFO1
LD (DE),A
INC DE
DJNZ INFO0
INFO1 LD IX,INFO_W ;Выводим на экран окно с характерис-
LD HL,(L5DD3) ;тиками
винчестера
LD (INFO_W+4),HL ;Переносим цвета в вектор
окна
XOR A
LD C,#61
RST #10
LD C,#66 ;Печать текста в окне
RST #10
;Подготовка к выводу меню на экран и само меню
MENU LD HL,(L5DCD) ;Переносим цвета меню
LD (MENU_W+4),HL
LD HL,(L5DCF) ;И цвета курсоров
LD A,L
LD (MENU_C),A
LD A,H
LD (MENU_C-2),A
LD IX,MENU_W ;Открываем окно меню
LD A,2
LD C,#61
RST #10
LD C,#91 ;И заходим в само меню
RST #10
RET C
JP QUIT ;После выхода из меню
выходим из программы
;Таблица параметров меню
DEFB 0 ;цвет
рабочего курсора
DEFB 0
MENU_C DEFB 0 ;цвет
курсора
DEFB 1 ;начальная
позиция курсора
DEFW INIT ;процедура инициализации
DEFW 0
DEFW TABKEY ;таблица обработки "горячих
клавиш"
DEFW TABENT ;таблица обработки нажатий на Enter
MENU_W DEFW #0601 ;вектор
окна меню
DEFW #0E0F
DEFB 7 ;цвета
окна меню
DEFB 1
DEFW #0E03
DEFB 1,1,1 ;карта
перемещений курсора по
DEFB 0 ;строкам
меню
DEFB 1,1,1,1,1,1,1,1
DEFB 1
DEFM "Hd:ٱ" ;Текст меню (здесь
и далее символ "ٱ" означает пробел)
L5F09 DEFM "ٱ123"
DEFB #0D
DEFM "Sc:ٱ"
L5F12 DEFM "ٱ123"
DEFB #0D
DEFM "Tr:ٱ"
L5F1B DEFM "ٱ123"
DEFB #0D
DEFM "ٱٱٱٱTrkٱٱٱSize"
DEFM "A:ٱ"
L5F31 DEFM "4096ٱٱ"
L5F37 DEFM "ٱٱٱٱٱ"
DEFM "B:ٱ4096ٱٱٱٱٱٱٱ"
DEFM "C:ٱ4096ٱٱٱٱٱٱٱ"
DEFM "D:ٱ4096ٱٱٱٱٱٱٱ"
DEFM "E:ٱ4096ٱٱٱٱٱٱٱ"
DEFM "F:ٱ4096ٱٱٱٱٱٱٱ"
DEFM "G:ٱ4096ٱٱٱٱٱٱٱ"
DEFM "H:ٱ4096ٱٱٱٱٱٱٱ"
DEFM "SAVE"
DEFB 3
;Таблица обработки нажатий на Enter на строках меню
TABENT DEFW SET_HD ;Установка кол-ва
головок
DEFW SET_HD ;Установка
кол-ва секторов
DEFW SET_CL ;Установка
кол-ва цилиндров
DEFW 0
DEFW SET_TR ;Установка
начальных треков устройств
DEFW SET_TR
DEFW SET_TR
DEFW SET_TR
DEFW SET_TR
DEFW SET_TR
DEFW SET_TR
DEFW SET_TR
DEFW SAVE ;Сохранение настроек
;Таблица адресов обработки "горячих клавиш"
TABKEY DEFB #73 ;"s"-Save
DEFB #0D ;активизируем выполнение нажатия
курсором
;на строку 13, где расположена
команда "SAVE"
DEFB #00 ;признак
эмуляции нажатия курсором
DEFB #20 ;Space
DEFW Q_MENU ;по
нажатию на Space выходим из меню
DEFB #FF ;конец таблицы
;Обработчик выхода из меню
Q_MENU OR #FF ;для выхода из меню
устанавливаем код #FF и
RET ;сбрасываем
флаг С
;Подпрограмма преобразования числа DE в строку HL. Число на входе ограничивается размером 0-255. Через
точку входа TRANS1 можно преобразовывать число в
пределах 0-65535
TRANS XOR A
LD D,A ;ограничиваем
входное число 0-255
TRANS1 LD A,4 ;длина
выходной строки 4 байта
LD BC,#0A7C ;переводим в десятичной
системе
RST #10
RET
;Процедура инициализации меню. Включает в себя
отображение в меню параметров драйвера и подсчет размеров устройств в
зависимости от номеров треков устройств
;Отображаем количество головок, секторов и цилиндров из тела
драйвера
INIT LD DE,(BUFER) ;D-кол-во головок, E-кол-во секторов
PUSH DE ;вычисляем произведение
LD B,D ;HEAD*SEC*2
LD D,0
LD H,D
LD L,D
L5FDA ADD HL,DE ;HL=HEAD*SEC
DJNZ L5FDA
ADD HL,HL ;HL=HEAD*SEC*2
LD (BUFER+18),HL ;сохраняем
по смещению +34 драйвера
POP DE ;переводим количество
головок в строку
LD HL,L5F09
CALL TRANS
LD DE,(BUFER+1) ;переводим
кол-во секторов в строку
LD HL,L5F12
CALL TRANS
LD DE,(BUFER+20) ;переводим
кол-во треков в строку
LD HL,L5F1B
XOR A
CALL TRANS1
;Отображаем в меню начальные треки устройств
LD HL,BUFER+2 ;ссылка
на адрес начального трека А
LD DE,L5F31 ;позиция
текста в меню для трека А
LD B,8 ;8 устройств
L6005 PUSH DE
LD E,(HL)
INC HL
LD D,(HL) ;номер
трека устройства А в DE
INC HL
XOR A ;переводим число в строку
LD A,4
EX (SP),HL ;HL-адрес текста с треком устройства
PUSH BC ;в меню
LD BC,#0A7C
RST #10
LD BC,14 ;переходим на следующую
строку меню
ADD HL,BC
POP BC ;восстанавливаем счетчик
EX (SP),HL
POP DE
DJNZ L6005
;Тут расположена процедура подсчета размеров устройств в
зависимости от номеров их треков.
LD HL,BUFER+2
LD A,8
LD DE,L5F37
L6024 PUSH AF
PUSH HL
PUSH DE
LD DE,#FFFF
LD (L6044+1),DE
LD C,(HL)
INC HL
LD B,(HL)
INC HL
LD A,8
LD HL,BUFER+2
L6037 LD E,(HL)
INC HL
LD D,(HL)
INC HL
EX DE,HL
OR A
SBC HL,BC
JR C,L6050
JR Z,L6050
PUSH DE
L6044 LD DE,#FFFF
SBC HL,DE
ADD HL,DE
POP DE
JR NC,L6050
LD (L6044+1),HL
L6050 ADD HL,BC
EX DE,HL
DEC A
JR NZ,L6037
LD DE,(L6044+1)
LD A,D
AND E
INC A
JR NZ,L6064
LD HL,(BUFER+20)
SBC HL,BC
EX DE,HL
L6064 LD BC,(BUFER+18)
XOR A
SBC HL,HL
L606B ADD HL,DE
JR C,L608D
DEC BC
LD A,C
OR B
JR NZ,L606B
EX DE,HL
L6074 LD A,E
AND #F8
LD E,A
XOR A
LD A,5
LD BC,#0A7C
POP HL
RST #10
LD DE,14
ADD HL,DE
EX DE,HL
POP HL
INC HL
INC HL
POP AF
DEC A
JR NZ,L6024
RET
L608D LD DE,#FFF8
JR L6074
;Процедура установки номеров треков устройств
SET_TR LD A,(IX-9) ;позиция
курсора (для устройств это 5-12)
ADD A,A ;умножаем
на 2
LD B,0
LD C,A
LD HL,BUFER-8
ADD HL,BC ;вычисляем
указатель на номер трека устройства в драйвере
LD E,(HL)
INC HL
LD D,(HL) ;DE-номер трека устройства
EX DE,HL
PUSH DE
LD D,(IX-9) ;устанавливаем
координаты для редактирования
LD E,3
LD C,#88 ;редактируем номер трека
LD A,H ;номер
должен быть не более 4095
AND #0F
LD H,A
LD A,4
RST #10
EXX
POP DE
JR C,SET_TR ;если ввели
неправильный номер
RET NZ ;если был выход по
спецклавише
EX DE,HL ;DE-новое число
LD A,D ;проверка
на число >4095
AND #F0
JR NZ,SET_TR ;если так, то ввод
числа снова
LD (HL),D ;заносим
число в драйвер
DEC HL
L60BD LD (HL),E
L60BE XOR A ;выход в меню
INC A
RET
;Установка количества головок и секторов в драйвере
SET_HD LD C,(IX-9) ;позиция
в меню (1 или 2)
LD B,0
LD HL,BUFER-1
ADD HL,BC
LD E,(HL) ;количество
головок или секторов
LD D,0
EX DE,HL
PUSH DE
LD D,C ;координаты
для ввода
LD E,5
LD A,3
LD C,#88
RST #10 ;редактируем
число
EXX
POP DE
JR C,SET_HD
RET NZ ;если был выход по
спецклавише
EX DE,HL ;проверка
на число>255
LD A,D
OR A
JR NZ,SET_HD ;если число
было>255, снова вводим
JR L60BD ;выход
в меню
;Установка количества цилиндров в драйвере
SET_CL LD HL,(BUFER+20) ;берем
количество треков
LD DE,#0304 ;устанавливаем координаты
для редактирования
LD A,4
LD C,#88
RST #10 ;редактируем
число
EXX
JR C,SET_CL ;если была ошибка
при вводе числа
RET NZ ;если был выход по
спецклавише
LD (BUFER+20),HL ;заносим
кол-во цилиндров в драйвер
JR L60BE ;выход
в меню
;Процедура сохранения настроек в драйвере
SAVE LD A,(BEGIN3+1) ;проверка, драйвер
был на диске или
OR A ;в
памяти
JR NZ,SAVE_M ;драйвер в памяти
;Сохранение настроек на диск
LD IX,BUFER ;буфер,
где расположен кусок драйвера
LD DE,22 ;22 байта сохраняем
XOR A
LD HL,16 ;записываем в драйвер с
байта 16
LD C,#2A ;непосредственно
запись
RST #10
RET C
LD HL,CALC ;считаем
контрольную сумму измененного
LD C,#48 ;файла с помощью резидента calc.res
RST #10
JR NC,FLUSH ;если
резидент был найден и все ОК.
CP 37 ;если
не было резидента, то просто оставим драйвер с непосчитанной КС
;и выйдем, сделав flush
SCF ;при
любой другой ошибке выходим в оболочку
RET NZ ;с ошибкой
;Делаем flush,
так как кэш мог быть изменен.
FLUSH LD C,#02
RST #10
RET
;Сохранение изменений в драйвере в памяти
SAVE_M LD DE,0 ;сюда записывается адес
драйвера в памяти со смещением +16 от начала.
LD HL,BUFER ;буфер,
где лежит измененный кусок драйвера
LD BC,22 ;22 байта
LDIR ;сохраняем
RET
CALC DEFM "@calc" ;строка
для активации резидента calc.res
DEFB #0D
;Процедура идентификации винчестера
;На входе в HL
должен быть адрес буфера, куда будет записываться идентификационный блок винчестера
(256 байт - половина блока)
;На выходе: NC-ОК,
C-ошибка при чтении портов винчестера
IDENT LD A,#A0 ;SDH-reg.
маска для устройства MASTER
LD BC,#FFD0 ;B=#FF - счётчик, C=#D0 - SDH-reg.
OUT
(C),A ;заносим маску в SDH-reg.
LD A,#0C ;значение для программного сброса HDD
(SRST=1)
LD C,#C8 ;Fixed disk register
OUT
(C),A ;сброс винчестера
DJNZ
$ ;выдерживаем паузу
DEC B ;B=#FF
LD A,#08 ;SRST=0,
снимаем сигнал сброса
OUT (C),A
L0 LD A,#FF
IN A,(#F0) ;читаем Status reg.
RLCA ;BSY
переносим в флаг CY
JR C,L0 ;если BSY активен,
то ждём
AND
#FB ;маска
CP
#A0 ;проверка на корректное завершение
сброса
SCF
RET NZ ;если были ошибки, то выход с флагом C
LD A,#EC ;команда Identify drive
LD C,#F0
OUT (C),A ;заносим в
Command register
LD BC,#8011 ;B=#80 - 128 слов по 2 байта - 256
байт
LD DE,#0000 ;счётчик
L1 LD A,#FF
IN A,(#F0) ;читаем Status reg.
BIT
3,A ;проверка состояния DRQ
JR NZ,L2 ;если накопитель готов, то переход
DEC DE ;уменьшаем значение счётчика
LD A,E
OR D ;проверка на 0
JR NZ,L1 ;ещё один цикл проверки готовности
накопителя
SCF ;выход
с установленным C - ошибка
RET
;Непосредственно
чтение идентификационного блока. В идентификационном блоке байты перепутаны,
поэтому читаем байт +1, затем +0
L2 INC HL ;байт
+1
LD A,#FF
IN A,(#10) ;читаем значение байта
LD (HL),A
DEC HL ;байт
+0
INI ;читаем
значение, HL=HL+1, B=B-1
INC HL ;байт
+1
JR NZ,L2 ;если B≠0, то
читаем ещё два байта
;256
байт прочитано, остальные байты из буфера винчестера читаем
"вхолостую"
L3 LD A,#FF
IN A,(#10)
LD A,#FF
IN A,(#F0)
BIT
3,A ;проверяем DRQ
JR NZ,L3 ;если буфер не пуст, то читаем снова
RRCA ;признак
ошибки винчестера сдвигаем в CY, т.е. если была ошибка,
;то флаг C установится
RET
;Окно с сообщением об ошибке IDE-драйвера
ERR_W DEFW #1401
DEFW #0E03
DEFB 7
DEFB 1
DEFW #0E03
DEFM "Not
IDE-driver"
;Строка с сообщением, что порты прочитать не удалось
N_PORT DEFM "Порты винта прочитать не
удалось"
DEFB #0D
;Окно с информацией о параметрах винчестера
INFO_W DEFW #0610
DEFW #0E0A
DEFB 5
DEFB 1
DEFW #0E17
DEFM "Hd:ٱ"
L61C7 DEFM "ٱ123"
DEFB #0D
DEFM "Sc:ٱ"
L61D0 DEFM "ٱ123"
DEFB #0D
DEFM "Tr:ٱ"
L61D9 DEFM "ٱ123"
DEFB #0D
L61DE DEFS 10
DEFB #0D
DEFS 8
DEFB #0D
DEFM "ٱٱٱٱٱٱٱٱٱٱ"
DEFM "ٱٱٱٱٱٱٱٱٱٱ"
DEFM "ٱٱٱٱٱٱٱٱٱٱ"
DEFM "ٱٱٱٱٱٱٱٱٱٱ"
DEFM "ٱٱٱٱٱٱٱٱٱٱ"
DEFB 3
;Тут конец программы. Буфера для данных располагаются уже
после тела программы.
BUFER
I_BUF EQU BUFER+44