ide_tune.com
;Дизассемблер 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