; Последняя редакция: 9.03.2007 ; ; метки ## - не ясные места (закомментарино) ; метки @@ - замена ориг. кода ; ; буфер D2E7C или T0400 также исп. для ввода/вывода файловых операций ? ; Примечания по ДОС-у ; ; Выравнивание кода на границу происходит в двух местах: 0100h и 0900h ; (есть немного лишнего места). ; ; ; Добавления: ; ~~~~~~~~~~~ ; Появилась новая функция #08 DSS_RESCAN (Пересканировать девайсы системы). ; ; Функция #00 (версия ДОС) дополн. возвращает в BC номер билда (0..999). ; ; Добавлен код обслуживания курсора (на прерываниях) и регистрация в системе ; знакогенераторов курсора с номерами 1Ah/19h (черта/блок). Функция #32 дора- ; ботана под новый курсор, а также не выводит ascii-код #00 (от курс. клавиш ; и т.д.). Переключение формы курсора клавишей "Ins". ; ; В функции #5F (символ на принтер) добавлено отслеживание байта состояния ; принтера (7..3 биты). При ошибке, функция возвращает байт состояния, а не ; печатаемый символ, как в фирменной версии. ; ; ;Добавлена функция #0C (tmp_filename) ; ; ; ; Исправления: ; ~~~~~~~~~~~~ ; 1) В отличии от оригинала, функции 0Ah/0Bh (Create file/New create file) ; перед созданием файла проверяют на переполнение таблицу свободных ; дескрипторов. ; 2) Убрано фирменное ограничение макс. длины строки переменной окружения ; в 32 символа и некорректная отработка функции #46 (в командах "path", ; "set"). Теперь макс. длина строки 255 символов. ; ; 3) Исправлена фирменная ошибка, при которой происходило зависание ; системы (непредсказуемое поведение) при превышении макс. числа ; открытых дескрипторов (функции search_handle, release_handle). ; ; 4) Исправлена фирменная ошибка, из-за которой в операциях с файлами не ; отслеживался атрибут "системный". ; ; 5) Исправлено не отслеживание атрибута файла "r/o" в функции #0E (удаление ; файла). ; ; 6) Пофиксен глюк вывода списка файлов, если число файлов в списке ; превышало 509. Сейчас список выводится корректно и может содержать ; макс. 510 файлов. Если число файлов в каталоге превышает 510, то выдается ; код ошибки 35 "слишком много файлов" (для списка каталогов выдается ; код ошибки 7 "каталог не найден"). ; ; 7) Пофиксен глюк "PrintScreen", выдававший скен-код #C7 клавиши и ; устанавливавший бит LShift-a. Версия ДОС стала 1.61.9. ; ; ; ; ДОС выделяется блок из 3 банок (функ. Init_DOS), используемых в качестве ; банок расширения. ; Исп. лог. номеров банок: ; 0 - кэш списка каталога ; 1 - кэш FAT ; 2 - path-переменная (запуск файла) и др. переменные окружения, а также ; сохранение текст. экрана при переключении в граф. режим ; ;3 - страница структуры tsr-обработчиков (моя) ; ; ; ; ; include "dos.inc" org 0000h ;RST 00h L0000: jp Func_41 ; заглушка (завершить программу) D0003: db -1 ; D0=сигнал переполн. буфера клавы, D1=сигнал перекл. на альт.раскладку db -1 db -1 db -1 db -1 ;RST 08h, Вызов функций Биоса push af ld a,0 ; вкл. ПЗУ Биоса в 0-е окно out (7Ch),a pop af ret db -1 ;RST 10h jp A006C ; вектор ДОС-а db -1 db -1 db -1 db -1 db -1 ;RST 18h jp drv_devices ; вектор дисковых устройств db -1 db -1 db -1 db -1 db -1 ;RST 20h, свободный jp empty__ ; заглушка db -1 db -1 db -1 db -1 db -1 ;RST 28h, свободный jp empty__ ; заглушка db -1 db -1 db -1 db -1 db -1 ;RST 30h jp MOUSE_vector ; вектор мышки db -1 db -1 db -1 db -1 db -1 ;RST 38h jp $+3 push af ex af,af' push af push bc push de push hl exx push bc push de push hl push ix push iy call keyb_scan ; обработчик клавиатуры ld c,80h ; обработчик аппаратн. прерыв. мышки rst 30h call cursor_interrupt ; вектор обслуж. курсора pop iy pop ix pop hl pop de pop bc exx pop hl pop de pop bc pop af ex af,af' pop af ei reti db -1 ;,-1,-1,-1 ; на границу 0064h ;0064h retn db 0 ; 0066h (от немаск. прерывания в IM0) db 0 db 0 jp $-5 ;------------------------------------------------- ; ДОС-овый вектор ;------------------------------------------------- A006C: push hl ld l,c ; номер команды ld h,T0200 / 256 ; 0200h..02FFh массив мл.байтов адресов ld c,(hl) ; загр. мл.байт адреса inc h ; 0300h..03FFh массив ст.байтов адресов ld h,(hl) ; загр. ст.байт адреса ld l,c ; готовый адрес ex (sp),hl ; в стек и ret ; перейти на него ; Вектор обслуживания курсора cursor_interrupt: ld a,(curs_inv_flag) or a ret z ;di ;поставил db 3Eh ; ld a,.. curs_timer: db 1 ; пауза мигания dec a call z,cursor ld (curs_timer),a ret ; Начало boot-сектора T0076: ds 3 ; 3 байта, код перехода на загрузчик ; 8 байт, OEM ID db "DSS_" db major_version + "0" db "." db (minor_version / 10) + "0" db (minor_version % 10) + "0" ; BPB, 17 байт D0081: dw 512 ;+11 ; байтов на сектор D0083: db 2 ;+13 ; секторов на кластер dw 1 ;+14 ; зарезерв. секторов D0086: db 2 ;+16 ; число копий FAT-ов dw 112 ;+17 ; записей в корне dw 1440 ;+19 ; # всех секторов на диске db 0F0h ;+21 ; байт формата D008C: dw 2 ;+22 ; # секторов на FAT dw 9 ;+24 ; секторов на сторону D0090: dw 2 ;+26 ; кол-во сторон диска ; extended boot-record dw 0,0 ;+28,+30 ; скрытых секторов dw 0,0 ;+32,+34 ; всех секторов на диске dw 80h ;+36 ; 0x00 физ. номер диска db 29h ;+38 ; сигнатура расш. boot-записи dw 0,0 ;+39,+41 ; серийный номер диска db "NO NAME " T00AC: db "FAT16 " ;----------------------------------------------------------- ; Настройка знакогенератора курсора черточкой ;----------------------------------------------------------- setup_znak: in a,(0C2h) push af ; сохр. порт ld a,(list_dos_pages+2) ; 2-й лог. номер страницы расш. ДОС out (0C2h),a ; получить сист. знакоген. ld de,8000h ; буфер для 2048 байт данных push de ld c,0B8h ; получить знакоген. rst 08h ; заполнить кодом 0FFh 2 нижние линии ld hl,8000h+(2048-(2*256)) ; последние 512 байт ld bc,511 ld a,1Ah; ; номер знакоген. "черточка" call fill_data_font pop hl ; заполнить остальные 6 линий (полный блок) ld bc,2048-513 ld a,19h; ; номер знакоген. "блок" call fill_data_font pop af out (0C2h),a ; восст. порт ret ; Настройка знакоген. и его регистрация ; вход: a=номер знакоген. ; hl=данные ; bc=размер данных fill_data_font: ld e,l ld d,h ld (hl),-1 inc de ldir ld de,8000h ; знакоген. ld c,0B6h ; уст. знакоген. rst 08h ret ;ds 100h - $ ; выровнить на границу #0100 L0100 equ $+100h AND 0FF00h ds L0100 - $ ;0100h. Массив списка выдел. страниц list_pages: ds 256 ; Младшие разряды адресов функций T0200: db Init_DOS%256, Func_01%256, Func_02%256, Func_03%256 ; 00..03 db empty__%256, empty__%256, empty__%256, empty__%256 ; 04..07 db Func_08%256, Func_09%256, Func_0A%256, Func_0B%256 ; 08..0B db Func_0C%256, empty__%256, Func_0E%256, empty__%256 ; 0C..0F db Func_10%256, Func_11%256, Func_12%256, Func_13%256 ; 10..13 db Func_14%256, Func_15%256, Func_16%256, Func_17%256 ; 14..17 db Func_18%256, Func_19%256, Func_1A%256, Func_1B%256 ; 18..1B db Func_1C%256, Func_1D%256, Func_1E%256, empty__%256 ; 1C..1F db empty__%256, Func_21%256, Func_22%256, empty__%256 ; 20..23 db empty__%256, empty__%256, empty__%256, empty__%256 ; 24..27 db empty__%256, empty__%256, empty__%256, empty__%256 ; 28..2B db empty__%256, empty__%256, empty__%256, empty__%256 ; 2C..2F db Func_30%256, Func_31%256, Func_32%256, Func_33%256 ; 30..33 db empty__%256, Func_35%256, Func_36%256, Func_37%256 ; 34..37 db Func_38%256, Func_39%256, Func_3A%256, Func_3B%256 ; 38..3B db Func_3C%256, Func_3D%256, Func_3E%256, Func_3F%256 ; 3C..3F db Func_40%256, Func_41%256, Func_42%256, Func_43%256 ; 40..43 db Func_44%256, Func_45%256, Func_46%256, Func_47%256 ; 44..47 db empty__%256, empty__%256, empty__%256, empty__%256 ; 48..4B db empty__%256, empty__%256, empty__%256, empty__%256 ; 4C..4F db Func_50%256, Func_51%256, Func_52%256, Func_53%256 ; 50..53 db Func_54%256, Func_55%256, Func_56%256, Func_57%256 ; 54..57 db Func_58%256, Func_59%256, Func_5A%256, Func_5B%256 ; 58..5B db Func_5C%256, empty__%256, empty__%256, Func_5F%256 ; 5C..5F db empty__%256, empty__%256, empty__%256, empty__%256 ; 60..63 db empty__%256, empty__%256, empty__%256, empty__%256 ; 64..67 db A0000%256, A0000%256, A0000%256, A0000%256 ; 68..6B db A0000%256, A0000%256, A0000%256, A0000%256 ; 6C..6F db A0000%256, A0000%256, A0000%256, A0000%256 ; 70..73 db A0000%256, A0000%256, A0000%256, A0000%256 ; 74..77 db A0000%256, A0000%256, A0000%256, A0000%256 ; 78..7B db A0000%256, A0000%256, A0000%256, A0000%256 ; 7C..7F db A0000%256, A0000%256, A0000%256, A0000%256 ; 80..83 db A0000%256, A0000%256, A0000%256, A0000%256 ; 84..87 db A0000%256, A0000%256, A0000%256, A0000%256 ; 88..8B db A0000%256, A0000%256, A0000%256, A0000%256 ; 8C..8F db A0000%256, A0000%256, A0000%256, A0000%256 ; 90..93 db A0000%256, A0000%256, A0000%256, A0000%256 ; 94..97 db A0000%256, A0000%256, A0000%256, A0000%256 ; 98..9B db A0000%256, A0000%256, A0000%256, A0000%256 ; 9C..9F db A0000%256, A0000%256, A0000%256, A0000%256 ; A0..A3 db A0000%256, A0000%256, A0000%256, A0000%256 ; A4..A7 db A0000%256, A0000%256, A0000%256, A0000%256 ; A8..AB db A0000%256, A0000%256, A0000%256, A0000%256 ; AC..AF db A0000%256, A0000%256, A0000%256, A0000%256 ; B0..B3 db A0000%256, A0000%256, A0000%256, A0000%256 ; B4..B7 db A0000%256, A0000%256, A0000%256, A0000%256 ; B8..BB db A0000%256, A0000%256, A0000%256, A0000%256 ; BC..BF db A0000%256, A0000%256, A0000%256, A0000%256 ; C0..C3 db A0000%256, A0000%256, A0000%256, A0000%256 ; C4..C7 db A0000%256, A0000%256, A0000%256, A0000%256 ; C8..CB db A0000%256, A0000%256, A0000%256, A0000%256 ; CC..CF db A0000%256, A0000%256, A0000%256, A0000%256 ; D0..D3 db A0000%256, A0000%256, A0000%256, A0000%256 ; D4..D7 db A0000%256, A0000%256, A0000%256, A0000%256 ; D8..DB db A0000%256, A0000%256, A0000%256, A0000%256 ; DC..DF db A0000%256, A0000%256, A0000%256, A0000%256 ; E0..E3 db A0000%256, A0000%256, A0000%256, A0000%256 ; E4..E7 db A0000%256, A0000%256, A0000%256, A0000%256 ; E8..EB db A0000%256, A0000%256, A0000%256, A0000%256 ; EC..EF db empty__%256, empty__%256, empty__%256, empty__%256 ; F0..F3 db empty__%256, empty__%256, empty__%256, empty__%256 ; F4..F7 db empty__%256, empty__%256, empty__%256, empty__%256 ; F8..FB db empty__%256, empty__%256, empty__%256, empty__%256 ; FC..FF ;0300h. Старшие разряды адресов функций db Init_DOS/256, Func_01/256, Func_02/256, Func_03/256 ; 00..03 db empty__/256, empty__/256, empty__/256, empty__/256 ; 04..07 db Func_08/256, Func_09/256, Func_0A/256, Func_0B/256 ; 08..0B db Func_0C/256, empty__/256, Func_0E/256, empty__/256 ; 0C..0F db Func_10/256, Func_11/256, Func_12/256, Func_13/256 ; 10..13 db Func_14/256, Func_15/256, Func_16/256, Func_17/256 ; 14..17 db Func_18/256, Func_19/256, Func_1A/256, Func_1B/256 ; 18..1B db Func_1C/256, Func_1D/256, Func_1E/256, empty__/256 ; 1C..1F db empty__/256, Func_21/256, Func_22/256, empty__/256 ; 20..23 db empty__/256, empty__/256, empty__/256, empty__/256 ; 24..27 db empty__/256, empty__/256, empty__/256, empty__/256 ; 28..2B db empty__/256, empty__/256, empty__/256, empty__/256 ; 2C..2F db Func_30/256, Func_31/256, Func_32/256, Func_33/256 ; 30..33 db empty__/256, Func_35/256, Func_36/256, Func_37/256 ; 34..37 db Func_38/256, Func_39/256, Func_3A/256, Func_3B/256 ; 38..3B db Func_3C/256, Func_3D/256, Func_3E/256, Func_3F/256 ; 3C..3F db Func_40/256, Func_41/256, Func_42/256, Func_43/256 ; 40..43 db Func_44/256, Func_45/256, Func_46/256, Func_47/256 ; 44..47 db empty__/256, empty__/256, empty__/256, empty__/256 ; 48..4B db empty__/256, empty__/256, empty__/256, empty__/256 ; 4C..4F db Func_50/256, Func_51/256, Func_52/256, Func_53/256 ; 50..53 db Func_54/256, Func_55/256, Func_56/256, Func_57/256 ; 54..57 db Func_58/256, Func_59/256, Func_5A/256, Func_5B/256 ; 58..5B db Func_5C/256, empty__/256, empty__/256, Func_5F/256 ; 5C..5F db empty__/256, empty__/256, empty__/256, empty__/256 ; 60..63 db empty__/256, empty__/256, empty__/256, empty__/256 ; 64..67 db A0000/256, A0000/256, A0000/256, A0000/256 ; 68..6B db A0000/256, A0000/256, A0000/256, A0000/256 ; 6C..6F db A0000/256, A0000/256, A0000/256, A0000/256 ; 70..73 db A0000/256, A0000/256, A0000/256, A0000/256 ; 74..77 db A0000/256, A0000/256, A0000/256, A0000/256 ; 78..7B db A0000/256, A0000/256, A0000/256, A0000/256 ; 7C..7F db A0000/256, A0000/256, A0000/256, A0000/256 ; 80..83 db A0000/256, A0000/256, A0000/256, A0000/256 ; 84..87 db A0000/256, A0000/256, A0000/256, A0000/256 ; 88..8B db A0000/256, A0000/256, A0000/256, A0000/256 ; 8C..8F db A0000/256, A0000/256, A0000/256, A0000/256 ; 90..93 db A0000/256, A0000/256, A0000/256, A0000/256 ; 94..97 db A0000/256, A0000/256, A0000/256, A0000/256 ; 98..9B db A0000/256, A0000/256, A0000/256, A0000/256 ; 9C..9F db A0000/256, A0000/256, A0000/256, A0000/256 ; A0..A3 db A0000/256, A0000/256, A0000/256, A0000/256 ; A4..A7 db A0000/256, A0000/256, A0000/256, A0000/256 ; A8..AB db A0000/256, A0000/256, A0000/256, A0000/256 ; AC..AF db A0000/256, A0000/256, A0000/256, A0000/256 ; B0..B3 db A0000/256, A0000/256, A0000/256, A0000/256 ; B4..B7 db A0000/256, A0000/256, A0000/256, A0000/256 ; B8..BB db A0000/256, A0000/256, A0000/256, A0000/256 ; BC..BF db A0000/256, A0000/256, A0000/256, A0000/256 ; C0..C3 db A0000/256, A0000/256, A0000/256, A0000/256 ; C4..C7 db A0000/256, A0000/256, A0000/256, A0000/256 ; C8..CB db A0000/256, A0000/256, A0000/256, A0000/256 ; CC..CF db A0000/256, A0000/256, A0000/256, A0000/256 ; D0..D3 db A0000/256, A0000/256, A0000/256, A0000/256 ; D4..D7 db A0000/256, A0000/256, A0000/256, A0000/256 ; D8..DB db A0000/256, A0000/256, A0000/256, A0000/256 ; DC..DF db A0000/256, A0000/256, A0000/256, A0000/256 ; E0..E3 db A0000/256, A0000/256, A0000/256, A0000/256 ; E4..E7 db A0000/256, A0000/256, A0000/256, A0000/256 ; E8..EB db A0000/256, A0000/256, A0000/256, A0000/256 ; EC..EF db empty__/256, empty__/256, empty__/256, empty__/256 ; F0..F3 db empty__/256, empty__/256, empty__/256, empty__/256 ; F4..F7 db empty__/256, empty__/256, empty__/256, empty__/256 ; F8..FB db empty__/256, empty__/256, empty__/256, empty__/256 ; FC..FF ; буфер 512 байт T0400: db ". ",10h,0,0,0,0 ; тек. каталог ds 16 db ".. ",10h,0,0,0,0 ; родит. каталог ds 16 ds 448 ;T0600. Выровнить на границу xx00h include "keyb.asm" ; включает "init_DOS" ;///////////////////////////////////////////////////////////////////// ; Функция #56. Очистить окно. ; ; вход: D - строка левого верхнего угла окна ; E - столбец левого верхнего угла окна ; H - высота окна ; L - ширина окна ; A - символ заполнитель ; B - атрибут заполнитель ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_56:ld c,8Dh ; очистка экрана указ. символом rst 08h and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #5C. Вывод строки на экран. ; ; вход: HL - указатель на строку символов ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_5C:ld a,(hl) inc hl or a ret z call Func_5B ; вывод "a" на экран jr Func_5C ;///////////////////////////////////////////////////////////////////// ; Функция #5B. Вывод символа на экран в тек. позиции. ; ; вход: A - символ ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_5B: cp " " jr nc,A0DFC cp 0Dh ; в начало строки jr z,A0E20 cp 0Ah ; на след. строку jr z,A0E28 cp 9 ; Tab jr z,A0E0F cp 8 ; Backspace jr z,A0E03 A0DFC: push hl ld bc,0182h ; вывести один символ без атрибута rst 08h pop hl ret ; Backspace A0E03: ld c,8Eh ; узнать полож. курсора rst 08h xor a cp e jp z,Func_52 ; уст. полож. курсора dec e jp Func_52 ; уст. полож. курсора ; Tab A0E0F: ld c,8Eh ; узнать полож. курсора rst 08h ld a,e and 0F8h add a,8 ld e,a ; X полож. курсора jp Func_52 ; уст. полож. курсора ; 0Dh - в начало строки A0E20: ld c,8Eh ; узнать полож. курсора rst 08h ld e,0 jp Func_52 ; уст. полож. курсора ; 0Ah - на след. строку A0E28: ld c,8Eh ; узнать полож. курсора rst 08h ld a,d cp 31 jr nc,A0E35 inc d jp Func_52 ; уст. полож. курсора ; A0E35: push hl push de ld bc,018Ah ; скроллинг вверх ld de,0020h ; нач./число строк ei halt di rst 08h ld de,1F00h ; Y/X полож. нижней строки call Func_52 ; уст. полож. курсора ld a," " ; символ ld bc,5082h ; вывести 80 симв. rst 08h ei pop de call Func_52 ; уст. полож. курсора pop hl ret ;///////////////////////////////////////////////////////////////////// ; Функция #52. Установить положение курсора. ; ; вход: D - строка курсора ; E - колонка курсора ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_52:ld c,84h ; уст. полож. курсора rst 08h ret ;///////////////////////////////////////////////////////////////////// ; Функция #53. Узнать положение курсора. ; ; вход: нет ; выход: D - строка курсора ; E - колонка курсора ;///////////////////////////////////////////////////////////////////// Func_53:ld c,8Eh ; узнать полож. курсора rst 08h ret ;///////////////////////////////////////////////////////////////////// ; Функция #57. Прочитать символ с экрана. ; ; вход: D - строка ; E - колонка ; выход: A - символ ; B - атрибут ;///////////////////////////////////////////////////////////////////// Func_57:xor a ld c,0B4h rst 08h ld a,l ld b,h and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #58. Вывести символ на экран. ; Управляющие символы выводятся как обычные символы. ; ; вход: D - строка ; E - колонка ; A - символ ; B - атрибут ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_58:ld c,a push bc push de ld c,0B4h ; символ с экрана xor a rst 08h pop de pop hl ld c,0B5h ; символ на экран xor a rst 08h and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #59. Сохранить окно экрана. ; ; вход: D - строка ; E - колонка левого верхнего угла окна ; H - высота окна ; L - ширина окна ; B - страница буфера ; IX - адрес буфера ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_59:ld a,r ; во флаг P/V сост. триггера разреш. прерываний push af xor a di ld c,0B2h rst 08h pop af ; восст. флаг scf ccf ret po ; прерывания разрешены ei ret ;///////////////////////////////////////////////////////////////////// ; Функция #5A. Восстановить окно экрана. ; ; вход: D - строка ; E - колонка левого верхнего угла окна ; H - высота окна ; L - ширина окна ; B - страница буфера ; IX - адрес буфера ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_5A:ld a,r ; во флаг P/V сост. триггера разреш. прерываний push af xor a di ld c,0B3h rst 08h pop af scf ccf ret po ; прерывания разрешены ei ret ;///////////////////////////////////////////////////////////////////// ; Функция #55. Скроллинг экрана. ; ; вход: D - строка левого верхнего угла окна ; E - колонка левого верхнего угла окна ; H - высота окна ; L - ширина окна ; B = 1 - прокрутка вверх ; B = 2 - прокрутка вниз ; A = 0 - очищать строку ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_55:djnz A0EBA ld b,a ld c,h push bc push de push hl db 0DDh ld h,d db 0DDh ld l,e inc d dec h xor a ld c,0B7h ; перемещ. окна di rst 08h ei pop hl pop de pop bc xor a cp b ret nz ; не очищать строку ld a,d add a,h dec a ld d,a A0EAA: push de call Func_52 ; уст. полож. курсора ld a," " ld b,l ld c,82h rst 08h pop de call Func_52 ; уст. полож. курсора and a ret ; A0EBA: djnz A0EE0 ld b,a ld c,l push de push bc db 0DDh ld h,d db 0DDh ld l,e db 0DDh inc h dec h xor a ld c,0B7h di rst 08h ei pop hl pop de xor a cp b jr z,A0EAA ; очистить строку ret ; A0EE0: ld a,EINVFNC ; код "неверный номер функции" scf ret ;///////////////////////////////////////////////////////////////////// ; Функция #54. Выбрать активную страницу экрана. ; ; вход: B - страница экрана 0/1 ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_54:push bc ld a,(mode_screen) ; тек. режим экрана bit 7,a jr nz,A0EF0 ld c,a call A0F04 A0EF0: pop bc ld a,b and 1 out (0C9h),a ret ;///////////////////////////////////////////////////////////////////// ; Функция #51. Получить текущий режим экрана. ; ; вход: нет ; выход: A - текущий режим экрана ; B - страница экрана 0/1 ;///////////////////////////////////////////////////////////////////// Func_51:in a,(0C9h) ; страница экрана 0/1 ld b,a ld a,(mode_screen) ; тек. режим экрана and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #50. Выбор режима экрана. ; ; вход: A - режим экрана ; 02h - текстовый 40x32x16 цветов ; 03h - текстовый 80x32x16 цветов ; 81h - графический 320x256x256 цветов ; 82h - графический 640x256x16 цветов ; B - страница экрана 0/1 ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_50:bit 7,a ld c,a jr nz,A0F27 ; уст. граф. режимы A0F04: ld ix,A1080 ; точка выхода (восст. экран граф. режима) push ix ex af,af' ld a,(mode_screen) ; тек. режим экрана ld (A1081+1),a ex af,af' inc a ; a=0 dec a jr z,A0F21 dec a ; a=1 jr z,A0F21 dec a ; a=2 jr z,A0F3F dec a ; a=3 jr z,A0F67 A0F21: pop ix ; восст. баланс стека (заодно ix) ld a,EERR48 ; код "ошибка 48" scf ret ; Установка граф. режимов A0F27: call A1042 ; сохр. экран текст. режима and 7Fh jp z,A0F8F ; a=80h dec a ; a=81h jp z,A0F93 dec a ; a=82h jp z,A0FBA dec a ; a=83h jp z,A0FE1 ld a,EERR48 ; код "ошибка 48" scf ret ; Уст. текст. режим 40x32. A0F3F: push bc ; текстовое, 8 точек/знакоместо, #0B - номер знакоген. ld hl,T101A ; описатель окна (8 байт) ld a,b rlca rlca rlca rlca or b and 11h xor 10h ld e,a ; флаги окна call open_window pop bc ld a,c ld (mode_screen),a ; тек. режим экрана ld a,b and 1 out (0C9h),a ld a,(mode_screen) ; тек. режим экрана ld c,81h rst 30h ld a,0C0h out (89h),a xor a ret ; Уст. текст. режим 80x32. A0F67: push bc ; текстовое, 16 точек/знакоместо, #0B - номер знакоген. ld hl,T1012 ; описатель окна (8 байт) ld a,b rlca rlca rlca rlca or b and 11h xor 10h ld e,a ; флаги окна call open_window pop bc ld a,c ld (mode_screen),a ; тек. режим экрана ld a,b and 1 out (0C9h),a ld a,(mode_screen) ; тек. режим экрана ld c,81h ; режим экрана для мышки rst 30h ld a,0C0h ; закр. спек-экран out (89h),a xor a ret ; A0F8F: ld a,EERR48 ; код "ошибка 48" scf ret ; A0F93: push bc ; графическое, 8 точек/знакоместо, 0-й экран ld hl,T102A ; описатель окна (8 байт) ld e,11h ; флаги окна call open_window ; графическое, 8 точек/знакоместо, 1-й экран ld hl,T103A ; описатель окна (8 байт) ld e,0 ; флаги окна call open_window pop bc ld a,c ld (mode_screen),a ; тек. режим экрана ld a,b and 1 out (0C9h),a ld a,(mode_screen) ; тек. режим экрана ld c,81h rst 30h ld a,0C0h out (89h),a xor a ret A0FBA: push bc ; графическое, 16 точек/знакоместо, 0-й экран ld hl,T1022 ; описатель окна (8 байт) ld e,11h ; флаги окна call open_window ; графическое, 16 точек/знакоместо, 1-й экран ld hl,T1032 ; описатель окна (8 байт) ld e,0 ; флаги окна call open_window pop bc ld a,c ld (mode_screen),a ; тек. режим экрана ld a,b and 1 out (0C9h),a ld a,(mode_screen) ; тек. режим экрана ld c,81h rst 30h ld a,0C0h out (89h),a xor a ret A0FE1: ld a,EERR48 ; код "ошибка 48" scf ret ; тек. режим экрана mode_screen: db 3 ; 80x32x16 текстовый ;------------------------------------------------- ; Открыть окно ; вход: hl=описатель окна ; e=флаги окна ;------------------------------------------------- open_window: push de ld de,LFEE0 ; куда ld bc,32 ; размер описателя (8..31 зарез.) call A1001 ; скопир. описатель в сист. страницу pop de ld ix,LFEE0 ; описатель окна (8 байт) ld c,0B0h ; откр. окно rst 08h ld a,0C0h ; закр. спек-экран out (89h),a xor a ret ;----------------------------------------------------- ; Скопировать описатель окна в сист. страницу Биоса ; вход: hl=откуда ; de=куда ; bc=сколько ;----------------------------------------------------- A1001: ld a,r ; во флаг P/V сост. триггера разреш. прерываний in a,(0E2h) ex af,af' ; сохр. флаг ld a,0FEh ; страница переменных Биоса out (0E2h),a ldir ex af,af' ; восст. флаг out (0E2h),a ret po ; прерывания разрешены ei ret ;----------------------------------------------------------- ; Массив описателей окон ; ; флаги окна: ; bit4 = 1/0 - text/graf режим ; bit5 = 1/0 - 8/16 точек в знакоместе ; graf_mode bit3..0 - не исп. ; bit7..6 - номер палитры (номер экрана) ; text_mode bit7..6, 3..0 - номер знакогенератора ; исключение: bit7..6="11" -> бордер ;----------------------------------------------------------- ; 80x32. текстовое, 16 точек/знакоместо, #0B - номер знакоген. T1012: db 40 ;+0 X размер окна в знакоместах db 32 ;+1 Y размер окна в знакоместах db 0 ;+2 X полож. окна на экране db 0 ;+3 Y полож. окна на экране db 00011011b ;+4 режим знакоместа db 0 ;+5 доп. режим знакоместа (bit0=1 спек. адресация экрана) db 0 ;+6 X полож. в поле графики (в знакоместах) db 0 ;+7 Y полож. в поле графики (в знакоместах) ; 40x32. текстовое, 8 точек/знакоместо, #0B - номер знакоген. T101A: db 40,32 ; X/Y габариты db 0,0 db 00111011b ;+4 5,4, bit3..0 номер знакоген. db 0,0,0 ; графическое, 16 точек/знакоместо, 0-й экран T1022: db 40,32 ; X/Y габариты (в знакоместах) db 0,0 db 00000000b ;+4 db 0,0,0 ; графическое, 8 точек/знакоместо, 0-й экран T102A: db 40,32 ; X/Y габариты (в знакоместах) db 0,0 db 00100000b ;+4 5-й бит db 0,0,0 ; графическое, 16 точек/знакоместо, 1-й экран T1032: db 40,32 ; X/Y габариты (в знакоместах) db 0,0 db 01000000b ;+4 6-й бит db 0 db 40 ;+6 X полож. в поле графики (в знакоместах) db 0 ; графическое, 8 точек/знакоместо, 1-й экран T103A: db 40,32 ; X/Y габариты (в знакоместах) db 0,0 db 01100000b ;+4 6,5 биты db 0 db 40 ;+6 X полож. в поле графики (в знакоместах) db 0 ;-------------------------------------------------- ; Сохранить экран текст. режима. ; Для буфера экрана исп. 2-я банка расширения ДОС. ;-------------------------------------------------- A1042: push af ld a,(mode_screen) ; тек. режим экрана bit 7,a jr nz,A107E ; граф. режим sub 2 jr c,A107E ; меньше 02h push bc push de push hl push ix push af ld c,8Eh ; узнать полож. курсора rst 08h ld (A10A0+1),de pop af ; режим экрана ld ix,LC000 ; буфер ld de,0000h ; Y/X полож. ld hl,2050h ; Y/X размер (32x80) or a jr nz,$+4 ; 80x32 текст. режим ld l,40 ; X размер ld (A1090+1),hl ld a,(list_dos_pages+2) ; номер банки расширения ДОС ld b,a xor a ld c,0B2h ; с экрана в буфер di rst 08h ei pop ix pop hl pop de pop bc A107E: pop af ret ;------------------------------------------------- ; Восстановить экран граф. режима. ; Буфер экрана во 2-й банке расширения ДОС. ;------------------------------------------------- A1080: push af A1081: ld a,0 ; тек. режим экрана rlca ; 4 такта jr nc,A10AB ; текстовый push bc push de push hl push ix ld ix,LC000 ; буфер ld de,0000h ; Y/X полож. A1090: ld hl,2050h ; Y/X размер (32x80 или 32x40) ld a,(list_dos_pages+2) ; номер банки расширения ДОС ld b,a xor a ld c,0B3h ; из буфера на экран di rst 08h ei A10A0: ld de,0 ; Y/X полож. ld c,84h ; уст. курсор rst 08h pop ix pop hl pop de pop bc A10AB: pop af ret ;///////////////////////////////////////////////////////////////////// ; Функция #5F. Вывод символа на принтер без ожидания. ; ; Интерпретация байта состояния принтера: ; 0..2 - не используются, обычно уст. в "1" ; 3 - ошибка принтера - есть/нет (1/0) ; 4 - принтер подключен/не подключен (1/0) ; 5 - бумаги нет/есть (1/0) ; 6 - принтер готов/выводит очередной символ (1/0) ; 7 - принтер свободен/занят (1/0) ; ; вход: A - символ ; выход: B - символ ; CF - ошибка, A=байт состояния (биты 7..3) ;///////////////////////////////////////////////////////////////////// Func_5F:ld b,a ld a,r ; во флаг P/V сост. триггера разреш. прерываний ld a,b di push af ; сохр. флаг xor a out (1Bh),a ld a,10h out (1Bh),a xor a out (1Bh),a in a,(1Bh) ; порт состояния принтера ld c,a; bit 5,a ; 0/1 есть/нет бумага jr nz,A10CC ; нет бумаги and 11011000b; jr z,A10CC; ; ошиб. ситуация ld a,b out (1Ch),a ; символ в принтер pop af ; восст. флаг scf ccf ; сбр. CF ret po ; прерывания разрешены ei ret ; A10CC: pop af ld a,c; ; байт состояния scf ; уст. CF ret po ; прерывания разрешены ei ret ; Иниц. портов A10D1: di ld a,0CFh ld bc,001Fh ; порт out (c),a ld a,63h out (c),a ld a,0C0h out (1Eh),a ld a,0Fh out (1Dh),a ld a,0 out (19h),a ld a,0 out (19h),a ld a,5 out (19h),a ld a,62h out (19h),a ret ; Установить начальный кластер для чтения A10F6: ld hl,1 ld (A10FD+1),hl ret A10FD: ld hl,1 A1100: inc hl ; номер кластера call A1132 ; прочитать из кеша FAT-а номер след. кластера cp 0Ah scf ret z ; ошибка ? ld a,d or e jr nz,A1100 ld (A10FD+1),hl xor a ret A1111: push hl call A10FD pop de ret c push hl push hl ex de,hl ; hl=номер кластера A111A: call A1132 ; прочитать из кеша FAT-а номер след. кластера ex de,hl jr nc,A111A ; не конец цепочки ex de,hl pop de ; номер кластера call A11C4 ; записать в кеш FAT-а номер кластера pop hl ld de,(D150E) ; номер кластера call A11C4 ; записать в кеш FAT-а номер кластера call A128B ; подкл. банку кеша FAT и записать его на диск and a ret ;----------------------------------------------------------- ; Прочитать из кеша FAT-а номер след. кластера ; вход: hl=номер кластера ; выход: hl=номер кластера ; de=номер след. кластера ; CF - конец цепочки ;----------------------------------------------------------- A1132: ex de,hl ld hl,(D12FF) and a sbc hl,de ex de,hl ld a,0Ah ret c exx ld a,1 ; лог. номер дос-банки (кэш FAT-а) call set_dos_page ; подключить банку расширения ДОС exx push hl push af ; старая банка порта ld a,(D150B) cp "2" ; fat12 jr z,A1177 ; fat16, просто читать след. номер ld a,h ld b,a and 0Fh ld h,a ld a,b rrca rrca rrca rrca and 0Fh add hl,hl ld bc,(D12FD) cp c call nz,A125B ; прочитать в кеш 16 секторов FAT-а ld de,LC000 ; начало кеша FAT-а add hl,de ; на ячейку FAT ld e,(hl) ; прочитать номер кластера inc hl ld d,(hl) pop af out (0E2h),a ; восст. порт ld hl,0FFEFh ;and a ;@@ xor a; sbc hl,de ; проверка на служ. кластеры pop hl ;ld a,0 ret ; fat12 A1177: ld d,h ld e,l add hl,hl add hl,de rr h ; сдвиг вправо через CF rr l push af ; сохр. флаг ld a,h ld b,a and 1Fh ld h,a ld a,b rlca rlca rlca and 7 ld bc,(D12FD) cp c call nz,A125B ; прочитать в кеш 16 секторов FAT-а ld de,LC000 ; начало кеша FAT-а add hl,de ; на ячейку FAT pop af ; восст. флаг ld e,(hl) inc hl ld d,(hl) jr c,A11A3 ; номер не четный ld a,d and 0Fh ld d,a jr A11B7 ; A11A3: ld a,e and 0F0h ld e,a rr d ; вправо на 4 битa rr e rr d rr e rr d rr e rr d rr e A11B7: pop af ; восст. порт out (0E2h),a ld hl,0FEFh ;and a xor a; sbc hl,de ; проверка на служ. кластеры pop hl ;ld a,0 ret ;----------------------------------------------------------- ; Записать в кеш FAT-а номер кластера ; вход: de=номер кластера ; hl=номер первого кластера ? ; выход: ;hl=номер след. кластера ? ; de=номер кластера ;----------------------------------------------------------- A11C4: push de ex de,hl ld hl,(D12FF) and a sbc hl,de ex de,hl pop de ld a,0Ah ret c exx ld a,1 ; лог. номер дос-банки (кэш FAT-а) call set_dos_page ; подключить банку расширения ДОС exx push hl push af ; старая банка порта ld a,1 ld (D12FE),a ld a,(D150B) cp "2" ; fat12 jr z,A120B ; fat16, просто сохр. номер push de ld a,h ld b,a and 0Fh ld h,a ld a,b rrca rrca rrca rrca and 0Fh add hl,hl ld bc,(D12FD) cp c call nz,A125B ; прочитать в кеш 16 секторов FAT-а ld de,LC000 ; кеш FAT add hl,de ; на ячейку FAT pop de ld (hl),e ; сохр. в кеше FAT-а inc hl ; номер кластера ld (hl),d ; pop af ; восст. порт pop hl out (0E2h),a xor a ret ; fat12 A120B: push de ld d,h ld e,l add hl,hl add hl,de rr h rr l push af ; сохр. флаг ld a,h ld b,a and 1Fh ld h,a ld a,b rlca rlca rlca and 7 ld bc,(D12FD) cp c call nz,A125B ; прочитать в кеш 16 секторов FAT-а ld de,LC000 ; кеш FAT add hl,de pop af pop de jr c,A123E ; номер не четный ld (hl),e inc hl ld a,(hl) and 0F0h or d ld (hl),a pop af ; восст. порт pop hl out (0E2h),a and a ret ; A123E: sla e ; влево на 4 битa rl d rl e rl d rl e rl d rl e rl d ld a,(hl) and 0Fh or e ld (hl),a ; сохр. в кеше FAT-а inc hl ; номер кластера ld (hl),d ; pop af ; восст. порт pop hl out (0E2h),a and a ret ; Прочитать в кеш 16 секторов FAT-а ; вход: a=.. ? A125B: push hl push af ld a,(D12FE) or a call nz,A129A ; запись кеша (всего ?) FAT-а на диск pop af ld l,a ld h,0 ld (D12FD),hl add hl,hl ;1+1=2 add hl,hl ;2+2=4 add hl,hl ;4+4=8 add hl,hl ;8+8=16 ld de,(D14FC) add hl,de ex de,hl ld ix,0 add ix,de ; номер лог. сектора ld hl,0 ; ст. разряд ld de,LC000 ; куда (кеш FAT) ld a,(disk) ; номер диска ld b,16 ; число секторов ld c,5 ; чтение секторов rst 18h pop hl ret ; Подключить банку кеша FAT и записать его на диск A128B: exx ld a,1 ; лог. номер дос-банки (кэш FAT-а) call set_dos_page ; подключить банку расширения ДОС exx push af ; старая банка порта call A129A ; запись кеша (всего ?) FAT-а на диск pop af out (0E2h),a ; восст. порт ret ; Запись кеша (всего ?) FAT-а на диск A129A: ld hl,(D12FD) ld h,0 ld (D12FD),hl add hl,hl ;1+1=2 add hl,hl ;2+2=4 add hl,hl ;4+4=8 add hl,hl ;8+8=16 push hl ld b,h ld c,l ld de,16 add hl,de ld de,(D008C) ; секторов на FAT ld a,16 ; число секторов and a sbc hl,de jr c,A12C3 ex de,hl ld hl,16 sbc hl,de jr c,A12FA ld a,l A12C3: ld h,b ld l,c ld de,(D14FC) add hl,de ex de,hl ld ix,0 add ix,de ; номер лог. сектора ld hl,0 ; ст. разряд ld de,LC000 ; откуда (кеш FAT) ld b,a ; число секторов ld c,6 ; запись секторов ld a,(disk) ; номер диска push bc rst 18h pop bc ; b=число секторов pop hl ld de,(D14FE) add hl,de ex de,hl ld ix,0 add ix,de ; номер лог. сектора ld de,LC000 ; откуда (кеш FAT) ld hl,0 ; ст. разряд ld a,(disk) ; номер диска ld c,6 ; запись секторов rst 18h ret ; A12FA: pop hl scf ret D12FD: db 0 D12FE: db 0 D12FF: dw 0FF0h ; макс. число кластеров FAT12 (без служ.) ;///////////////////////////////////////////////////////////////////// ; Функция #00. Версия ДОС. ; Возвращает номер версии дисковой системы. ; вход: нет ; выход: DE=номер версии/модификации ; BC=номер билда (0..999) ;///////////////////////////////////////////////////////////////////// Func_00:xor a ld de,(major_version SHL 8) + minor_version ; 1.61 версия ДОС ld bc,build_version ; номер билда ld h,a ld l,a ret ;///////////////////////////////////////////////////////////////////// ; Функция #01. Смена текущего диска. ; ; вход: A - номер диска (0=A,1=B,..) ; выход: A - макс. номер диска, если CF=0 ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_01:push af ; номер девайса ld c,1 ; открыть девайс rst 18h pop bc jr c,A1323 ; ошибка ld a,b ld (disk),a ; номер тек. диска call A1370 ret c ld a,(last_drive) ; номер послед. диска and a ret ; A1323: cp EINVDRV ; код "неверный номер устройства" scf ret z ld a,ENORDY ; код "нет готовности" ret ;///////////////////////////////////////////////////////////////////// ; Функция #02. Номер текущего диска. ; ; вход: нет ; выход: A - номер диска (0=A,1=B,..) ;///////////////////////////////////////////////////////////////////// Func_02:ld a,(disk) and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #03. Информация о диске. ; Возвращает информацию об общем и свободном пространстве дискового ; устройства. ; ; вход: A - номер диска (0=A,1=B,..0FFh-текущий) ; выход: A - размер кластера в секторах, если CF=0 ; HL - общее кол-во кластеров ; DE - свободных кластеров ; BC - размер сектора в байтах ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_03:inc a jr z,A1338 dec a call Func_01 ; смена текущего диска ret c A1338: ld hl,2 ; номер кластера ld bc,0 A133E: push bc call A1132 ; прочитать из кеша FAT-а номер след. кластера pop bc cp 0Ah jr z,A1353 ; ошибка ? xor a cp e jr nz,A134F cp d jr nz,A134F inc bc A134F: inc hl jr A133E ; A1353: ld d,b ; свободных кластеров ld e,c ld hl,(D12FF) ; общее кол-во кластеров dec hl ld bc,(D0081) ; байтов на сектор (512) ld a,(D0083) ; секторов на кластер and a ret ; Номер последнего диска в системе last_drive: db 2 ; "B" диск ; список дисковых устройств ? ds 5 ; нет обращения L1368: ld a,(disk) ; номер диска ld c,3 ; проверка смены носителя в девайсе rst 18h ; всегда выдает "менялся" or a ret z ; не менялся ; A1370: ld c,0E2h in b,(c) push bc in a,(82h) out (0E2h),a ld de,LC400 ; буфер ld a,(disk) ; номер диска ld c,4 ; прочитать BPB rst 18h pop bc out (c),b ; восст. порт jp c,A14F0 ; ошибка (нет готовности) push iy ld de,0AA55h ; сигнатура ld hl,(T0400+510) and a sbc hl,de jp nz,A14EA ; ошибка "не известный формат" ld hl,T0400 ; откуда ld de,T0076 ; куда ld bc,62 ldir ld iy,T0076 ; структура boot-сектора ld a,(iy+21) cp 0F0h ; байт формата jp c,A14EA ld hl,0 ld e,(iy+14) ; de=зарезерв. секторов ld d,(iy+15) add hl,de ld (D14FC),hl ld (D14FC),hl ld (D14FE),hl ld e,(iy+22) ; de=число секторов на FAT ld d,(iy+23) ld a,(D0086) ; число копий FAT-ов cp 1 jr z,A13D2 dec a add hl,de ld (D14FE),hl A13D2: add hl,de dec a jr nz,A13D2 ld (D1502),hl ld c,(iy+11) ; bc=байтов на сектор ld b,(iy+12) rl c rl b rl c rl b rl c rl b ld c,b ld b,0 ld a,c ld (D1504),a ld e,(iy+17) ; de=записей в корне ld d,(iy+18) ex de,hl dec hl xor a A13FB: inc a jp z,A14EA sbc hl,bc jr nc,A13FB ex de,hl ld c,a ld b,0 ld (D1505),a add hl,bc ld (D1506),hl ld c,(iy+11) ; bc=байтов на сектор ld b,(iy+12) ld hl,0 ld a,(D0083) ; число секторов на кластер A141A: add hl,bc dec a jr nz,A141A ld (D1508),hl ; размер блока "секторов на кластер" ex de,hl ld hl,4000h-1 ; константа xor a A1426: inc a jp z,A14EA sbc hl,de jr nc,A1426 ld (D150A),a ld hl,T00AC ; "FAT16 " ld de,T14F4 ; "FAT" ld b,3 A1439: ld a,(de) cp (hl) jp nz,A14D1 inc hl inc de djnz A1439 A1442: ld a,(hl) inc hl cp " " jr z,A1442 cp "1" jp nz,A14EA ld a,(hl) cp "6" ld hl,0FFFFh ; ячейка FAT16 jr z,A145D cp "2" jp nz,A14EA ld hl,0FFFh ; ячейка FAT12 A145D: ld (D150B),a ; "2"/"6" fat12/fat13 ld (D150E),hl ld hl,0 ld c,(iy+24) ; bc=секторов на сторону ld b,(iy+25) ld a,(D0090) ; кол-во сторон диска A146F: add hl,bc dec a jr nz,A146F ld (D150C),hl ld de,(D1506) ld l,(iy+19) ; hl=всех секторов на диске ld h,(iy+20) ld a,h or l jr nz,A149B ; extended boot-record ld l,(iy+32) ; hl=мл.разряд всех секторов на диске ld h,(iy+33) ; ld c,(iy+34) ; bc=ст.разряд ld b,(iy+35) ; sbc hl,de jr nc,A14A1 dec bc jr A14A1 ; A149B: sbc hl,de ld bc,0 A14A1: ld a,(D0083) ; секторов на кластер scf A14A5: rra jr c,A14B3 rr b rr c rr h rr l jr A14A5 ; A14B3: inc hl ld (D12FF),hl pop iy ; iy=структура дескр. ld hl,0 ld (D12FD),hl ld a,1 ; лог. номер дос-банки (кэш FAT-а) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта xor a call A125B ; прочитать в кеш 16 секторов FAT-а pop af out (0E2h),a call A10F6 ; уст. начальный кластер для чтения xor a ret ; A14D1: ld a,(iy+15h) cp 0F0h ; формат 720kB дискеты jr c,A14EA cp 0F8h ; байт-дескриптор винта ld a,"6" ld hl,0FFFFh ; ячейка FAT16 jr z,A145D ld a,"2" ld hl,0FFFh ; ячейка FAT12 jp A145D ; A14EA: pop iy ld a,EINVMED ; код "не известный формат" scf ret ; A14F0: ld a,ENORDY ; код "нет готовности" scf ret T14F4: db "FAT" ; db 0 db 0 db 0 db 0 disk: db 1 ; номер диска ДОС D14FC: dw 0 D14FE: dw 0 D1500: dw 0 D1502: dw 0 D1504: db 0 D1505: db 0 D1506: dw 0 D1508: dw 0 ; размер блока "секторов на кластер" D150A: db 0 D150B: db 0 ; "6"/"2" fat16/fat12 D150C: dw 0 D150E: dw 0FFFFh ; 0FFFFh/0FFFh fat16/fat12 ; Буфер текущего пути (каталога) системы T1510: db '\' ds 256 ; <<< Массив структур дескрипторов, 44*10=440 байт >>> ; ; Структура дескриптора тек. каталога handle: db ". " ;+0 имя файла (+0=0 - дескр. свободен) db " " ;+8 расш. файла db 10h ;+11 атрибут ds 10 ;+12 резерв dw 0 ;+22 время dw 0 ;+24 дата dw 0 ;+26 номер первого кластера dw 0,0 ;+28 размер файла dw 0 ;+32 мл.разряд указателя файла dw 0 ;+34 ст.разряд dw 0 ;+36 номер первого кластера каталога (из +26) dw 0 ;+38 индекс записи в списке каталога (исп. #11 функ.) db 0 ;+40 номер диска (drive or current) db 0 ;+41 режим доступа к файлу (r,w,r/w). 7-й бит - признак изменения файла db 0 ;+42 уровень тек. программы (задача (владелец)) db 0 ;+43 резерв size_struc_handle equ $-handle ; размер структуры (44 байта) ; 9 файловых структур ds size_struc_handle * max_handles ; 44*9=396 ;------------------------------------------------- ; Поиск дескриптора файла. ; вход: a=номер дескр. ; выход: iy=адрес структуры дескр. ; CF - нет дескриптора ;------------------------------------------------- search_handle: inc a cp max_handles+1 ; запред. число дескрипторов jr nc,A17E3 push de ld iy,handle - size_struc_handle ; массив дескр. - 44 ld de,size_struc_handle ; 44 размер структуры дескриптора add iy,de dec a jr nz,$-3 ; ищем нужный дескр. pop de ld a,(iy+0) ; номер тек. дескр. or a ld a,EZERO ; код "Ok" ret nz ; дескр. занят A17E3: ld a,EINVHND ; код "не существующий дескриптор" scf ret ;----------------------------------------------------------- ; Освобождение дескриптора файла. ; вход: a=номер дескриптора ; выход: CF - при ошибке "не существующий дескриптор" ;----------------------------------------------------------- release_handle: inc a cp max_handles+1 ; запред. число дескрипторов jr nc,A17E3 push de ld iy,handle - size_struc_handle ; массив дескр. - 44 ld de,size_struc_handle ; 44 размер структуры дескриптора add iy,de dec a jr nz,$-3 ; ищем нужный дескриптор pop de ld a,(iy+0) ; имя файла в дескрипторе or a ; структура свободна ? ld a,EINVHND ; код "не существующий дескриптор" exx scf ret z ; да xor a ld (iy+0),a ; освоб. тек. дескриптор ret ;------------------------------------------------- ; Поиск свободного дескриптора. ; вход: нет ; выход: c=номер дескриптора ; CF - нет своб. дескриптора ;------------------------------------------------- search_free_handle: ld b,max_handles+1 ; 10 макс.число дескрипторов+1 ld c,-1 ; счетчик номера дескр. ld iy,handle - size_struc_handle ; массив дескр. - 44 ld de,size_struc_handle ; 44 размер структуры дескриптора A1815: add iy,de inc c ; 0..9 ld a,(iy+0) or a ; тек. структура дескриптора свободна ? ret z ; да djnz A1815 ; на след. структуру ld a,EMFILE ; код "слишком много откр. файлов" scf ret ;///////////////////////////////////////////////////////////////////// ; Функция #15. Перемещение указателя в файле. ; ; вход: A - дескриптор файла ; HL:IX - смещение указателя в файле ; B - способ перемещения ; B=0 от начала файла ; B=1 от текущего значения указателя ; B=2 от конца файла ; выход: HL:IX - новое значение указателя ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_15:call search_handle ; поиск дескр. файла ret c ; не найден inc b dec b jr z,A1835 ; от начала dec b jr z,A184B ; от тек. полож. dec b jr z,A183D ; от конца empty__:ld a,EINVFNC ; код "не верный номер функции" scf ret ; От начала файла A1835: ld bc,0 ; для мл. разряда ld e,c ; для ст. разряда ld d,c jr A1857 ; От конца файла A183D: ld c,(iy+1Ch) ; iy=дескр. файла ld b,(iy+1Dh) ld e,(iy+1Eh) ld d,(iy+1Fh) jr A1857 ; От тек. положения A184B: ld c,(iy+20h) ld b,(iy+21h) ld e,(iy+22h) ld d,(iy+23h) A1857: add ix,bc ; мл. разряд adc hl,de ; ст. разряд db 0DDh ld d,h db 0DDh ld e,l ld (iy+20h),e ld (iy+21h),d ld (iy+22h),l ld (iy+23h),h xor a ret A186D: ld l,(iy+1Ch) ld h,(iy+1Dh) ld e,(iy+20h) ld d,(iy+21h) and a sbc hl,de ld l,(iy+1Eh) ld h,(iy+1Fh) ld e,(iy+22h) ld d,(iy+23h) sbc hl,de ret A188B: pop bc pop de and a ret ; A188F: pop bc pop de scf ; ошибка ret ; A1893: push bc ld (D1CFB),ix ld a,(D0083) ; секторов на кластер ld c,a ld b,0 call A1CD9 db 0DDh ld b,h db 0DDh ld c,l push hl ld l,(iy+26) ; номер первого кластера (из дескр.) ld h,(iy+27) ; ld a,h or l jr nz,A18BB jr A188B ; файл нулевой длины ; A18B2: push bc call A1132 ; прочитать из кеша FAT-а номер след. кластера pop bc jr c,A188B ; конец цепочки ex de,hl ; hl=номер след. кластера dec bc A18BB: ld a,b or c jr nz,A18B2 ; прочитать след. сектор (кластер) pop de pop bc ld a,(D0083) ; секторов на кластер sub e ld c,a cp b jr c,A18CA ld c,b A18CA: ld a,b sub c ld b,a push hl push bc push de call A1CB8 pop de add ix,de jr nc,$+3 inc hl ld de,(D1CFB) ; буфер ld a,(disk) ; номер диска ld b,c ; число секторов ld c,5 ; чтение секторов rst 18h jr c,A188F ; ошибка pop bc ld hl,(D1CFB) ld de,(D0081) ; байтов на сектор (512) A18EF: add hl,de dec c jr nz,A18EF ld (D1CFB),hl pop de ld a,b or a ret z A18FA: ld hl,D0083 ; секторов на кластер ld a,b sub (hl) ld b,a ld c,(hl) jr nc,A1909 ld b,0 add a,(hl) ld c,a or a ret z A1909: ex de,hl ; hl=номер кластера push bc call A1132 ; прочитать из кеша FAT-а номер след. кластера pop bc jr c,A1938 ; конец цепочки ex de,hl ; hl=номер след. кластера push hl push bc call A1CB8 ld de,(D1CFB) ; куда ld a,(disk) ; номер диска ld b,c ; число секторов ld c,5 ; чтение секторов rst 18h jp c,A188F ; ошибка pop bc ld hl,(D1CFB) ld de,(D0081) ; байтов на сектор (512) A192E: add hl,de dec c jr nz,A192E ld (D1CFB),hl pop de jr A18FA ; A1938: and a ret A193A: pop bc A193B: pop bc pop de scf ret ; A193F: push bc ld (D1CFB),ix ld a,(D0083) ; секторов на кластер ld c,a ld b,0 call A1CD9 db 0DDh ld b,h db 0DDh ld c,l push hl ld l,(iy+1Ah) ; hl=номер первого кластера ld h,(iy+1Bh) ; ld a,h or l jr nz,A198A push bc call A10FD jr c,A193A ld (iy+1Ah),l ; hl=номер первого кластера ld (iy+1Bh),h ; ld de,(D150E) ; номер кластера call A11C4 ; записать в кеш FAT-а номер кластера push hl call A128B ; подкл. банку кеша FAT и записать его на диск pop hl pop bc jr A198A ; A1977: push bc call A1132 ; прочитать из кеша FAT-а номер след. кластера jr nc,A1987 ; не конец цепочки push hl ; номер кластера (не следующего) call A1111 pop hl jr c,A193A call A1132 ; прочитать из кеша FAT-а номер след. кластера A1987: pop bc ex de,hl ; hl=номер след. кластера dec bc A198A: ld a,b or c jr nz,A1977 pop de pop bc ld a,(D0083) ; секторов на кластер sub e ld c,a cp b jr c,$+3 ld c,b ld a,b sub c ld b,a push hl push bc push de call A1CB8 pop de add ix,de jr nc,$+3 inc hl ld de,(D1CFB) ; буфер ld a,(disk) ; номер диска ld b,c ; число секторов ld c,6 ; запись секторов rst 18h jp c,A193B ; ошибка pop bc ld hl,(D1CFB) ld de,(D0081) ; байтов на сектор (512) add hl,de dec c jr nz,$-2 ld (D1CFB),hl pop de ld a,b or a ret z A19C9: ld hl,D0083 ; секторов на кластер ld a,b sub (hl) ld b,a ld c,(hl) jr nc,A19D8 ld b,0 add a,(hl) ld c,a or a ret z A19D8: ex de,hl push bc call A1132 ; прочитать из кеша FAT-а номер след. кластера jr nc,A19E9 ; не конец цепочки push hl ; номер кластера (не следующего) call A1111 pop hl jr c,A1A10 ; нет места на диске call A1132 ; прочитать из кеша FAT-а номер след. кластера A19E9: pop bc ex de,hl ; hl=номер след. кластера push hl push bc call A1CB8 ld de,(D1CFB) ; буфер ld a,(disk) ; номер диска ld b,c ; число секторов ld c,6 ; запись секторов rst 18h jp c,A193B ; ошибка pop bc ld hl,(D1CFB) ld de,(D0081) ; байтов на сектор (512) add hl,de dec c jr nz,$-2 ld (D1CFB),hl pop de jr A19C9 ; A1A10: pop bc ld a,ENOSPACE ; код "нет места на диске" scf ret A1A15: xor a ld (D1CFA),a ld l,(iy+20h) ld h,(iy+21h) add hl,de exx ld e,a ld d,a ld l,(iy+22h) ld h,(iy+23h) adc hl,de exx ld c,(iy+1Ch) ld b,(iy+1Dh) and a sbc hl,bc exx ld c,(iy+1Eh) ld b,(iy+1Fh) sbc hl,bc exx ret c ex de,hl sbc hl,de ex de,hl ld a,-1 ld (D1CFA),a ret ;///////////////////////////////////////////////////////////////////// ; Функция #13. Чтение из файла. ; ; вход: A - дескриптор файла (0-й = чтение списка диска) ; HL - буфер ; DE - кол-во читаемых байт ; выход: DE - реальное кол-во прочитанных байт ; если CF=0: ; A=0 прочитаны все байты ; A=0FFh прочитано меньшее число байт ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_13:ld (D1D01),hl ld (D1D03),hl call search_handle ; поиск дескр. файла ret c ; не найден call A1A15 ld a,d or e jp z,A1B02 push de ld a,(iy+40) ; номер диска из дескр. call A2147 jp c,A1B57 ld c,(iy+32) ; мл.разряд указателя файла ld a,(iy+33) ; ld e,a and 1 ld b,a ld d,(iy+34) ; ст.разряд ld l,(iy+35) ; ld h,0 or a rr l rr d rr e ld a,b or c jp nz,A1B07 A1A85: pop bc push bc srl b jr z,A1ABA ld (D1CFD),hl ld (D1CFF),de ld ix,(D1D01) call A1893 jp c,A1B57 ld de,(D1D01) ld hl,(D1CFB) and a sbc hl,de ld c,h ld b,0 add hl,de ld (D1D01),hl srl c ld hl,(D1CFF) add hl,bc ex de,hl ld hl,(D1CFD) ld c,b adc hl,bc A1ABA: pop bc ld a,b and 1 ld b,a or c jr z,A1AEA push bc ld ix,LC400 ld b,1 in a,(0E2h) push af in a,(82h) out (0E2h),a call A1893 pop bc ld c,0E2h ; порт out (c),b ; восст. порт jp c,A1B57 ld hl,T0400 ; откуда ld de,(D1D01) pop bc ldir ld (D1D01),de A1AEA: ld hl,(D1D03) ld de,(D1D01) ex de,hl and a sbc hl,de push hl ex de,hl db 0DDh ld h,d db 0DDh ld l,e ld hl,0 call A184B pop de A1B02: ld a,(D1CFA) or a ret ; A1B07: push bc push hl push de ld ix,LC400 ld b,1 in a,(0E2h) push af in a,(82h) out (0E2h),a call A1893 pop bc ld c,0E2h out (c),b ; восст. порт pop hl jr c,A1B55 ld bc,1 ;T0001 add hl,bc ex de,hl pop hl ld c,b adc hl,bc exx pop de ld hl,512 ;T0200 ? and a sbc hl,de ld b,h ld c,l pop hl and a sbc hl,bc jr nc,A1B42 add hl,bc ld b,h ld c,l ld hl,0 A1B42: push hl ld hl,T0400 ; откуда add hl,de ld de,(D1D01) ; куда ldir ld (D1D01),de exx jp A1A85 ; A1B55: pop hl pop hl A1B57: pop bc scf ret ; A1B5A: pop hl A1B5B: pop hl A1B5C: pop bc scf ret ; A1B5F: pop de ld a,EROFILE ; код "файл r/o" scf ret ;///////////////////////////////////////////////////////////////////// ; Функция #14. Запись в файл. ; ; вход: A - дескриптор файла (0-й = запись списка диска) ; HL - буфер данных ; DE - кол-во записываемых байт ; выход: DE - реальное кол-во записанных байт ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_14:ld (D1D01),hl ld (D1D03),hl push de call search_handle ; поиск дескр. файла jr c,A1B5C ; не найден ld a,(iy+41) ; режим доступа к файлу (r,w,r/w) and 1 ; на чтение jr nz,A1B5F ; запись не возможна (файл r/o) set 7,(iy+41) ; уст. признак изменения файла set 5,(iy+11) ; бит "архивный" в ячейке атрибута ld a,(iy+40) ; номер диска call A2147 jr c,A1B5C ld c,(iy+32) ld a,(iy+33) ld e,a and 1 ld b,a ld d,(iy+34) ld l,(iy+35) ld h,0 or a rr l rr d rr e ld a,b or c jp nz,A1C4E A1BA7: pop bc push bc srl b jr z,A1BD1 push hl push de push bc ld ix,(D1D01) call A193F pop bc jp c,A1B5A ld c,b ld hl,(D1D01) ld de,512 ; размер сектора add hl,de djnz $-1 ld (D1D01),hl pop hl add hl,bc ex de,hl pop hl ld c,b adc hl,bc A1BD1: pop bc ld a,b and 1 ld b,a or c jr z,A1C19 push hl push de push bc ld ix,LC400 ld b,1 in a,(0E2h) push af in a,(82h) out (0E2h),a call A1893 pop bc ld c,0E2h out (c),b ; восст. порт ld de,T0400 ; куда ld hl,(D1D01) ; откуда pop bc jp c,A1B5B ldir ld (D1D01),hl pop de pop hl ld ix,LC400 ld b,1 in a,(0E2h) push af in a,(82h) out (0E2h),a call A193F pop bc ld c,0E2h out (c),b ; восст. порт ret c A1C19: ld de,(D1D03) ld hl,(D1D01) and a sbc hl,de push hl ex de,hl db 0DDh ld h,d db 0DDh ld l,e ld hl,0 call A184B call A186D pop de ret nc ld l,(iy+20h) ld h,(iy+21h) ld c,(iy+22h) ld b,(iy+23h) ld (iy+1Ch),l ld (iy+1Dh),h ld (iy+1Eh),c ld (iy+1Fh),b and a ret ; A1C4E: push bc push hl push de ld ix,LC400 ld b,1 in a,(0E2h) push af in a,(82h) out (0E2h),a call A1893 pop bc ld c,0E2h out (c),b ; восст. порт pop de pop hl exx pop de jp c,A1B5C ld hl,512 ;T0200 and a sbc hl,de ld b,h ld c,l pop hl and a sbc hl,bc jr nc,A1C81 add hl,bc ld b,h ld c,l ld hl,0 A1C81: push hl ld hl,T0400 ; куда add hl,de ld de,(D1D01) ; откуда ex de,hl ldir ld (D1D01),hl exx push hl push de ld ix,LC400 ld b,1 in a,(0E2h) push af in a,(82h) out (0E2h),a call A193F pop bc ld c,0E2h out (c),b ; восст. порт pop hl jp c,A1B5B ld bc,1 ;T0001 add hl,bc ex de,hl pop hl ld c,b adc hl,bc jp A1BA7 A1CB8: dec hl dec hl ex de,hl ld a,(D0083) ; секторов на кластер ld b,a ld hl,0 ld ix,0 A1CC6: add ix,de jr nc,$+3 inc hl djnz A1CC6 ld de,(D1506) add ix,de ld e,b ld d,b adc hl,de ret A1CD9: db 0DDh ld h,d db 0DDh ld l,e ex de,hl ld hl,0 ld a,32 A1CE3: add ix,ix ex de,hl adc hl,hl ex de,hl adc hl,hl sbc hl,bc jr nc,A1CF4 add hl,bc dec a jr nz,A1CE3 ret ; A1CF4: inc ix dec a jr nz,A1CE3 ret D1CFA: db 0 D1CFB: dw 0 D1CFD: dw 0 D1CFF: dw 0 D1D01: dw 0 D1D03: dw 0 ;///////////////////////////////////////////////////////////////////// ; Функция #16. Получение/изменение атрибута файла. ; ; вход: HL - указатель на имя файла ; B - режим доступа: ; B=0 получить атрибут ; B=1 установить атрибут ; A - атрибут файла ; выход: A - атрибут файла, если CF=0 ; код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_16:inc b dec b jr z,A1D12 ; b=0 dec b jr z,A1D24 ; b=1 ld a,EINVFNC ; код "неверный номер функции" scf ret ; Получить атрибут файла A1D12: xor a ; атрибут записи call A1E5F ret c ld b,(iy+11) ; атрибут записи из дескр. push bc call Func_12 ; закрыть файл pop bc ret c ld a,b and a ret ; Изменить атрибут файла A1D24: push af xor a ; атрибут записи call A1E5F pop bc ret c set 7,(iy+41) ; уст. признак изменения файла res 3,b ; бит "метка тома" ld (iy+11),b ; ячейка атрибутов записи push bc call Func_12 ; закрыть файл pop bc ret c ld a,b and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #0A. Создание файла. ; ; вход: HL - указатель на имя файла ; A - атрибут файла ; выход: A - дескриптор файла, если CF=0 ; код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_0A:and 11100111b ; маска, скрыть биты dir/label ld (D1F3A),a ; раб. ячейка ld (file_name+1),hl ; имя файла push hl call search_free_handle ; поиск своб. дескриптора pop hl ret c ; не найден call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c ; недоп. имя call search_rec_file ; поиск записи файла в списке диска call nc,mark_delete ; найден, пометить запись как "удаленная" jr A1D7B ;///////////////////////////////////////////////////////////////////// ; Функция #0B. Создание нового файла. ; Проверяет, существует ли файл с таким же именем. ; ; вход: HL - указатель на имя файла ; A - атрибут файла ; выход: A - дескриптор файла, если CF=0 ; код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_0B:and 11100111b ; маска, скрыть биты dir/label ld (D1F3A),a ; раб. ячейка ld (file_name+1),hl ; имя файла push hl call search_free_handle ; поиск своб. дескриптора pop hl ret c ; не найден call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c ; недоп. имя call search_rec_file ; поиск записи файла в списке диска ld a,EEXIST ; код "файл существует" ccf ret c ; найден ; создать в буфере новую запись A1D7B: ld hl,T2364 ld de,T1F3B ld bc,11 ldir ex de,hl ld a,(D1F3A) ; раб. ячейка (здесь атрибут записи) ld (hl),a ;+11 в записи inc hl ld bc,0A00h ; b=10 байт резерва ld (hl),c inc hl djnz $-2 push hl call Func_21 ; узнать тек. дату и время call A2599 ; закодировать время/дату pop hl ld (hl),e ;+22 время inc hl ld (hl),d inc hl ld (hl),c ;+24 дата inc hl ld (hl),b inc hl ld bc,0600h ; 6 ячеек, № кластера и размер файла ld (hl),c inc hl djnz $-2 call A1F5B ; скопир. новую запись в список диска (каталога) call flush_cash_dir ; сбросить кеш каталога на диск ; открыть созданный файл file_name: ld hl,0 ; адрес имени файла xor a ; на чтение/запись jp Func_11 ; открыть файл ;///////////////////////////////////////////////////////////////////// ; Функция #0C. Создание файла с уникальным именем. ; В конце строки пути должно быть как минимум 12 байт, ; на размещение созданного имени файла. Сама строка должна ; заканчиваться нулем. ; Если созданный файл уже существует, он обнуляется и откры- ; вается на чтение/запись. ; ; вход: HL - указатель на строку пути (и/или с диском). ; A - атрибут файла ; выход: A - дескриптор файла, если CF=0 ; код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_0C:jp empty__ ; код "не верный номер функции" ;push af ;push hl ; создать уник. имя ;call Func_21 ; узнать тек. дату и время ;call A2599 ; закодировать время/дату ;; bc=дата, de=время ;ld hl,T2364 ; буфер имени 11 симв. формата ;ld a,b ;call byte2dec ;ld a,c ;call byte2dec ;ld a,d ;call byte2dec ;ld a,e ;call byte2dec ;pop hl ;push hl ;; перейти на конец строки ;xor a ;ld bc,256 ;cpir ;dec hl ;ex de,hl ;; добавить имя файла в конец строки ;ld hl,T2364 ; буфер имени 11 симв. формата ;ld bc,8 ; имя ;ldir ;ex de,hl ;ld (hl),"." ;inc hl ;ld a,"$" ; расш. файла ;ld (hl),a ;inc hl ;ld (hl),a ;inc hl ;ld (hl),a ;inc hl ;ld (hl),0 ;pop hl ; имя файла ;pop af ; атрибут ;; создать файл ;jp Func_0A ; Цифру в hex-формате в буфер. ; вход: hl=буфер ; a=цифра ;byte2dec: ;push af ;rra ;rra ;rra ;rra ;call $+4 ;pop af ;and 0Fh ;add a,90h ;daa ;adc a,40h ;daa ;ld (hl),a ;inc hl ;ret ;///////////////////////////////////////////////////////////////////// ; Функция #0E. Удаление файла. ; Файлы "r/o" нельзя стереть данной функцией. ; ; вход: HL - указатель на имя файла ; A - атрибут файла ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_0E:bit 0,a scf ld a,EROFILE ; код "файл r/o" ret nz ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c ld hl,T2364 ld bc,11 ld a,"?" cpir ld a,EINVFNAM ; код "неверное имя" scf ret z call A228F ; прочитать список каталога call search_rec_file ; поиск записи файла в списке диска ret c ; не найден ; пометить запись как "удаленная" mark_delete: xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС ld (ix+0),0E5h ; признак удаления файла ld e,(ix+26) ; № первого кластера ld d,(ix+27) out (0E2h),a ; восст. порт ld a,e or d jp z,flush_cash_dir ; сбросить кеш каталога на диск A1DEA: ex de,hl ; hl=номер кластера call A1132 ; прочитать из кеша FAT-а номер след. кластера push de ; номер след. кластера push af ld de,0 ; номер кластера call A11C4 ; записать в кеш FAT-а номер кластера pop af pop de jr nc,A1DEA ; не конец цепочки call A128B ; подкл. банку кеша FAT и записать его на диск jp flush_cash_dir ; сбросить кеш каталога на диск ;///////////////////////////////////////////////////////////////////// ; Функция #10. Переименование файла. ; Глобальные символы * и ? в именах файлов не допускаются. ; ; вход: HL - указатель на старое имя файла ; DE - указатель на новое имя файла ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_10:push de ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат pop de ret c ld hl,T2364 ld bc,11 ld a,"?" cpir ld a,EINVFNAM ; код "неверное имя" scf ret z push de call A228F ; прочитать список каталога ld a,33h ; атрибут "arch + dir + r/o + hidden" call search_record ; поиск записи в списке диска pop hl ; 8.3 имя ret c ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c ld hl,T2364 ld bc,11 ld a,"?" cpir ld a,EINVFNAM ; код "неверное имя" scf ret z push ix ; адр. записи переимен. файла ld a,33h ; атрибут "arch + dir + r/o + hidden" call search_record ; поиск записи в списке диска pop ix ld a,EEXIST ; код "файл существует" ccf ret c xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС ld hl,T2364 db 0DDh ld d,h db 0DDh ld e,l ld bc,11 ldir out (0E2h),a ; восст. порт jp flush_cash_dir ; сбросить кеш каталога на диск A1E5F: ld (D1F3A),a ; раб. ячейка (здесь атрибут записи) call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c ld a,37h ; атрибут "все, кроме метки тома" call search_record ; поиск записи в кэше списка каталога jr nc,A1E8D ; на поиск своб. дескриптора ; запись не найдена ret ;///////////////////////////////////////////////////////////////////// ; Функция #11. Открытие файла. ; ; вход: HL - указатель на имя файла ; A - режим доступа: ; A=0 чтение/запись ; A=1 чтение ; A=2 запись ; выход: A - дескриптор файла, если CF=0 ; код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_11:ld (D1F3A),a ; раб. ячейка call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c A1E89: call search_rec_file ; поиск записи файла в списке диска ret c ; не найден A1E8D: call search_free_handle ; поиск своб. дескриптора ret c ; не найден ; заполнить структуру дескриптора ld a,c ; номер своб. дескриптора ex af,af' exx ld (iy+38),e ; de=индекс записи в списке каталога (исп. #11 функ.) ld (iy+39),d exx db 0FDh ; ld de,iy ld d,h db 0FDh ld e,l ld hl,T1F3B ; 32 байта ld bc,32 ldir ; заполнить дескриптор ld a,(D1F3A) ; режим доступа к файлу (раб. ячейка) ld (iy+41),a ld a,(D2E70) ; уровень текущей программы (владелец) ld (iy+42),a xor a ld (iy+32),a ld (iy+33),a ld (iy+34),a ld (iy+35),a ld a,(disk) ; номер диска ld (iy+40),a ld hl,handle+26 ; ячейка № первого кластера ld e,(hl) inc hl ld d,(hl) ld (iy+36),e ; № первого кластера ld (iy+37),d ex af,af' and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #12. Закрытие файла. ; ; вход: A - дескриптор файла ; выход: A - код ошибки, если CF=1 ; ;///////////////////////////////////////////////////////////////////// Func_12:ld (D1F3A),a ; дескр. (раб. ячейка) call search_handle ; поиск дескр. файла ret c ; не найден ld a,(D2E70) ; уровень текущей программы cp (iy+42) ; уровень из дескриптора ld a,EACCES ; код "ресурс не доступен" scf ret nz bit 7,(iy+41) ; флаг изменения файла jr z,A1F31 ; освоб. дескр. файла ; файл изменялся ld d,(iy+36) ld e,(iy+37) push de xor a ; номер дескр. call search_handle ; поиск дескр. файла pop de ld (iy+36),d ld (iy+37),e call A228F ; прочитать список каталога ld a,(D1F3A) ; дескриптор (раб. ячейка) call search_handle ; поиск дескр. файла ld hl,LC000 ld de,32 ld c,(iy+38) ; bc=индекс записи в списке каталога ld b,(iy+39) jr A1F17 ; A1F15: add hl,de dec bc A1F17: ld a,b or c jr nz,A1F15 db 0FDh ld d,h db 0FDh ld e,l ex de,hl push hl xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС pop hl ld bc,32 ldir out (0E2h),a ; восст. порт call flush_cash_dir ; сбросить кеш каталога на диск A1F31: ld a,(D1F3A) ; дескр. (раб. ячейка) jp release_handle ; освоб. дескр. файла D1F3A: db 0 ; раб. ячейка (режим поиска/доступа/..) ; 32 байта. Буфер записи файла/каталога T1F3B: ds 11 D1F46: db 0 ;+11 ячейка атрибутов файла ds 14 D1F55: dw 0 ds 4 ;----------------------------------------------------------- ; Скопировать новую запись в кэш списка каталога ;----------------------------------------------------------- A1F5B: xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта ld ix,LC000 ; начало списка диска exx ld de,0 ; сбр. индекс записи (исп. #11 функ.) exx A1F6A: ld a,(ix+0) or a ; конец списка jr z,A1F82 cp 0E5h ; признак удал. записи jr z,A1F82 ld bc,32 add ix,bc ; на след. запись jr nc,A1F6A ; за границей 0FFFFh pop af out (0E2h),a ; восст. порт ld a,EROOT ; код "переполнение root-каталога" scf ret ; скопир. новую запись в список диска A1F82: db 0DDh ld d,h ; de=куда db 0DDh ld e,l ld hl,T1F3B ; откуда 32 байта (новая запись) ld bc,32 ldir ; скопир. новую запись в список диска pop af out (0E2h),a ; восст. порт ld hl,LC000 ; начало списка диска ld bc,(size_cash_directory) dec bc add hl,bc and a sbc hl,de ret nc ld hl,(size_cash_directory) ld bc,(D1508) ; размер блока "секторов на кластер" add hl,bc ld (size_cash_directory),hl and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #44. Преобразовать имя файла (11 -> 8.3 и обратно). ; ; вход: B=0, преобразовать из 11 символьного формата в формат ДОС ; HL - 11 символов имени файла ; DE - буфер для имени в формате ДОС (13 байт) ; B=1, преобразовать из формата ДОС в 11 символьный формат ; HL - имя файла в формате ДОС ; DE - 11 символов имени файла ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_44:inc b dec b ; b=0 jr z,A1FB8 ; преобр. имя 11 -> 8.3 формат dec b ; b=1 jp z,A2384 ; преобр. имя 8.3 -> 11 формат ld a,EINVFNC ; код "неверный номер функции" scf ret ;------------------------------------------------- ; Преобразовать имя 11 -> 8.3 формат ; ; вход: hl=откуда ; de=куда ;------------------------------------------------- A1FB8: ld bc,08FFh ; b=счетчик A1FBB: ld a,(hl) cp " " jr nz,A1FC5 inc hl djnz $-1 jr A1FC9 ; A1FC5: ldi djnz A1FBB A1FC9: ld a,(hl) cp " " ld a,"." jr nz,A1FD2 ld a,0 A1FD2: ld (de),a inc de ret z ld b,3 A1FD7: ld a,(hl) cp " " ret z ldi xor a ld (de),a djnz A1FD7 ret D1FE2: dw 0 ; адрес раб. буфера (f_first, f_next) D1FE4: dw 0 ; адрес след. записи (f_first, f_next) D1FE6: db false ; флаг отработки "f_first" D1FE7: db false ; флаг 8.3 или 11 формата имени (f_first, f_next) ;///////////////////////////////////////////////////////////////////// ; Функция #19. Поиск первого совпадающего файла. ; ; вход: HL - указатель на имя файла ; DE - рабочий буфер 44 байта, если B=0, иначе 46 байт ;256 байт ; A - атрибуты, используемые при поиске ; B=0 - имя найденного файла в формате 11 байт "FilenameExt" ; B=1 - имя найденного файла в формате DOS "filename.ext",0 ; выход: de'= индекс записи в списке каталога (исп. #11 функ.) ; A - код ошибки, если CF=1 ; ; формат раб. буфера: ; +00 8 db "FILE????" ; шаблон имени ; +08 3 db "???" ; шаблон расширения ; +11 1 db 20h ; атрибуты для поиска ; +12 10 ds 10 ; зарезервировано ; +22 2 dw 0000h ; время создания файла ; +24 2 dw 0000h ; дата создания файла ; +26 2 dw 0000h ; номер первого кластера ; +28 4 dw 0000h ; мл.разряд размер файла в байтах ; dw 0000h ; ст.разряд ; +32 1 db 20h ; атрибут найденного файла ; +33 11 db "FILENAMEEXT" ; имя найденного файла (копия из каталога) ;///////////////////////////////////////////////////////////////////// Func_19:ld (D1F3A),a ; атрибут поиска ld (D1FE2),de ; адрес раб. буфера ld a,b ld (D1FE7),a ; флаг 8.3 или 11 формата имени push hl ; имя файла call A228F ; прочитать список каталога (также указ. в строке) pop hl call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c ld a,(D1F3A) ; раб. ячейка (здесь атрибут записи) call search_record ; поиск записи в списке диска ret c ; запись не найдена/слишком много файлов ld hl,T2364 ; буфер имени 11 симв. формата ld de,(D1FE2) ; адрес раб. буфера ld bc,11 ldir ; перекачать "???????.." ld a,(D1F3A) ; раб. ячейка (здесь атрибут записи) ld (de),a ;+11 раб. буфер функции A201D: inc de ld bc,32 add ix,bc ld (D1FE4),ix ;; след. запись ld hl,T1F3B+12 ; смещ. в записи ld bc,20 ldir ld a,(T1F3B+11) ; ячейка атрибутов файла ld (de),a ;+32 в раб. буфере функции inc de ld hl,T1F3B ; найденная запись файла/каталога ld a,(D1FE7) ; флаг 8.3 или 11 формата имени or a jr nz,A2049 ; 11 -> 8.3 ; скопир. имя найд. файла (формат 11) ld bc,11 ldir A2042: ld a,true ld (D1FE6),a ; флаг отработки "F_FIRST" xor a ret ; преобр. 11 -> 8.3 формат A2049: call A1FB8 jr A2042 ;///////////////////////////////////////////////////////////////////// ; Функция #1A. Поиск следующего совпадающего файла. ; ; вход: de = указатель на рабочий буфер ; выход: de'= индекс записи в списке каталога (исп. #11 функ.) ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_1A:ld a,(D1FE6) ; флаг отработки "F_FIRST" or a ld a,EUNOPER ; код "невозможная операция" scf ret z ld (D1FE2),de ; адрес раб. буфера ld hl,T2364 ; буфер имени 11 симв. формата ex de,hl ld bc,11 ldir xor a ld (D1FE6),a ; сбр. флаг отработки "f_first" ld a,(hl) ; ячейка атрибутов записи push hl call A207B ; найти след. запись pop de ret c ; не найдена или слишком много файлов jr A201D ; скопир. остальные 20 байт записи ; поиск след. записи A207B: ex af,af' ; сохр. атрибуты записи xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта ex af,af' ; восст. атрибуты записи cpl ld c,a exx ld de,0 ; сбр. индекс записи (исп. #11 функ.) exx ld ix,(D1FE4) ;; адрес след. записи db 0DDh ld a,h db 0DDh or l jr z,search_record_too_many ; вышли за границу 0FFFFh jr search_record_loop ; на цикл поиска записи ;------------------------------------------------- ; Поиск записи каталога в списке каталога ; ; вход: a=атрибут записи ; выход: de'=индекс записи в списке каталога ; CF - каталог не найден ;------------------------------------------------- search_rec_dir: ld a,10h ; атрибут "dir" call search_record ret nc ld a,ENOPATH ; код "неверный путь" ret ;------------------------------------------------- ; Поиск записи файла в списке каталога. ; ; вход: a=атрибут записи ; выход: ix=адрес найденной записи ; de'=индекс записи в списке каталога (для #11 функ.) ; CF - при ошибке, A=код ошибки ;------------------------------------------------- search_rec_file: ld a,27h ; атрибут "все, кроме папки и метки тома" search_record: ex af,af' ; сохр. атрибут записи xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта ex af,af' ; восст. атрибут записи cpl ld c,a ld ix,LC000 ; кэш списка каталога диска exx ld de,0 ; сбр. индекс записи (исп. #11 функ.) exx ; цикл поиска записи search_record_loop: ld a,(ix+0) or a jr z,search_record_not_found cp 0E5h ; код удал. записи jp z,search_record_next ld a,(ix+11) ; атрибут записи and c ; искомый атрибут ? jp nz,search_record_next ; нет ld hl,T2364 ; готовое имя файла (11 симв. формат) db 0DDh ld d,h db 0DDh ld e,l ld b,11 ex de,hl A20C9: ld a,(de) cp "?" jr z,A20D1 cp (hl) jp nz,search_record_next A20D1: inc hl inc de djnz A20C9 db 0DDh ld d,h db 0DDh ld e,l ld hl,T1F3B ; 32 буфер записи ex de,hl ld bc,32 ldir ; скопир. найденную запись в буфер pop af out (0E2h),a ; восст. порт and a ret ; search_record_next: exx inc de ; ++индекс записи (исп. #11 функ.) exx ld de,32 add ix,de ; на след. запись jp nc,search_record_loop ; выход за границу 0FFFFh search_record_too_many: ld e,ETMFILE ; код "слишком много файлов" jr $+4 search_record_not_found: ld e,ENOFILE ; код "файл не обнаружен" pop af out (0E2h),a ; восст. порт ld a,e ; код ошибки scf ret ;------------------------------------------------- ; Тест на допустимое имя и настроиться на диск. ; вход: hl=строка имени ;------------------------------------------------- A20F8: ld de,D213A ; куда ld bc,0DFFh ; b=счетчик A20FE: ld a,(hl) inc hl cp '\' jr z,A2114 cp ":" jr z,A2122 ld (de),a inc de cp " "+1 ccf ret nc djnz A20FE ld a,EINVFNAM ; код "неверное имя" scf ret ; A2114: ld a,0 ld (de),a push hl ld hl,D213A call A2164 pop hl jr nc,A20F8 ret ; A2122: ld a,(D213A) ; буква диска cp "a" jr c,A212F cp "z"+1 jr nc,A212F sub 20h A212F: sub "A" push hl call A2147 pop hl jr nc,A20F8 ret ; Буфер имени 8.3 формата D213A: db " ",0 ; 12 пробелов A2147: push af ; номер девайса ld c,1 ; открыть девайс rst 18h pop bc jr c,A215C ; ошибка ld a,b ld (disk),a ; номер диска call A1370 ret c ld a,(last_drive) ; номер посл. диска and a ret ; A215C: cp EINVDRV ; код "bad drive number" scf ret z ld a,ENORDY ; код "нет готовности" scf ret A2164: xor a ; номер дескр. call search_handle ; поиск дескр. файла ld a,(hl) ; 8.3 имя or a jr nz,A2183 A216D: ld de,0 ld (iy+26),e ld (iy+27),d call A228F ; прочитать список каталога ld hl,T1510 ; буфер тек. пути (каталога) системы ld (hl),'\' inc hl ld (hl),0 and a ret ; A2183: cp "." jr nz,A21AF ld a,(iy+26) or (iy+27) jr nz,A2195 inc hl ld a,(hl) or a dec hl jr z,A216D A2195: exx ld hl,T2364 ld de,T2364+1 ld bc,10 ld (hl)," " ldir exx ld de,T2364 A21A7: ldi ld a,(hl) or a jr nz,A21A7 jr A21B6 ; A21AF: ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c A21B6: call A21DC ret c ld (iy+26),e ld (iy+27),d ld de,L4000 ld (iy+28),e ld (iy+29),d call A228F ; прочитать список каталога and a ret A21CE: ld bc,32 add ix,bc ; на след. запись jr nc,A21E6 ; превышение границы #FFFF A21D5: pop af out (0E2h),a ; восст. порт ld a,ENOPATH ; код "неверный путь" scf ret ; A21DC: xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта ld ix,LC000 ; кеш списка каталога A21E6: ld a,(ix+0) or a jr z,A21D5 ; список пустой cp 0E5h jr z,A21CE ; файл удален ld a,(ix+11) ; ячейка атрибутов and 10h ; каталог ? jr z,A21CE ; нет, на след. запись ; каталог ld hl,T2364 db 0DDh ld d,h db 0DDh ld e,l ex de,hl ld b,11 A2201: ld a,(de) cp "?" jr z,A2209 cp (hl) jr nz,A21CE ; на след. запись A2209: inc hl inc de djnz A2201 ld a,(ix+0) cp "." jr nz,A2245 ld a,(ix+1) cp "." jr nz,A223A ; родит. каталог ld hl,T1510 ; буфер тек. пути (каталога) системы ld d,h ld e,l ld bc,256 xor a cpir ld bc,256 ld a,'\' cpdr inc hl and a ex de,hl sbc hl,de ex de,hl jr nz,A2238 inc hl A2238: ld (hl),0 A223A: ld e,(ix+26) ld d,(ix+27) pop af out (0E2h),a ; восст. порт and a ret ; A2245: db 0DDh ld e,l db 0DDh ld d,h ld hl,T1510 ; буфер тек. пути (каталога) системы ld bc,255 xor a cpir dec hl dec hl ld a,'\' cp (hl) inc hl jr z,$+4 ld (hl),a inc hl ld bc,0820h ; b=счетчик, c=пробел A225F: ld a,(de) inc de cp c jr z,A2266 ld (hl),a inc hl A2266: djnz A225F ld a,(de) inc de cp c jr z,A227F ld (hl),"." inc hl ld (hl),a inc hl ld a,(de) inc de cp c jr z,A227F ld (hl),a inc hl ld a,(de) cp c jr z,A227F ld (hl),a inc hl A227F: ;ld (hl),'\' ; ; концовка пути ;inc hl; ld (hl),0 jr A223A ;///////////////////////////////////////////////////////////////////// ; Функция #1E. Информация о текущем каталоге. ; ; вход: HL - буфер в памяти 256 байт ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_1E:ex de,hl ; de=куда ld hl,T1510 ; откуда ; DIRSPEC ld a,(hl) or a ldi jr nz,$-4 ret ;------------------------------------------------- ; Прочитать список каталога ;------------------------------------------------- A228F: xor a ld l,a ld h,a push hl pop ix ld b,a ; от начала файла call Func_15 ; перемещение указателя в файле xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта ; очистить кеш каталога /* ld hl,LC000 ;@@ ld de,LC000+1 ld bc,4000h-1 ld (hl),l ldir ; 21 * #3FFF = 344.043 */ ld (.stack),sp ; сохр. стек ld de,0 ; байты заполнения ld bc,400h / 2 ld sp,0000h ; откуда (вниз) .loop: push de push de push de push de push de push de push de push de push de push de push de push de push de push de push de push de dec bc ld a,c or b jp nz,.loop db 31h ; ld sp,.. .stack: dw 0 ; ld a,(disk) ; номер диска ld (iy+40),a ; сохр. в дескриптор ld d,(iy+26) ; de=номер первого кластера ld e,(iy+27) ld a,d or e jr z,A22D2 ; root ?? ld hl,LC000 ; куда ld de,4000h ; сколько xor a ; дескриптор call Func_13 ; чтение из файла ld (size_cash_directory),de ; число прочит. байтов pop af out (0E2h),a ; восст. порт and a ret ; A22D2: ld hl,(D1500) ; ст. разряд ld ix,(D1502) ; номер лог. сектора ld a,(D1505) ld b,32 ; размер root-каталога sub b jr nc,A22E3 add a,b ld b,a ; число секторов A22E3: ld a,(disk) ; номер диска ld c,5 ; чтение секторов ld de,LC000 ; буфер rst 18h pop af out (0E2h),a ; восст. порт and a ret ;------------------------------------------------- ; Сбросить кеш каталога на диск. ; вход: iy=структура дескриптора ;------------------------------------------------- flush_cash_dir: xor a ld l,a ld h,a push hl ; ст. разряд pop ix ; мл. разряд ld b,a ; от начала файла call Func_15 ; перемещение указателя в файле xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта ld a,(disk) ; номер диска ld (iy+40),a ; сохр. в дескрипторе ld d,(iy+26) ; de=номер первого кластера ld e,(iy+27) ld a,d or e jr z,A2325 ; root ?? ld hl,LC000 ; откуда ld de,(size_cash_directory) ; сколько xor a ; дескр. call Func_14 ; запись в файл pop af out (0E2h),a ; восст. порт and a ret ; A2325: ld hl,(D1500) ; ст. разряд ld ix,(D1502) ; лог. номер сектора ld a,(D1505) ld b,32 ; макс. число секторов ? sub b jr nc,$+4 add a,b ld b,a ; число секторов ld a,(disk) ; номер диска ld c,6 ; запись секторов ld de,LC000 ; буфер rst 18h pop af out (0E2h),a ; восст. порт and a ret size_cash_directory: dw 0 ; размер списка каталога ;----------------------------------------------------------- ; Подключить банку расширения ДОС в 3-е окно ; ; вход: a=лог. номер банки (0..2, в данной версии ДОС) ; выход: a=старая банка порта ;----------------------------------------------------------- set_dos_page: ld c,a ld b,0 ld hl,list_dos_pages ; 16 байт, номера банок расширения ДОС add hl,bc in a,(0E2h) ; сохр. порт ld c,0E2h ; порт outi ; один байт (hl) -> порт (bc) ret ; Массив лог. номеров банок расширения ДОС. 16 байт. list_dos_pages: db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 db -1 ; Буфер 11 симв. имени (первые 11 байт) T2364: ds 8 ; имя файла T236C: ds 3 ; расш. ; ds 21 ; 11+21=32 ;------------------------------------------------- ; Преобразовать имя 8.3 -> 11 формат ; вход: hl = 8.3 имя ; de = буфер имени 11 симв. формата ; при ошибке CF - недоп. имя ;------------------------------------------------- A2384: push hl push de ld h,d ld l,e inc de ld (hl)," " ld bc,10 ldir pop de pop hl ld a,(hl) cp "." scf jr z,A239A cp " "+1 A239A: ld a,EINVFNAM ; код "неверное имя" ret c ld bc,0902h ; b=счетчик A23A0: ld a,(hl) cp " "+1 ccf ret nc cp '"' jr z,A23E9 ; ошибка cp "*" jr z,A23ED cp "+" jr z,A23E9 ; ошибка cp "," jr z,A23E9 ; ошибка cp "." jr z,A23FE cp "/" jr z,A23E9 ; ошибка cp ":" jr z,A23E9 ; ошибка cp ";" jr z,A23E9 ; ошибка cp "<" jr z,A23E9 cp "=" jr z,A23E9 cp ">" jr z,A23E9 cp "[" jr z,A23E9 cp '\' jr z,A23E9 cp "]" jr z,A23E9 cp "|" jr z,A23E9 call upper ; a..z -> A..Z ld (de),a inc hl inc de djnz A23A0 A23E9: ld a,EINVFNAM ; код "неверное имя" scf ret ; A23ED: ld a,"?" inc hl djnz A23F6 jr A23E9 ; A23F6: ld (de),a inc de djnz A23F6 ld b,1 jr A23A0 A23FE: ld a," " inc hl djnz A240D A2403: ld b,4 dec c jr nz,A23A0 jr A23E9 ; код "неверное имя" ; A240D: ld (de),a inc de djnz A240D jr A2403 ; a..z -> A..Z upper: cp "a" ret c cp "z"+1 jr nc,A2425 sub 20h ret ; A2425: cp "а" ; русская ret c cp "п"+1 jr nc,A2430 sub 20h ret ; A2430: cp "р" ; русская ret c cp "Ё" jr nc,A243B sub 50h ret ; A243B: cp "ё" ret nz dec a ; ё -> Ё ret ;///////////////////////////////////////////////////////////////////// ; Функция #21. Текущая дата и время. ; ; вход: нет ; выход: D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; C - день недели ;///////////////////////////////////////////////////////////////////// Func_21:ld c,0F5h rst 08h jp c,A24D0 ld d,7 ; номер регистра call A24BB ; чтение регистров CMOS push af ld d,8 call A24BB pop de ld e,a push de ld d,4 call A24BB push af ld d,2 call A24BB pop de ld e,a push de ld d,0 call A24BB push af ld d,6 ld c,0F6h rst 08h pop de ld e,a push de ld d,9 call A24BB push af ld d,32h ld c,0F6h rst 08h db 0DDh ld h,a pop af cp 80 ;50h push af jr c,A248B ld a,19h db 0DDh cp h jr z,A249A jr A2491 ; A248B: ld a,20h db 0DDh cp h jr z,A249A A2491: push af ld d,32h ld c,0F7h rst 08h pop af db 0DDh ld h,a A249A: pop af db 0DDh ld l,a db 0DDh ld a,h call A24BE ld l,a ld h,0 ld c,l ld b,h db 0DDh ld h,b add hl,hl add hl,hl add hl,bc add hl,hl ld b,h ld c,l add hl,hl add hl,hl add hl,bc add hl,hl ex de,hl add ix,de pop bc pop hl pop de and a ret ; Чтение регистров CMOS ; вход: d=номер регистра A24BB: ld c,0F6h rst 08h A24BE: ld e,a rrca rrca rrca rrca and 0Fh ld d,a add a,a add a,a add a,d add a,a ld d,a ld a,e and 0Fh add a,d ret A24D0: ld de,(D255D) ld hl,(D255F) ld bc,(D2561) ld ix,(D2563) and a ret A24E1: ld c,0 ld (D255D),de ld (D255F),hl ld (D2561),bc ld (D2563),ix and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #22. Установить текущую дату и время. ; ; вход: D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_22:push ix push bc push hl push de ld c,0F5h rst 08h jr c,A24E1 pop af push af ld d,7 ; номер регистра call A2544 ; запись регистров CMOS pop bc ld a,c ld d,8 call A2544 pop af push af ld d,4 call A2544 pop bc ld a,c ld d,2 call A2544 pop af push af ld d,0 call A2544 pop bc ld a,c ld d,6 ld c,0F7h rst 08h pop hl xor a ld de,100 A252E: inc a sbc hl,de jr nc,A252E add hl,de dec a push hl ld d,32h call A2544 pop bc ld a,c ld d,9 call A2544 and a ret ; Запись регистров CMOS ; вход: d=номер регистра A2544: call A254B ld c,0F7h rst 08h ret ; A254B: ld bc,0AFFh ; константа A254E: inc c sub b jr nc,A254E add a,b ld b,a ld a,c rlca rlca rlca rlca and 0F0h or b ret ; Дата по-умолчанию D255D: dw 0101h ; день:месяц D255F: dw 0000h ; часы:минуты D2561: dw 0001h ; 00h=секунды D2563: dw 2005 ; год ;///////////////////////////////////////////////////////////////////// ; Функция #17. Информация о дате и времени файла. ; ; вход: A - дескриптор файла ; выход: D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_17:call search_handle ; поиск дескр. файла ret c ; не найден ; время/дату из структуры дескр. ld e,(iy+22) ; время ld d,(iy+23) ; ld c,(iy+24) ; дата ld b,(iy+25) ; call A25C3 ; раскодировать время/дату and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #18. Изменение даты и времени файла. ; ; вход: A - дескриптор файла ; D - день ; E - месяц ; IX - год ; H - час ; L - минуты ; B - секунды ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_18:push af call A2599 ; закодировать время/дату pop af ; дескриптор push de push bc call search_handle ; поиск дескр. файла pop bc pop de ret c ; не найден ; время/дату в структуру дескр. ld (iy+22),e ; время ld (iy+23),d ; ld (iy+24),c ; дата ld (iy+25),b ; set 7,(iy+41) ; уст. признак изменения файла and a ret ;------------------------------------------------- ; Закодировать время/дату ; вход: de - день/месяц ; hl - часы/минуты ; b - секунды ; ix - год ; выход: de - время ; bc - месяц/день ; ix - год ;------------------------------------------------- A2599: ld a,l rlca rlca sla a rl h sla a rl h sla a rl h srl b or b ld l,a ld bc,-1980 add ix,bc ld a,e rlca rlca rlca rlca and 0F0h db 0DDh ld b,l sla a rl b or d ld c,a ex de,hl and a ret ;------------------------------------------------- ; Раскодировать время/дату ; вход: de - время ; bc - месяц/день ; ix - год ; выход: de - день/месяц ; hl - часы/минуты ; b - секунды ; ix - год ;------------------------------------------------- A25C3: ex de,hl ld a,c and 1Fh ld d,a srl b rr c ld a,c rrca rrca rrca rrca and 0Fh ld e,a ld c,b ld b,0 ld ix,1980 add ix,bc ld a,l and 1Fh add a,a ld b,a srl h rr l srl h rr l srl h rr l srl l srl l and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #1D. Смена текущего каталога. ; Меняет текущий каталог и текущий диск, если он указан в файловой ; спецификации. Если путь начинается с "\" - это означает путь от ; корневого каталога, иначе от текущего. ; ; вход: HL - указатель на имя каталога ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_1D:call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ld a,(hl) or a call nz,A2164 ret ;///////////////////////////////////////////////////////////////////// ; Функция #1B. Создание каталога. ; ; вход: HL - указатель на имя каталога ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_1B:call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c call A228F ; прочитать список каталога call search_rec_dir ; поиск записи каталога в списке диска ld a,EEXISDIR ; код "каталог существует" ccf ret c ; каталог найден call A10FD ret c push hl ld de,(D150E) ; номер кластера call A11C4 ; записать в кеш FAT-а номер кластера call A128B ; подкл. банку кеша FAT и записать его на диск ld hl,T2364 ld de,T1F3B ld bc,11 ldir ex de,hl ld a,10h ; атрибут записи каталога ld (hl),a inc hl ld bc,0A00h ; b=счетчик ld (hl),c inc hl djnz $-2 push hl call Func_21 ; узнать тек. дату и время call A2599 ; закодировать время/дату pop hl ld (hl),e ; de=время inc hl ld (hl),d inc hl ld (hl),c ; день inc hl ld (hl),b ; месяц inc hl pop de push de ld (hl),e inc hl ld (hl),d inc hl ld bc,0400h ; b=счетчик ld (hl),c inc hl djnz $-2 call A1F5B ; скопир. новую запись в список диска (каталога) call flush_cash_dir ; сбросить кеш каталога на диск ld hl,T0400 ; буфер ld (hl),"." ; запись тек. каталога ld bc,0A20h ; b=счетчик, c=пробел inc hl ld (hl),c djnz $-2 inc hl ld de,T1F3B+11 ; ячейка атрибутов файла ex de,hl ld bc,21 ldir ex de,hl ld (hl),"." ; запись родит. каталога inc hl ld (hl),"." ld bc,0920h ; b=счетчик, c=пробел inc hl ld (hl),c djnz $-2 inc hl push hl xor a ; лог. номер стр. (кэш списка каталога) call set_dos_page ; подключить банку расширения ДОС pop hl push af ; старая банка порта ld a,(LC000) cp "." ld de,LC000+11 ; атрибуты записи jr z,A26A9 ld ix,T1F3B xor a ld (ix+26),a ld (ix+27),a ld de,T1F3B+11 ; ячейка атрибутов файла A26A9: ex de,hl ld bc,21 ldir pop af out (0E2h),a ; восст. порт ex de,hl ld d,h ld e,l inc de ld (hl),0 ld bc,447 ldir pop hl call A1CB8 ld a,(D0083) ; секторов на кластер A26C4: push af push hl ; ст. разряд push ix ; номер лог. сектора in a,(0E2h) push af in a,(82h) out (0E2h),a ld de,LC400 ; буфер ld b,1 ; число секторов ld a,(disk) ; номер диска ld c,6 ; запись секторов rst 18h pop af out (0E2h),a ld hl,T0400 ; откуда ld de,T0400+1 ; куда ld bc,512-1 ld (hl),0 ldir pop ix pop hl inc ix db 0DDh ld a,h db 0DDh or l jr nz,$+3 inc hl pop af dec a jr nz,A26C4 and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #1C. Удаление каталога. ; Можно удалить только пустой каталог. ; ; вход: HL - указатель на имя каталога ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_1C:call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c ld hl,T2364 ld bc,11 ld a,"?" cpir ld a,EINVFNAM ; код "неверное имя" scf ret z call A228F ; прочитать список каталога call search_rec_dir ; поиск записи каталога в списке диска ret c ; не найден ld hl,(D1F55) push ix A2724: push hl call A1CB8 ld a,(D0083) ; секторов на кластер A272B: push af push hl ; ст. разряд push ix ; номер лог. сектора in a,(0E2h) push af in a,(82h) out (0E2h),a ld de,LC400 ; буфер ld bc,0105h ; чтение одного сектора ld a,(disk) ; номер диска rst 18h pop af out (0E2h),a ld b,16 ld hl,T0400 A2748: ld a,(hl) or a jr z,A2783 cp "." jr z,A2761 cp 0E5h ; байт удаления файла jr z,A2761 ld de,11 ; смещ. до байта атрибутов add hl,de ld a,(hl) sbc hl,de ;bit 3,a ;@@ бит "метка тома" and 00001000b ; 7 тактов jr z,A278A A2761: ld de,32 add hl,de djnz A2748 pop ix pop hl inc ix db 0DDh ld a,h db 0DDh or l jr nz,$+3 inc hl pop af dec a jr nz,A272B pop hl ; номер кластера call A1132 ; прочитать из кеша FAT-а номер след. кластера ex de,hl ; hl=номер след. кластера jr nc,A2724 ; не конец цепочки A277E: pop ix jp mark_delete ; пометить запись как "удаленная" ; A2783: pop ix pop hl pop af pop hl jr A277E ; A278A: pop ix pop hl pop af pop hl pop ix ld a,ENOEMPTY ; код "каталог не пуст" scf ret D2795: dw 0 ;///////////////////////////////////////////////////////////////////// ; Функция #47. Получение информации приложения. ; ; вход: HL - буфер данных ; B - номер подфункции: ; B=0 - получение параметров командной строки ; B=1 - получение полного пути к каталогу программы ; B=2 - получение полного пути и имени файла программы ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_47: inc b djnz A27A8 ex de,hl xor a ld (de),a ld hl,(D2795) ld c,(hl) inc c ret z inc hl ldir and a ret ; Получение параметров командной строки A27A8: djnz A27CF ex de,hl ld hl,(D2795) ld c,(hl) inc hl add hl,bc inc hl inc hl push hl ld bc,256 xor a cpir ld a,'\' cpdr inc hl inc hl pop bc and a sbc hl,bc ld a,b ld b,h ld h,a ld a,c ld c,l ld l,a ldir xor a ld (de),a ret ; Получение полного пути к каталогу программы A27CF: djnz A27E1 ex de,hl ld hl,(D2795) ld c,(hl) inc hl add hl,bc inc hl inc hl A27DA: ld a,(hl) ldi or a jr nz,A27DA ret ; A27E1: ld a,EINVFNC ; код "неверный номер функции" scf ret ;///////////////////////////////////////////////////////////////////// ; Функция #45. Разбор командной строки. ; ; вход: HL - указатель командной строки ; DE - указатель на буфер пользователя ; B - номер подфункции: ; 0 - Разобрать строку ; 1 - Выделить имя диска ; 2 - Выделить директорию ; 3 - Выделить имя файла ; 4 - Выделить расширение файла ; 5 - Выделить имя диска, путь к файлу, имя файла и расш. файла ; 6 - Зарезервировано ; 7 - Выделить параметр командной строки ; 8 - Преобразовать из 11 символьного формата в формат ДОС ; 9 - Преобразовать из формата ДОС в 11 символьный формат ; выход: нет ;///////////////////////////////////////////////////////////////////// Func_45:exx ld hl,T0400 ld (D2947),hl ld hl,T2952 ld (D2943),hl ld hl,T295F ld (D2945),hl ld hl,T2949 ld (D2941),hl exx inc b dec b jr z,A2857 ; разобрать строку dec b jr z,A2825 ; выделить имя диска dec b jr z,A2845 ; выделить директорию dec b jr z,A284B ; выделить имя файла dec b jr z,A2851 ; выделить расширение файла dec b jr z,A2859 ; выделить диск, путь, файл и расш. dec b ; зарезервировано jr z,A2821 dec b jp z,Func_43 ; выделить параметр ком-строки dec b jp z,A1FB8 ; преобр. имя 11 -> 8.3 формат dec b jp z,A2384 ; преобр. имя 8.3 -> 11 формат A2821: ld a,EINVFNC ; код "неверный номер функции" scf ret ; Выделить имя диска A2825: ld (D2941),de call A287C ret c ld de,(D2941) ld a,(de) dec a cp -1 ret z cp "@" jr c,A2841 cp "Z" jr nc,A2841 sub "A"-1 ret ; A2841: ld a,EINVDRV ; код "не верный номер устройства" scf ret ; Выделить директорию A2845: ld (D2947),de jr A287C ; Выделить имя файла A284B: ld (D2943),de ; куда jr A287C ; Выделить расширение файла A2851: ld (D2945),de jr A287C ; Разобрать строку A2857: jr A287C ; Выделить диск, путь, файл и расш. A2859: ex de,hl ld c,(hl) inc hl ld b,(hl) inc hl ld (D2941),bc ld c,(hl) inc hl ld b,(hl) inc hl ld (D2947),bc ld c,(hl) inc hl ld b,(hl) inc hl ld (D2943),bc ld c,(hl) inc hl ld b,(hl) ld (D2945),bc ex de,hl jr A287C A287C: ex af,af' exx xor a ld hl,(D2947) ld (hl),a ld hl,(D2943) ; адрес буфера под имя файла ld (hl),a ld hl,(D2945) ld (hl),a ld hl,(D2941) ld (hl),a exx ex af,af' A2891: ld de,T2934 ld bc,0D01h ; счетчики A2897: ld a,(hl) call upper ; a..z -> A..Z ld (de),a inc hl inc de inc c ; ++счетчик cp '\' jr z,A2916 cp ":" jr z,A2900 cp " "+1 jr c,A28BF cp "?" jr z,A28B9 cp "*" jr z,A28B9 A28B3: djnz A2897 ld a,EINVFNAM ; код "неверное имя" scf ret ; A28B9: ex af,af' set 7,a ex af,af' jr A28B3 ; A28BF: ld a,2 cp c jr z,A28FD push hl ld hl,T2934 ld de,(D2943) ; адрес буфера под имя файла ld b,0 dec c dec c ld a,c ldir ld c,a xor a ld (de),a ld hl,(D2943) ; адрес буфера под имя файла ld a,"." cpir jr nz,A28F8 ld c,3 ld de,(D2945) A28E5: ld a,(hl) or a jr nz,A28EC ld a," " dec hl A28EC: ld (de),a inc hl inc de dec c jr nz,A28E5 xor a ld (de),a ex af,af' set 1,a ; указано расш. файла ex af,af' A28F8: ex af,af' set 0,a ; указано имя файла ex af,af' pop hl A28FD: ex af,af' and a ret A2900: xor a ld (de),a push hl ld hl,T2934 ld de,(D2941) ld b,0 ldir pop hl ex af,af' set 3,a ; указано имя диска ex af,af' jp A2891 A2916: xor a ld (de),a push hl push bc ld hl,(D2947) ld bc,255 cpir dec hl ex de,hl ld hl,T2934 ; 12 пробелов pop bc ld b,0 ldir pop hl ex af,af' set 2,a ; указан путь файла ex af,af' jp A2891 T2934: db " ",0 ; 12 пробелов D2941: dw T2949 D2943: dw T2952 D2945: dw T295F D2947: dw T0400 ; 512 байт, ".", ".." записи T2949: ds 9 T2952: db " ",0 ; 9 пробелов T295F: db " ",0 ;///////////////////////////////////////////////////////////////////// ; Функция #43. Выделить параметр командной строки. ; ; вход: HL - указатель командной строки ; DE - буфер для выдел. параметра ; выход: HL - указатель на след. параметр ком-строки ; CF=0 - конец строки не достигнут (есть другие параметры) ; CF=1 - конец строки (в буфер перенесён последний параметр или ноль) ;///////////////////////////////////////////////////////////////////// Func_43:xor a ld (de),a A2965: ld a,(hl) inc hl cp " " ret c jr z,A2965 A296C: ld (de),a ld a,(hl) inc hl inc de cp " "+1 jr nc,A296C cp " " ld a,0 ld (de),a ret ;///////////////////////////////////////////////////////////////////// ; Функция #3C. Информация о памяти. ; ; вход: нет ; выход: HL - общее кол-во страниц ; BC - кол-во своб. страниц ;///////////////////////////////////////////////////////////////////// Func_3C:ld c,0C0h rst 08h ret ;///////////////////////////////////////////////////////////////////// ; Функция #3D. Выделение блока памяти. ; ; вход: B - размер блока в страницах по 16kB ; выход: A - идентификатор блока памяти, если CF=0 ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_3D:ld c,0C2h rst 08h ld e,a ld a,ENOMEM ; код "не хватает памяти" ret c ld d,0 ld hl,list_pages ; массив списка выдел. страниц add hl,de ld a,(D2E70) ; уровень текущей программы ld (hl),a ld a,e and a ret ;///////////////////////////////////////////////////////////////////// ; Функция #3E. Освобождение блока памяти. ; ; вход: A - идентификатор блока памяти ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_3E:ld e,a ld d,0 ld hl,list_pages ; массив списка выдел. страниц add hl,de ld a,(D2E70) ; уровень текущей программы cp (hl) ld a,EINVMEM ; код "не существующий блок памяти" scf ret nz push de ld a,e ld c,0C3h rst 08h pop de ld a,EINVMEM ; код "не существующий блок памяти" ret c ld hl,list_pages ; массив списка выдел. страниц add hl,de xor a ld (hl),a ret ;///////////////////////////////////////////////////////////////////// ; Функция #3F. Изменение блока памяти. ; ; вход: A - идентификатор блока памяти ; B - новый размер блока ; выход: A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_3F:ld e,a ld d,0 ld hl,list_pages ; массив списка выдел. страниц add hl,de ld a,(D2E70) ; уровень текущей программы cp (hl) ld a,EINVMEM ; код "не существующий блок памяти" scf ret nz ld d,b push de ld a,e call A29EE pop de ld a,EINVMEM ; код "не существующий блок памяти" ret c ld a,b cp d ret z jr c,A29DB ld b,d ld a,e ld c,9Dh rst 08h ld a,b ld c,0C3h rst 08h xor a ret ; A29DB: ld a,d sub b ld b,a ld c,e push bc ld c,0C2h rst 08h pop bc ld b,a ld a,ENOMEM ; код "недостаточно памяти" ret c ld a,c ld c,9Eh rst 08h xor a ret A29EE: ld b,-1 ld c,a A29F1: inc b push bc ld a,c ld c,0C4h rst 08h pop bc jr nc,A29F1 or a scf ret z xor a ret A29FF: ld hl,list_pages ; массив списка выдел. страниц ld bc,256 A2A05: ld a,(D2E70) ; уровень текущей программы cpir ret nz push hl push bc dec hl and a ld de,256 sbc hl,de ld a,l call Func_3E ; освоб. блок памяти pop bc pop hl jr A2A05 ;///////////////////////////////////////////////////////////////////// ; Функция #38. Подключение страницы памяти. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; H - биты 6 и 7 задают номер окна, в которое будет подкл. страница ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_38:bit 7,h jr z,Func_39 ; в 1-е bit 6,h jr z,Func_3A ; во 2-е jr Func_3B ; в 3-е ;///////////////////////////////////////////////////////////////////// ; Функция #39. Подключение страницы памяти в первое окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_39:ld c,0C4h ex de,hl rst 08h ex de,hl ret c ld c,0A2h in b,(c) out (c),a ld a,b ret ;///////////////////////////////////////////////////////////////////// ; Функция #3A. Подключение страницы памяти во второе окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_3A:ld c,0C4h ex de,hl rst 08h ex de,hl ret c ld c,0C2h ; порт in b,(c) out (c),a ld a,b ret ;///////////////////////////////////////////////////////////////////// ; Функция #3B. Подключение страницы памяти в третье окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_3B:ld c,0C4h ex de,hl rst 08h ex de,hl ret c ld c,0E2h in b,(c) out (c),a ld a,b ret ;///////////////////////////////////////////////////////////////////// ; Функция #40. Выполнить файл. ; ; вход: HL - указатель на имя файла ; B=0 - загрузить и выполнить программу ; выход: A - код завершения, если CF=0 ; код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_40: inc b dec b jp z,A2AFE dec b jp z,A2B09 ld a,EINVFNC ; код "не верный номер функции" scf ret A2A5D: ld a,(hl) inc hl cp '\' ret z cp "/" ret z cp " "+1 jr nc,A2A5D ret A2A6A: ld a,2 ; лог. номер стр. (path, перем. окруж.) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта call Func_02 ; получить номер тек. диска add a,"A" ld hl,LFD00 ld (hl),a inc hl ld a,":" ld (hl),a inc hl call Func_1E ; инфа о тек. каталоге call A2AC1 ld hl,LFC80 A2A87: ld e,(hl) inc hl ld d,(hl) inc hl bit 1,(hl) inc hl push hl push bc ex de,hl call z,A2AB8 call Func_1D ; смена текущего каталога jr c,A2AAC ld hl,D2E7C ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат jr c,A2AAC call A2CB6 ; сравнить/добавить расш. с "EXE" (если задано) jr c,A2AAC ; не совпадает call search_rec_file ; поиск записи файла в списке диска A2AAC: pop bc pop hl jr nc,A2AB3 ; запись найдена djnz A2A87 scf A2AB3: pop bc ld a,b out (0E2h),a ; восст. порт ret A2AB8: push hl ld hl,LFD00 call Func_1D ; смена текущего каталога pop hl ret A2AC1: ld hl,LFC7F ld de,LFDFF ld b,0 A2AC9: ld (hl),c inc hl xor a ld (de),a ld c,a inc de ld (hl),e inc hl ld (hl),d inc hl inc b A2AD4: ld a,(de) cp '\' jr nz,A2ADB set 1,c A2ADB: ld a,(de) cp ";" jr z,A2AC9 inc de cp ":" jr z,A2AD4 or a jr nz,A2ADB ld (hl),c inc hl ld (hl),a inc hl ld (hl),a ret T2AEE: db "PATH=",0 ; имя перем. окружения ; ++уровня текущей программы A2AF4: ld hl,D2E70 inc (hl) ret ; --уровня текущей программы A2AF9: ld hl,D2E70 dec (hl) ret ;------------------------------------------------------------------------ ; Загрузить и выполнить программу. ; функ. 40h, B=0. ; ; 1) Открывает exe-файл на чтение; ; 2) Считывает в рабочую область префикс exe-файла; ; 3) Выделяет блок памяти, требуемый для загрузки всего файла или первичного ; загрузчика, если его размер не равен нулю; ; 4) Сохраняет стек; ; 5) Подключает страницы из выделенного блока; ; 6) Строит префикс запуска программы и устанавливает на него регистр IX; ; 7) Считывает файл по адресу указанному в смещении 16 (Адрес расположения ; кода в памяти); ; 8) Закрывает exe-файл, если это не первичный загрузчик; ; 9) Устанавливает стек равным значению из смещения 20 (Адрес расп. стека); ; 10) Передает управление по адресу указанному в смещении 18 (Адрес запуска); ; ; Префикс запуска файла: ; ; -03 1 db ? ; Дескриптор файла, если exe-файл с первичным загрузчиком ; -02 1 db ? ; Идентификатор блока памяти ; -01 1 db ? ; Уровень текущей программы ; +00 1 db ? ; Длина ком-строки ; +01 127 ds ? ; Параметры ком-строки, заканчивается нулем ;------------------------------------------------------------------------ A2AFE: ld (D2E78),hl call A2A5D ld hl,(D2E78) jr c,A2B32 ; B=1. A2B09: ld (D2E78),hl ld a,1 ld (D1F3A),a ; раб. ячейка call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c call A2CB6 ; сравнить/добавить расш. с "EXE" (если задано) ld a,ENOFILE ; код "файл не найден" ret c call A2AF4 call A1E89 jr nc,A2B75 jr A2AF9 ; A2B32: ld a,1 ld (D1F3A),a ; раб. ячейка call A20F8 ; тест на допуст. имя и настр. на диск ret c ld hl,D213A ; 8.3 имя ld de,T2364 ; буфер имени 11 симв. формата call A2384 ; преобр. имя 8.3 -> 11 формат ret c call A2CB6 ; сравнить/добавить расш. с "EXE" (если задано) ld a,ENOFILE ; код "файл не найден" ret c call A2AF4 call A1E89 jr nc,A2B75 call A2AF9 ld hl,T2AEE ; имя перем. окружения "PATH=" ld de,LFE00 ; куда ld b,1 ; получить перем. окружения call Func_46 ; функция сист. окружения ld hl,(D2E78) ld de,D2E7C A2B67: ld a,(hl) ldi or a jr nz,A2B67 call A2A6A ld hl,(D2E78) jr A2B09 ; A2B75: ld (D2E76),a ; сохр. дескр. файла ld hl,D2E7C ; буфер ld de,128 ; число чит. байт ld a,(D2E76) ; дескр. файла call Func_13 ; чтение из файла jp c,A2CD7 ld ix,D2E7C ld hl,(D2E7C) ld de,"XE" ; сигнатура sbc hl,de ld a,EINVEXE ; код "неправильный EXE-файл" scf jp nz,A2CD7 ld a,(ix+3) or a ld a,ENSUPEXE ; код "не поддерж. версия EXE-файла" scf jp nz,A2CD7 ld de,(D2E84) ld a,e or d jp nz,A2CE4 ld l,a ld h,a push hl pop ix ld b,2 ; от конца файла ld a,(D2E76) ; дескр. файла call Func_15 ; перемещение указателя в файле ld de,(D2E8C) ld a,d and 3Fh ld d,a add ix,de ld de,0 adc hl,de ld a,xh sla a rl l rl h sla a rl l rl h or xl jr z,1F inc hl 1: ld a,h or a jp nz,A2CD5 ld b,l call Func_3D ; выделить блок памяти jp c,A2CD5 ld (D2E77),a ; идентиф. блока памяти exx pop de ld hl,0 add hl,sp ld sp,(D2E7A) push hl push de in a,(0E2h) ld d,a in a,(0C2h) ld e,a in a,(0A2h) push de push af ld (D2E7A),sp ld sp,hl exx ld a,(D2E77) ; идентиф. блока памяти ld de,T2E71 ld bc,00C4h rst 08h ld (de),a inc de ld a,(D2E77) ; идентиф. блока памяти ld bc,01C4h rst 08h ld (de),a inc de ld a,(D2E77) ; идентиф. блока памяти ld bc,02C4h rst 08h ld (de),a inc de ld a,(D2E77) ; идентиф. блока памяти ld bc,03C4h rst 08h ld (de),a ld hl,(D2E78) ld de,T0400+1 call A2E52 ld a,128 ;80h sub b ld (T0400),a ld sp,T307A ld a,0FFh ; номер стр. out (0A2h),a out (0C2h),a out (0E2h),a ld hl,(D2E8C) ld de,T2E71 ld a,h and 0C0h cp 40h ; 40(00)h jr z,A2C5E cp 80h ; 80(00)h jr z,A2C62 cp 0C0h ; 0C0(00)h jr z,A2C66 A2C5E: ld a,(de) out (0A2h),a inc de A2C62: ld a,(de) out (0C2h),a inc de A2C66: ld a,(de) out (0E2h),a call A2DE9 ld hl,(D2E82) ld ix,(D2E80) ld b,0 ; от начала файла ld a,(D2E76) ; дескр. файла call Func_15 ; перемещение указателя в файле ld sp,L403F ld de,(D2E8C) xor a ld l,a ld h,a sbc hl,de ex de,hl ; de=число чит. байт ld hl,(D2E8C) ; буфер ld a,(D2E76) ; дескр. файла call Func_13 ; чтение из файла ld a,(D2E76) ; дескр. файла call Func_12 ; закрыть файл ld sp,(D2E90) ld hl,(D2E8C) ld de,128 ;T0080 and a sbc hl,de ex de,hl db 0DDh ld h,d db 0DDh ld l,e ld hl,(D2E8E) ld de,A2CB3 ; адрес п/п "завершить процесс" push de push hl ret ; A2CB3: jp Func_41 ; завершить программу (процесс) ;------------------------------------------------- ; Если расш. файла не задано, задать "exe". ; Если расш. файла задано, сравнить его с "exe". ;------------------------------------------------- A2CB6: ld hl,T2E6D ; "EXE" ld de,T236C ld b,3 ld a,(de) cp " " jr nz,A2CCB ; задано расш. ldi ldi ldi xor a ret ; ; сравнить расш. с "EXE" A2CCB: ld a,(de) cp (hl) scf ret nz ; не совпадает inc hl inc de djnz A2CCB xor a ; Ok ret A2CD5: ld a,1Eh A2CD7: push af ld a,(D2E76) ; дескр. файла call Func_12 ; закрыть файл ld hl,D2E70 dec (hl) ; --уровня текущей программы pop af ret A2CE4: ex de,hl ld de,(D2E8C) ld a,d and 3Fh ld d,a adc hl,de xor a sla h rla sla h rla ld b,a ld a,h or l jr z,A2CFC inc b A2CFC: call Func_3D ; выделить блок памяти jr c,A2CD5 ld (D2E77),a ; идентификатор блока памяти exx pop de ld hl,0 add hl,sp ld sp,(D2E7A) push hl push de in a,(0E2h) ld d,a in a,(0C2h) ld e,a in a,(0A2h) push de push af ld (D2E7A),sp ld sp,hl exx ld de,T2E71 ld bc,00C4h ld a,(D2E77) ; идентификатор блока памяти rst 08h ld (de),a inc de ld bc,01C4h ld a,(D2E77) ; идентификатор блока памяти rst 08h ld (de),a inc de ld bc,02C4h ld a,(D2E77) ; идентификатор блока памяти rst 08h ld (de),a inc de ld bc,03C4h ld a,(D2E77) ; идентификатор блока памяти rst 08h ld (de),a ld hl,(D2E78) ld de,T0400+1 call A2E52 ld a,80h sub b ld (T0400),a ld sp,T307A ld a,0FFh ; номер стр. out (0A2h),a out (0C2h),a out (0E2h),a ld hl,(D2E8C) ld de,T2E71 ld a,h and 0C0h cp 40h ; 40(00)h jr z,A2D76 cp 80h jr z,A2D7A cp 0C0h jr z,A2D7E A2D76: ld a,(de) out (0A2h),a inc de A2D7A: ld a,(de) out (0C2h),a inc de A2D7E: ld a,(de) out (0E2h),a call A2DE9 ld hl,(D2E82) ld ix,(D2E80) ld b,0 ; от начала файла ld a,(D2E76) ; дескр. файла call Func_15 ; перемещение указателя в файле ld sp,L403F ld hl,(D2E8C) ; буфер ld de,(D2E84) ; число чит. байт ld a,(D2E76) ; дескр. файла call Func_13 ; чтение из файла ld sp,(D2E90) ld hl,(D2E8C) ld de,128 and a sbc hl,de ex de,hl ld xh,d ld xl,e ld hl,(D2E8E) ld de,A2CB3 ; дос-заглушка push de push hl ret ;///////////////////////////////////////////////////////////////////// ; Функция #41. Завершить программу (процесс). ; ; вход: B - код завершения ; выход: A - код ошибки, если CF=1 ; ; Выход из EXE-файла: ; ; 1) Освобождаются все блоки памяти которые выделялась данному приложению. ; 2) Восстанавливаются страницы которые были подключены до запуска EXE-файла. ; 3) Вспоминается стек. ; 4) В регистр A помещается код возврата и выполняется RET. ; ;///////////////////////////////////////////////////////////////////// Func_41: ld a,b ld (return_code),a ; код завершения программы call A29FF ld hl,D2E70 dec (hl) ; --уровня текущей программы ld sp,(D2E7A) pop af pop hl out (0A2h),a ld a,l out (0C2h),a ld a,h out (0E2h),a pop de pop hl ld (D2E7A),sp ld sp,hl ex de,hl ld a,(return_code) ; код завершения программы and a jp (hl) ;///////////////////////////////////////////////////////////////////// ; Функция #42. Получить код завершения программы. ; ; вход: нет ; выход: A - код завершения ;///////////////////////////////////////////////////////////////////// Func_42:ld a,(return_code) and a ret A2DE9: ld hl,(D2E8C) dec h ld d,h ld e,l inc de ld bc,00FFh ld (hl),b ldir ex de,hl dec h ld de,128 ;T0080 add hl,de ex de,hl db 0DDh ld h,d db 0DDh ld l,e ld hl,T0400 ; откуда ld c,(hl) inc c ldir ex de,hl ld (hl),b ld a,(D2E70) ; уровень текущей программы ld (ix-1),a ; в префикс exe-файла ld a,(D2E77) ; идентификатор блока памяти ld (ix-2),a ; в префикс exe-файла ld a,(D2E76) ; дескр. файла ld (ix-3),a ; в префикс exe-файла inc hl ld (hl),b inc hl call Func_02 ; получить номер тек. диска add a,"A" ld (hl),a inc hl ld a,":" ld (hl),a inc hl push hl call Func_1E ; инфа о тек. каталоге pop hl xor a ld bc,256 cpir dec hl dec hl ld a,'\' cp (hl) inc hl jr z,A2E3F ld (hl),a inc hl A2E3F: ex de,hl ld hl,D213A A2E43: ld a,(hl) ldi cp " "+1 jr nc,A2E43 dec de xor a ld (de),a ld (D2795),ix ret A2E52: ld bc,8021h A2E55: ld a,(hl) cp c jr c,A2E61 inc hl djnz A2E55 xor a ld (de),a ld b,80h ret A2E61: ld bc,8020h A2E64: ld a,(hl) ld (de),a inc hl inc de cp c ret c djnz A2E64 ret T2E6D: db "EXE" D2E70: db 1 ; уровень текущей программы T2E71: db 0 db 0 db 0 db 0 return_code: db 0 ; код завершения программы (процесса) D2E76: db 0 ; дескр. файла D2E77: db 0 ; идентификатор блока памяти D2E78: dw 0 D2E7A: dw L317B ; адрес стека ; 512 байт. exe-заголовок, после раб. буфер D2E7C: db "EXE" db 0 ; exe версия D2E80: dw 0 ; 512, мл. смещ. кода D2E82: dw 0 ; ст. смещ. кода D2E84: dw 0 ; end-beg, первичный загрузчик dw 0,0,0 ; резерв D2E8C: dw 0 ; адрес загрузки кода D2E8E: dw L0000 ; адрес передачи управления D2E90: ds 490 T307A: ds 257 L317B: db 0 ; начало стека ;///////////////////////////////////////////////////////////////////// ; Функция #46. Системное окружение. ; ; вход: B - номер подфункции: ; B=0, получение системного окружения ; HL - буфер ; B=1, получить переменную окружения ; HL - имя переменной ; DE - буфер для значения переменной ; B=2, установить/удалить переменную окружения ; HL - имя переменной и значение, разделенные символом "=" ; т.е. ПЕРЕМЕННАЯ=ЗНАЧЕНИЕ ; В конце строки должен стоять нуль. ; выход: A - состояние, если CF=0 ; DE - указывает на конец буфера (только для B=1) ; A=0FFh - переменная обнаружена ; A=0 - переменная не обнаружена ; A - код ошибки, если CF=1 ;///////////////////////////////////////////////////////////////////// Func_46: inc b jr z,A318E ; B=#FF dec b jr z,A31B2 ; B=0. получить сист. окружение dec b jr z,A31DB ; B=1. получить перем. окружения dec b jr z,A31FD ; B=2. установить/удалить перем. окружения ld a,EINVFNC ; код "неверный номер функции" scf ret ;------------------------------------------------- ; Инициализация буфера переменных окружения ;------------------------------------------------- A318E: ld a,2 ; лог. номер стр. (path, перем. окруж.) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта ld de,LE400 ; начало буфера переменных окружения xor a ld (de),a inc de ld hl,DEFAULT_ENV ld bc,1 ldir ld (de),a ex de,hl ld de,LE400 ; начало буфера переменных окружения and a sbc hl,de ld (D3296),hl pop af out (0E2h),a ; восст. порт and a ret ;------------------------------------------------- ; Получить сист. окружение ;------------------------------------------------- A31B2: push hl ld a,2 ; лог. номер стр. (path, перем. окруж.) call set_dos_page ; подключить банку расширения ДОС ld h,a ; старая банка порта ld c,0E2h in l,(c) exx ld hl,LE400 ; начало буфера переменных окружения inc hl pop de ld bc,(D3296) exx A31C8: out (c),l exx ld a,(hl) exx out (c),h ; восст. порт exx ld (de),a inc hl inc de dec bc ld a,b or c exx jr nz,A31C8 xor a ret ;------------------------------------------------- ; Получить переменную окружения ;------------------------------------------------- A31DB: push de call A325F ; скопир. строку перем. окруж. в буферы ld a,2 ; лог. номер стр. (path, перем. окруж.) call set_dos_page ; подключить банку расширения ДОС ex af,af' ; старая банка порта call A323D ; найти конец всех переменных ? pop de ld a,0 ld (de),a jr nc,A31F7 A31EE: ld a,(hl) ldi or a jr nz,A31EE dec de ld a,-1 A31F7: ex af,af' out (0E2h),a ; восст. порт ex af,af' and a ret ;------------------------------------------------- ; Установить/Удалить переменную окружения ; ; вход: hl=имя перем. и значение, раздел. символом "=" ;------------------------------------------------- A31FD: ; в D2E7C "EXE" ; в T0400 содержимое system.bat call A325F ; скопир. строку перем. окруж. в буферы ld a,2 ; лог. номер стр. (path, перем. окруж.) call set_dos_page ; подключить банку расширения ДОС push af ; старая банка порта call A323D ; найти конец всех переменных ? jr nc,A3214 xor a cpir ld a,b or c jr z,A3214 ldir A3214: ld a,(T0400) or a jr z,A322D ld hl,D2E7C ; 512 байт, буфер A321D: ld a,(hl) ldi cp "=" ; символ разделения jr nz,A321D ld hl,T0400 ; откуда A3227: ld a,(hl) ldi or a jr nz,A3227 A322D: xor a ld (de),a ld hl,LE400 ; начало буфера переменных окружения ex de,hl sbc hl,de ld (D3296),hl pop af out (0E2h),a ; восст. порт and a ret ; найти конец всех переменных ? A323D: ld hl,LE400 ; начало буфера переменных окружения ld bc,(D3296) push hl A3245: pop de ld de,D2E7C ; 512 байт буфер xor a cpir push hl A324D: ld a,(hl) or a jr z,A325D ld a,(de) cp (hl) inc hl inc de dec bc jr nz,A3245 cp "=" ; символ разделения jr nz,A324D scf A325D: pop de ret ;----------------------------------------------------------- ; Скопировать строку переменной окружения в буферы ; (имя и значение в разные буферы) ; вход: hl=имя перем. и значение, раздел. символом "=" ;----------------------------------------------------------- A325F: ld b,maxlen_env_string ; 255 макс. длина строки (имя+знач.) ld de,D2E7C ; куда xor a ld (de),a ld (T0400),a ; скопир. в "D2E7C" имя переменной A3269: ld a,(hl) inc hl cp "=" ; символ разделения jr z,A3283 ; конец имени or a jr z,A327B ; конец строки call upper ; a..z -> A..Z ld (de),a inc de djnz A3269 jr A3294 ; слишком длинная строка ; значение не задано A327B: ld a,"=" ; символ разделения ld (de),a inc de xor a ld (de),a inc de ret A3283: ld (de),a ; сохр. "=" inc de xor a ld (de),a ; в конец имени перем. ; скопир. в "T0400" значение переменной (строку путей) ld de,T0400 ; 512 байт, буфер ld (de),a ld c,255 ; чтобы "ldi" не портила "b" A328D: ld a,(hl) ldi or a ret z ; конец строки знач. переменной djnz A328D A3294: ld a,b ld (de),a ; обрезать слишком длинную строку inc de scf ret D3296: dw 1 DEFAULT_ENV: db 0 include "mouse.asm" ; код мышки db " " ; 12 ds 20 db "FILENAME.EXT",0 ;------------------------------------------------- ; RST 18h. Вектор дисковых устройств ; вход: a=номер устройства (0-25) ;------------------------------------------------- drv_devices: push hl push bc ; сохр. bc ld c,a add a,a ;1+1=2 add a,c ;2+1=3 ld c,a ld b,0 ld hl,A38FC ; таблица переходов add hl,bc ld a,(hl) inc a jr z,A38F4 ; было a=0FFh dec a inc hl ld c,(hl) ; загр. адрес обработчика inc hl ; ld h,(hl) ; ld l,c pop bc ; восст. bc ex (sp),hl ; адрес в стек ret ; перейти на него ; A38F4: pop bc pop hl ld a,EINVDRV ; код "неверный номер устройства" scf ret A38FA: dw A38FC ; Таблица адресов обработчиков девайсов. 26 элементов (диски A..Z ?). A38FC: db -1 ;00 dw -1 db -1 ;01 dw -1 db -1 ;02 dw -1 db -1 ;03 dw -1 db -1 ;04 dw -1 db -1 ;05 dw -1 db -1 ;06 dw -1 db -1 ;07 dw -1 db -1 ;08 dw -1 db -1 ;09 dw -1 db -1 ;10 dw -1 db -1 ;11 dw -1 db -1 ;12 dw -1 db -1 ;13 dw -1 db -1 ;14 dw -1 db -1 ;15 dw -1 db -1 ;16 dw -1 db -1 ;17 dw -1 db -1 ;18 dw -1 db -1 ;19 dw -1 db -1 ;20 dw -1 db -1 ;21 dw -1 db -1 ;22 dw -1 db -1 ;23 dw -1 db -1 ;24 dw -1 db -1 ;25 dw -1 db -1 ; конец ;----------------------------------------------------------- ; Просканировать систему на FDD/HDD девайсы и RAM-диски ;----------------------------------------------------------- scan_all_devices: xor a ld (last_drive),a ; сбр. ячейку ld hl,A38FC ld (A38FA),hl ; восст. ячейку ; FDD девайсы ld c,a ; c="open device" call A3D7A ; узнать число FDD-девайсов ld de,A3D7A ; адрес обработчика тек. девайса call A397B ; иниц. таблицу переходов ; HDD девайсы xor a ld c,a ; c="open device" call A39CC ; узнать число HDD-девайсов ld de,A39CC ; адрес обработчика тек. девайса call A397B ; иниц. таблицу переходов ; RAM-диски xor a ld c,a ; c="open device" call A3E5E ; узнать число RAM-дисков ld de,A3E5E ; адрес обработчика тек. девайса call A397B ; иниц. таблицу переходов xor a ret ; Инициировать таблицу переходов девайса. ; вход: de=адрес обработчика девайса ; a=число девайсов (0=нет) A397B: ld c,a ld hl,last_drive ; ячейка номера посл. диска add a,(hl) ld (hl),a ld a,c ld c,0 ; сбр. or a ret z ; нет девайсов ld hl,(A38FA) ; тек. полож. в таблице A3989: ld (hl),c ; индекс ? inc hl ld (hl),e ; de=адрес обработчика inc hl ld (hl),d inc hl inc c ; ++индекс ? dec a jr nz,A3989 ld (A38FA),hl ; сохр. новое полож. в таблице dec a ld (hl),a ; a=0FFh ret ;///////////////////////////////////////////////////////////////////// ; Функция #08 (DSS_RESCAN). Пересканировать девайсы системы. ; ; вход: нет ; выход: A - номер последнего лог. диска в системе ;///////////////////////////////////////////////////////////////////// Func_08:di call scan_all_devices ; перескан. все девайсы ld a,(last_drive) ei ret ;///////////////////////////////////////////////////////////////////// ; Функция #09. Номер системного диска. ; Возвращает номер диска, c которого загружена система. ; ; вход: B = 0 (01h - исп. boot-загрузчик системы) ; выход: A - номер системного диска (0=A,1=B,..) ;///////////////////////////////////////////////////////////////////// Func_09: inc b dec b jr z,A39A5 dec b jr z,A39AA ; с какого диска загр. система (для загрузчика) ld a,EINVFNC ; код "неверный номер функции" scf ret ; A39A5: db 3Eh ; ld a,.. boot_disk: db -1 ; номер диска, с которого загружалась система and a ret ; Сообщить DSS с какого диска загружается система. ; Исп. загрузчик системы для иниц. ячейки "boot_disk". A39AA: ld b,a ld c,0 A39AD: push bc ld a,c ld bc,0008h ; получить геометрию диска ld de,55AAh ; сигнатура rst 18h pop bc jr c,A39C3 ; ошибка ex af,af' cp b jr nz,A39C3 ld a,c ld (boot_disk),a ; иниц. ячейку and a ret ; A39C3: inc c ; ++номер boot-диска ld a,(last_drive) ; номер посл. диска системы cp c jr nz,A39AD scf ret ;------------------------------------------------- ; Обработчик HDD (rst 18h) ;------------------------------------------------- A39CC: inc c dec c ; c=0 jr z,A3A01 dec c ; c=1 open jp z,A3BD1 dec c ; c=2 close jp z,A3BD3 dec c ; c=3 media check (смена носителя) jp z,A3BD5 dec c ; c=4 get BPB jp z,A3BD9 dec c ; c=5 input (чтение секторов) jp z,A3C27 dec c ; c=6 output (запись секторов) jp z,A3C1C dec c ; c=7 jp z,A3BCD dec c ; c=8 узнать геометрию диска jp z,A3B34 dec c ; c=9 jr z,A39FD dec c ; c=10 jp z,A3C06 dec c ; c=11 jp z,A3C11 A39FD: ld a,1 ; код "bad command" scf ret ; c=0 A3A01: push iy ld hl,T3A4C ; таблица лог.дисков (16*12) ld (D3D78),hl ; адрес структуры тек. лог. диска ld ix,L4000 ; буфер под список (5 байт) ld c,5Fh ; список дисковых устройств rst 08h xor a ld b,(ix+2) ; кол-во HDD устройств cp b jr z,A3A25 ; нет винтов ; ld c,80h ; мастер на первом канале A3A19: push bc ld a,c ld (D3D6F),a ; номер девайса (80h/81h мастер/слейв) call A3C9A ; узнать лог. диски винта и создать их таблицы pop bc inc c ; слейв на первом канале djnz A3A19 ; A3A25: pop iy ld hl,(D3D78) ; адрес структуры тек. лог. диска ld de,T3A4C ; таблица лог.дисков (16*12) xor a ; счетчик лог. дисков sbc hl,de ret z ; структура первого лог. диска ld de,16 ; размер структуры лог. диска inc a sbc hl,de jr nz,$-3 ; перейти на структуру первого лог. диска and a ; a=кол-во лог.дисков ret ; нет обращения ;L3A3B: ld a,0FFh ;inc hl ;cp (hl) ;ret nz ;inc hl ;cp (hl) ;ret nz ;inc hl ;cp (hl) ;ret nz ;inc hl ;cp (hl) ;ret nz ;inc hl ;cp (hl) ;ret ; Таблица лог. дисков ДОС-а ; ; +0 - номер девайса (80h,...) ; +1,+2,+3,+4 - абс. номер нач. сектора лог. диска ; +5,+6,+7,+8 - размер лог. диска (число секторов) ; ; T3A4C: ds 16*12 ; 192 C..N ; вход: a=0..11 (индекс) ; выход: ix,hl - абс. номер нач. сектора ; a - номер девайса (80h,...) A3B0C: push de push bc push hl ld l,a ld h,0 add hl,hl ;1+1=2 add hl,hl ;2+2=4 add hl,hl ;4+4=8 add hl,hl ;8+8=16 ex de,hl ld iy,T3A4C ; таблица лог.дисков (16*12) add iy,de ld c,(iy+1) ; абсолютный номер ld b,(iy+2) ; начального сектора ld e,(iy+3) ; раздела ld d,(iy+4) ; pop hl add ix,bc adc hl,de ld a,(iy+0) ; тип девайса (80h,...) pop bc pop de ret ;c=8. Узнать геометрию диска (CHS) A3B34: bit 7,b jr nz,A3B49 inc b dec b ; b=0 jr z,A3B6F dec b ; b=1 jr z,A3B5C dec b ; b=2 jr z,A3B60 ld a,EINVFNC ; код "неверный номер функции" scf ret ; A3B49: res 7,b inc b dec b jr z,A3B65 dec b jr z,A3B67 dec b jr z,A3B6B ld a,1 ; код "bad command" scf ret ; A3B5C: ld a,0Bh ; код "failure" scf ret ; A3B60: ld b,l jp A3C32 ; A3B65: and a ret ; A3B67: ld a,0Bh ; код "failure" scf ret ; A3B6B: ld a,0Bh ; код "failure" scf ret ;c=8. Узнать геометрию диска (CHS) ;b=0. ; вход: a - индекс (0..11) A3B6F: ex de,hl ld bc,55AAh ; сигнатура раздела and a sbc hl,bc ld l,a ; индекс раздела ld a,0Bh ; код "failure" scf ret nz push iy ld h,0 add hl,hl ; *16 add hl,hl add hl,hl add hl,hl ld b,h ld c,l ld iy,T3A4C ; таблица лог.дисков (16*12) add iy,bc ld e,(iy+5) ; размер раздела (число секторов) ld d,(iy+6) ; ld l,(iy+7) ; ст. разряд ld h,(iy+8) ; ld a,(iy+0) ; тип девайса (80h,...) ld c,a ld iy,LC1C0 ; LC000+01BEh+2 ?? and 0Fh jr z,A3BA7 ; ld iy,LC1C8 ; LC000+01BEh+0Ah ?? A3BA7: in a,(0E2h) push af ld a,0FEh ; номер стр. out (0E2h),a ld a,(iy+0) exx ld l,(iy+3) ; ld h,(iy+4) ; ld e,(iy+2) ; ld d,0 ld b,d ld c,(iy+1) ; exx ex af,af' pop af out (0E2h),a ld a,c ex af,af' pop iy and a ret A3BCD: ld a,1 ; код "bad command" and a ret A3BD1: xor a ret A3BD3: xor a ret A3BD5: ld a,-1 and a ret A3BD9: push iy push de ld l,a ld h,0 add hl,hl ; *16 add hl,hl add hl,hl add hl,hl ld b,h ld c,l ld iy,T3A4C ; таблица лог.дисков (16*12) add iy,bc ld e,(iy+1) ; мл. разряд номера сектора ld d,(iy+2) ld l,(iy+3) ; ст. разряд ld h,(iy+4) db 0DDh ld l,e db 0DDh ld h,d ld a,(iy+0) ; тип девайса (80h,...) pop de ; буфер pop iy ld bc,0155h ; прочитать один сектор rst 08h ret A3C06: push iy call A3B0C ; получить абс. номер нач. сектора ld c,52h ; чтение секторов в зад. блок памяти rst 08h pop iy ret A3C11: push iy call A3B0C ; получить абс. номер нач. сектора ld c,53h ; ? rst 08h pop iy ret A3C1C: push iy call A3B0C ; получить абс. номер нач. сектора ld c,56h ; записать "b" секторов rst 08h pop iy ret A3C27: push iy call A3B0C ; получить абс. номер нач. сектора ld c,55h ; прочитать "b" секторов rst 08h pop iy ret A3C32: push iy call A3B0C ; получить абс. номер нач. сектора ld c,54h ; проверка секторов (не работает?) rst 08h pop iy ret ; на лог. диск раздела A3C3D: ld e,(iy+8) ; абсолютный (лог.) номер ld d,(iy+9) ; начального сектора ld l,(iy+10) ; раздела ld h,(iy+11) ; ld ix,(D3D70) ; мл.разряд add ix,de ld de,(D3D72) ; ст.разряд adc hl,de db 0DDh ld d,h db 0DDh ld e,l ld ix,(D3D78) ; адрес структуры тек. лог. диска ld (ix+1),e ld (ix+2),d ld (ix+3),l ld (ix+4),h ; ld e,(iy+12) ; размер раздела (число секторов) ld d,(iy+13) ; ld l,(iy+14) ; ст. разряд ld h,(iy+15) ; ld (ix+5),e ld (ix+6),d ld (ix+7),l ld (ix+8),h ld a,(D3D6F) ; номер девайса (80h/81h мастер/слейв) ld (ix+0),a ld de,16 ; размер таблицы лог.диска ? add ix,de ld (D3D78),ix ; адрес структуры след. лог. диска A3C90: ld de,16 ; размер раздела add iy,de pop bc djnz A3CD3 ; проверить след. раздел and a ; конец разделов в MBR ret ;---------------------------------------------------- ; Узнать лог. диски винта и создать их таблицы ;---------------------------------------------------- A3C9A: in a,(0E2h) ; сохр. стр. push af ld a,0FFh ; номер стр. out (0E2h),a call A3CA8 pop af out (0E2h),a ; восст. стр. ret A3CA8: ld ix,0 ld de,0 ld (D3D74),de ld (D3D76),ix ; цикл A3CB7: ld (D3D70),de ; мл.разряд номера сектора ld (D3D72),ix ; ст.разряд call read_one_sector ; прочитать один сектор (MBR, 0-й сектор) ld hl,(LC000+510) ; конец сектора ld de,0AA55h ; сигнатура таблицы разделов and a sbc hl,de jr nz,A3D1A ; не знакомый раздел, выйти ld iy,LC000+01BEh ; на описатель 1-го раздела ld b,4 ; макс. число разделов винта A3CD3: push bc ; тест на расш. раздел ld a,(iy+4) ; байт-идентиф. раздела cp 5 ; "Расширенный" 0-2Гб (MS-DOS 3.3) jr nz,A3CFE ; на след. раздел A3CDB: push iy ld de,(D3D70) ; мл.разряд номера сектора ld ix,(D3D72) ; ст.разряд push de push ix call next_partition ; на след. раздел pop ix pop de ld (D3D70),de ; мл.разряд номера сектора ld (D3D72),ix ; ст.разряд call read_one_sector ; прочитать один сектор pop iy jr A3C90 ; ; тест на расш. раздел A3CFE: cp 0Fh ; "Расширенный" 0-2Гб (Win95) jr z,A3CDB ; на след. раздел ; тест на осн. раздел cp 0Eh ; "Основной" 32Мб-2Гб FAT16 (Win95) jp z,A3C3D ; на лог. диск раздела cp 6 ; "Основной" 32Мб-2Гб FAT16 (MS-DOS 4.0) jp z,A3C3D cp 4 ; "Основной" 16Мб-32Мб FAT16 (MS-DOS 3.0) jp z,A3C3D cp 1 ; "Основной" 0Мб-15Мб FAT12 (MS-DOS 2.0) jp z,A3C3D call test_others; ; поставил jr z,A3CDB; ; на след. раздел pop bc or a ret z ; конец разделов A3D1A: scf ; не знакомый раздел ret ; перейти на след. раздел next_partition: ld hl,(D3D74) ld de,(D3D76) ld a,l or h or e or d ld e,(iy+8) ; абсолютный (лог.) номер ld d,(iy+9) ; начального сектора ld l,(iy+10) ; раздела ld h,(iy+11) ; jr nz,A3D44 ld (D3D74),de ld (D3D76),hl ld ix,(D3D76) jp A3CB7 ; A3D44: ld ix,(D3D74) ; мл. разряд add ix,de push ix ld de,(D3D76) ; ст. разряд adc hl,de push hl pop ix pop de jp A3CB7 ; тест на другие типы разделов ; вход: a - тип раздела ; выход: Z - на след. раздел test_others: cp 0Bh ; "Основной" 512Мб-2Тб FAT32 (OSR2) ret z cp 7 ; NTFS ret z cp 82h ; Linux swap ret z cp 83h ; Linux ret z cp 0EBh ; BeOS ret ;------------------------------------------------- ; Чтение одного сектора в буфер 0C000h ;------------------------------------------------- read_one_sector: push iy ld ix,(D3D70) ; мл.разряд номера сектора ld hl,(D3D72) ; ст.разряд ld de,LC000 ; буфер ld bc,0155h ; прочитать один сектор ld a,(D3D6F) ; номер девайса (80h/81h мастер/слейв) rst 08h pop iy ret D3D6F: db 0 ; номер девайса (80h/81h мастер/слейв) ; D3D70: dw 0 ; мл.разряд номера сектора D3D72: dw 0 ; ст.разряд D3D74: dw 0 D3D76: dw 0 ; D3D78: dw T3A4C ; адрес структуры тек. лог. диска ;------------------------------------------------- ; Обработчик FDD (rst 18h) ;------------------------------------------------- A3D7A: inc c dec c ; c=0 jr z,A3DA7 dec c ; c=1 jr z,A3DAB dec c ; c=2 jr z,A3DAF dec c ; c=3 jr z,A3DB1 dec c ; c=4 jr z,A3DB5 dec c ; c=5 jr z,A3DDB dec c ; c=6 jr z,A3DDF dec c ; c=7 jp z,A3E5A dec c ; c=8 jr z,A3DE3 ld a,EINVFNC ; код "неверный номер функции" scf ret ; c=0 A3DA7: ld a,2 and a ret ; c=1 A3DAB: ld c,51h ; сбр. контроллер и настр. на диск rst 08h ret ; c=2 A3DAF: xor a ret ; c=3 A3DB1: ld a,-1 and a ret ; c=4 A3DB5: ld ix,0 ; мл. разряд номера сектора ld hl,0 ; ст. разряд push de push af ld bc,0155h ; прочитать один сектор rst 08h pop de pop hl ret c ld bc,24 add hl,bc ld e,(hl) push de ld a,d ld c,58h ; получить парам. носителя rst 08h ld a,h pop hl push hl ld h,a pop af ld c,59h ; уст. парам. носителя rst 08h xor a ret ; c=5 A3DDB: ld c,55h ; чтение с девайса rst 08h ret ; c=6 A3DDF: ld c,56h ; запись на девайс rst 08h ret ; c=8 A3DE3: bit 7,b jr nz,A3DF0 inc b dec b jr z,A3DFB ld a,1 ; код "bad command" scf ret ; A3DF0: res 7,b inc b dec b jr z,A3E41 ld a,1 ; код "bad command" scf ret ; A3DFB: ex de,hl ld bc,55AAh ; сигнатура and a sbc hl,bc ld l,a ld a,0Bh ; код "failur" scf ret nz ld a,l and 0Fh push af ld c,58h ; получить парам. носителя rst 08h jr c,A3E3C push hl push de ld a,h ld h,0 add hl,hl dec a jr nz,$-2 ld b,h ld c,l ex af,af' xor a ld l,a ld h,a A3E20: ex af,af' add hl,bc adc a,0 dec de ex af,af' ld a,d or e jr nz,A3E20 ex af,af' ld e,a ex de,hl exx pop de pop hl pop af ex af,af' ld a,b ld c,l ld b,0 ld l,h ld h,b ex de,hl exx and a ret ; A3E3C: pop af ld a,2 ; код "bad drive number" scf ret ; A3E41: push af exx ex de,hl ld h,l ld l,c pop af and 0Fh push af push hl push de ld c,58h ; получить парам. носителя rst 08h pop de pop hl jr c,A3E3C pop af ld c,59h ; уст. парам. носителя rst 08h ret c and a ret ; c=7 A3E5A: ld a,1 and a ret ;------------------------------------------------- ; Обработчик RAM-дисков ;------------------------------------------------- A3E5E: inc c dec c ; c=0 jp z,A3EF5 dec c ; c=1 jr z,A3E7F dec c ; c=2 jr z,A3E81 dec c ; c=3 jr z,A3E83 dec c ; c=4 jr z,A3E87 dec c ; c=5 jr z,A3E93 dec c ; c=6 jr z,A3EC4 ld a,1 ; код "bad command" scf ret ; c=1 A3E7F: xor a ret ; c=2 A3E81: xor a ret ; c=3 A3E83: ld a,-1 and a ret ; c=4 A3E87: ld ix,0 ld hl,0 ld b,1 ; c=5 A3E93: push bc push ix push hl push bc call A3F35 pop bc ld ix,512 ; размер сектора ? A3EA0: push bc push ix call A3F71 pop ix pop bc djnz A3EA0 pop hl pop ix pop bc xor a cp b ld c,b ld b,a jr z,A3EBC add ix,bc ld c,b adc hl,bc xor a ret ; A3EBC: inc b add ix,bc ld b,c adc hl,bc xor a ret ; c=6 A3EC4: push bc push ix push hl push bc call A3F35 pop bc ld ix,512 ; размер сектора ? A3ED1: push bc push ix call A3FAD pop ix pop bc djnz A3ED1 pop hl pop ix pop bc xor a cp b ld c,b ld b,a jr z,A3EED add ix,bc ld c,b adc hl,bc xor a ret ; A3EED: inc b add ix,bc ld b,c adc hl,bc xor a ret ; c=0. Просканировать число RAM-дисков. A3EF5: ;ld hl,0200h ; ## ; ld a,80h ;A3EFA: srl a ; / 2 (мл.бит в CF) ; rr h ; цикл. сдвиг вправо через CF ; jr nc,A3EFA ; выход: h=0, a=20h ld a,20h ; поставил ld (D3F70),a ld de,T3F25 ; таблица номеров (0..15) RAM-дисков ld bc,00CEh ; получить id блока, назнач. на RAM-диск A3F09: push bc ld a,b ; номер RAM-диска 0..15 rst 08h or a jr z,A3F11 ; блок не назначен ld (de),a ; id блока в таблицу inc de A3F11: pop bc inc b ; ++номер ram-диска ld a,15+1 ; макс. номер + 1 cp b jr nz,A3F09 ; выход за пределы 0..15 диапазона (нет своб. ram-дисков) ld hl,T3F25 ; таблица номеров (0..15) RAM-дисков ex de,hl and a sbc hl,de ld a,l ; число RAM-дисков (0=нет) ;ld hl,T3FEB; ; нужен ? and a ret ; Таблица номеров (0..15) RAM-дисков T3F25: db -1,-1,-1,-1,-1,-1,-1,-1 db -1,-1,-1,-1,-1,-1,-1,-1 A3F35: ld bc,T3F25 add a,c ld c,a ld a,0 adc a,b ld b,a ld a,(bc) ex af,af' db 0DDh ld b,h db 0DDh ld c,l ld a,(D3F70) A3F47: rrca ; цикл. сдвиг вправо (мл.разряд в CF) jr c,A3F54 rr h rr l rr b rr c jr A3F47 ; A3F54: ld b,c ; лог. номер страницы ld c,0C4h ; получить физ. номер страницы блока ex af,af' rst 08h ex af,af' ld a,(D3F70) ld c,a dec c db 0DDh ld a,l and c inc a ld hl,LC000 ld bc,512 sbc hl,bc add hl,bc dec a jr nz,$-2 ret D3F70: db 0 A3F71: ld a,d cp 0A0h ld c,0E2h set 6,h jr c,A3F7E ld c,0A2h res 7,h A3F7E: in a,(c) ex af,af' di out (c),a db 0DDh ld b,h db 0DDh ld h,c db 0DDh ld c,l ldir ex af,af' db 0DDh ld c,h out (c),a ld a,h and 7Fh ei ret nz ld c,0E2h in b,(c) ld a,0FEh out (c),a ex af,af' db 0DDh ld h,0C2h db 0DDh ld l,a ld a,(ix+0) ex af,af' out (c),b ld h,0C0h ret A3FAD: ld a,d cp 0A0h ld c,0E2h set 6,h ; 00->40h jr c,A3FBA ld c,0A2h res 7,h A3FBA: in a,(c) ex af,af' di out (c),a db 0DDh ld b,h db 0DDh ld h,c db 0DDh ld c,l ex de,hl ldir ex de,hl ex af,af' db 0DDh ld c,h out (c),a ld a,h and 7Fh ei ret nz ld c,0E2h in b,(c) ; сохр. порт ld a,0FEh ; номер стр. out (c),a ex af,af' db 0DDh ld h,0C2h db 0DDh ld l,a ld a,(ix+0) ex af,af' out (c),b ; восст. порт ld h,0C0h ret include "cursor.asm" ; вход: de=скен-код/ascii-код (d - сбр. 7-й бит) ; ;TSR: ld a,b ; and 00110000b ; биты Ctrl+Alt ; cp 00110000b ; 30h ; jp nz,A06DD ; сохр. de,bc в кольц. буфере клавы ; ; de=скен-код/ascii-код ; ; очистить буфер клавиатуры ; ld a,(D0641) ; ld (D0640),a ; ret; ; ; ; res 7,d ; ld a,d ; ld e,a ; ld d,0 ; de=индекс скен-кода (hot-клавиши) ; ; вкл. стр. с таблицей ; ld a,3 ; лог. номер дос-банки ; call set_dos_page ; подкл. дос-банку в 0C000h ; ld (tsr2+1),a ; старая банка 0E2h порта ; ; ; ld hl,0C000h ; add hl,de ; адрес элемента обраб. hot-клавиши ; ld a,(hl) ; or a ; jr z,tsr1 ; обраб. не определен ; ld (tsr2+1),a ; стр. обработчика ; inc hl ; ld a,(hl) ; адрес обработчика hot-клавиши ; inc hl ; ld h,(hl) ; ld l,a ; ld (tsr4+1),hl ; адрес обработчика ; jr tsr3 ; ; ;tsr1: ;tsr2: ld a,-1 ; out (0E2h),a ; восст. порт ; ret ; ; ;tsr3: call tsr1 ; вкл. страницу обработчика ;tsr4: jp 0 ; перейти на обработчик ; раб. буфер, исп. 16 байт (п/п рам-дисков) ;T3FEB: db 0