;АДРЕС: #3FF0 вывод в порт ;АДРЕС: #3FF3 чтение порта ;ИСХОДНЫЙ ТЕКСТ TR-DOS 5.03 для SjASMPlus ;Основано на книге "ПОЛHОЕ ОПИСАHИЕ + ПОЛHЫЙ ДИЗАССЕМБЛЕP ПЗУ TR-DOS 5.04T (5.03) ДЛЯ ПРОФЕССИОНАЛОВ, А ТАКЖЕ ДЛЯ ТЕХ, КТО ХОЧЕТ ИМИ СТАТЬ." ;Автор книги: Федин Павел Юрьевич, 04.04.1996. ;Перевод всех чисел в шестнадцатеричный формат, переформатирование: Spectre, 19.10.2005 ;Исправление, переформатирование: Keeper, 21.06.2009 ;Кодировка: CP-1251 ;Правка под версию Tr-Dos 5.03: PLM, 2022.04.03 DEVICE ZXSPECTRUM48 ;Адрес 0. Полная инициализация системы. ORG 0 x0000 DI JP x0844 ;new LD A,7 JR x0009 ;Адрес 8. Инициализация системы. В DE поместите адрес вершины памяти, в A - 7 и запретите прерывания. Используется также с адреса 9. x0008 NOP x0009 NOP NOP x000B LD A,#3F x000D JR x0013 x000F NOP ;Адрес #10. Переход к подпрограмме печати символа из регистра A. x0010 JP x3D82 ;Адрес #13. Инициализация системы. В DE поместите адрес вершины памяти, установите белый бордюр, поместите в A старший байт низшего адреса памяти и запретите прерывания. x0013 LD I,A JP x001B ;Адрес #18. Переход к подпрограмме печати строки. x0018 JP x2707 ;Адрес #1B. То же, что и #24. x001B ld h,d ld l,e inc de JR x0024 ;Адрес #20. Переход к подпрограмме вызова подпрограмм из ПЗУ бейсика. Адрес вызываемой подпрограммы поместите в двух байтах после команды RST #20. Например: x0020 JP x2F72 x0023 RET ;Адрес #24. Инициализация системы. В DE поместите адрес вершины памяти, установите белый бордюр, поместите в A старший байт низшего адреса памяти и запретите прерывания. x0024 ld (hl),#00 JR x002B ;инициализация системы ;Адрес #28. Выборка адреса текущего канала с учетом сдвига, заданного в регистре C. x0028 JP x2323 ;Адрес #2B. Инициализация системы. В DE и HL поместите адрес вершины памяти, установите белый бордюр, поместите в A старший байт низшего адреса памяти и запретите прерывания. x002B ld bc,#BFFF jr x003A x0030 nop nop nop x0033 out (c),a nop halt rst #38 ;Адрес #38. Обработка маскируемого прерывания. x0038 ei ret ;Адрес #3A. Инициализация системы. В DE поместите адрес вершины памяти в HL - адрес дна, установите белый бордюр, заполните обозначенную область памяти байтом 2 и запретите прерывания. x003A ldir jr x0048 nop nop nop nop nop nop nop nop nop nop x0048 LD (#5CB4),HL ;установка P_RAMT LD DE,#3EAF ;адрес символов для UDG LD BC,#A8 ;длина UDG - #A8 байтов LD A,E EX DE,HL ;переброска адреса символов для UDG в HL LD SP,#6000 ;установка временного стека LD (#5F00),HL ;сохранение адреса символов для UDG LD HL,#79 ;возвращаться в #79 PUSH HL ;помещение его на стек LD HL,x3D2F ;адрес переключателя ПЗУ на TR-DOS PUSH HL ;помещение его на стек LD HL,#B8ED ;код команды LDDR JR x0069 ;установка UDG ;Адрес #66. Подпрограмма обработки немаскируемого прерывания. x0066 JP x2A56 ;Адрес #69. Выполнение любой команды процессора. Поместите в HL коды команды, установите регистры (#5F00 вместо HL) и поместите в HL коды команды. x0069 LD (#5F10),HL ;помещение кодов команды в память PUSH AF ;сохранение AF LD A,#C9 ;код команды RET LD (#5F12),A ;помещение его в память POP AF ;восстановление AF LD HL,(#5F00) ;берем адрес символов для UDG JP #5F10 ;выполнение команды и возврат ;Адрес #79. Инициализация системы. Установите P_RAMT, знакогенератор пользователя, белый бордюр, поместите в DE адрес начала знакогенератора минус 1 и запретите прерывания. x0079 EX DE,HL ;загрузка адреса UDG в HL INC HL LD (#5C7B),HL ;установка переменной UDG DEC HL ;следующий адрес LD BC,#1E40 ;установка RASP и PIP LD (#5C38),BC LD (#5CB2),HL ;установка RAMTOP LD HL,#3C00 ;установка CHARS LD (#5C36),HL LD HL,(#5CB2) ;берем адрес RAMTOP LD (HL),#3E ;признак конца стека GO SUB DEC HL ;следующий адрес LD SP,HL ;установка постоянного стека DEC HL ;установка ERR_SP DEC HL LD (#5C3D),HL LD DE,#1303 ;адрес подпрограммы обработки ошибок PUSH DE ;установка его IM 1 ;установка первого режима прерываний LD IY,#5C3A ;установка регистра IY LD HL,#5CB6 ;установка CHANS LD (#5C4F),HL LD DE,#15AF ;адрес области описателей каналов в ПЗУ бейсика LD BC,#15 ;ее длина - #15 байт EX DE,HL CALL x0117 ;перенос области описателей каналов в ОЗУ EX DE,HL DEC HL ;установка DATADD LD (#5C57),HL INC HL ;следующий адрес LD (#5C53),HL ;установка PROG LD (#5C4B),HL ;установка VARS LD (HL),#80 ;конец области INC HL ;следующий адрес LD (#5C59),HL ;установка E_LINE LD (HL),#D ;конец строки INC HL ;следующий адрес LD (HL),#80 ;конец области INC HL ;следующий адрес LD (#5C61),HL ;установка WORKSP LD (#5C63),HL ;установка STKBOT LD (#5C65),HL ;установка STKEND LD A,#38 ;атрибуты экрана LD (#5C8D),A ;установка ATTR_P LD (#5C8F),A ;установка ATTR_T LD (#5C48),A ;установка BORDER LD HL,#523 ;установка REPDEL и REPPER LD (#5C09),HL DEC (IY-#3A) ;клавиши не нажаты DEC (IY-#36) LD HL,#15C6 ;адрес таблицы STRMS в ПЗУ бейсика LD DE,#5C10 ;адрес переменной STRMS LD BC,#0E ;длина таблицы - #18 байта CALL x0117 ;перенос таблицы в ОЗУ SET 1,(IY+1) ;открыт поток 3 LD HL,#5CC2 ;помещение команды RET в ОЗУ LD (HL),#C9 ;Внимание!!! Системных переменных TR-DOS пока еще нет, и это портит память. RST #20 ;инициализация буфера принтера и экрана DW #0EDF LD HL,#5C6B ;буфер принтера использовался LD (HL),2 LD HL,#128B ;возвращаться в #128B PUSH HL LD A,#AA ;выполнять команду RUN "boot" LD (#5B00),A EI ;разрешение прерываний JP x3D31 ;вход в TR-DOS ;Адрес #117. Выполнение команды LDIR. Установите HL, DE и BC и поместите байт #C9 по адресу #5F12. x0117 LD (#5F00),HL ;сохранение HL LD HL,x3D2F ;адрес переключателя ПЗУ на TR-DOS PUSH HL ;помещение его на стек LD HL,#B0ED ;коды команды LDIR LD (#5F10),HL ;помещение команды в ОЗУ LD HL,(#5F00) ;восстановление HL JP #5F10 ;выполнение команды и возврат ;Адрес #12A. Обработка номера строки автостарта программы на бейсике. Установите #5D10 и загрузите программу. x012A CALL x20E5 ;изменение памяти и удаление буфера CALL x1D97 ;очистка экрана LD HL,(#5C59) ;берем адрес, по которому находится номер INC HL ;строки автозапуска программы LD E,(HL) ;берем этот номер INC HL LD D,(HL) LD A,D ;это 0? OR E EX DE,HL ;переброска его в HL JR Z,x0140 ;если это не 0, то программу запускать XOR A LD (#5D10),A x0140 PUSH HL ;сохранение номера строки автостарта CALL x0232 ;восстановление старого адреса подпрограммы обработки ошибок POP HL ;восстановление номера строки автостарта LD (#5C42),HL ;установка его XOR A ;строку запускать с первого оператора LD (#5C44),A RST #20 ;очистка рабочей области памяти, стека калькулятора и буфера редактора DW #16B0 LD HL,(#5C53) ;выполнение RESTORE DEC HL LD (#5C57),HL LD SP,(#5C3D) ;очистка стека LD A,(#5D10) ;программу запускать? OR A LD HL,#1B76 ;адрес подпрограммы выполнения программы на бейсике JR Z,x0166 ;если можно, то запуск программы RST #20 ;сообщение O.K. DW #1BB0 x0166 PUSH HL ;помещение на стек адреса подпрограммы выполнения программы на бейсике LD HL,#5CC2 ;помещение на стек адреса переключателя ПЗУ на бейсик PUSH HL RET ;переход к подпрограмме выполнения программы на бейсике ;Адрес #16C. То же, что и #3D1A, но не создает системные переменные. x016C CALL x20F1 ;изменение памяти CALL x294A ;создание буфера LD A,#FF ;сообщения не печатать LD (#5D15),A XOR A ;обнуление #5CF7 LD (#5CF7),A LD A,#AA ;заставку не выводить LD (#5D17),A LD HL,#201 ;возвращаться в бейсик LD (#5D1A),HL LD HL,0 ;сохранение SP ADD HL,SP LD (#5D1C),HL DEC HL ;выделение места для адреса подпрограммы DEC HL ;обработки ошибок LD SP,HL CALL x021D ;установка адреса подпрограммы обработки ошибок LD HL,(#5CB2) ;командная строка находится выше RAMTOP? LD DE,(#5C5D) SBC HL,DE EX DE,HL JR NC,x01A5 ;если да, то при выделении буфера она не OR A ;перемещалась LD DE,#101 SBC HL,DE x01A5 LD (#5C5D),HL x01A8 CALL x01C7 ;следующий символ строки ENTER? x01AB JP Z,x01D3 ;если да, то завершение CP #EA ;это REM? INC HL ;следующий символ JR NZ,x01A8 ;если нет, то следующий символ CALL x01C7 ;следующий символ строки ENTER? JR Z,x01AB ;если да, то завершение CP ":" ;это двоеточие? JP NZ,x01D3 ;если нет, то возврат INC HL ;следующий символ CALL x3048 ;сжатие строки LD HL,(#5D11) JP x030A ;выполнение команды ;Адрес #1C7. берет символ по адресу из HL и возвращает его в аккумуляторе плюс флаг Z если это 0, #D или #80, иначе NZ. x01C7 LD A,(HL) ;берем байт по нужному адресу CP #D ;это #D? RET Z ;если да, то возврат CP #80 ;это #80? RET Z ;если да, то возврат OR A ;сравнение его с нулем RET ;возврат x01D0 CALL x1E43 ;Адрес #1D3. Подпрограмма завершения. Вход: установить #5CB6, #5D0C, #5D0F, #5D11, #5D18, #5D1A, #5D1C и #5D1F. Выход: в SP адрес из #5D1C, а в BC код ошибки. x01D3 LD HL,0 ;буфер убирать, память изменять LD (#5CF8),HL CALL x20E5 ;если есть буфер, то уберем его CALL x1D63 ;если надо, то очистка рабочей области памяти LD HL,#5D17 ;заставку не выводить LD (HL),#AA LD HL,#5D1F ;команда поступила из машинного кода? LD A,(HL) OR A LD (HL),0 ;следующая команда будет не из машинного кода JR NZ,x01F3 ;если команда была не из машинного кода, то CALL x1E1C ;удаление из строки 5-байтовых чисел CALL x0212 ;и прогон символов до конца строки x01F3 LD SP,(#5D1C) ;помещаем в SP адрес из #5D1C LD HL,(#5D1A) ;берем адрес выхода из этой подпрограммы LD BC,(#5D0F) ;помещаем в BC код ошибки LD B,0 JP (HL) ;переход по назначенному адресу ;Адрес #201. Проверка на ошибку. Вход: установите #5C3A и #5D13. x0201 CALL x0232 ;помещение в #5C3D адреса из #5D13 BIT 7,(IY+0) ;была ошибка? RET NZ ;если нет, то возврат LD DE,#5CC2 ;адрес команды RET в ОЗУ LD SP,(#5C3D) ;установка SP на дно стека PUSH DE ;переход на обработку ошибок RET ;Адрес #212. Прогон символов до конца строки. Установите в #5C5D адрес одного из символов строки. На выходе там будет адрес конца строки. x0212 CALL x1D8C ;берем текущий символ строки CP #D ;это ENTER? RET Z ;если да, то возврат CALL x1E2A ;берем следующий символ строки JR x0212 ;повтор ;Адрес #21D. Установка адреса обработки ошибок. Вход: в #5D1C должен быть адрес на 2 больше того, по которому размещаете адрес подпрограммы обработки ошибок. Выход: старое содержимое #5C3D копируется в #5D13, а в #5C3D помещается адрес, по которому находится размещенный адрес. x021D LD HL,(#5C3D) ;сохранение старого содержимого #5C3D LD (#5D13),HL LD HL,(#5D1C) ;берем адрес из #5D12 DEC HL ;берем нужный нам адрес DEC HL LD (#5C3D),HL ;установка #5C3D LD DE,x3D16 ;адрес подпрограммы обработки ошибок LD (HL),E ;запись его в наши ячейки INC HL LD (HL),D RET ;возврат ;Адрес #232. Помещение в #5C3D адреса из #5D13. Установите #5D13. x0232 LD HL,(#5D13) LD (#5C3D),HL RET ;Адрес #239. Вход в командный процессор. Используется также с адреса #27B (запуск файла "boot"). x0239 LD HL,0 ;обнуление #5CF7 и #5CF8 LD (#5CF7),HL ADD HL,SP ;сохранение SP LD (#5D1C),HL DEC HL ;выделение места для адреса подпрограммы DEC HL ;обработки ошибок LD SP,HL CALL x021D ;установка адреса подпрограммы обработки ошибок LD HL,#5D17 ;заставку выводить? LD A,(HL) CP #AA LD A,0 ;ошибок нет LD (#5D0F),A JP Z,x02CB ;если заставка не нужна, то переход к командному процессору LD (HL),#AA ;в следующий раз заставку не выводить CALL x1D97 ;очистка экрана CALL x1D88 ;открытие потока 2 LD HL,x0360 ;вывод текста заставки RST #18 CALL x106E ;вывод цветных полос LD A,(#5CB6) ;интерфейс-1 есть? CP #F4 JR Z,x0271 ;если да, то LD HL,x1000 ;вывод "Interface one fitted" RST #18 x0271 LD A,(#5B00) ;файл "boot" запускать? CP #AA JR NZ,x02CB ;если нет, то вход в командный процессор CALL x20F1 ;изменение памяти x027B LD HL,(#5C59) ;берем адрес буфера команд LD A,#FE ;был запущен файл "boot" LD (#5D0E),A LD (HL),#F7 ;ввод команды RUN "boot" INC HL LD (HL),#22 INC HL LD (HL),"b" INC HL LD (HL),"o" INC HL LD (HL),"o" INC HL LD (HL),"t" INC HL LD (HL),#22 INC HL LD (#5C5B),HL ;установка адреса курсора LD (HL),#D ;ENTER INC HL LD (HL),#80 ;конец области INC HL LD (#5C61),HL ;установка переменной WORKSP LD (#5C63),HL ;установка и очистка стека калькулятора LD (#5C65),HL SET 3,(IY+1) ;установка режима L JR x02EF ;выполнение команды ;Адрес #2B0. Перенос трех байтов из адреса HL по адресу DE. x02B0 LD B,3 ;количество байтов x02B2 LD A,(HL) ;перенос байта LD (DE),A INC HL ;адреса следующих байтов INC DE DJNZ x02B2 ;повтор до конца RET ;возврат ;Адрес #2B9. Остановка дисковода. В A поместите значение системного регистра. x02B9 LD B,#20 ;#20 повтора x02BB PUSH BC ;сохранение количества повторов XOR 8 ;переключение бита 3 OUT (#FF),A ;загрузка системного регистра PUSH AF ;сохранение значения системного регистра LD A,5 ;задержка в #462A такта CALL x3DFF POP AF ;восстановление значения системного регистра POP BC ;и количества повторов DJNZ x02BB ;повтор до конца RET ;возврат ;Адрес #2CB. Командный процессор. Используется также с адресов: ;#2EF - исполнение команды. Сжатую команду поместите в буфер командной строки; ;#30A - исполнение команды. Установите все для #1D3, #5D11 и загрузите из #5D11 HL. x02CB LD HL,(#5D1C) ;очистка стека DEC HL DEC HL LD SP,HL CALL x20F1 ;изменение памяти CALL x1D83 ;открытие потока 0 LD A,(#5D16) ;выбор дисковода D: OR 3 CALL x02B9 ;остановка его LD A,(#5D16) ;остановка текущего дисковода CALL x02B9 XOR A ;сообщения об ошибках печатать LD (#5D15),A CALL x2135 ;принятие команды CALL x3032 ;сжатие командной строки x02EF CALL x1D9F ;очистка низа экрана LD HL,x02CB ;возвращаться в командный процессор LD (#5D1A),HL XOR A ;ошибок не было LD (#5D0F),A LD HL,(#5C59) ;берем адрес командной строки PUSH HL ;сохраняем его LD DE,#5D20 ;адрес буфера CALL x02B0 ;сохранение трех первых символов строки POP HL ;восстановление адреса строки LD (#5D11),HL ;установка адреса командной строки x030A LD A,(HL) ;берем первый символ строки LD B,A ;сохраняем его AND #80 ;его код меньше #80? LD A,B ;восстановление символа JR Z,x031A ;если его код меньше #80, то дисковод не устанавливать CP #FE ;это RETURN? JR Z,x031A ;если да, то дисковод не устанавливать PUSH AF ;сохранение символа CALL x3DC8 ;активизация дисковода по умолчанию POP AF ;восстановление символа x031A LD HL,x2FF3 ;адрес таблицы команд DEC HL LD C,0 ;проверка первой команды x0320 INC C LD D,A ;сохранение символа LD A,#15 ;пройдена вся таблица? CP C JP C,x01D3 ;если да, то завершение ;Лучше было бы поставить здесь JP C,#1D1A для выдачи сообщения "*ERROR*". LD A,D ;восстановление символа INC HL ;адрес следующей команды в таблице CP (HL) ;символы совпали? JR NZ,x0320 ;если нет, то повтор CP #FE ;введена команда RETURN? CALL NZ,x294A ;если нет, то создание буфера LD A,9 ;поиск файла вести по 9 байтам LD (#5D06),A XOR A ;ошибок не было LD (#5D0F),A LD (#5CD6),A ;расширение файла принимать LD (#5D10),A ;на случай загрузки или верификации файла LD HL,#5C3B ;проверка строки на синтаксис RES 7,(HL) LD B,0 ;перевод номера команды в двухбайтную форму LD HL,x3008 ;адрес таблицы адресов подпрограмм DEC C ;команды считать с нуля SLA C ;умножение номера подпрограммы на 2 ADD HL,BC ;определение адреса в таблице LD E,(HL) ;берем адрес подпрограммы INC HL LD D,(HL) EX DE,HL ;переносим его в HL PUSH HL ;сохраняем его LD DE,x0359 ;возврат будет в #359 PUSH DE JP (HL) ;вызов подпрограммы x0359 LD HL,#5C3B ;выполнение команды SET 7,(HL) POP HL ;восстановление адреса подпрограммы JP (HL) ;вызов подпрограммы ;Адрес #360. Текст заставки TR-DOS. x0360 DB #16,1,#5 DB "* TR-DOS Ver 5.03 *" DB #D,#D,#7F DB " 1986 Technology Research Ltd." DB #16,5,#B DB "(U.K.)" DB #16,7,5 DB "BETA 128" DB 0 ;Адрес #3AC. Завершение выдачи каталога. x03AC CALL x03FD ;загрузка в буфер сектора 8 дорожки 0 CALL x3D80 ;перевод строки CALL x3D80 ;еще раз LD BC,(#5E0A) ;берем количество свободных секторов на диске CALL x1DA9 ;печать его LD HL,x29D2 ;печать FREE RST #18 ;Адрес #3C0. Переход к подпрограмме завершения. x03C0 JP x01D3 ;Адрес #3C3. Печать сообщения об ошибке. В HL установите адрес сообщения, в A - код ошибки. x03C3 PUSH AF ;сохранение кода ошибки LD A,(#5D0E) ;ошибка произошла при автозагрузке? CP #FE JR NZ,x03CD ;если нет, то установка кода ошибки POP AF ;снятие со стека кода ошибки RET ;возврат x03CD POP AF ;восстановление кода ошибки LD (#5D0F),A ;установка кода ошибки LD A,(#5D15) ;печать сообщений разрешена? OR A CALL Z,x2707 ;если да, то печать сообщения ;Ошибка!!! Перед печатью надо открыть поток 0 и очистить низ экрана. RET ;возврат x03D9 LD HL,x2A28 LD A,1 JP x1C4A ;Адрес #3E1. Вывод сообщения O.K. x03E1 LD HL,x2766 ;адрес сообщения O.K. XOR A ;код ошибки - 0 JP x1C4A ;выдача сообщения и завершение ;Адрес #3E8. Загрузка сектора 0 дорожки 0 в буфер. Обнуляет #5CCC. Используется также с адресов: ;#3EC - загрузка сектора дорожки 0 в буфер. Установите #5CCC. ;#3F2 - загрузка сектора в буфер, номер сектора в E, дорожки ? в D). x03E8 XOR A ;текущий сектор 0 LD (#5CCC),A x03EC LD DE,(#5CCC) ;берем номер сектора LD D,0 ;дорожка 0 x03F2 CALL x294A ;создание буфера LD HL,#5D25 ;загружать в буфер LD B,1 ;1 сектор JP x1E3D ;загрузка сектора ;Адрес #3FD. Загрузка в буфер сектора 8 дорожки 0. Установите #5D0C. x03FD CALL x294A ;создание буфера, если его нет LD DE,8 ;дорожка 0, сектор 8 JR x03F2 ;загрузка сектора в буфер ;Адрес #405. Настройка на диск. Меняет переменную с типом дисковода. x0405 CALL x03FD ;чтение в буфер сектора 8 дорожки 0 LD A,(#5E0C) ;диск от TR-DOS? CP #10 JR Z,x0415 ;если да, то установка типа дисковода LD HL,x29E2 ;адрес сообщения DISC ERROR RST #18 ;печать сообщения JR x03C0 ;завершение ;Внимание, ошибка!!! Неправильно обрабатывается ошибка. Здесь программа должна быть такой: ; LD HL,#29E2 ; LD A,7 ; JP #1C4A ;А в этом случае ваша программа не получит код ошибки, а внизу экрана совершенно не к месту появится DISC ERROR. x0415 CALL x3E11 ;берем тип дисковода RES 0,(HL) ;установка типа дисковода под тип диска RES 1,(HL) ;и возврат LD A,(#5E08) BIT 0,A JR NZ,x0425 SET 0,(HL) x0425 BIT 3,A RET NZ SET 1,(HL) RET ;Ошибка!!! Перед установкой типа надо бы проверить совместимость диска и дисковода. ;Адрес #42B. Проверка второго символа командной строки. Вход: установите #5D11. На выходе будет установлен флаг Z, если это ENTER и сброшен, если нет. x042B LD HL,(#5D11) ;берем адрес начала строки команды INC HL ;берем адрес ее второго символа LD A,(HL) ;берем этот символ CP #D ;сравнение его с ENTER RET ;возврат ;Адрес #433. Выполнение команды CAT. Установите #5D11 и #5C3B. Используется также с адреса: ;#479 (вывод каталога диска; в A - номер потока, в буфере - сектор 8 дорожки 0). x0433 CALL x042B ;второй символ строки команды ENTER? LD BC,2 ;каталог выводить в поток 2 LD (#5CDB),BC JR Z,x046A ;если второй символ строки ENTER, то вывод каталога CP "#" ;второй символ строки "#"? JR NZ,x045D ;если нет, то установка дисковода и вывод каталога LD (#5C5D),HL ;установка CH_ADD на второй символ строки CALL x1E0B ;установка номера потока CALL x1D8C ;берем текущий символ CP #D ;это ENTER? JR Z,x046A ;если да, то вывод каталога CP "," ;это запятая? JP NZ,x1D1A ;если нет, то синтаксическая ошибка CALL x1E2A ;берем следующий символ CALL x1DBD ;помещение имени дисковода на стек калькулятора JR x0460 ;установка дисковода и вывод каталога x045D CALL x1DDF ;установка CH_ADD и помещение имени дисковода на стек калькулятора x0460 CALL x1D75 ;если строка проверяется на синтаксис, то возврат CALL x1DB5 ;снятие имени дисковода со стека калькулятора EX DE,HL CALL x1C81 ;установка дисковода x046A CALL x1D75 ;если проверка на синтаксис, то возврат LD A,(#5CF6) ;помещение номера дисковода в #5CF9 LD (#5CF9),A CALL x0405 ;настройка на диск LD A,(#5CDB) ;берем номер потока x0479 CP 2 ;выводим в поток 2? PUSH AF ;сохранение номера потока CALL Z,x1D97 ;если назначен поток 2, то очистка экрана POP AF ;восстановление номера потока CP #11 ;он больше #10? ;Ошибка!!! Всего потоков #F, а не #10. JP NC,x1D1A ;если да, то ошибка CALL x1D84 ;открытие потока ;Ошибка!!! Надо бы проверить, подключен ли куда-нибудь этот поток. LD A,#FF ;установка #5CF8 в #FF LD (#5CF8),A LD HL,x29F7 ;печать TITLE: RST #18 LD HL,#5E1A ;печать имени диска RST #18 CALL x3D80 ;перевод строки LD A,(#5E09) ;вычисление количества нестертых файлов на диске LD HL,#5E19 SUB (HL) PUSH HL CALL x1DA3 ;печать его LD HL,x2A2B ;печать FILES RST #18 POP HL LD C,(HL) ;берем количество стертых файлов CALL x1DA4 ;печать его LD HL,x2A1D ;печать DEL.FILES RST #18 CALL x03E8 ;загрузка в буфер сектора 0 дорожки 0 LD HL,#5D25 ;берем начало буфера x04B6 CALL x04F6 ;проверка достижения конца каталога CALL x3D80 ;перевод строки LD A,(#5CF6) ;печать имени дисковода ADD A,"A" RST #10 LD B,2 ;печатаем по 2 имени в строке x04C4 CALL x04F6 ;если файл стерт, то пропуск его PUSH BC ;сохранение количества имен файлов в строке LD A,":" ;печать двоеточия RST #10 PUSH HL ;сохранение адреса текущего описателя файла в буфере CALL x2938 ;печать имени и расширения файла LD BC,#D ;вычисление адреса, по которому находится POP HL ;размер файла в секторах PUSH HL ADD HL,BC LD C,(HL) ;берем размер файла PUSH BC ;сохраним его LD A,C ;перегрузим его в A LD B,2 ;вычисление количества пробелов перед числом CP #A JR C,x04DF DEC B x04DF CP #64 JR NC,x04E8 x04E3 LD A," " ;печать пробелов RST #10 DJNZ x04E3 x04E8 POP BC ;восстановление размера файла CALL x1DA9 ;печать его POP HL ;восстановление адреса текущего описателя файла POP BC ;восстановление количества имен файлов в строке LD DE,#10 ;следующий описатель ADD HL,DE DJNZ x04C4 ;если напечатали только 1 файл, то печать второго JR x04B6 ;следующая строка ;Адрес #4F6. Проверка переменной #5CF9 и проверка достижения конца каталога при его печати. x04F6 PUSH HL ;сохранение HL и BC PUSH BC LD A,(#5CF9) ;берем номер дисковода для выдачи каталога LD HL,#5CF6 ;назначен этот дисковод? CP (HL) CALL NZ,x3DCB ;если нет, то о последствиях читайте в конце ;Ошибка в программе!!! Об этом особо в конце текста. POP BC ;восстановление HL и BC POP HL JP x2FC6 ;проверка достижения конца каталога и возврат ;Обратите особое внимание на команду CALL NZ,#3DCB. В аналогичной подпpогpамме для LIST стоит CALL NZ,#3DCB. В нашем же случае упpавление будет передано в подпрограмму печати символа (ее адрес #3D80) на адрес, где находятся 2 байта адреса от команды CALL #3D94. Программа с этого адреса будет такой: ;SUB H ;DEC A ;CALL #20F1 ;POP DE ;POP BC ;POP HL ;RET ;Таким образом, произойдет изменение памяти, если оно разрешено, затем со стека будут сняты 3 адреса и помещены в регистры и затем произойдет возврат. Последствия всего этого определяются программой, вызвавшей #4F6. ;Адрес #507. Прибавление #10 к HL. x0507 LD DE,#10 ADD HL,DE RET ;Адрес #50C. Проверка и обработка достижения конца буфера при работе с каталогом. Установите #5CCC и поместите в HL текущее место буфера. Если достигнут его конец, то в HL будет начало буфера и в него будет загружен следующий сектор каталога. x050C PUSH HL ;сохранение HL и BC PUSH BC LD BC,#A1DB ;достигнут конец буфера? ADD HL,BC JR C,x0517 ;если да, то загрузка следующего сектора POP BC ;восстановление HL и BC POP HL RET ;возврат x0517 LD HL,#5CCC ;следующий сектор INC (HL) CALL x03EC ;загрузка его в буфер POP BC ;восстановление BC и HL POP HL LD HL,#5D25 ;помещение в HL адреса начала буфера RET ;возврат ;Адрес #524. Вычисление номера дисковода по его имени. Имя поместите в А, на выходе там будет номер. x0524 AND #DF ;буква заглавная SBC A,#41 ;вычисление номера дисковода JP C,x1D1A ;если именем был символ меньше "A", то ошибка CP 4 ;номер получился больше 3? JP NC,x1D1A ;если да, то ошибка RET ;возврат x0531 CALL x1DB5 LD A,C CP B JP Z,x1D1A RET ;Адрес #53A. Выполнение команды NEW. Установите #5D11 и #5C3B. Используется также с адреса #569 (запись информации о файле; номер файла задайте в регистре C). x053A CALL x1DCD ;прием имен файлов на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x102E ;прием расширения файла CALL x1CB0 ;установка старого имени файла LD A,(#5CF6) ;берем номер дисковода LD (#5CF8),A ;сохраняем его JP NZ,x03D9 ;если файл не найден, то ошибка PUSH BC ;сохранение номера файла CALL x165D ;загрузка описателя файла CALL x1CB0 ;установка нового имени файла PUSH AF ;сохранение результата проверки имени файла LD A,(#5CF8) ;в новом имени файла назначен другой дисковод LD HL,#5CF6 CP (HL) JP NZ,x1D1A ;если да, то ошибка CALL x0405 ;настройка на диск POP AF ;восстановление результата проверки имени файла JP Z,x1C50 ;если такой файл уже есть, то ошибка POP BC ;восстановление номера файла x0569 CALL x166B ;загрузка сектора с описателем файла и замена описателя CALL x1E43 ;перезапись сектора JP x03E1 ;сообщение O.K. ;Адрес #572. Проверка переменной #5D10. Соответственно содержимому будет установлен флаг Z, а само содержимое будет в аккумуляторе. x0572 LD A,(#5D10) OR A RET ;Адрес #577. Проверка количества стертых файлов. Установите #5D11. Если там 0, то будет сообщение NO FILE, иначе O.K. x0577 LD A,(#5D07) ;берем количество стертых файлов OR A ;оно равно 0? JP Z,x03D9 ;если да, то NO FILE JP x03E1 ;иначе O.K. ;Адрес #581. Запрос на стирание файла. Установите #5CDD и #5CF6, а в регистр C поместите номер файла. При ответе Y файл будет стерт и включится флаг Z, иначе он будет выключен. x0581 PUSH BC ;сохранение номера файла CALL x1D97 ;очистка экрана и открытие потока 0. LD A,(#5CF6) ;берем номер дисковода ADD A,"A" ;вычисляем имя дисковода CALL x3D82 ;печать его LD A,":" ;печать двоеточия CALL x3D82 LD HL,#5CDD ;адрес переменной с именем и расширением файла CALL x2938 ;печать имени и расширения файла LD HL,x2820 ;печать FILE EXISTS. OVERWRITE? CALL x2707 CALL x1052 ;ввод клавиши CP "Y" ;это "Y"? PUSH AF ;сохранение результата проверки CALL x1D97 ;очистка экрана POP AF ;восстановление AF и номера файла POP BC RET NZ ;если был ответ N, то возврат PUSH BC ;сохранение номера файла CALL x1D97 ;очистка экрана POP BC ;восстановление номера файла CALL x0781 ;стирание файла XOR A ;включение флага Z RET ;возврат ;Адрес #5B4. Проверка на существование блока файла с расширением #. Установите #5CDD, #5CE5 и #5CE6. Если блок найден или у файла другое расширение, то включается флаг Z, иначе он будет выключен. x05B4 LD A,(#5CE5) ;берем расширение файла CP "#" ;это "#"? JR Z,x05BD ;если нет, то XOR A ;включение флага Z RET ;и возврат x05BD LD A,#A ;файл ищем по #A байтам LD (#5D06),A CALL x1CB3 ;поиск файла LD A,9 ;файл ищем по 9 байтам LD (#5D06),A RET ;возврат ;Адрес #5CB. Выполнение команды COPY "*","*". Первую звездочку поместите в #5CDD, вторую - на стек калькулятора и установите #5CF8, #5D23 и #5CCF. x05CB LD A,(#5CDD) ;берем первый символ имени файла CP "*" ;это "*"? JP NZ,x03D9 ;если нет, то NO FILE CALL x1DB5 ;снятие строки со стека калькулятора EX DE,HL CALL x1C81 ;установка дисковода-приемника LD A,(HL) ;берем следующий символ строки CP "*" ;это "*"? JP NZ,x1D1A ;если нет, то ошибка LD A,(#5CF6) ;сохранение номера дисковода-приемника LD (#5CF9),A LD A,(#5CF9) ;выбор дисковода-приемника CALL x3DCB CALL x0405 ;настройка на диск LD A,#FF ;начнем с файла 0 LD (#5D0D),A x05F4 LD A,(#5CF8) ;выбор дисковода-источника CALL x3DCB CALL x0405 ;настройка на диск LD A,(#5D0D) ;следующий файл INC A LD (#5D0D),A LD C,A CALL x165D ;чтение его описателя LD A,(#5CDD) ;берем первый символ его имени CP 0 ;это конец каталога? JP Z,x03E1 ;если да, то O.K. CP 1 ;файл стерт? JR Z,x05F4 ;если да, то следующий файл LD HL,#5CE6 ;сохранение части описателя файла LD DE,#5CED LD BC,7 LDIR LD A,(#5CF9) ;выбор дисковода-приемника CALL x3DCB CALL x1CB3 ;поиск файла JR NZ,x0634 ;если не нашли, то копирование файла CALL x05B4 ;проверка файла с расширением "#" JR NZ,x0634 ;если копируется другой блок, то копируем его CALL x0581 ;запрос OVERWRITE? JR NZ,x05F4 ;если был ответ N, то следующий файл x0634 CALL x063C ;копирование файла CALL x1E43 ;перезапись сектора с описателем файла JR x05F4 ;повтор до конца каталога ;Адрес #63C. Копирование файла при двух дисководах. Поместите описатель файла в #5CDD и его часть в #5CED. x063C CALL x03FD ;загрузка в буфер сектора 8 дорожки 0 LD A,(#5E09) ;берем количество файлов на диске CP #80 ;уже есть #80 файлов? JP Z,x1C45 ;если да, то NO SPACE ;Ошибка!!! Надо выводить DIRECTORY FULL. LD HL,#5CED ;восстановление описателя файла LD DE,#5CE6 LD BC,7 LDIR LD DE,(#5CEA) ;берем длину файла в секторах LD D,0 OR A LD HL,(#5E0A) ;берем количество свободных секторов на диске SBC HL,DE ;уменьшаем свободное место JP C,x1C45 ;если места не хватило, то NO SPACE LD (#5E0A),HL ;установка нового количества свободных секторов LD HL,(#5E06) ;берем адрес свободного пространства на диске LD (#5CEB),HL ;установка адреса файла на диске PUSH HL ;сохранение его CALL x072F ;копирование файла POP HL ;восстановление адреса файла на диске LD (#5CEB),HL ;установка его LD HL,(#5CF4) ;берем новый адрес свободного места на диске LD (#5E06),HL ;установка его LD HL,#5E09 ;записали 1 файл INC (HL) LD C,(HL) ;берем номер записываемого файла DEC C LD B,0 PUSH BC ;сохраняем его LD DE,9 ;записывать сектор 8 дорожки 0 LD (#5CF4),DE CALL x1E43 ;запись сектора POP BC ;восстановление номера файла CALL x166B ;установка описателя файла RET ;возврат ;Адрес #690. Выполнение команды COPY. Установите #5D11 и #5C3B. x0690 LD HL,(#5D11) ;берем адрес второго символа командной строки INC HL LD A,(HL) ;берем этот символ AND #DF ;буква заглавная CP "S" ;это "S"? JP Z,x1360 ;если да, то копируем 1 файл на одном дисководе CP "B" ;это "B"? JP Z,x152C ;если да, то копирование всего диска на одном дисководе CALL x1DCD ;прием имен файлов CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x166F ;выделение места в памяти CALL x102E ;прием расширения файла CALL x1CB0 ;установка старого имени файла LD A,(#5CF6) ;сохранение номера дисковода - источника LD (#5CF8),A JP NZ,x05CB ;если файл не найден, то проверка COPY "*","*" ;Ошибка!!! COPY "*","*" надо проверять всегда, иначе при наличии на диске файла с именем "*" скопируется только этот файл, а в целом тут должно быть так: ;LD (#5CF8),A ;PUSH AF ;CALL #5CB ;POP AF ;JP NZ,#3D9 ;А в подпрограмме #5CB вместо JP NZ,#3D9 должно быть RET NZ. CALL x165D ;чтение описателя файла LD HL,#5CE6 ;сохранение его части LD DE,#5CED LD BC,7 LDIR CALL x1CB0 ;установка нового имени файла PUSH AF ;сохранение результата проверки PUSH BC ;и номера файла LD A,(#5CF6) ;сохранение номера дисковода - приемника LD (#5CF9),A LD A,(#5CF8) ;выбор дисковода - источника CALL x3DCB CALL x0405 ;настройка на диск LD A,(#5CF9) ;выбор дисковода - приемника CALL x3DCB CALL x0405 ;настройка на диск POP BC ;восстановление номера файла POP AF ;и результата проверки нового имени файла JR NZ,x06F3 ;если файл не найден, то копирование файла CALL x05B4 ;проверка файла с расширением "#" JR NZ,x06F3 ;если копируется другой блок, то копируем его CALL x0581 ;запрос OVERWRITE? JP NZ,x03E1 ;если был ответ N, то O.K. x06F3 CALL x063C ;копирование файла CALL x1E43 ;перезапись сектора с описателем файла LD A,(#5CE5) ;берем расширение файла CP "#" ;это "#"? JP NZ,x03E1 ;если нет, то O.K. LD A,#A ;файл искать по #A байтам LD (#5D06),A LD HL,#5CE6 ;следующий блок INC (HL) LD A,(#5CF8) ;выбор дисковода - источника CALL x3DCB CALL x05B4 ;поиск блока JP NZ,x03E1 ;если не нашли, то O.K. CALL x165D ;чтение его описателя LD HL,#5CE6 ;сохранение его части LD DE,#5CED LD BC,7 LDIR LD A,(#5CF9) ;выбор дисковода - приемника CALL x3DCB CALL x0405 ;настройка на диск JR x06F3 ;повтор ;Адрес #72F. Копирование файла при двух дисководах. Установите ;#5CF1, #5D23, #5CF8, #5CF9, #5CF2, #5CCF и #5CEB. x072F LD A,(#5CF1) ;берем количество секторов OR A ;все скопировали? RET Z ;если да, то возврат PUSH HL ;сохранение HL LD HL,#5D23 ;адрес переменной с длиной рабочей области памяти SUB (HL) ;области хватит? POP HL ;восстановление HL JR NC,x0775 ;если рабочей области не хватит, то копируем часть файла LD A,(#5CF1) ;копируем весь остаток LD B,A XOR A ;скопировали все LD (#5CF1),A x0744 PUSH BC ;сохранение количества копируемых сектоpов LD A,(#5CF8) ;выбор дисковода-источника CALL x3DCB POP BC ;восстановление количества копируемых секторов PUSH BC ;и снова сохранение его LD HL,(#5CCF) ;берем адрес рабочей области памяти PUSH HL ;сохраняем его LD DE,(#5CF2) ;берем адрес части файла на диске-источнике CALL x1E3D ;загрузка секторов LD HL,(#5CF4) ;установка адреса следующей группы секторов LD (#5CF2),HL ;на диске-источнике LD A,(#5CF9) ;выбор дисковода-приемника CALL x3DCB POP HL ;восстановление адреса рабочей области памяти POP BC ;и количества копируемых секторов LD DE,(#5CEB) ;берем адрес части файла на диске-приемнике CALL x1E4D ;запись секторов LD HL,(#5CF4) ;установка адреса следующей группы секторов LD (#5CEB),HL ;на диске-приемнике JR x072F ;повтор x0775 LD (#5CF1),A ;установка оставшегося количества секторов PUSH HL ;сохранение HL LD HL,#5D23 ;копируем столько секторов, сколько LD B,(HL) ;поместится в рабочую область POP HL ;восстановление HL XOR A ;обнуление аккумулятора JR x0744 ;копирование секторов ;Адрес #781. Стирание файлов. Вход: установите #5CDD, #5CE5, и произведите поиск файла. Программа устанавливает #5D08 и #5D07. x0781 XOR A ;обнуление количества стертых файлов LD (#5D07),A JR x07A0 ;стирание файлов ;Адрес #787. Выполнение команды ERASE. Установите #5D11 и #5C3B. x0787 CALL x1DDF ;прием имени файла на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x102E ;прием расширения файла XOR A ;пока ничего не стерто LD (#5D07),A CALL x292F ;установка и проверка имени стираемого файла CALL x07A0 ;стирание файла JP NZ,x0577 ;если стерли файл не в конце каталога, то проверка, сколько файлов стерли JP x03E1 ;сообщение O.K. ;Адрес #7A0. Стирание файлов. Вход: установите #5CDD, #5CE5, обнулите #5D07 и произведите поиск файла. Программа устанавливает #5D08 и #5D07. x07A0 LD A,(#5CDD) ;сохранение первого символа имени файла LD (#5D08),A RET NZ ;если файл не был найден, то возврат LD HL,#5D07 ;стерт еще один файл INC (HL) PUSH BC ;сохранение номера файла CALL x03FD ;чтение в буфер сектора 8 дорожки 0 LD A,(#5E09) ;берем количество файлов на диске POP BC ;восстановление номера файла INC C ;этот файл последний? CP C JR NZ,x07BC ;если нет, то стирание обычным порядком DEC A ;на диске теперь на 1 файл меньше LD (#5E09),A XOR A ;стираемый файл в конце каталога x07BC PUSH AF ;сохранение признака метода стирания JR Z,x07C3 ;если файл не в конце каталога, LD HL,#5E19 ;то увеличение на 1 количества стертых файлов INC (HL) x07C3 PUSH BC ;сохранение номера стираемого файла CALL x1E43 ;перезапись сектора 8 дорожки 0 POP BC ;восстановление номера стираемого файла DEC C CALL x165D ;загрузка описателя файла POP AF ;восстановление флага метода стирания JP Z,x07D2 ;если файл в конце каталога, то первый символ имени будет CHR$ 0 LD A,1 ;иначе он будет CHR$ 1 x07D2 LD (#5CDD),A ;установка первого символа имени PUSH AF ;сохранение метода стирания CALL x1E40 ;запись описателя файла LD A,(#5D08) ;восстановление первого символа имени файла LD (#5CDD),A POP AF ;восстановление метода стирания JR Z,x07E7 ;если стерт файл в конце каталога, то реорганизация описателя диска CALL x1CB3 ;поиск следующего файла с таким именем JR x07A0 ;стирание его, если он есть x07E7 CALL x03FD ;чтение сектора 8 дорожки 0 LD HL,(#5CEB) ;установка нового начала свободного места LD (#5E06),HL LD DE,(#5CEA) ;установка нового количества свободных секторов LD HL,(#5E0A) LD D,0 ADD HL,DE LD (#5E0A),HL JP x1E43 ;перезапись сектора 8 дорожки 0 и возврат ;Адрес #800. Позиционирование с быстрой скоростью перемещения головки. Поместите физический номер дорожки в регистр данных, а команду позиционирования - в аккумулятор. x0800 and #FC ;позиционировать с быстрой скоростью jp x3D9A ;выдача команды и ожидание INTRQ x0805 db #FF,#FF ;new Адpес #807. нажатие magic x0807 push af ld a,r push af ld a,#04 push af inc sp push bc ld bc,#1FFD push hl ld hl,(#C001) ex (sp),hl ld a,#55 ld (#C001),a cpl ld (#C002),a ld a,#12 jp x0033 ;new Адрес #826. Вызов функции rst 8 ; a - номер дисковода x0826 ex (sp),hl push af ld a,#CF ;rst 8 ld (#5CBF),a ld a,(hl) inc hl ld (#5CC0),a ld a,#C9 ld (#5CC1),a pop af ex (sp),hl push hl ld hl,x3D2F ex (sp), hl push hl ld hl,#5CBF ex (sp),hl ret ;new Адрес #844. x0844 ld de,#4000 ld a,#07 jp x000B ;new Адрес #84C. x084C rst #20 dw #1F54 ret c rst #20 dw #1B7B ;new Адрес #853. x0853 ld a,(#5CF6) ld bc,#7FBA in c,(c) cp #01 jr z,x0867 jr nc,x086B bit 7,c jr nz,x08A3 jr x086F x0867 bit 6,c jr nz,x08A3 x086B cp #04 jr nc,x08A3 x086F ld de,(#5CF4) ld hl,(#5D00) ld bc,#0105 ld a,(#5CFE) cp #A0 jr nz,x0881 inc c x0881 call x0826 db #81 jr c,x088B pop hl pop de ei ret x088B call x0A64 ld b,#40 cp #02 jr z,x089C ld b,#01 cp #01 jr z,x089C ld b,#04 x089C ld a,b pop hl pop de ei jp x3F39 x08A3 ld hl,(#5D00) ret ;new Адрес #8A7. x08A7 ld a,(#5CF6) ld bc,#7FBA in c,(c) cp #01 jr z,x08BB jr nc,x08BF bit 7,c jr nz,x08C7 jr x08C3 x08BB bit 6,c jr nz,x08C7 x08BF cp #04 jr nc,x08C7 x08C3 xor a jp x3E63 x08C7 jp x3D98 ;new Адрес #8CA. x08CA ld (#5CCA),hl ;для дисководов C и D =#00 ld a,#FF ld (#5CD1),a ; ld hl,#8282 ret x08D6 DISPLAY "Free space at ",$,": ",/D,#901-$," byte(s)" ds #08FF-$,#00 ds #0901-$,#FF ;new Адрес #901. ; a - номер дисковода x0901 ld (#5CF6),a ;номер дисковода ld bc,#7FBA in c,(c) cp 1 ;дисковод B? jr z,x0914 ;если да, то переход jr nc,x0917 ;если дисковод C или D bit 7,c ;дисковод A ret nz ;если реальный дисковод, выход jr x091A x0914 bit 6,c ret nz ;если реальный дисковод, выход x0917 cp #04 ret nc ;выход, если дисковод >3 x091A or #80 ld c,#28 ;подфункция #28 call x0826 ;вызов rst 8 db #81 ld a,(#5CF6) ;номер дисковода jr nc,x092D ;нет ошибки cp #02 ret c ;ошибка x092A jp x3EE7 ;ошибка no disk x092D ld hl,#5D16 ld c,a ld a,%00111100 or c ld (hl),a ld a,(#5CF6) ;номер дисковода ld c,#01 ;подфункция #01 (выбор текущего дисковода) call x0826 ;вызов rst 8 db #81 jr c,x092A ;ошибка no disk call x3E08 ;выборка времени перемещения головки текущего дисковода ld (hl),#00 call x3E11 ;выборка типа дисковода ld (hl),#83 ld a,#80 ld (#5CCD),a ;гтовность дисковода pop hl ret x0951 DISPLAY "Free space at ",$,": ",/D,#A01-$," byte(s)" ds #09FF-$,#00 ds #0A01-$,#FF ;new Адрес #A01. x0A01 ld a,(#5CF6) push bc ld bc,#7FBA in c,(c) cp 1 ;дисковод B? jr z,x0A16 ;если да, то переход jr nc,x0A1A ;если дисковод C или D bit 7,c ;дисковод A jr nz,x0A2D jr x0A1E x0A16 bit 6,c jr nz,x0A2D ;если реальный дисковод x0A1A cp #04 jr nc,x0A2D ;если дисковод >3 x0A1E pop bc ld d,c push bc ld c,#02 call x0826 db #81 pop bc jp c,x3EE7 pop hl ret x0A2D pop bc jp x1FEB ;new Адрес #A31. x0A31 ld a,(#5CF6) ld bc,#7FBA in c,(c) cp 1 ;дисковод B? jr z,x0A45 ;если да, то переход jr nc,x0A49 ;если дисковод C или D bit 7,c ;дисковод A jr nz,x0A4F jr x0A4D x0A45 bit 6,c jr nz,x0A4F x0A49 cp #04 jr nc,x0A4F x0A4D pop hl ret x0A4F jp x3EB2 ;new Адрес #A52. Чтение переменной монитора x0A52 push de push bc push hl ld bc,#000D ld de,#0004 or a call x0826 db #82 bit 5,a jr x0A72 ;new Адрес #A64. Чтение переменной монитора x0A64 push de push bc push hl ld bc,#001D ld de,#0004 or a call x0826 db #82 x0A72 pop hl pop bc pop de ret ;new Адрес #A76. x0A76 ld a,(#5CF6) push bc ld bc,#7FBA in c,(c) cp 1 ;дисковод B? jr z,x0A8B ;если да, то переход jr nc,x0A8F ;если дисковод C или D bit 7,c ;дисковод A jr nz,x0A97 jr x0A93 x0A8B bit 6,c jr nz,x0A97 x0A8F cp #04 jr nc,x0A97 x0A93 pop bc xor a inc a ret x0A97 pop bc xor a ret x0A9A DISPLAY "Free space at ",$,": ",/D,#B01-$," byte(s)" ds #0AFF-$,#00 ds #0B01-$,#FF ;new Адрес #B01. x0B01 call x0A76 jp z,x1FF6 pop hl jp x1F16 ;new Адрес #B0B. x0B0B call x0A76 ld hl,#5CD7 ret z inc hl ld (hl),#00 pop hl ld hl,#5D25 ld (hl),#00 ld de,#5D26 ld bc,#00FF ldir ld d,#00 x0B25 ld e,#00 x0B27 call x084C ld hl,#5D25 ld bc,#0106 push de call x0826 db #81 jr nc,x0B44 call x0A64 ld c,a ld b,#00 call x1DA9 ld hl,#5CD6 inc (hl) x0B44 pop de inc e bit 4,e jr z,x0B27 ld a,#2B rst #10 xxx inc d ld a,d cp #A0 jr nz,x0B25 ret ;new Адрес #B54. x0B54 call x0A76 jp z,x1FEB ret x0B5B DISPLAY "Free space at ",$,": ",/D,#C01-$," byte(s)" ds #0BFF-$,#00 ds #0C01-$,#FF ;new Адрес #C01. x0C01 ld bc,#7FBA in a,(c) and %00000100 jr z,x0C1C ld bc,#047F x0C0D in a,(#FF) and #C0 jp nz,x3FD1 inc de ld a,e or d jr nz,x0C0D djnz x0C0D ret x0C1C ret ;new Адрес #C1D. x0C1D ld bc,#7FBA in a,(c) and %00000100 jr z,x0C38 ld bc,#047F x0C29 in a,(#FF) and #C0 jp nz,x3FEC inc de ld a,e or d jr nz,x0C29 djnz x0C29 ret x0C38 ret x0C39 DISPLAY "Free space at ",$,": ",/D,#FF3-$," byte(s)" ds #0CFF-$,#00 ds #0D01-$,#FF ds #0DFF-$,#00 ds #0E01-$,#FF ds #0EFF-$,#00 ds #0F01-$,#FF ds #0FF3-$,#00 x0FF3 push af push bc push de jp x2A59 x0FF9 DISPLAY "Free space at ",$,": ",/D,#1000-$," byte(s)" ds #FFF-$,#00 ds #1000-$,#FF DISPLAY "Free space at ",$,": ",/D,#1000-$," byte(s)" DS #1000-$,#FF ;Адрес #1000. Текст "Interface one fitted" x1000 DB #16,9,5 DB "Interface one fitted" DB 0 ;Адрес #1018. Выполнение команды "*". Установите #5D11 и #5C3B. x1018 CALL x1DDF ;установка CH_ADD и прием имени дисковода на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x0531 ;снятие имени дисковода со стека калькулятора LD A,(DE) ;берем первый символ имени CALL x0524 ;вычисление номера дисковода LD (#5D19),A ;установка дисковода по умолчанию CALL x3DCB ;выбор дисковода JP x03E1 ;сообщение O.K. ;Адрес #102E. Прием расширения файла. Установите #5C5D и #5CD6. x102E LD B,"C" ;расширение C LD A,(#5CD6) ;расширение принимать? OR A JR NZ,x104D ;если нет, то установка расширения файла CALL x1D8C ;берем текущий символ CP #AF ;это CODE? LD B,"C" ;расширение C JR Z,x104D ;если да, то установка расширения файла CP #E4 ;это DATA? LD B,"D" ;расширение D JR Z,x104D ;если да, то установка расширения файла CP "#" ;это #? LD B,"#" ;расширение # JR Z,x104D ;если да, то установка расширения файла LD B,"B" ;расширение B x104D LD HL,#5CE5 ;адрес переменной с расширением файла LD (HL),B ;установка расширения RET ;возврат ;Адрес #1052. Ввод клавиши с ожиданием. x1052 DI ;запрет прерываний PUSH HL ;сохранение регистров PUSH BC PUSH DE x1056 RST #20 ;определение номера нажатой клавиши DW #028E LD C,0 ;режим клавиатуры - C или L JR NZ,x1056 ;если нажата бессмысленная комбинация клавиш, то повтор RST #20 ;определение кода нажатой клавиши DW #031E JR NC,x1056 ;если ничего не нажато, то повтор DEC D ;режим клавиатуры - C или L LD E,A ;помещение кода клавиши в регистр E RST #20 ;обработка клавиш CAPS SHIFT и SYMBOL SHIFT DW #0333 POP DE ;восстановление регистров POP BC POP HL AND #DF ;буква будет заглавная EI ;разрешение прерываний RET ;возврат ;Адрес #106E. Вывод цветных полос для заставки. x106E LD HL,#58E5 ;адрес линии атрибутов LD B,#A ;установка атрибутов x1073 LD (HL),7 INC HL DJNZ x1073 LD (HL),2 INC HL LD (HL),#16 INC HL LD (HL),#34 INC HL LD (HL),#25 INC HL LD (HL),#28 INC HL LD (HL),7 LD HL,#40EE ;адрес верхней линии пикселей LD B,8 ;8 линий пикселей в знакоместе XOR A ;обнуление аккумулятора x108F PUSH BC ;сохранение количества линий SCF ;сдвиг пикселей RLA PUSH HL ;сохранение адреса линии пикселей PUSH AF ;и байта для заполнения LD B,5 ;в линии 5 байтов x1096 INC HL ;заполнение линии LD (HL),A DJNZ x1096 POP AF ;восстановление байта для заполнения линии, POP HL ;адреса линии POP BC ;и количества линий LD DE,#100 ;берем адрес следующей линии ADD HL,DE DJNZ x108F ;повтор до конца RET ;возврат x10A4 RET ;Адрес #10A5. Сообщения команды LIST. x10A5 DB " Del." x10AA DB " File(s)" DB 0 x10B3 DB "Title:" DB #A0 x10BA DB #17,#11 DB " Disk Drive: " DB 0 x10CA DB #17,#10," ",0 x10CE DB #17,#10," 40 Track S. Side" DB 0 x10E2 DB #17,#10," 80 Track S. Side" DB 0 x10F6 DB #17,#10," 40 Track D. Side" DB 0 x110A DB #17,#10," 80 Track D. Side" DB 0 x111E DB #17,#10 DB " Free Sector " DB 0 x112E DB #D,#D DB " File Name Start Length Line" DB 0 ;Адрес #1151. Выделение #222 байтов в рабочей области. Устанавливает #5CCF. x1151 LD HL,(#5C61) ;берем адрес рабочей области LD (#5CCF),HL ;установка адреса пространства LD BC,#222 ;выделять #222 байтов JP x1E23 ;выделение области и возврат ;Адрес #115D. Печать числа из HL с нулями. x115D XOR A ;в числе 0 десятков тысяч LD DE,#2710 x1161 SBC HL,DE ;вычитание из числа 10000 JR C,x1168 ;если получилось число меньше 10000, то следующий разряд INC A ;следующий десяток тысяч JR x1161 ;повтор x1168 ADD A,"0" ;печать десятков тысяч CALL x11A8 ADD HL,DE ;восстановление остатка числа XOR A ;в числе 0 тысяч x116F LD DE,#3E8 x1172 SBC HL,DE ;вычитание из числа 1000 JR C,x1179 ;если получилось число меньше 1000, то следующий разряд INC A ;следующая тысяча JR x1172 ;повтор x1179 ADD A,"0" ;печать тысяч CALL x11A8 ADD HL,DE ;восстановление остатка числа XOR A ;в числе 0 сотен LD DE,#64 x1183 SBC HL,DE ;вычитание из числа 100 JR C,x118A ;если получилось число меньше 100, то следующий разряд INC A ;следующая сотня JR x1183 ;повтор x118A ADD A,"0" ;печать сотен CALL x11A8 ADD HL,DE ;восстановление остатка числа XOR A ;в числе 0 десятков LD DE,#A x1194 SBC HL,DE ;вычитание из числа 10 JR C,x119B ;если получилось число меньше 10, то следующий разряд INC A ;следующий десяток JR x1194 ;повтор x119B ADD A,"0" ;печать десятков CALL x11A8 ADD HL,DE ;восстановление остатка числа LD A,L ;печать единиц ADD A,"0" CALL x11A8 RET ;возврат ;Адрес #11A8. То же, что и #3D82. x11A8 PUSH HL ;сохранение HL и DE PUSH DE CALL x3D82 ;печать символа POP DE ;восстановление DE и HL POP HL RET ;возврат ;Адрес #11B0. Проверка достижения конца буфера при работе с каталогом. Установите #5CF9 и #5CCC, а в HL поместите текущий адрес буфера. Если конец буфера достигнут, то в буфер загрузится следующий сектор каталога, а в HL будет #5D25. x11B0 PUSH HL ;сохранение HL и BC PUSH BC LD A,(#5CF9) ;берем номер дисковода из #5CF9 LD HL,#5CF6 ;берем номер текущего дисковода CP (HL) ;назначен другой дисковод? CALL NZ,x3DCB ;если да, то выбор назначенного дисковода POP BC ;восстановление HL и BC POP HL CALL x050C ;проверка достижения конца буфера LD A,(HL) ;берем первый символ имени файла OR A ;конец каталога? JP Z,x01D3 ;если да, то завершение CP 1 ;файл стерт? CALL Z,x0507 ;если да, то пропуск файла RET NZ ;иначе возврат JR x11B0 ;если файл был пропущен, то повтор ;Адрес #11CE. Выполнение команды LIST. Установите #5D11 и #5C3B. x11CE CALL x042B ;проверка второго символа строки LD BC,2 ;по умолчанию печатать в поток 2 LD (#5CDB),BC JR Z,x1205 ;если второй символ строки ENTER, то вывод каталога CP "#" ;если второй символ строки "#"? JR NZ,x11F8 ;если нет, то установка дисковода LD (#5C5D),HL ;установка CH_ADD CALL x1E0B ;прием номера потока CALL x1D8C ;берем текущий символ CP #D ;это ENTER? JR Z,x1205 ;если да, то вывод каталога CP "," ;это ","? JP NZ,x1D1A ;если нет, то ошибка CALL x1E2A ;следующий символ CALL x1DBD ;прием имени дисковода на стек калькулятора JR x11FB ;установка дисковода x11F8 CALL x1DDF ;установка CH_ADD и прием имени дисковода на стек калькулятора x11FB CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x1DB5 ;снятие имени дисковода со стека калькулятора EX DE,HL ;переброска его адреса в HL CALL x1C81 ;установка дисковода x1205 CALL x1D75 ;если идет проверка на синтаксис, то возврат LD A,(#5CF6) ;загрузка имени дисковода в #5CF9 LD (#5CF9),A CALL x0405 ;настройка на диск LD A,(#5CDB) ;берем номер потока CP 2 ;это 2? PUSH AF ;сохраняем его CALL Z,x1D97 ;если да, то очистка экрана POP AF ;восстановление номера потока CP #11 ;он больше #10? JP NC,x1D1A ;если да, то ошибка CALL x1D84 ;открытие потока LD A,#FF ;буфер не убирать, память не изменять LD (#5CF8),A CALL x1151 ;выделение памяти в рабочей области LD HL,#5E06 ;начало описателя диска в буфере LD DE,(#5CCF) ;берем адрес WORKSP LD BC,#20 ;длина описателя диска LDIR ;сохранение описателя диска CALL x03E8 ;загрузка в буфер сектора 0 дорожки 0 LD HL,#5D25 ;адрес буфера PUSH HL ;сохранение его x123E LD HL,x10B3 ;адрес сообщения TITLE: PUSH BC ;сохранение BC RST #18 ;печать TITLE: LD HL,(#5CCF) ;берем адрес WORKSP LD BC,#14 ;#14-й байт ADD HL,BC RST #18 ;печать имени диска LD HL,x10BA ;печать DISC DRIVE: RST #18 LD A,(#5CF6) ;берем номер дисковода ADD A,"A" ;вычисление имени дисковода CALL x3D82 ;печать его CALL x3D80 ;перевод строки LD HL,(#5CCF) ;3-й байт описателя диска LD BC,3 ADD HL,BC LD A,(HL) ;берем количество файлов на диске LD HL,(#5CCF) ;#13-й байт LD BC,#13 ADD HL,BC SUB (HL) ;вычисление количества нестертых файлов PUSH HL ;сохранение адреса #13-го байта описателя диска CALL x1DA3 ;печать количества нестертых файлов LD HL,x10AA ;печать FILE(S) RST #18 LD HL,(#5CCF) ;2-й байт описателя диска LD BC,2 ADD HL,BC LD A,(HL) ;берем тип диска LD HL,x10CE ;адрес сообщения 40 TRACKS, S.SIDE CP #19 ;это #19? JR Z,x1292 ;если да, то печать сообщения LD HL,x10E2 ;адрес сообщения 80 TRACKS, S.SIDE CP #18 ;это #18? JR Z,x1292 ;если да, то печать сообщения LD HL,x10F6 ;адрес сообщения 40 TRACKS, D.SIDE CP #17 ;это #17? JR Z,x1292 ;если да, то печать сообщения LD HL,x110A ;адpес сообщения 80 TRACKS, D.SIDE x1292 RST #18 ;печать сообщения POP HL ;восстановление адреса #13-го байта описателя диска LD C,(HL) ;берем количество стертых файлов CALL x1DA4 ;печать его LD HL,x10A5 ;печать DEL.FILES RST #18 LD HL,x111E ;печать FREE SECTORS: RST #18 LD HL,(#5CCF) ;4-й байт LD BC,4 ADD HL,BC LD C,(HL) ;берем количество свободных секторов INC HL LD B,(HL) CALL x1DA9 ;печать его LD HL,x112E ;печать FILE NAME, START, LENGTH, LINE RST #18 POP BC ;восстановление BC и текущего адреса в буфеpе POP HL LD B,#10 ;печатать информацию о #10 файлах x12B5 CALL x11B0 ;проверка достижения конца буфера CALL x3D80 ;перевод строки PUSH BC ;сохранение количества оставшихся файлов PUSH HL ;и текущего адреса в буфеpе CALL x2938 ;печать имени и расширения файла LD BC,#D ;#D-й байт описателя файла POP HL ;восстановление текущего адреса в буфере PUSH HL ADD HL,BC LD C,(HL) ;берем размер файла в секторах PUSH BC ;сохраняем его LD A,C ;загружаем его в C LD B,2 ;печатать 2 пробела перед числом CP #A ;длина файла меньше 10 секторов? JR C,x12D0 ;если да, то печать пробелов DEC B ;печатать один пробел x12D0 CP #64 ;длина файла меньше 100 сектоpов? JR NC,x12D9 ;если нет, то пробелы не печатать x12D4 LD A," " ;печать пробелов RST #10 DJNZ x12D4 x12D9 POP BC ;восстановление длины файла в секторах CALL x1DA9 ;печать ее LD HL,x10CA ;#10 пробелов RST #18 POP HL ;восстановление адреса описателя файла в буфере PUSH HL ;и снова сохранение его LD BC,9 ;9-й байт описателя ADD HL,BC LD E,(HL) ;берем адрес загрузки файла INC HL LD D,(HL) PUSH HL ;сохранение текущего адреса в описателе файла EX DE,HL ;переброска адреса загрузки файла в HL CALL x115D ;печать его LD A," " ;пробел CALL x3D82 POP HL ;восстановление текущего адреса в описателе файла INC HL ;следующий адрес LD E,(HL) ;берем длину файла INC HL LD D,(HL) EX DE,HL ;перенос ее в HL CALL x115D ;печать ее POP HL ;восстановление адреса описателя файла PUSH HL ;и снова сохранение его LD BC,8 ;8-й байт ADD HL,BC LD A,(HL) ;берем расширение файла CP "B" ;это "B"? CALL Z,x131B ;если да, то печать строки автозапуска POP HL ;восстановление адреса описателя файла POP BC ;и счетчика файлов LD DE,#10 ;адрес следующего описателя файла ADD HL,DE DJNZ x12B5 ;повтор до конца PUSH HL ;сохранение адреса описателя файла CALL x3D80 ;2 раза перевод строки CALL x3D80 JP x123E ;повтор с самого начала ;Адрес #131B. Печать строки автостарта прогpаммы на бейсике. В HL поместите адрес описателя файла плюс 8 и установите #5CCF. x131B LD BC,5 ;берем адрес длины файла в секторах ADD HL,BC LD B,(HL) ;берем эту длину INC HL ;следующий адрес в описателе LD E,(HL) ;берем адрес файла на диске INC HL LD D,(HL) DEC B ;загружать будем 2 сектоpа JR Z,x1335 DEC B JR Z,x1335 ;если длина файла не больше 2-х секторов, то загрузка секторов LD A,#10 ;на дорожке #10 секторов x132C INC E ;следующий сектор CP E ;конец дорожки? JR NZ,x1333 ;если да, то LD E,0 ;следующий сектор 0 INC D ;и берем следующую дорожку x1333 DJNZ x132C ;повтор до конца x1335 LD HL,(#5CCF) ;берем адрес рабочей области LD BC,#21 ;#21 байт уже занято ADD HL,BC LD B,2 ;загружать 2 сектора PUSH HL ;сохранение адреса загрузки секторов CALL x1E3D ;загрузка секторов LD A,#80 ;будем искать конец программы POP HL ;восстановление адреса секторов в памяти LD BC,#200 ;длина области - #200 байтов CPIR ;поиск конца программы LD A,(HL) ;берем следующий байт CP #AA ;это #AA? RET NZ ;если нет, то возврат INC HL ;берем номер строки автостарта LD C,(HL) INC HL LD B,(HL) LD A,B ;это 0? OR C RET Z ;если да, то возврат PUSH BC ;сохранение номера строки автостарта LD A," " ;печать пробела CALL x3D82 POP BC ;восстановление номера строки автостарта CALL x1DA9 ;печать его RET ;возврат ;Адрес #1360. Выполнение команды COPY S. Установите #5D11 и #5C3B. x1360 CALL x1DC5 ;установка CH_ADD CALL x1E2A ;следующий символ CALL x1DBD ;прием имени файла на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x166F ;резервирование места в памяти LD HL,x27AA ;печать INSERT SOURCE DISC CALL x2707 x1375 CALL x1052 ;ввод символа с клавиатуры CP "Y" ;это "Y"? JR NZ,x1375 ;если нет, то повтор CALL x1D9F ;очистка низа экрана CALL x102E ;прием расширения файла CALL x1CB0 ;установка имени файла JP NZ,x03D9 ;если такого файла нет, то ошибка CALL x13B7 ;копирование файла LD A,(#5CE5) ;расширение файла #? CP "#" JP NZ,x03E1 ;если нет, то O.K. x1393 LD A,#A ;файл искать по #A символам LD (#5D06),A LD HL,#5CE6 ;следующий блок INC (HL) CALL x1D97 ;очистка экрана LD HL,x27AA ;печать INSERT SOURCE DISC CALL x2707 x13A5 CALL x1052 ;ввод клавиши CP "Y" ;это "Y"? JR NZ,x13A5 ;если да, то повтор CALL x1CB3 ;поиск блока JP NZ,x03E1 ;если не нашли, то O.K. CALL x13B7 ;копирование блока JR x1393 ;повтор ;Адрес #13B7. Копирование файла при одном дисководе. Номер файла поместите в регистр C. x13B7 CALL x165D ;чтение описателя файла LD HL,#5CE6 ;сохранение его части LD DE,#5CED LD BC,7 LDIR LD A,(#5CF1) ;установка объема файла в секторах LD (#5D10),A CALL x0405 ;настройка на диск CALL x3E11 ;сохранение режима дисковода LD (#5CD9),A LD A,#FF ;первый проход LD (#5D21),A ;Внимание!!! Эта переменная уже занята. В ней хранятся первые 3 символа командной строки. CALL x1451 ;копирование файла LD HL,(#5D1F) ;берем адрес файла на диске - приемнике LD (#5CEB),HL ;устанавливаем его LD HL,(#5CF4) ;берем новый адрес свободного места на диске LD (#5E06),HL ;устанавливаем его LD HL,#5E09 ;записали 1 файл INC (HL) LD C,(HL) ;берем номер файла DEC C LD B,0 ;переводим его в двухбайтную форму PUSH BC ;сохраняем его LD DE,9 ;записывать сектор 8 дорожки 0 LD (#5CF4),DE CALL x1E43 ;запись сектора POP BC ;восстановление номера файла CALL x166B ;чтение и замена описателя файла CALL x1E43 ;запись сектора с описателем RET ;возврат ;Адрес #1403. Проверка наличия свободного места на диске-приемнике для команды COPY S. Поместите описатель файла в #5CDD и его часть в #5CED и установите #5D10. В дисководе должен быть диск-приемник. Подпрограмма устанавливает #5CEA, #5CEB и #5D1F. x1403 XOR A ;не первый проход LD (#5D21),A CALL x0405 ;настройка на диск CALL x3E11 ;берем режим дисковода LD (#5CDA),A ;сохраняем его CALL x1CB3 ;поиск файла JP Z,x1C50 ;если нашли, то FILE EXISTS CALL x03FD ;загрузка в буфер сектора 8 дорожки 0 LD A,(#5E09) ;берем количество файлов на диске CP #80 ;их 128? JP Z,x2723 ;если да, то DIRECTORY FULL LD HL,#5CED ;восстановление описателя файла LD DE,#5CE6 LD BC,7 LDIR CALL x03FD ;загрузка в буфер сектора 8 дорожки 0 LD A,(#5D10) ;восстановление длины файла в секторах LD (#5CEA),A LD DE,(#5CEA) ;перевод ее в двухбайтную форму LD D,0 OR A ;сброс флага C LD HL,(#5E0A) ;уменьшаем свободное место на диске SBC HL,DE JP C,x1C45 ;если его не хватило, то NO SPACE LD (#5E0A),HL ;установка нового количества свободного места на диске LD HL,(#5E06) ;берем адрес свободного места на диске LD (#5CEB),HL ;установка адреса файла на диске-приемнике LD (#5D1F),HL ;сохранение его ;Боже мой!!! Ну что это такое! Ведь эта переменная - флаг способа вызова TR-DOS. И на этом DOS все работают. Ужас какой-то. RET ;возвpат ;Адрес #1451. Копирование файла на одном дисководе. Поместите описатель файла в #5CDD и его часть в #5CED и установите #5CF1, #5D21, #5D23 и #5CCF. Подпрограмма устанавливает #5CBB, #5CD9, #5CDA и #5C92. x1451 LD A,(#5CF1) ;все скопировали? OR A RET Z ;если да, то возврат LD A,(#5D21) ;первый проход? OR A JR NZ,x146F ;если да, то диск - источник уже в дисководе CALL x1D97 ;очистка экрана LD HL,x27AA ;печать INSERT SOURCE DISC CALL x2707 x1465 CALL x1052 ;ожидание клавиши "Y" CP "Y" JR NZ,x1465 CALL x1D9F ;очистка низа экрана x146F LD A,(#5CF1) ;все скопировали? OR A RET Z ;если да, то возврат PUSH HL ;сохранение HL LD HL,#5D23 ;копируется часть файла SUB (HL) POP HL ;восстановление HL JR NC,x14CB ;если еще не конец, то копируется часть файла LD A,(#5CF1) ;копируем остаток LD B,A XOR A ;скопировали все LD (#5CF1),A x1484 PUSH BC ;сохранение количества копируемых секторов LD (#5CCE),A ;обнуление #5CCE LD HL,(#5CCF) ;берем адрес рабочего пространства PUSH HL ;сохраняем его LD DE,(#5CF2) ;берем адрес копируемого участка диска CALL x14D8 ;настройка дисковода под диск-источник CALL x1E3D ;загрузка секторов LD HL,(#5CF4) ;установка адреса на диске следующего сектора LD (#5CF2),HL CALL x1D97 ;очистка экрана LD HL,x2785 ;печать INSERT DESTINATION DISC CALL x2707 x14A5 CALL x1052 ;ожидание клавиши "Y" CP "Y" JR NZ,x14A5 CALL x1D9F ;очистка низа экрана LD A,(#5D21) ;первый проход? OR A CALL NZ,x1403 ;если да, то проверка наличия места на диске POP HL ;восстановление адреса рабочего пространства POP BC ;и количества копируемых секторов LD DE,(#5CEB) ;берем адрес текущего участка диска CALL x14E4 ;настройка дисковода под диск-приемник CALL x1E4D ;запись секторов LD HL,(#5CF4) ;установка адреса на диске следующего сектора LD (#5CEB),HL JP x1451 ;повтор x14CB LD (#5CF1),A ;установка длины оставшейся части файла PUSH HL ;сохранение HL LD HL,#5D23 ;берем длину рабочей области LD B,(HL) POP HL ;восстановление HL XOR A ;обнуление аккумулятора JP x1484 ;копирование ;Адрес #14D8. Помещение значения #5CD9 в переменную режима дисковода. Установите #5CD9. x14D8 PUSH HL ;сохранение DE и HL PUSH DE CALL x3E11 ;берем адрес переменной с типом дисковода LD A,(#5CD9) ;берем тип дисковода из #5CD9 LD (HL),A ;установка типа дисковода POP DE ;восстановление DE и HL POP HL RET ;возврат ;Адрес #14E4. Помещение значения #5CDA в переменную режима дисковода. Установите #5CDA. x14E4 PUSH HL ;сохранение DE и HL PUSH DE CALL x3E11 ;берем адрес переменной с типом дисковода LD A,(#5CDA) ;берем тип дисковода из #5CD9 LD (HL),A ;установка типа дисковода POP DE ;восстановление DE и HL POP HL RET ;возврат ;Адрес #14F0. Проверка наличия места на диске-приемнике для команды COPY B. Установите #5CDF и поместите в дисковод диск-приемник. Устанавливает #5CDA, #5CE7, #5CDD и обнуляет #5D21. x14F0 XOR A ;обнуление #5D21 LD (#5D21),A CALL x0405 ;настройка на диск CALL x3E11 ;берем режим дисковода LD (#5CDA),A ;сохраняем его LD A,(#5E08) ;сохраняем тип диска LD (#5CE7),A LD HL,#280 ;вычисление количества секторов на CP #19 ;диске-приемнике JR Z,x151F LD HL,#500 CP #18 JR Z,x151F CP #17 JR Z,x151F LD HL,#A00 CP #16 JR Z,x151F JP x1D1A ;если в качестве типа диска стоит неопределенное значение, то *ERROR* ;Лучше DISC ERROR. x151F LD (#5CDD),HL ;сохранение количества секторов на диске-приемнике LD BC,(#5CDF) ;берем количество копируемых секторов SBC HL,BC ;места хватит? JP C,x1C45 ;если нет, то NO SPACE RET ;возврат ;Адрес #152C. Выполнение команды COPY B. Установите #5C3B. x152C CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x166F ;резервирование места в памяти LD HL,x2779 ;печать BACKUP DISC CALL x2707 LD HL,x27AA ;печать INSERT SOURCE DISC CALL x2707 x153E CALL x1052 ;ввод клавиши CP "Y" ;это "Y"? JR NZ,x153E ;если да, то повтор CALL x1D9F ;очистка низа экрана LD A,#FF ;первый проход LD (#5D21),A ;Внимание!!! Эта переменная уже занята. В ней хранятся первые 3 символа командной строки. CALL x0405 ;настройка на диск CALL x3E11 ;берем режим дисковода LD (#5CD9),A ;сохраняем его LD A,(#5E08) ;берем тип диска CP #19 ;диск 40-дорожечный односторонний? LD HL,#280 ;всего на диске #280 секторов JR Z,x1575 ;если да, то копирование LD HL,#500 ;всего на диске #500 секторов CP #18 ;диск 80-дорожечный односторонний? JR Z,x1575 ;если да, то копирование CP #17 ;диск 40-дорожечный двухсторонний? JR Z,x1575 ;если да, то копирование LD HL,#A00 ;всего на диске #A00 секторов CP #16 ;диск 80-дорожечный двухсторонний? JR Z,x1575 ;если да, то копирование JP x1D1A ;иначе *ERROR* ;Внимание!!! Лучше выдавать сообщение DISC ERROR. x1575 LD BC,(#5E0A) ;берем количество свободных секторов SBC HL,BC ;вычисляем количество занятых секторов LD (#5CE5),HL ;установка количества секторов LD (#5CDF),HL LD HL,0 ;скопировано 0 секторов LD (#5CE1),HL LD (#5CE3),HL CALL x15B8 ;копирование секторов CALL x0405 ;настройка на диск LD A,(#5CE7) ;установка нового типа диска-приемника LD (#5E08),A LD HL,(#5CDD) ;берем общее число секторов на диске-приемнике LD BC,(#5CDF) ;берем число скопированных секторов SBC HL,BC ;вычисление числа свободных секторов на диске - приемнике LD (#5E0A),HL ;установка его CALL x14E4 ;настройка дисковода под диск-приемник LD DE,9 ;записывали сектор 8 дорожки 0 LD (#5CF4),DE CALL x1E43 ;запись сектора JP x03E1 ;O.K. ;Адрес #15B2. Проверка переменной #5CE5. Соответственно содержимому будет установлен флаг Z, а само содержимое будет в HL. x15B2 LD HL,(#5CE5) ;берем содержимое переменной #5CE5 LD A,H ;проверка его на 0 OR L RET ;возврат ;Адрес #15B8. Копирование секторов. Установите #5CD9, #5CCF, #5CE5, #5D21, #5D23 и #5CDB x15B8 CALL x15B2 ;все скопировали? RET Z ;если да, то возврат LD A,(#5D21) ;первый проход? OR A JR NZ,x15DB ;если да, то диск-источник уже в дисководе CALL x1D97 LD HL,x2779 ;печать BACKUP DISC CALL x2707 LD HL,x27AA ;печать INSERT SOURCE DISC CALL x2707 x15D1 CALL x1052 ;ожидание нажатия "Y" CP "Y" JR NZ,x15D1 CALL x1D9F ;очистка низа экрана x15DB CALL x15B2 ;все скопировали? RET Z ;если да, то возврат PUSH BC ;сохранение BC и количества секторов PUSH HL LD HL,#5D23 ;берем длину рабочей области в секторах LD C,(HL) LD B,0 POP HL ;восстановление количества секторов SBC HL,BC ;уменьшение количества секторов POP BC ;восстановление BC JP NC,x1644 ;если рабочего пространства мало, то это еще не конец LD BC,(#5CE5) ;берем оставшееся количество секторов LD HL,0 ;все скопировали LD (#5CE5),HL x15F8 PUSH BC ;сохранение количества секторов LD HL,(#5CCF) ;берем адрес рабочей области PUSH HL ;сохраняем его CALL x14D8 ;настройка дисковода под диск-источник LD DE,(#5CE1) ;берем адрес группы секторов на диске-источнике LD B,C CALL x1E3D ;загрузка секторов LD HL,(#5CF4) ;установка адреса следующей группы секторов LD (#5CE1),HL ;на диске-источнике CALL x1D97 ;очистка экрана LD HL,x2779 ;печать BACKUP DISC CALL x2707 LD HL,x2785 ;печать INSERT DESTINATION DISC CALL x2707 x161D CALL x1052 ;ожидание нажатия "Y" CP "Y" JR NZ,x161D CALL x1D9F ;очистка низа экрана LD A,(#5D21) ;первый проход? OR A CALL NZ,x14F0 ;если да, то проверка наличия места на диске POP HL ;восстановление адреса рабочей области POP BC ;и количества копируемых секторов LD DE,(#5CE3) ;берем адрес группы секторов на диске-приемнике LD B,C CALL x14E4 ;настройка дисковода под диск-приемник CALL x1E4D ;запись секторов LD HL,(#5CF4) ;установка адреса следующей группы секторов LD (#5CE3),HL ;на диске-приемнике JP x15B8 ;повтор x1644 LD (#5CE5),HL ;установка оставшегося количества секторов PUSH HL ;сохранение его LD HL,#5D23 ;берем длину рабочей области LD C,(HL) ;столько секторов будем копировать LD B,0 POP HL ;восстановление оставшегося количества секторов XOR A ;обнуление аккумулятора JP x15F8 ;копирование ;Адрес #1653. Проверка состояния файла. Номер файла задайте в регистре A. Возвращает Z, если файл стерт и NZ, если нет, а в A будет первый символ имени файла. x1653 CALL x165D ;чтение описателя файла LD A,(#5CDD) ;берем первый символ имени файла CP 1 ;проверка состояния файла RET ;возврат ;Адрес #165C. Чтение описателя файла. На входе в регистр A поместите номер файла. Описатель будет загружен по адресу #5CE5. Используется также с адресов: ;#165D - то же, что и #165C, но номер файла в регистре C. ;#165E - то же, что и #17E9, но сохраняет номер файла. x165C LD C,A ;перенос номера файла в рег. C x165D XOR A ;переносим описатель из буфера в память x165E PUSH BC ;сохранение номера файла CALL x17E9 ;чтение сектора с описателем и перенос описателя POP BC ;восстановление номера файла RET ;возврат ;Адрес #1664. запись информации о файле. Вход: описатель расположить по адресу #5CDD, а в аккумулятор поместить номер файла. x1664 LD C,A ;перенос в C номера файла CALL x166B ;чтение сектора и замена описателя файла в нем JP x1E43 ;перезапись сектора ;Адрес #166B. Чтение в буфер сектора с описателем файла и замена описателя. Поместите описатель по адресу #5CDD. x166B LD A,#FF ;описатель перемещать из переменных в буфер JR x165E ;то же, что и #17E9, но с сохранением BC ;Адрес #166F. Резервирование места в памяти. Устанавливает #5CCF и #5D23. x166F LD A,#FF ;WORKSP использовалась LD (#5D0E),A CALL x1680 ;вычисление размера доступной памяти LD HL,(#5C61) ;установка адреса рабочей области LD (#5CCF),HL JP x1E23 ;выделение места в памяти и возврат ;Адрес #1680. Вычисление количества свободной памяти в секторах. Размер свободной памяти в байтах будет в BC, а в секторах ? в #5D23. x1680 RST #20 ;берем количество свободной памяти в байтах DW #1F1A LD HL,#FFFF SBC HL,BC LD A,H ;свободно меньше 16 секторов? CP #10 JR NC,x168F ;если да, то LD A,#11 ;будем выделять 16 секторов x168F DEC A ;1 сектор на всякий случай LD (#5D23),A ;установка размера свободной памяти в секторах LD B,A ;установка размера свободной памяти в байтах LD C,0 RET ;возврат ;Адрес #1697. Помещает HL в #5CD7 и #5CDB и прибавляет #5CEA (1 байт) к #5CD9 (2 байта). x1697 LD (#5CD7),HL ;установка #5CD7 и #5CD9 LD (#5CDB),HL LD DE,(#5CEA) ;сложение #5CEA и #5CD9 LD HL,(#5CD9) LD D,0 ADD HL,DE LD (#5CD9),HL RET ;возврат ;Адрес #16AB. Выполнение команды MOVE. Установите #5C3B. x16AB CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x166F ;резервирование места в памяти CALL x0405 ;настройка на диск LD A,(#5E19) ;стертые файлы на диске есть? OR A JP Z,x03E1 ;если нет, то сообщение O.K. LD HL,0 ;пока освободилось 0 секторов LD (#5CD9),HL LD C,#FF ;начнем с файла номер 0 x16C3 INC C ;следующий файл CALL x1653 ;он стерт? JR NZ,x16C3 ;если нет, то следующий файл LD A,C ;сохранение номера стираемого файла LD (#5CD4),A LD HL,(#5CEB) ;берем адрес стираемого файла на диске LD (#5CD5),HL ;сохраняем его CALL x1697 ;приращение счетчика освободившихся секторов x16D6 INC C ;следующий файл CALL x1653 ;он стерт? JR Z,x16D6 ;если да, то следующий файл CP 0 ;это конец каталога? JP NZ,x1710 ;если нет, то меняем файлы местами LD A,(#5CD4) ;берем номер стираемого файла LD C,A x16E5 INC C ;следующий файл CALL x1653 ;это конец каталога? CP 0 JR Z,x176C ;если да, то реорганизация описателя диска XOR A ;конец каталога LD (#5CDD),A CALL x1E40 ;запись описателя файла CALL x1697 ;приращение счетчика освободившихся секторов JR x16E5 ;повтор x16F9 call x1701 ret nz jr x170D x16FF db #FF,#FF x1701 in a,(#1F) and #02 cp b ret nz inc de ld a,e or d jr nz,x1701 ret x170D jp x3EE7 x1710 LD A,(#5CEA) ;берем размер перемещаемого файла в секторах LD (#5CD3),A ;сохраняем его LD (#5CD1),A LD HL,(#5CEB) ;берем адрес перемещаемого файла на диске LD (#5CD5),HL ;сохраняем его PUSH BC ;сохранение номера перемещаемого файла CALL x17A5 ;перемещение файла POP BC ;восстановление номера перемещаемого файла LD HL,(#5CF4) ;перемещение продолжится с этого места LD (#5CD5),HL LD (#5CEB),HL XOR A ;размер стертого файла - 0 секторов LD (#5CEA),A LD A,(#5CDD) ;сохранение первого символа имени файла PUSH AF LD A,1 ;файл стерт LD (#5CDD),A CALL x1E40 ;запись описателя стертого файла POP AF ;восстановление первого символа имени файла LD (#5CDD),A LD A,(#5CD4) ;берем номер стертого файла LD C,A LD HL,(#5CDB) ;установка нового адреса перемещенного файла LD (#5CEB),HL ;на диске LD A,(#5CD1) ;восстановление размера перемещенного файла LD (#5CEA),A ;на диске CALL x1E40 ;запись описателя перемещенного файла LD A,(#5CD4) ;берем номер файла после перемещенного INC A LD C,A CALL x165D ;чтение его описателя LD HL,(#5CD5) ;установка его нового адреса на диске LD (#5CEB),HL CALL x1E40 ;запись его описателя LD A,(#5CD4) ;берем номер перемещенного файла LD C,A JP x16C3 ;повтор ;Адpес #176C. Реорганизация описателя диска. Установите #5CCF, #5CD9 и #5CD5. x176C LD HL,(#5CCF) ;берем адрес рабочего пространства LD BC,#1000 ;сокращаем его на #1000 байтов CALL x1E2E CALL x03FD ;загрузка в буфер сектора 8 дорожки 0 LD HL,(#5E0A) ;увеличение количества свободного места на LD DE,(#5CD9) ;диске ADD HL,DE LD (#5E0A),HL LD A,(#5E09) ;уменьшение количества файлов на диске на LD HL,#5E19 ;число стертых SUB (HL) LD (#5E09),A LD (HL),0 ;на диске больше нет стертых файлов LD HL,(#5CD5) ;установка нового адреса свободного места на LD (#5E06),HL ;диске PUSH AF ;сохранение количества файлов на диске CALL x1E43 ;запись сектора 8 дорожки 0 POP AF ;восстановление количества файлов на диске LD C,A CALL x165D ;чтение описателя файла за последним XOR A ;это конец каталога LD (#5CDD),A JP x0569 ;запись описателя файла и завершение ;Адрес #17A5. Перемещение файла. Установите #5CD3, #5D23, #5CCF, #5CD5 и #5CD7. x17A5 LD A,(#5CD3) ;перемещен весь файл? OR A RET Z ;если да, то возврат PUSH HL ;сохранение HL LD HL,#5D23 ;буфера хватит на остаток? SUB (HL) POP HL ;восстановление HL JR NC,x17DD ;если буфера не хватит, то перемещаем часть файла LD A,(#5CD3) ;берем количество оставшихся секторов LD B,A XOR A ;переместили все LD (#5CD3),A x17BA PUSH BC ;сохранение количества перемещаемых секторов LD HL,(#5CCF) ;берем адрес рабочей области PUSH HL ;сохранение его LD DE,(#5CD5) ;берем адрес части перемещаемого файла на старом месте CALL x1E3D ;загрузка секторов LD HL,(#5CF4) ;установка адреса следующей части файла LD (#5CD5),HL POP HL ;восстановление адреса рабочей области POP BC ;и количества перемещаемых секторов LD DE,(#5CD7) ;берем адрес части перемещаемого файла на новом месте CALL x1E4D ;запись секторов LD HL,(#5CF4) ;установка адреса следующей части файла LD (#5CD7),HL JR x17A5 ;повтор x17DD LD (#5CD3),A ;установка количества оставшихся секторов PUSH HL ;сохранение HL LD HL,#5D23 ;берем длину рабочей области в секторах LD B,(HL) POP HL ;восстановление HL XOR A ;обнуление аккумулятора JR x17BA ;перемещение секторов ;Адрес #17E9. Загрузка в буфер сектора с описателем файла и перенос описателя. В регистре C - номер файла, в A - направление перемещения (0 - в переменные, иначе - в прочитанный сектор). x17E9 PUSH AF ;сохранение направления перемещения LD HL,#5CCC ;первый сектор каталога - 0 LD (HL),0 LD A,C ;определение номера сектора с описателем файла x17F0 SUB #10 JR C,x17F7 INC (HL) JR x17F0 x17F7 ADD A,#10 ;берем номер описателя в секторе LD C,A PUSH BC ;сохраним его CALL x03EC ;загрузка в буфер сектора с описателем POP BC ;восстановление номера описателя в секторе POP AF ;и направление перемещения CALL x1CA4 ;определение адреса описателя файла в буфере LD DE,#5CDD ;берем второй адрес для LDIR LD BC,#10 ;берем длину описателя OR A ;установка направления перемещения JR Z,x180D EX DE,HL x180D LDIR ;перенос описателя файла RET ;возврат ;Адрес #1810. Выполнение команды VERIFY. Установите #5D11 и #5C3B. Используется также с адресов: ;#1815 - выполнение команды LOAD. Установите #5D11 и #5C3B; ;#1818 - выполнение команды LOAD, PEEK или POKE; Установите #5D11, #5C3B и #5D10. x1810 LD A,#FF ;верификация файла LD (#5CF9),A x1815 CALL x1852 ;обнуление #5D10 x1818 CALL x1836 ;обработка параметров и загрузка файла CALL x1D75 ;если идет проверка на синтаксис, то возврат LD A,#FF ;выполняется команда LOAD LD (#5D10),A LD A,(#5CF9) ;выполняется VERIFY? CP #FF JP Z,x03E1 ;если да, то O.K. LD A,(#5CE5) ;расширение файла B? CP "B" ;Внимание!!! Если была операция с одним сектором файла, то надо выходить независимо от расширения. JP Z,x012A ;если да, то обработка строки автостарта JP x03E1 ;иначе O.K. ;Адрес #1836. Обработка параметров для команды LOAD и загрузка файла. Установите #5D11, #5C3B, #5CF9 и #5D10. x1836 CALL x187A ;принятие параметров CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x18AB ;проверка параметров JP x1921 ;загрузка файла и возврат ;Адрес #1842. Обработка параметров для команды LOAD...CODE. Установите #5C5D на расширение файла. На выходе устанавливает #5CD6, #5CD9 и #5CDB. x1842 LD HL,(#5C5D) ;следующий символ строки ENTER? INC HL LD A,(HL) CP #D RET Z ;если да, то возврат LD A,1 ;задан адрес загрузки LD (#5CD6),A CALL x1DEB ;прием одного или двух чисел x1852 XOR A ;обнуление #5D10 LD (#5D10),A RET ;возврат x1857 CALL x102E ;прием расширения файла LD A,"B" ;это "B"? CP B JR NZ,x1866 ;если да, то декремент CH_ADD, так как для LD HL,(#5C5D) ;программы на бейсике расширение не DEC HL ;указывается LD (#5C5D),HL x1866 CALL x1DEB ;прием чисел LD HL,(#5CD9) ;установка адреса загрузки/записи сектора LD (#5CD7),HL LD HL,(#5CDB) ;установка номера сектора LD (#5CD9),HL XOR A ;обнуление #5CD6 LD (#5CD6),A RET ;возврат ;Адрес #187A. Принятие параметров для команды LOAD. Вход: установите #5D11 и #5C3B. Выход: устанавливает #5CD2, #5CD7, #5CD9, #5CE5 и #5CD6 и читает описатель файла. x187A CALL x042B ;второй символ командной строки ENTER? JP Z,x027B ;если да, то вход в командный процессор с вводом команды RUN "boot" ;Ошибка!!! это некорректно, так как при ошибке вы попадете в командный процессор TR-DOS, а не вернетесь в бейсик. CALL x1DDF ;помещение имени файла на стек калькулятора CALL x0572 ;операция со всем файлом? CALL NZ,x1857 ;если нет, то прием расширения и двух чисел CALL x1D8C ;берем текущий символ строки CP #AF ;это CODE? CALL Z,x1842 ;если да, то прием чисел, если они есть CP #E4 ;это DATA? PUSH AF ;сохранение результата проверки CALL x0572 ;операция со всем файлом? CALL Z,x102E ;если да, то прием расширения POP AF ;восстановление результата проверки CALL Z,x1BFC ;если символ DATA, то прием имени массива CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x292F ;установка имени файла и поиск файла ;Адрес #18A4. Чтение описателя файла, если он был найден. Установите #5CDD, #5CE5 и флаг Z: при Z=1 происходит чтение описателя, иначе ошибка NO FILE. x18A4 JP NZ,x03D9 ;если файл не найден, то NO FILE CALL x165D ;чтение описателя файла RET ;возврат ;Адрес #18AB. Обработка параметров для подпрограммы загрузки файла. На входе установите #5CD6, #5CD9 и #5CDB ; считайте описатель нужного вам файла. На выходе в #5CDB будет длина файла для загрузки, в #5CD6 0, если длина менялась, иначе 3. В HL будет адрес загрузки файла, в DE - его адрес на диске, в B - количество секторов для загрузки. При загрузке массива или программы на бейсике будет произведена подготовка памяти к загрузке. x18AB LD A,(#5CD6) ;берем флаг загрузки OR A ;начало и длину брать из каталога? LD HL,(#5CE6) ;берем начало файла из описателя JR Z,x18B7 ;если параметры берем не из каталога, то LD HL,(#5CD9) ;берем начальный адрес, назначенный нами x18B7 LD DE,(#5CEB) ;берем адрес файла на диске CP 3 ;все параметры назначены пользователем? LD A,(#5CEA) ;берем размер файла в секторах PUSH DE ;сохранение адреса файла на диске LD DE,(#5CE8) ;берем длину файла из описателя JR NZ,x18CB ;если нужно брать ее не оттуда, то берем LD DE,(#5CDB) ;длину загрузки, назначенную нами x18CB LD B,A ;сохранение размера файла в секторах LD (#5CDB),DE ;установка длины файла для загрузки LD A,(#5CE5) ;расширение файла C? CP "C" LD A,B ;восстановление длины файла в секторах JR NZ,x18FD ;если расширение не C, то длину не менять LD A,B ;если длина файла в байтах соответствует его CP D ;размеру в секторах, то длина загрузки не меняется JR Z,x18F6 DEC A CP D LD A,B JR Z,x18F6 LD A,(#5CD6) ;длина назначена пользователем? CP 3 LD A,B ;восстановление размера файла в секторах JR Z,x18F6 ;если мы сами назначили длину загрузки, то она не меняется XOR A ;грузить только полностью заполненные сектора LD (#5CD6),A LD D,B ;вычисление длины файла в байтах из его длины LD E,0 ;в секторах LD (#5CDB),DE ;установка новой длины JR x18F9 x18F6 CALL x191B ;файл загружать весь x18F9 LD A,B ;восстановление размера файла в секторах CALL x1EAC ;вычисление количества секторов для загрузки x18FD LD B,A ;сохранение его LD A,(#5CE5) ;расширение файла C? CP "C" POP DE ;восстановление адреса файла на диске RET Z ;если расширение файла C, то возврат ;Ошибка!!! Если выполняется чтение или запись сектора файла, то здесь должен быть возврат. Из-за этой ошибки нельзя прочитать или записать сектор файла с расширением B или D. PUSH DE ;сохранение адреса файла на диске CP "B" ;расширение B? PUSH AF ;сохранение расширения файла CALL Z,x1A01 ;если расширение B, то подготовка к загрузке программы на бейсике POP AF ;восстановление расширения CP "D" ;расширение D? CALL Z,x1A4C ;если да, то подготовка к загрузке массива CALL x191B ;длина загрузки не менялась LD A,(#5CDC) ;берем количество секторов для загрузки LD B,A POP DE ;восстановление адреса файла на диске RET ;возврат ;Адрес #191B. Помещает число 3 по адресу #5CD6. x191B LD A,3 LD (#5CD6),A RET ;Адрес #1921. Загрузка/верификация файла, а также загрузка/запись сектора файла. Вход: установите #5CF9, #5D10, #5CD7, #5CDB, в HL - адрес загрузки, в DE - адрес файла на диске, в B - количество секторов для загрузки. x1921 CALL x0572 ;выполняется загрузка или верификация? JR Z,x192D ;если да, то выполнение операций со всем файлом PUSH AF ;сохранение флага операции CALL x1A94 ;вычисление адреса сектора на диске POP AF ;восстановление флага операции CP #FF ;чтение сектора файла? x192D PUSH AF CALL Z,x195C ;если да, то чтение сектора или операция с файлом POP AF JR Z,x1937 ;и завершение загрузки или верификации JP x1E4D ;иначе запись сектора и возврат x1937 LD A,(#5CD6) ;загружать весь файл? CP 3 ;Не нужно этого делать!!! Лучше так: ;LD A,(#5D10) ;OR A ;и PEEK будет работать правильно. Не будет грузится мусор после загруженного сектора. ведь если в #5CD6 находится 0, то младший байт длины всегда равен 0 и #1946 не будет работать. CALL Z,x1946 ;если да, то загрузка или верификация конца файла LD HL,(#5C59) ;отметка конца программы на бейсике DEC HL LD (HL),#80 RET ;возврат ;Адрес #1946. Загрузка или верификация конца файла. Установите #5CF4, #5CDB и #5CF9. x1946 LD A,(#5CF9) ;верификация? CP #FF JP NZ,x2FDE ;если нет, то загрузка конца файла LD A,(#5CDB) ;файл занимает сектора без остатка? OR A RET Z ;если да, то возврат LD C,A ;берем длину остатка LD B,1 ;1 сектор LD DE,(#5CF4) ;текущее место диска JR x196A ;верификация конца файла и возврат ;Адрес #195C. Загрузка/верификация файла, а также загрузка сектора файла. Установите #5CF9 ,в DE поместите адрес файла на диске, в HL - адрес файла в памяти, в B - длину файла в секторах. Используется также с адреса #196A для верификации заданного количества байтов (все для #195C, кроме #5CF9 плюс в B ? количество байтов). x195C LD A,(#5CF9) ;верификация? CP #FF JP NZ,x1E3D ;если нет, то загрузка секторов и возврат LD (#5CF4),DE ;запомним адрес файла на диске LD C,0 ;в секторе #100 байтов x196A LD A,B ;верифицируем 0 секторов? OR A RET Z ;если да, то возврат LD (#5CD7),HL ;сохранение адреса файла в памяти LD (#5CD9),DE ;сохранение адреса файла на диске x1974 PUSH BC ;сохранение количества секторов LD B,1 ;загружать 1 сектор LD DE,(#5CD9) ;с текущего места диска LD HL,#5D25 ;в буфер CALL x1E3D ;загрузка сектора LD HL,(#5CF4) ;адрес следующего сектора на диске LD (#5CD9),HL POP BC ;восстановление количества секторов LD HL,(#5CD7) ;берем адрес файла в памяти LD DE,#5D25 ;адрес сектора в буфере x198E LD A,(DE) ;сравнение их CP (HL) JR NZ,x199D ;если несовпадение, то VERIFY ERROR INC HL ;следующие байты INC DE DEC C JR NZ,x198E ;повтор до конца LD (#5CD7),HL ;установка следующего адреса DJNZ x1974 ;повтор до конца RET ;возврат x199D LD HL,x276B ;адрес сообщения VERIFY ERROR LD A,#D ;код ошибки - #D JP x1C4A ;обработка ошибок ;Адрес #19A5. Выполнение команды PEEK. Установите #5D11 и #5C3B. x19A5 LD A,#FF ;код функции PEEK JR x19AB ;выполнение команды ;Адрес #19A9. Выполнение команды POKE. Установите #5D11 и #5C3B. Используется также с адреса #19AB (выполнение команды LOAD, PEEK или POKE; Установите #5D11 и #5C3B, а в аккумулятор поместите код функции). x19A9 LD A,#EE ;код функции POKE x19AB LD (#5D10),A ;установка кода функции JP x1818 ;выполнение команды ;Адрес #19B1. Выполнение команды MERGE. Установите #5D11 и #5C3B. x19B1 LD A,#FF ;использовалась рабочая область LD (#5D1F),A ;Ошибка!!! Флаг состояния рабочей области находится по адресу #5D15. CALL x187A ;обработка параметров CALL x1D75 ;если идет проверка на синтаксис, то возврат LD A,(#5CE5) ;расширение файла B? CP "B" JP NZ,x1D1A ;если нет, то ошибка LD BC,(#5CE6) ;установка длины файла для загрузки LD (#5CDB),BC PUSH BC ;сохранение ее INC BC ;оставим место для байта #80 RST #20 ;выделение места в рабочей области DW #0030 LD (HL),#80 ;маркер конца программы EX DE,HL ;переброска адреса загрузки в HL POP DE ;снятие со стека длины файла PUSH HL ;сохранение адреса загрузки LD DE,(#5CEB) ;берем адрес файла на диске CALL x191B ;загружать весь файл LD A,(#5CDC) ;берем длину файла в блоках LD B,A CALL x1852 ;операция со всем файлом CALL x1921 ;загрузка файла POP HL ;восстанавливаем адрес загрузки LD DE,(#5C53) ;берем адрес программы на бейсике RST #20 ;объединение программ DW #08D2 JP x03E1 ;сообщение O.K. ;Адрес #19F2. Проверка места в памяти для резервирования нового пространства вместо старого. В HL - старая длина, в DE - новая. Используется также с адреса: ;#19FD (проверка наличия пространства в памяти; длина пространства должна быть в DE). x19F2 EX DE,HL SCF ;вычисление разности длин SBC HL,DE RET C ;если новая длина меньше старой, то возврат LD DE,#A ;должно остаться еще #A байтов ADD HL,DE LD B,H ;переброска разности длин в BC LD C,L x19FD RST #20 ;проверка наличия пространства в памяти DW #1F05 RET ;возврат ;Адрес #1A01. Подготовка к загрузке программы на бейсике. x1A01 LD DE,(#5C53) ;берем адрес начала программы на бейсике LD HL,(#5C59) ;берем адрес конца программы на бейсике DEC HL PUSH HL ;сохранение начала и конца программы PUSH DE SBC HL,DE ;вычисление длины программы на бейсике LD DE,(#5CE6) ;берем длину программы с переменными PUSH DE ;сохраняем ее PUSH HL ;сохранение длины старой программы LD HL,0 ;идет верификация? LD A,(#5CF9) CP #FF JR Z,x1A20 ;если да, то длину не меняем LD HL,5 ;иначе увеличим ее на 5 байтов x1A20 ADD HL,DE LD (#5CDB),HL ;установка длины загрузки POP HL ;восстановление длины старой программы LD A,(#5CF9) ;верификация? CP #FF JR NZ,x1A31 ;если нет, то подготовка памяти POP DE ;снятие регистров со стека POP DE POP HL JR x1A48 ;возврат x1A31 CALL x19F2 ;проверка наличия места для программы POP BC ;восстановление длины программы с переменными POP DE ;восстановление начала программы POP HL ;восстановление конца программы PUSH BC ;сохранение длины программы RST #20 ;стирание старой программы DW #19E5 POP BC ;восстановление длины программы CALL x1E32 ;резервирование места для новой программы INC HL ;установка переменной VARS LD BC,(#5CE8) ADD HL,BC LD (#5C4B),HL x1A48 LD HL,(#5C53) ;берем адрес загрузки программы RET ;возврат ;Адрес #1A4C. Подготовка памяти к загрузке массива. Установите #5CE8, #5CD7, #5CD9 и #5CF9. x1A4C LD DE,(#5CE8) ;загружать весь файл LD (#5CDB),DE LD HL,(#5CD7) ;берем адрес массива в памяти LD A,(#5CF9) ;верификация? CP #FF RET Z ;если да, то возврат LD HL,(#5CD9) ;берем адрес загрузки файла PUSH HL ;сохраняем его x1A61 CALL x19F2 ;проверка наличия места для массива POP HL ;восстановление адреса загрузки файла LD A,H ;он равен 0? OR L JR Z,x1A79 ;если да, то старый массив не убираем LD HL,(#5CD7) ;берем начало старого массива DEC HL DEC HL DEC HL LD BC,(#5CD9) ;берем его длину INC BC INC BC INC BC CALL x1E2E ;стирание старого массива x1A79 LD HL,(#5C59) ;берем начало области переменных DEC HL LD BC,(#5CE8) ;берем длину файла PUSH BC ;сохраняем ее INC BC INC BC INC BC CALL x1E32 ;резервирование места для нового массива INC HL ;установка имени массива LD A,(#5CD2) LD (HL),A INC HL ;восстановление и установка длины массива POP DE LD (HL),E INC HL LD (HL),D INC HL ;берем адрес тела массива RET ;возврат ;Адрес #1A94. Вычисление адреса сектора файла на диске по его номеру в файле. Вход: установите #5CD7 и #5CD9 и поместите в регистр B длину файла в секторах, а в DE - адрес файла на диске. Выход: в DE будет адрес сектора на диске, а в B помещается 1. x1A94 LD A,(#5CD9) ;берем номер сектора в файле LD C,B LD B,A LD A,C CP B ;он меньше, чем количество секторов в файле? JR C,x1AB6 ;если нет, то ошибка ;Внимание, ошибка!!! Вы не сможете загрузить последний сектор файла, т.к. его номер равен количеству секторов в файле. LD A,B ;он равен 0? OR A JP Z,x1D1A ;если да, то синтаксическая ошибка DEC B ;он был равен 1? JR Z,x1AB0 ;если да, то его адресом будет адрес файла LD A,#10 ;на дорожке 16 секторов x1AA7 INC E ;вычисление адреса сектора на диске CP E JR NZ,x1AAE LD E,0 INC D x1AAE DJNZ x1AA7 x1AB0 LD B,1 ;загружать надо 1 сектор LD HL,(#5CD7) ;берем адрес загрузки сектора RET ;возврат x1AB6 LD HL,x29ED ;адрес сообщения REC.O/F LD A,5 ;код ошибки - 5 JP x1C4A ;обработка ошибки ;Адрес #1ABE. Проверка наличия файла и свободного места в каталоге. Имя файла поместите на стек калькулятора. Используется также с адреса #1AC4 (проверка наличия свободного места в каталоге диска). x1ABE CALL x292F ;установка имени и поиск файла JP Z,x1C50 ;если нашли, то FILE EXISTS x1AC4 CALL x03FD ;загрузка в буфер сектора 8 дорожки 0 LD A,(#5E09) ;на диске 128 файлов? CP #80 JP Z,x2723 ;если да, то сообщение DIRECTORY FULL RET ;иначе возврат ;Адрес #1AD0. Выполнение команды SAVE. Установите #5C3B и #5D11. Используется также с адресов: ;#1B27 - запись программы на бейсике. Установите #5CDD и #5CE5. ;#1B53 - запись файла. Установите #5CDD, #5CE5, #5CD7, #5CD9 и #5CDB. x1AD0 CALL x1852 ;обнуление #5D10 LD HL,0 ;автостарт бейсика не производить LD (#5CD1),HL CALL x1DDF ;помещение имени файла на стек калькулятора CALL x1D8C ;берем текущий символ CP #AF ;это CODE? JR Z,x1B39 ;если да, то прием начала и длины CP #CA ;это LINE? JR NZ,x1AF8 ;если нет, то проверка остальных расширений CALL x1E0B ;прием строки автостарта бейсика CALL x1D75 ;если проверка на синтаксис, то возврат LD HL,(#5CDB) ;установка строки автостарта бейсика LD (#5CD1),HL LD HL,#5CE5 JR x1B1F ;переход на запись бейсика x1AF8 CP #AA ;текущий символ SCREEN$? JR NZ,x1B0D ;если нет, то проверка расширения DATA LD HL,#4000 ;начало файла - #4000 LD (#5CD7),HL LD HL,#1B00 ;его длина - #1B00 байтов LD (#5CD9),HL LD (#5CDB),HL JR x1B48 ;запись файла с расширением C x1B0D CALL x1D75 ;если проверка на синтаксис, то возврат CALL x1D8C ;берем текущий символ LD HL,#5CE5 CP #E4 ;это DATA? JR Z,x1B2C ;если да, то запись массива CP #D ;это ENTER? JP NZ,x1D1A ;если нет, то ошибка x1B1F LD (HL),"B" ;расширение B CALL x1ABE ;проверка наличия такого файла и свободного места в каталоге CALL x1E1C ;удаление из командной строки пятибайтных чисел x1B27 CALL x1BDE ;установка начала и длины файла JR x1B53 ;запись файла x1B2C LD (HL),"D" ;расширение D CALL x1ABE ;проверка наличия файла и места в каталоге CALL x1C0F ;установка начала и длины файла JR NC,x1B53 ;если все в порядке, то запись файла JP C,x1D1A ;иначе ошибка x1B39 CALL x1DE5 ;принятие начала и длины файла LD HL,(#5CD9) ;установка начала файла LD (#5CD7),HL LD HL,(#5CDB) ;установка длины файла LD (#5CD9),HL x1B48 CALL x1D75 ;если проверка на синтаксис, то возврат LD A,"C" ;расширение C LD (#5CE5),A CALL x1ABE ;проверка наличия файла и места в каталоге x1B53 CALL x1B59 ;запись файла JP x0569 ;запись информации о нем ;Адрес #1B59. Запись файла. Установите #5CD1, #5CD7, #5CD9 и #5CDB, а в буфер загрузите сектор 8 дорожки 0. x1B59 LD HL,(#5CD7) ;установка начала файла LD (#5CE6),HL EX DE,HL ;переброска его в DE LD HL,(#5CD9) ;берем длину файла LD A,L ;она равна 0? OR H JP Z,x1D1A ;если да, то ошибка LD A,L ;вычисление длины файла в секторах OR A JR Z,x1B6D INC H x1B6D LD A,H ;установка длины файла в секторах LD (#5CEA),A LD E,A ;вычисление нового количества свободных секторов LD D,0 LD HL,(#5E0A) SBC HL,DE JP C,x1C45 ;если на диске нет места, то ошибка x1B7B PUSH HL ;сохранение нового количества свободных секторов LD HL,(#5C59) ;добавление к программе на бейсике байта #AA LD (HL),#AA INC HL LD DE,(#5CD1) ;и номера строки автостарта LD (HL),E INC HL LD (HL),D LD HL,(#5CDB) ;установка длины файла LD (#5CE8),HL LD HL,(#5E06) ;установка адреса файла на диске LD (#5CEB),HL EX DE,HL ;переброска его в DE LD HL,(#5CE6) ;берем начало файла LD A,(#5CEA) ;берем его длину в секторах LD B,A CALL x1E4D ;запись файла LD HL,(#5CF4) ;берем адрес свободного пространства диска PUSH HL ;сохраняем его CALL x03FD ;загрузка в буфер сектора 8 дорожки 0 POP HL ;восстановление адреса свободного места на диске LD (#5E06),HL ;установка его POP HL ;восстановление количества свободных секторов LD (#5E0A),HL ;установка его LD HL,#5E09 ;берем номер файла LD A,(HL) LD (#5D1E),A ;установка его INC (HL) ;записали еще 1 файл PUSH HL ;сохранение адреса с кол-вом файлов на диске CALL x1E43 ;перезапись сектора 8 дорожки 0 POP HL ;восстановление адреса с кол-вом файлов LD C,(HL) ;берем номер записанного файла DEC C LD A,(#5CE5) ;расширение файла B? CP "B" CALL Z,x1BC8 ;если да, то установка длины программы без переменных RET ;возврат ;Адрес #1BC8. Установка длины программы на бейсике без переменных. Длину с переменными программа помещает в #5CE6, длину без переменных - в #5CE8. x1BC8 LD HL,(#5C59) ;вычисление длины программы с переменными LD DE,(#5C53) SCF SBC HL,DE LD (#5CE6),HL ;установка ее LD HL,(#5C4B) ;вычисление длины только программы SBC HL,DE LD (#5CE8),HL ;установка ее RET ;возврат ;Адрес #1BDE. Установка начала и длины файла для записи программы на бейсике. x1BDE LD HL,(#5C4B) ;вычисление длины программы с переменными LD DE,(#5C53) SBC HL,DE LD (#5CDB),HL ;установка длины файла для каталога LD HL,(#5C53) ;установка начала файла LD (#5CD7),HL LD HL,(#5C59) ;вычисление длины файла с параметрами автозапуска INC HL INC HL INC HL SBC HL,DE LD (#5CD9),HL ;установка действительной длины файла RET ;возврат ;Адрес #1BFC. Прием имени массива для команды LOAD...DATA. Вход: установите #5C5D на расширение файла и установите #5CF9. Выход: устанавливает #5CD2, #5CD7, #5CD9 и #5CDB. Используется также с адреса #1C0F (то же, что и #1C1B, но с обработкой ошибок). x1BFC CALL x1C1B ;поиск массива RET NC ;если массив найден, то возврат LD HL,0 ;старого массива нет LD (#5CD9),HL LD A,(#5CF9) ;идет загрузка? CP #FF RET NZ ;если да, то возврат JP x1C13 ;ошибка x1C0F CALL x1C1B ;поиск массива RET NC ;если массив найден, то возврат x1C13 LD A,#E ;код ошибки - #E LD HL,x27DD ;адрес сообщения ARRAY NOT FOUND JP x1C4A ;обработка ошибок ;Адрес #1C1B. Поиск массива без обработки ошибок. Будут установлены #5CD2, #5CD7, #5CD9 и #5CDB. При ошибке флаг C будет установлен, иначе сброшен. x1C1B CALL x1E2A ;берем следующий символ CALL x1D9B ;поиск массива SET 7,C ;установка бита 7 в его имени LD A,C ;установка его имени LD (#5CD2),A JR NC,x1C2B ;если массив найден, то установка его параметров x1C29 SCF ;была ошибка RET ;возврат x1C2B JR NZ,x1C29 ;если флаг Z сброшен, то ошибка INC HL ;берем длину массива LD E,(HL) ;установка длины массива INC HL LD D,(HL) INC HL LD (#5CD7),HL ;установка адреса тела массива LD (#5CDB),DE ;установка длины массива LD (#5CD9),DE CALL x1E2A ;следующий символ CP ")" ;это ")"? JR NZ,x1C2B ;если нет, то ошибка RET ;возврат ;Адрес #1C45. Обработка ошибки NO SPACE. Используется также с адреса #1C4A (обработка ошибок; в A - код ошибки, в HL - адрес сообщения). x1C45 LD HL,x29BB ;адрес сообщения NO SPACE LD A,3 ;код ошибки - 3 x1C4A CALL x03C3 ;если надо, то печать сообщения JP x01D3 ;завершение ;Адрес #1C50. Обработка ошибки FILE EXISTS. x1C50 LD HL,x29C5 ;адрес сообщения FILE EXISTS LD A,2 ;код ошибки - 2 JR x1C4A ;обработка ошибок ;Адрес #1C57. Установка имени файла. Установите #5C5D на имя файла. Будет выбран дисковод и установлена переменная #5CDD. x1C57 LD HL,#5CDD ;адрес переменной с именем файла LD B,8 ;ее длина - 8 байтов x1C5C LD (HL)," " ;очистка ее INC HL DJNZ x1C5C CALL x0531 ;снятие строки со стека калькулятора EX DE,HL CALL x1C81 ;установка дисковода LD A,C ;имя файла - пустая строка? OR A ;Ошибка в программе!!! Здесь должно быть OR B. JP Z,x1D1A ;если да, то ошибка CP 9 ;в имени файла больше 8 символов JR C,x1C73 ;если да, то обрезаем его LD C,8 ;Внимание!!! Это будет работать неправильно при длине имени файла больше #FF символов. x1C73 LD A,(HL) ;берем первый символ имени файла CP " " ;его код меньше #20? JP C,x1D1A ;если да, то ошибка LD DE,#5CDD ;адрес переменной с именем файла PUSH BC ;сохранение длины имени LDIR ;установка имени POP BC ;восстановление длины имени RET ;возврат ;Адрес #1C81. Установка дисковода для операции с файлом. В HL поместите начало имени файла в ASCII представлении, а в BC ? его длину. HL установится на начало имени без дисковода, а в BC будет его длина. x1C81 INC HL ;берем адрес следующего символа имени LD A,(HL) ;берем этот символ CP ":" ;это двоеточие? JR NZ,x1C98 ;если нет, то активизация дисковода по умолчанию DEC HL ;берем адрес имени дисковода LD A,(HL) ;берем имя дисковода CALL x0524 ;преобразование имени дисковода в его номер PUSH BC ;сохранение длины имени файла PUSH HL ;и адреса имени дисковода CALL x3DCB ;выбор дисковода POP HL ;восстановление адреса имени дисковода POP BC ;и длины имени файла DEC BC ;отсекли 2 символа DEC BC INC HL ;берем адрес имени файла без дисковода INC HL RET ;возврат x1C98 DEC HL ;берем адрес имени файла LD A,(#5D19) ;берем дисковод по умолчанию PUSH BC ;сохранение длины и адреса имени файла PUSH HL CALL x3DCB ;выбор дисковода POP HL ;восстановление длины и адреса имени файла POP BC RET ;возврат ;Адрес #1CA4. Определение адреса описателя файла в буфере по его номеру в секторе. В C должен быть номер описателя в секторе. На выходе в HL будет его адрес. x1CA4 LD L,C ;перевод номера описателя файла в двухбайтную LD H,0 ;форму ADD HL,HL ;умножение его на #10 ADD HL,HL ADD HL,HL ADD HL,HL LD BC,#5D25 ;адресуемся от начала буфера ADD HL,BC RET ;возврат ;Адрес #1CB0. Установка и проверка имени файла. Имя файла должно быть помещено на стек калькулятора. Выход: если файл с таким именем есть, то будет установлен флаг Z, а в рег. C и в #5D1E будет его номер, а если такого файла нет, то флаг Z сбросится. Используется также с адреса: ;#1CB3 (поиск файла, установите #5CDD и #5CE5, выход как и из #1CB0). x1CB0 CALL x1C57 ;установка имени файла x1CB3 CALL x03E8 ;начнем с сектора 0 LD B,#80 ;всего 128 файлов LD C,0 ;начнем с нулевого описателя в секторе x1CBA PUSH BC ;сохраним номер файла и счетчик CALL x1CA4 ;определим начало описателя в буфере CALL x050C ;проверка и обработка достижения конца буфера POP BC ;восстановление номера описателя в секторе и PUSH BC ;счетчика файлов без изменения стека LD A,C ;просмотрен весь сектор? CP #10 JR NZ,x1CCD ;если да, то POP BC ;снятие номера описателя и счетчика со стека LD C,0 ;нулевой описатель в секторе JR x1CBA ;повтор проверки x1CCD LD DE,#5CDD ;берем адрес части описателя для проверки LD A,(#5D06) ;берем длину этой части LD B,A XOR A ;конец каталога? CP (HL) JR NZ,x1CDB ;если нет, то переход на проверку описателя POP BC ;снятие номера описателя и счетчика со стека JR x1CE4 ;выход с флагом NZ x1CDB CALL x2713 ;сравнение частей описателей POP BC ;восстановление номера описателя и счетчика JR Z,x1CE7 ;если части описателей совпали, то на выход INC C ;следующий описатель DJNZ x1CBA ;повтор до конца x1CE4 OR #FF ;выключение флага Z RET ;возврат x1CE7 LD A,#80 ;определение номера файла SUB B LD C,A LD (#5D1E),A ;помещение его в #5D1E XOR A ;сброс флага Z RET Z ;возврат ;Адрес #1CF0. Поиск файла. Часть описателя, подлежащую проверке, установите по адресу #5CDD и установите #5D06. Если файл не найден, то будет сброшен флаг Z и в #5D0F будет #FF, а если найден, то включится флаг Z, а номер файла будет в рег. C и по адресам #5D0F и #5D1E. x1CF0 CALL x1CB3 ;поиск файла LD HL,#5D0F LD (HL),C ;загрузка регистра C в #5D0F RET Z ;если файл найден, то возврат LD (HL),#FF ;помещаем в #5D0F #FF RET ;возврат ;Адpес #1CFB. Выполнение команды RETURN. Установите #5C3B, #5D1C и #5D13. x1CFB CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x20E5 ;изменение памяти RES 3,(IY+1) ;установка режима ввода "K" CALL x0232 ;восстановление старого ERR_SP LD SP,(#5D1C) ;восстановление стека LD HL,(#5C3D) ;берем адрес перед адресом из ERR_SP DEC HL LD A,#12 ;там находится #12? CP (HL) JR NZ,x1D19 ;если нет, то возврат DEC HL ;установка ERR_SP на адрес ниже LD (#5C3D),HL x1D19 RET ;возврат ;Адрес #1D1A. Обработка синтаксической ошибки. Установите #5C3A, #5D0E, #5D15, и все для подпрограммы #1D3. Используется также с адреса: ;#1D29 (обработка ошибок; в A - код ошибки, в HL ? адрес сообщения). x1D1A BIT 7,(IY+0) ;код ошибки бейсика уже назначен? JR Z,x1D25 ;если нет, то установка ошибки LD A,#B ;NONSENCE IN BASIC LD (#5C3A),A x1D25 INC A ;получение кода ошибки DOS LD HL,x29B2 ;адрес сообщения ERROR x1D29 CALL x03C3 ;печать сообщения, если можно JP x01D3 ;завершение ;Адрес #1D2F. Обработка ошибки, поступившей из пзу бейсика без очистки стека. Установите #5C3A. x1D2F LD A,(#5C3A) ;берем код ошибки бейсика LD HL,x27CA ;адрес сообщения *BREAK* CP #14 ;BREAK INTO PROGRAM? JR Z,x1D29 ;если да, то печать сообщения CP #C ;BREAK - CONT REPEATS? JR Z,x1D29 ;если да, то печать сообщения LD HL,x27D2 ;адрес сообщения OUT OF RAM CP 3 ;OUT OF MEMORY? JR Z,x1D29 ;если да, то печать сообщения LD HL,x27DD ;адрес сообщения ARRAY NOT FOUND CP 1 ;VARIABLE NOT FOUND? JR Z,x1D29 ;если да, то печать сообщения JR x1D1A ;иначе сообщение *ERROR* ;Адрес #1D4D. Выполнение команды RUN. Установите #5D11 и #5C3B. x1D4D CALL x1852 ;выполнять загрузку файла CALL x1836 ;обработка параметров и загрузка файла CALL x1D75 ;если идет проверка на синтаксис, то возврат LD HL,(#5CE6) ;берем адрес загрузки файла по умолчанию ;Ошибка!!! Ведь файл могли загрузить и по другому адресу. В подпрограмме #18AB надо сохранять в #5D20 действительный адрес загрузки файла, а здесь восстанавливать его. LD A,(#5CE5) ;расширение файла B? CP "B" JP Z,x012A ;если да, то запуск программы на бейсике PUSH HL ;запуск программы в кодах RET ;Боже!!! Ну кто так делает!!! Во-первых, адрес программы при запуске должен быть в BC; во-вторых, надо совсем выйти из TR-DOS, иначе программа спятит при вызове #3D13; в третьих, куда программа будет возвращаться?; в четвертых... В общем, надо так (после CALL #1D75): ; LD A,(#5CE5) ; CP "D" ; JP Z,#1D1A ; CP "B" ; JP Z,#12A ; LD HL,START ; LD (#5D1A),HL ; JP #1D3 ; ;START CALL #232 ; LD BC,(#5D20) ; PUSH BC ; RET ;Адрес #1D63. Очистка рабочей области памяти. x1D63 LD HL,#5D0E ;рабочую область очищать? LD A,(HL) CP #FF LD (HL),0 ;рабочая область очищена RET NZ ;если рабочая область очищена, то возврат RST #20 ;очистка рабочей области DW #16BF RET ;возврат ;Адрес #1D70. Проверка, идет ли проверка строки на синтаксис или выполнение команды. Если идет выполнение, то флаг Z будет сброшен, иначе установлен. x1D70 BIT 7,(IY+1) RET ;Адрес #1D75. Если идет проверка на синтаксис, то возврат из программы, вызвавшей эту подпрограмму. Установите #5C3B. x1D75 CALL x1D70 ;проверка, что делается RET NZ ;если идет выполнение, то возврат POP HL ;снятие адреса возврата в вашу программу RET ;возврат по следующему адресу ;Адрес #1D7B. Помещение числа на стек калькулятора. Установите #5C5D на символ перед числом. Если строка проверяется на синтаксис, то будет установлен флаг Z, а при выполнении он сброшен. x1D7B CALL x1E2A ;берем следующий символ строки CALL x1DC1 ;помещение числа на стек калькулятора JR x1D70 ;проверка, идет выполнение или проверка и возврат ;Адрес #1D83. Открытие потока 0. Используется также с адреса #1D84 (открытие потока; номер в регистре A). x1D83 XOR A ;номер потока - 0 x1D84 RST #20 ;открытие потока DW #1601 RET ;возврат ;Адрес #1D88. Открытие потока 2. x1D88 LD A,2 ;номер потока - 2 JR x1D84 ;открытие потока ;Адрес #1D8C. Выборка текущего символа строки. Поместите его адрес в #5C5D. x1D8C RST #20 DW #0018 RET ;Адрес #1D90. Ввод команды. x1D90 CALL x1D83 ;открытие потока 0 RST #20 ;редактирование командной строки DW #0F2C RET ;возврат ;Адрес #1D97. Очистка экрана и открытие потока 0. x1D97 RST #20 DW #0D6B RET ;Адрес #1D9B. Поиск массива. Установите #5C5D на имя массива. Если массив найден, то в HL будет его адрес. x1D9B RST #20 DW #28B2 RET ;Адpес #1D9F. Очистка низа экрана. x1D9F RST #20 DW #0D6E RET ;Адрес #1DA3. Печать числа из регистра A. Используется также с адресов: ;#1DA4 (печать числа из регистра C), ;#1DA9 (печать числа из регистра BC). x1DA3 LD C,A ;переброска числа в C x1DA4 LD B,0 ;перевод числа в двухбайтную форму JP x1DA9 ;странная команда! x1DA9 PUSH BC ;сохранение числа CALL x20F1 ;изменение памяти POP BC ;восстановление числа RST #20 ;печать числа DW #1A1B CALL x20F1 ;восстановление памяти RET ;возврат ;Адрес #1DB5. Снятие строки со стека калькулятора. В DE будет адрес строки, в BC - ее длина. x1DB5 RST #20 DW #2BF1 RET x1DB9 RST #20 DW #1E99 RET ;Адрес #1DBD. Помещение строки на стек калькулятора. Установите #5C5D на начало строки. x1DBD RST #20 DW #1C8C RET ;Адрес #1DC1. Помещение числа из BC на стек калькулятора. x1DC1 RST #20 DW #1C82 RET ;Адрес #1DC5. Установка CH_ADD на второй символ строки. Установите #5D11. x1DC5 LD HL,(#5D11) ;берем адрес строки команды INC HL ;берем адрес ее второго символа LD (#5C5D),HL ;помещаем его в CH_ADD RET ;возврат ;Адрес #1DCD. Принятие 2-х строк на стек калькулятора. Поместите в #5D11 адрес первой строки. x1DCD CALL x1DDF ;прием первой строки на стек калькулятора x1DD0 CALL x1D8C ;берем текущий символ CP "," ;это запятая? JP NZ,x1D1A ;если нет, то ошибка CALL x1E2A ;следующий символ CALL x1DBD ;прием второй строки на стек калькулятора RET ;возврат ;Адрес #1DDF. Установка CH_ADD и помещение строки на стек калькулятора. Установите #5D11. x1DDF CALL x1DC5 ;установка CH_ADD JP x1DBD ;помещение строки на стек калькулятора ;Адрес #1DE5. Принятие одного или двух чисел после символа CODE. Первое число будет в #5CD9, второе - в #5CDB. Если было одно число, то оно будет в обеих ячейках. Если принято 2 числа, то в #5CD6 будет 3. На входе установите #5C5D и #5C3B. Используется также с адреса: ;#1E0B (принятие числа; установите #5C5D и #5C3B; число будет в #5CDB, а в #5CD6 будет 3). x1DE5 CALL x1D8C ;берем текущий символ строки CP #AF ;это CODE? RET NZ ;если нет, то возврат x1DEB CALL x1D7B ;принятие числа на стек калькулятора JR Z,x1DFB ;если идет проверка на синтаксис, то дальнейшая проверка CALL x1DB9 ;снятие числа со стека калькулятора LD (#5CD9),BC ;установка первого числа LD (#5CDB),BC x1DFB CALL x1D8C ;берем текущий символ CP "," ;это запятая? JR Z,x1E0B ;если да, то принятие второго числа CP #D ;это ENTER? JP NZ,x1D1A ;если нет, то ошибка CALL x1D75 ;если строка проверяется на синтаксис, то возврат RET ;возврат x1E0B CALL x1D7B ;прием второго числа на стек калькулятора RET Z ;если проверка на синтаксис, то возврат CALL x1DB9 ;снятие числа со стека калькулятора LD (#5CDB),BC ;помещение его в #5CDB LD A,3 ;приняли 2 числа LD (#5CD6),A RET ;возврат ;Адрес #1E1C. Удаление из командной стpоки пятибайтных чисел x1E1C LD HL,(#5D11) ;берем адрес строки команды RST #20 ;удаление из нее пятибайтных чисел DW #11A7 RET ;возврат ;Адрес #1E23. Выделение пространства в рабочей области. В BC поместите длину требуемого пространства. x1E23 LD HL,(#5C61) ;загрузка HL из #5C61 RST #20 ;выделение пространства DW #0030 RET ;возврат ;Адрес #1E2A. Выборка следующего символа строки. Установите #5C5D. x1E2A RST #20 DW #0020 RET ;Адрес #1E2E. Удаление области памяти. В HL поместите начало области, в BC - длину. x1E2E RST #20 DW #19E8 RET x1E32 RST #20 DW #1655 RET ;Адрес #1E36. Загрузка регистра дорожки. Установите #5CD1. При выходе по ошибке в #5D17 помещается #FF. Можно использовать с адреса: ;#1E3A для прямого вывода в порт #3F. x1E36 CALL x0A31 ;new определение номера дорожки, на которой стоит головка LD A,H ;установка регистра дорожки x1E3A OUT (#3F),A RET ;возврат ;Адрес #1E3D. Загрузка секторов. Вход: в HL - адрес загрузки, в D - номер дорожки, в E - номер сектора, в B - кол-во секторов. x1E3D XOR A ;признак загрузки JR x1E64 ;переход к подпрограмме загрузки/записи секторов ;Адрес #1E40. Запись информации о файле. На входе в C должен быть номер файла. Используется также с адресов: ;#1E43 - запись сектора из буфера. Вход: в #5CF4 установите номер сектора+1, а в #5CF5 - номер дорожки. ;#1E4D - запись секторов. В HL - адрес, в D - номер дорожки, в E - номер сектора, в B - кол-во секторов. ;#1E64 - загрузка/запись секторов. Предварительные установки как и для предыдущей подпрограммы плюс в A установите 0 для загрузки или что-нибудь другое для записи. x1E40 CALL x166B ;чтение сектора с описателем файла и замена описателя x1E43 LD DE,(#5CF4) ;берем номер сектора для записи DEC DE LD B,1 ;записывать 1 сектор LD HL,#5D25 ;записывать будем из буфера x1E4D PUSH HL ;сохраним адрес секторов на диске и в памяти PUSH DE CALL x3E11 ;берем тип дисковода BIT 7,(HL) ;он 40-дорожечный? JR Z,x1E60 ;если да, то записывать можно BIT 0,(HL) ;используем 40 дорожек на 80-дорожечном? JR NZ,x1E60 ;если нет, то записывать можно LD HL,x29D8 ;адрес сообщения READ ONLY JP x1D29 ;переход на обработку ошибок ;Внимание, ошибка!!! В аккумуляторе забыли установить код ошибки. x1E60 POP DE ;восстановление адресов секторов POP HL x1E62 LD A,#FF ;признак записи x1E64 LD (#5CCE),A ;установка признака операции x1E67 LD (#5CF4),DE ;установка адреса секторов на диске PUSH BC ;сохранение количества секторов PUSH HL ;и адреса загрузки / записи CALL x1E36 ;чтение индексной области дорожки POP HL ;восстановление адреса загрузки / записи POP BC ;и количества секторов XOR A ;количество секторов равно 0? OR B RET Z ;если да, то возврат x1E75 PUSH BC ;сохраняем адрес и кол-во секторов PUSH HL CALL x3F06 ;установка адреса загрузки / записи секторов LD A,(#5CF4) ;установка номера сектора CALL x3F02 LD A,(#5CF5) ;позиционирование головки на дорожку CALL x3E63 LD A,(#5CCE) ;берем флаг операции OR A ;загрузка? PUSH AF CALL Z,x3F0E ;если да, то загрузка сектора POP AF CALL NZ,x3F0A ;иначе запись сектора POP HL ;берем адрес следующего сектора LD DE,#100 ADD HL,DE PUSH HL ;сохраняем его LD A,#10 ;на дорожке 16 секторов LD HL,#5CF4 INC (HL) ;следующий сектор CP (HL) ;конец дорожки? JR NZ,x1EA7 ;если да, то номер следующего сектора 0 LD (HL),0 LD HL,#5CF5 ;и берем следующую дорожку INC (HL) x1EA7 POP HL ;восстановление адреса следующего сектора POP BC ;и количества секторов DJNZ x1E75 ;если не все, то повтор RET ;возврат ;Адрес #1EAC. Вычисление количества полных секторов файла из его длины в байтах. В A должно быть количество секторов файла, а в DE - длина загружаемой части файла. x1EAC PUSH HL ;сохранение HL LD H,A ;берем полную длину файла LD L,0 PUSH HL ;сохраняем ее SBC HL,DE ;она меньше длины загрузки? CALL C,x1EBC ;если да, то загружать весь файл POP HL ;восстановление полной длины файла LD A,H ;вычисление количества полных секторов из полной длины файла POP HL ;восстановление HL RET C ;если полная длина файла больше длины загрузки, LD A,D ;то количество полных секторов берем из длины загрузки RET ;возврат ;Адрес #1EBC. Обнуление #5CD6 и установка флага C. x1EBC XOR A LD (#5CD6),A SCF RET ;Адрес #1EC2. Выполнение команды FORMAT. Установите #5D11 и #5C3B. Используется также с адреса #1EDD (повторение форматирования; установите #5CDD). x1EC2 LD HL,#FFFF LD (#5CD7),HL ;дорожки не проверять LD (#5CD9),HL ;форматировать одну сторону диска LD (#5CD1),HL ;ошибку при чтении адресного маркера игнорировать CALL x042B ;следующий символ ENTER? JP Z,x1D1A ;если да, то ошибка CALL x1DDF ;прием имени диска на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x1C57 ;установка имени диска x1EDD CALL x3E11 ;берем тип дисковода AND #80 ;дисковод 40-дорожечный? LD A,#28 ;форматировать 40 дорожек JR Z,x1EE8 ;если дисковод 80-дорожечный, LD A,#50 ;то форматировать 80 дорожек x1EE8 LD (#5CD7),A ;установка количества дорожек CALL x08A7 ;new восстановление CALL x0B01 ;new выбор нижней стороны диска CALL x3EA0 ;задержка в 3135098 тактов LD E,1 ;форматирование дорожки с номером 1 CALL x1FFD CALL x1FEB ;выбор верхней стороны диска LD E,0 ;форматирование дорожки с номером 0 CALL x1FFD LD A,(#5CDD) ;форматировать только одну сторону диска CP "$" JR Z,x1F1B ;если да, то форматирование диска CALL x1FF6 ;выбор нижней стороны диска CALL x3EA0 ;задержка в 3135098 тактов CALL x3EB5 ;чтение адресного маркера LD A,H ;номер дорожки - 1? CP 1 JR NZ,x1F1B ;если нет, то форматирование диска x1F16 LD A,#80 ;форматировать обе стороны диска LD (#5CDA),A x1F1B CALL x20BD ;форматирование диска LD HL,#5D25 ;адрес начала буфера LD (HL),0 ;очистка первого байта LD DE,#5D26 ;адрес второго байта буфера LD BC,#FF ;осталось очистить #FF байтов LDIR ;очистка буфера LD BC,#5CD7 ;адрес переменной с количеством дорожек LD DE,#5CDA ;адрес переменной с количеством сторон LD A,(BC) ;форматировали 80 дорожек? CP #50 JR Z,x1F49 ;если да, то диск 80-дорожечный LD A,(DE) ;форматировали 2 стоpоны? CP #80 JR Z,x1F42 ;если да, то диск 40-дорожечный двухстоpонний LD A,#19 ;диск 40-дорожечный односторонний LD HL,#270 ;свободно #270 сектора JR x1F55 ;создание описателя диска x1F42 LD A,#17 ;диск 40-дорожечный двухсторонний x1F44 LD HL,#4F0 ;свободно #4F0 сектора JR x1F55 ;создание описателя диска x1F49 LD A,(DE) ;форматировали 2 стороны? CP #80 LD A,#18 ;если нет, то диск 80-дорожечный односторонний JR NZ,x1F44 LD A,#16 ;иначе диск 80-дорожечный двухсторонний LD HL,#9F0 ;свободно #9F0 сектора x1F55 LD (#5E08),A ;установка типа диска LD (#5E0A),HL ;установка количества свободных секторов LD A,1 ;первая свободная дорожка - 1 LD (#5E07),A LD A,#10 ;признак принадлежности диска к TR-DOS LD (#5E0C),A LD HL,#5E0F ;9 байтов #20 с адреса #5E0F LD DE,#5E10 LD BC,8 LD (HL),#20 LDIR LD HL,#5CDD ;установка имени диска LD DE,#5E1A LD BC,8 LDIR CALL x0B54 ;new выбор верхней стороны диска LD B,1 ;записать 1 сектор LD DE,8 ;сектор 8 дорожки 0 LD HL,#5D25 ;из буфера CALL x1E62 ;запись сектора LD A,(#5CD6) ;берем количество дефектных секторов PUSH AF ;сохраняем его XOR A ;расширение - CHR$ 0 LD (#5CE5),A ;установка расширения LD HL,(#5E0A) ;берем количество свободных секторов LD (#5CD7),HL ;сохраняем его LD HL,#5CDD ;печать имени диска RST #18 LD A,#D ;перевод строки RST #10 LD HL,(#5CD7) ;восстановление количества свободных секторов POP AF ;восстановление количества дефектных секторов PUSH HL ;сохранение количества свободных секторов LD D,0 ;перевод количества дефектных секторов в LD E,A ;двухбайтную форму SBC HL,DE ;вычисление количества хороших секторов LD B,H ;переброска его в BC LD C,L CALL x1DA9 ;печать его LD A,"/" ;печать "/" RST #10 POP BC ;восстановление количества свободных секторов CALL x1DA9 ;печать его JP x01D3 ;Адрес #1FB9. Таблица секторов для форматирования обычного диска. Используется также с адреса #1FBA для проверки дорожки. x1FB9 DB 1 x1FBA DB 9,2,#A,3,#B,4,#C,5,#D,6,#E,7,#F,8,#10,1 ;Адрес #1FCA. Определение количества дорожек дисковода. Вход: установите время перемещения головки дисковода. Выход: в #5CD7 и регистре A будет количество дорожек дисковода. x1FCA CALL x3E08 ;берем время перемещения головки OR #11 ;позиционирование на дорожку #32 LD B,A LD A,#32 CALL x3E44 LD A,2 ;затем на дорожку 2 CALL x3E44 CALL x3DFD ;задержка в 725779 тактов IN A,(#1F) ;головка в исходном положении? AND 4 LD A,#50 ;если нет, то у дисковода 80 дорожек JR Z,x1FE7 LD A,#28 ;иначе 40 x1FE7 LD (#5CD7),A ;установка количества дорожек RET ;возврат ;Адрес #1FEB. Выбор верхней стороны диска. Установите #5D16. Используется также с адреса #1FF0 (загрузка системного регистра, код - в аккумуляторе). Вы можете также использовать с адреса: ;#1FF3 для прямого вывода в порт #FF. x1FEB LD A,(#5D16) ;берем копию системного регистра OR #3C ;формат MFM, верхняя сторона, выключение сброса и готовности x1FF0 LD (#5D16),A ;запоминаем копию системного регистра x1FF3 OUT (#FF),A ;установка системного регистра RET ;возврат ;Адрес #1FF6. Выбор нижней стороны диска. Установите #5D16. x1FF6 LD A,(#5D16) ;берем копию системного регистра AND #6F ;формат MFM, нижняя сторона, выключение сброса и готовности JR x1FF0 ;установка системного регистра ;Адрес #1FFD. Форматирование дорожки. В регистр Е поместите ее номер и спозиционируйте головку дисковода. Из переменных установите #5CD8, #5CE6, #5CE8 и обнулите #5CD6. Используется также с адреса #1FC9 (проверка дорожки; установите #5CD8, #5CE8 и обнулите #5CD6 и спозиционируйте головку). x1FFD DI ;запрет прерываний LD A,#F4 ;запись дорожки OUT (#1F),A LD HL,#1FB9 ;берем адрес таблицы секторов для форматирования LD C,#7F ;адрес регистра данных x2007 LD B,#A ;#A раз #4E (первый пробел) LD D,#4E CALL x20B1 ;запись байта заданное число раз LD B,#C ;синхропромежуток LD D,0 CALL x20B1 LD B,3 ;синхроимпульс LD D,#F5 CALL x20B1 LD D,#FE ;1 раз #FE (адресная метка идентификатора) CALL x20AF ;запись байта 1 раз LD D,E ;номер дорожки CALL x20AF LD D,0 ;номер стороны (в TR-DOS всегда 0) CALL x20AF LD D,(HL) ;номер сектора из таблицы CALL x20AF LD D,1 ;длина сектора - #100 байтов CALL x20AF LD D,#F7 ;запись контрольной суммы CALL x20AF LD B,#16 ;второй пробел LD D,#4E CALL x20B1 LD B,#C ;синхропромежуток LD D,0 CALL x20B1 LD B,3 ;синхроимпульс LD D,#F5 CALL x20B1 LD D,#FB ;адресная метка данных CALL x20AF LD B,0 ;данные (#100 нулей) LD D,0 CALL x20B1 LD D,#F7 ;запись контрольной суммы CALL x20AF LD B,#32 ;третий пробел LD D,#4E CALL x20B1 LD A,(HL) ;берем адрес номера следующего сектора INC HL CP #10 ;конец таблицы? JR NZ,x2007 ;если нет, то форматирование следующего сектора LD B,0 ;пробел до конца дорожки CALL x20B1 JP M,x2076 CALL x20B1 x2076 IN A,(#1F) ;берем состояние контроллера AND #40 ;запись запрещена? JP NZ,x3F39 ;если да, то сообщение READ ONLY x207D LD A,(#5CD8) ;дорожку проверять? OR A RET NZ ;если нет, то возврат ;Внимание!!! Перед возвратом или выходом по ошибке надо разрешать прерывания. LD C,#7F ;адрес регистра данных LD A,E ;установка номера дорожки OUT (#3F),A LD HL,#1FBA ;берем адрес таблицы секторов для проверки x208A LD B,3 ;3 попытки LD A,(HL) ;берем номер сектора из таблицы OUT (#5F),A ;установка сектора PUSH HL ;сохранение адреса таблицы секторов x2090 DI ;запрет прерываний LD A,#80 ;чтение сектора OUT (#1F),A PUSH BC ;сохранение количества попыток CALL x3FE5 ;чтение данных по адресу из HL (в пзу, не страшно) IN A,(#1F) ;все в порядке? AND #7F POP BC ;восстановление счетчика попыток JR Z,x20A6 ;если все в порядке, то следующий сектор DJNZ x2090 ;следующая попытка LD HL,#5CD6 ;есть 1 битый сектор INC (HL) x20A6 POP HL ;восстановление адреса таблицы секторов LD A,(HL) ;берем номер текущего сектора INC HL ;берем адрес номера следующего сектора CP 1 ;конец таблицы? JR NZ,x208A ;если нет, то повтор EI ;разрешение прерываний RET ;возврат ;Адрес #20AF. Запись байта 1 pаз. В регистр D поместите байт, в C - #7F и выдайте команду записи на вг-#5D. Используется также с адреса #20B1 (запись байта несколько раз; все для #20AF плюс в B количество выдач). x20AF LD B,1 ;запись 1 раз x20B1 IN A,(#FF) ;ожидание DRQ или INTRQ AND #C0 JR Z,x20B1 RET M ;если поступил INTRQ, то возврат OUT (C),D ;выдача байта DJNZ x20B1 ;повтор до конца RET ;возврат ;Адрес #20BD. Форматирование диска. Установите #5CDA, #5CD7, #5CE6 и #5CE8. x20BD call x0B0B ;берем число форматируемых дорожек LD B,(HL) XOR A ;дорожки проверять INC HL LD (HL),A LD E,#FF ;начнем с дорожки 0 x20C6 PUSH BC ;сохранение количества дорожек INC E ;следующая дорожка LD A,E LD B,#1B ;позиционирование CALL x3E44 CALL x1FEB ;выбор верхней стороны диска CALL x1FFD ;форматирование дорожки и возврат LD A,(#5CDA) ;берем флаг количества сторон CP #80 ;форматировать 2 стороны? JR NZ,x20E1 ;если да, то CALL x1FF6 ;выбор нижней стороны диска CALL x1FFD ;форматирование дорожки и возврат x20E1 POP BC ;восстановление количества дорожек DJNZ x20C6 ;если еще не все, то повтор RET ;возврат ;Адрес #20E5. Удаление буфера с изменением памяти. На входе установите переменные #5CB6, #5CF8, #5D0C и #5D18. Выход: в #5D18 записывается #FF, а если в #5D0C выл 0, то туда также засылается #FF. Используется также с адреса: ;#20F1 (изменение памяти, работает только с #5CB6 и #5D18). x20E5 PUSH AF ;сохранение AF LD A,(#5CF8) ;ничего не делать? CP #FF JR Z,x211C ;если да, то возврат POP AF ;восстановление AF CALL x2970 ;удаление буфера x20F1 PUSH AF ;сохранение AF LD A,(#5CB6) ;изменение разрешено? CP #F4 JR Z,x211C ;если нет, то возврат XOR A LD HL,#5D18 ;подтверждение есть? OR (HL) LD (HL),#FF ;в следующий раз подтверждение будет JR Z,x211C ;если его не было, то возврат LD A,(#5D0C) ;буфер есть? OR A LD HL,#5CC3 ;начало первого блока LD DE,#5D33 ;начало второго блока JR NZ,x2111 ;если есть буфер, то второй блок смещен на #101 LD DE,#5E34 ;байтов x2111 LD B,#2D ;длина блоков - #2D байтов x2113 LD C,(HL) ;меняем блоки местами LD A,(DE) LD (HL),A LD A,C LD (DE),A INC HL INC DE DJNZ x2113 x211C POP AF ;восстановление AF RET ;возврат ;Адрес #211E. Очистка буфера редактора. x211E LD HL,(#5C59) ;берем адрес буфера редактора LD (HL),#D ;ENTER LD (#5C5B),HL ;установка курсора INC HL ;конец области LD (HL),#80 RET ;возврат ;Адрес #212A. Восстановление командной строки. Установите #5D20. x212A LD DE,(#5C59) ;символы переносить в буфер редактора LD HL,#5D20 ;из #5D20 CALL x02B0 ;перенос символов RET ;возврат ;Адрес #2135. Принятие команды. Установите #5D0F и если там не 0, то и #5D20. x2135 LD A,(#5D0F) ;ошибка была? OR A PUSH AF ;сохранение результата проверки CALL NZ,x212A ;если да, то восстановление первых трех символов ;Не надо этого делать!!! COPY портит буфер по адресу #5D20, а буфер редактора всегда остается цел. POP AF ;восстановление результата проверки CALL Z,x211E ;если ошибки не было, то стирание старой строки LD HL,(#5C59) ;эта команда тоже не нужна CALL x3D80 ;перевод строки LD A,(#5D19) ;берем номер дисковода по умолчанию ADD A,"A" ;печать его имени RST #10 LD A,">" ;печать ">" RST #10 LD HL,#5C3A ;для нормального выхода из редактора LD (HL),#FF JP x1D90 ;ввод команды и возврат ;Адрес #2158. Прием числа. CH_ADD установите на символ перед числом. Число, увеличенное на 1, будет помещено в #5CD7, а содержимое #5CDB будет скопировано в #5CD9. Число не должно равняться 0. x2158 CALL x1E2A ;следующий символ CALL x1D8C CP "," ;это запятая? JP NZ,x1D1A ;если да, то ошибка LD HL,(#5CDB) ;сохранение #5CDB LD (#5CD9),HL CALL x1E0B ;помещение числа на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат LD HL,(#5CDB) ;число pавно 0? LD A,H OR A JP NZ,x1D1A ;если да, то ошибка INC HL ;еще будет байт ENTER LD (#5CD7),HL ;установка числа LD HL,(#5CD9) ;восстановление #5CDB LD (#5CDB),HL RET ;возврат ;Адрес #2182. Выполнение команды OPEN#. Установите #5D11 и #5C3B. x2182 LD HL,(#5D11) ;установка CH_ADD LD (#5C5D),HL CALL x1E0B ;принятие номера потока CALL x1DD0 ;принятие имени файла на стек калькулятора x218E CALL x1D8C ;берем текущий символ CP "A" ;он меньше "A"? JR NC,x219A ;если нет, то проверка режима файла CALL x1E2A ;следующий символ JR x218E ;повтор x219A CP #A5 ;это RND? PUSH AF ;сохранение символа и результата проверки CALL Z,x2158 ;если это RND, то обработка длины записи POP AF ;восстановление символа и результата проверки JR Z,x21AE ;если это RND, то открытие потока AND #DF ;буква заглавная CP "R" ;это "R"? JR Z,x21AE ;если да, то открытие потока CP "W" ;это "W"? JP NZ,x1D1A ;если нет, то ошибка x21AE LD (#5D09),A ;сохранение буквы режима файла CALL x1D75 ;если идет проверка на синтаксис, то возврат LD A,"#" ;расширение файла - "#" LD (#5CE5),A LD A,0 ;поиск начинать с блока 0 LD (#5CE6),A CALL x21DB ;поиск последнего блока файла PUSH AF ;сохранение флага результата поиска CALL x220F ;проверка потока POP AF ;восстановление флага результата поиска PUSH AF ;сохранение флага результата поиска CALL NZ,x2288 ;если файл не был найден, то создание блока 0 POP AF ;восстановление флага результата поиска CALL x2242 ;открытие потока LD HL,(#5D11) ;коррекция переменной с адресом командной строки LD BC,#124 ADD HL,BC LD (#5D11),HL JP x01D3 ;завершение ;Адрес #21DB. Поиск блока файла данных. Вход: поместите имя файла на стек калькулятора, установите #5CDD и #5D09 и поместите в #5CE6 номер первого блока файла. Выход: если файл найден, то будет считан описатель последнего или первого блока в зависимости от #5D09 и обнулен аккумулятор и установлен флаг Z; иначе флаг Z будет сброшен, а в аккумуляторе будет байт из #5D09. x21DB LD A,#A ;поиск файла ведем по #A байтам LD (#5D06),A CALL x1CB0 ;установка имени файла и поиск файла PUSH AF ;сохранение результата поиска CALL x0405 ;настройка на диск POP AF ;восстановление результата поиска JR NZ,x2206 ;если файл не найден, то проверка режима файла LD A,(#5D09) ;открываем файл для чтения? CP "R" JR Z,x2201 ;если да, то выход x21F1 LD HL,#5CE6 ;следующий блок INC (HL) CALL x1CB3 ;поиск блока JR Z,x21F1 ;если блок найден, то следующий блок LD HL,#5CE6 DEC (HL) ;последний существующий блок CALL x1CB3 ;определение его номера в каталоге x2201 CALL x165D ;чтение его описателя XOR A ;обнуление аккумулятора и установка флага Z RET ;возврат x2206 LD A,(#5D09) ;открываем файл для чтения? CP "R" RET NZ ;если да, то возврат JP x03D9 ;сообщение NO FILE ;Адрес #220F. Проверка занятости потока. Вход: установите #5CDB. Выход: в HL будет адрес элемента таблицы STRMS, отвечающего за данный поток. Используется также с адреса #2225 (то же, что и #1C4A). x220F LD A,(#5CDB) ;берем номер потока RST #20 ;берем относительный адрес описателя потока, к DW #1727 ;которому подключен канал LD A,B ;поток занят? OR C JP NZ,x221B ;если да, то ошибка RET ;возврат x221B LD A,#19 ;код ошибки бейсика PARAMETER ERROR ;Внимание!!! Лучше выдавать сообщение INVALID STREAM. LD (#5C3A),A LD HL,x2804 ;адрес сообщения STREAM OPENED LD A,#A ;код ошибки TR-DOS - #A x2225 JP x1C4A ;обработка ошибки ;Адрес #2228. Обработка ошибки NOT DISC FILE. x2228 LD A,#B ;код ошибки - #B LD HL,x2812 ;адрес сообщения NOT DISC FILE JR x2225 ;обработка ошибки ;Адрес #222F. Инициализация признаков файла произвольного доступа. Установите #5CD7 и откройте канал файла данных. Подпрограмма помещает в A #7F. x222F PUSH HL ;сохранение HL LD C,#20 ;берем адрес #20-го байта описателя канала RST #28 LD A,(#5CD7) ;установка длины записи LD (HL),A INC HL XOR A LD (HL),A ;адресация от начала записи - 0 INC HL LD (HL),A ;будет приниматься номер записи INC HL LD (HL),A ;сектор переписывать LD A,#7F ;загрузка аккумулятора POP HL ;восстановление HL RET ;возврат ;Адрес #2242. Создание описателя канала для файла данных и подключение к нему потока. Установите #5CDB. x2242 PUSH AF ;сохранение результата поиска файла CALL x220F ;берем адрес элемента таблицы STRMS, отвечающего за поток EX DE,HL ;сохранение его LD HL,(#5C53) ;вычисление относительного адреса нового LD BC,(#5C4F) ;описателя канала SBC HL,BC EX DE,HL ;восстановление адреса элемента таблицы STRMS LD (HL),E ;установка относительного адреса описателя INC HL ;канала LD (HL),D CALL x22B2 ;создание описателя канала LD A,(#5D09) ;берем способ открытия файла CP #A5 ;это RND? CALL Z,x222F ;если да, то инициализация признаков файла произвольного доступа JR Z,x226B ;и установка признака способа открытия файла LD A,(#5D09) ;берем способ открытия файла CP "R" ;это R? LD A,#FF ;если да, то признак способа открытия файла - JR NZ,x226B ;#FF XOR A ;иначе это 0 x226B LD (HL),A ;установка признака способа открытия файла POP AF JP x2270 x2270 PUSH AF LD BC,#14 ;берем адрес фрагмента текста в описателе ADD HL,BC ;канала минус 1 PUSH HL ;сохраняем его CALL x2423 ;вычисление адреса текущего сектора файла на диске POP HL ;восстановление адреса фрагмента текста минус 1 INC HL LD B,1 ;загружать 1 сектоp POP AF ;восстановление результата поиска файла OR A ;был создан новый файл? PUSH AF ;сохранение результата проверки CALL NZ,x1E4D ;если был создан новый файл, то запись сектора POP AF ;сохранение результата проверки CALL Z,x1E3D ;если файл существовал, то загрузка файла RET ;возврат ;Адрес #2288. Создание нулевого блока файла данных. x2288 LD HL,(#5CD7) ;сохранение #5CD7 PUSH HL LD HL,#2000 ;блок 0 LD (#5CD7),HL CALL x229A ;создание блока POP HL ;восстановление #5CD7 LD (#5CD7),HL RET ;возврат ;Адрес #229A. Создание блока файла данных. Установите #5CD7 и #5CDB, #5CDD и #5CE5. x229A LD HL,#1000 ;длина блока - #1000 байтов LD (#5CD9),HL CALL x1AC4 ;проверка наличия свободного места на диске CALL x1B59 ;запись файла LD HL,0 ;заполнено 0 байтов LD (#5CE8),HL CALL x166B ;замена описателя блока JP x1E43 ;перезапись сектора с описателем и возврат ;Внимание!!! После записи сектора надо снова открыть канал файла данных, так как при ошибке открывается поток 0. ;Адрес #22B2. Создание описателя канала и открытие потока. x22B2 LD HL,(#5C53) ;открытие потока DEC HL LD (#5C51),HL PUSH HL ;сохранение адреса описателя канала LD BC,#124 ;его длина - #124 байта CALL x1E32 ;создание области для описателя канала LD A,0 ;заполнять область нулями LD B,0 ;длина области - #100 байтов x22C4 LD (DE),A ;очистка байта DEC DE ;следующий адрес DJNZ x22C4 ;повтор до конца POP HL ;восстановление адреса описателя канала PUSH HL ;и снова сохранение LD DE,x3D0E ;адрес подпрогpаммы вывода в канал LD (HL),E INC HL LD (HL),D INC HL LD DE,x3D06 ;адрес подпрограммы ввода из канала LD (HL),E INC HL LD (HL),D INC HL LD (HL),"D" ;имя канала - "D" INC HL ;пропуск четырех байтов INC HL INC HL INC HL INC HL LD (HL),#24 ;байт #24 INC HL LD (HL),1 ;байт 1 INC HL LD A,(#5CF6) ;номер дисковода LD (HL),A INC HL LD A,(#5D1E) ;номер последнего блока файла LD (HL),A INC HL LD A,(#5D09) ;файл открывается для чтения? CP "R" LD (HL),0 ;если да, то пройдено 0 байтов JR Z,x22FC ;иначе количество пройденных байтов берем из LD A,(#5CE8) ;поля длины записанной части файла LD (HL),A x22FC INC HL LD (HL),B JR Z,x2304 LD A,(#5CE9) LD (HL),A x2304 INC HL EX DE,HL ;сохранение адреса #F-го байта описателя канала POP HL ;восстановление адреса описателя канала PUSH DE LD DE,#10 ;адрес #10-го байта описателя канала ADD HL,DE EX DE,HL LD HL,#5CDD ;установка описателя файла LD BC,#10 LDIR POP HL ;восстановление адреса #F-го байта описателя канала RET ;возврат ;Адpес #2317. Вычисление адреса текущего символа файла данных в описателе канала. Откройте поток, связанный с файлом данных. На выходе адрес символа будет в HL. x2317 LD C,#D ;адрес #D-го байта описателя канала RST #28 LD C,(HL) ;берем номер текущего символа в текущем секторе файла RST #28 ;вычисление смещения до символа LD BC,#24 ;текст начинается с #24-го байта описателя канала ADD HL,BC ;вычисление адреса символа RET ;возврат ;Адрес #2321. Вычисление адреса фрагмента текста в описателе канала. Откройте поток, связанный с файлом данных. Используется также с адреса #2323 (вычисление адреса байта в описателе текущего канала; откройте канал и поместите номер байта в C; на выходе в HL будет адрес байта). x2321 LD C,#24 ;текст начинается с #24-го байта x2323 LD B,0 ;перевод номера байта в 2-х байтный формат LD HL,(#5C51) ;берем адрес описателя текущего канала ADD HL,BC ;вычисление адреса байта RET ;возврат ;Адрес #232A. Проверка достижения конца сектора в описателе канала. Откройте поток, связанный с файлом данных. При достижении конца сектора будет загружен следующий. Если достигнут конец блока, а следующий отсутствует, то он будет создан. x232A LD C,#D ;адрес #D-го байта описателя канала RST #28 INC (HL) ;следующий байт RET NZ ;если не конец сектора, то возврат PUSH HL ;сохранение адреса #D-го байта описателя канала CALL x2443 ;установка дисковода CALL x23FC ;запись текущего сектора POP HL ;восстановление адреса #D-го байта описателя канала INC HL ;#E-ый байт INC (HL) ;следующий сектор PUSH HL ;сохранение адреса #E-го байта описателя канала CALL x2418 ;загрузка сектора POP HL ;восстановление адреса #E-го байта описателя канала LD A,#10 ;в блоке 16 секторов CP (HL) ;конец блока? RET NZ ;если нет, то возврат PUSH HL ;сохранение адреса #E-го байта описателя канала LD C,#F ;#F-ый байт RST #28 LD A,(HL) ;файл прямого доступа? CP #7F POP HL ;восстановление адреса #E-го байта описателя канала JR Z,x2358 ;если файл прямого доступа, то проверка наличия следующего блока LD HL,(#5C51) ;берем адрес описателя канала CALL x26E1 ;запись описателя блока LD C,#E ;#E-ый байт RST #28 JP x2379 ;создание следующего блока файла x2358 CALL x23CF ;поиск следующего блока файла PUSH AF ;сохранение результата поиска CALL Z,x2418 ;если блок найден, то загрузка сектора из блока LD C,#E ;#E-ый байт RST #28 POP AF ;восстановление результата поиска блока CALL NZ,x2370 ;если блок не был найден, то создание его RET ;возврат ;Адрес #2367. Помещение в D числа #20, в E - содержимого #19-го байта описателя канала и обнуление байта по адресу, помещенному в HL. Откройте нужный канал. x2367 LD (HL),0 ;обнуление байта LD C,#19 ;берем адрес #19-го байта описателя канала RST #28 LD D,#20 ;помещение в регистр D числа #20 LD E,(HL) ;помещение в E числа из #20-го байта описателя канала RET ;возврат ;Адрес #2370. Создание блока файла данных. Откройте поток, связанный с файлом данных. x2370 CALL x2367 ;берем номер создаваемого блока LD (#5CD7),DE ;установка его JR x2381 ;создание и возврат ;Адрес #2379. Cоздание блока файла данных. Откройте поток, связанный с файлом данных, используется, также, с адреса #2381 (создание блока файла данных; установите #5CD7 и #5CDB, #5CDD и #5CE5). x2379 CALL x2367 ;берем номер текущего блока INC E ;следующий блок LD (#5CD7),DE ;установка номера блока x2381 CALL x229A ;создание блока CALL x2970 ;удаление буфера ;Внимание!!! Если выполняется команда CAT# или LIST#, то буфеp удалять нельзя. LD C,#10 ;берем адрес #10-го байта описателя канала RST #28 EX DE,HL ;перенос его в DE LD HL,#5CDD ;перенос описателя блока в описатель канала LD BC,#10 LDIR LD C,#C ;#C-ый байт RST #28 LD A,(#5D1E) ;установка номера блока в каталоге LD (HL),A RET ;возврат ;Адрес #239B. Проверка достижения конца сектора при чтении файла данных. Откройте поток, связанный с файлом данных. x239B LD C,#D ;адрес #10-го байта описателя канала RST #28 INC (HL) ;следующий байт сектора RET NZ ;если не конец сектора, то возврат INC HL ;#11-ый байт INC (HL) ;следующий сектор PUSH HL ;сохранение адреса #11-го байта описателя канала CALL x2443 ;установка дисковода LD C,#23 ;#23-ый байт RST #28 LD A,(HL) ;это 0? OR A JR Z,x23B6 ;если да, то сектор не переписывать POP HL ;восстановление адреса #11-го байта описателя канала PUSH HL ;и снова сохранение его DEC (HL) ;восстановление номера текущего сектора CALL x23FC ;запись сектора POP HL ;восстановление адреса #11-го байта описателя канала PUSH HL ;и снова сохранение его INC (HL) ;следующий сектор x23B6 CALL x2418 ;загрузка сектора POP HL ;восстановление адреса #11-го байта описателя канала LD A,#10 ;в блоке 16 секторов CP (HL) ;конец блока? CALL Z,x23C1 ;если да, то открытие следующего RET ;возврат ;Адрес #23C1. Открытие следующего блока файла данных. Откройте поток, связанный с файлом данных, поместите в HL адрес #E-го байта описателя канала и установите #5D06. x23C1 CALL x23CF ;поиск следующего блока файла данных PUSH AF ;сохранение результата поиска CALL x2970 ;удаление буфера ;Внимание!!! Hадо проверять #5D16, так как если выполняется команда CAT#, или LIST#, то буфер удалять нельзя. POP AF ;восстановление результата поиска блока JP NZ,x2492 ;если блок не найден, то END OF FILE JP x2418 ;загрузка сектора из блока ;Адрес #23CF. Поиск следующего блока файла данных. Откройте поток, связанный с файлом данных, поместите в HL адpес #E-го байта описателя канала и установите #5D06. Если блок найден, то флаг Z будет включен, иначе выключен. x23CF LD (HL),0 ;номер текущего сектора - 0 LD C,#19 ;#19-ый байт описателя потока RST #28 INC (HL) ;следующий блок LD C,#10 ;#10-ый байт RST #28 LD DE,#5CDD ;установка описателя блока LD BC,#10 LDIR CALL x1CB3 ;поиск блока ;Внимание!!! После поиска блока надо снова открывать поток, связанный с файлом данных, так как при дисковых ошибках открывается поток 0. RET NZ ;если блок не найден, то возврат ;Адрес #23E4. Открытие блока. Номер блока в каталоге поместите в A. x23E4 CALL x165D ;чтение описателя блока ;Внимание!!! После чтения описателя надо снова открывать поток, связанный с файлом данных, так как при дисковых ошибках открывается поток 0. LD C,#10 ;берем адрес #10-го байта описателя канала RST #28 EX DE,HL ;переброска его в DE LD HL,#5CDD ;перенос описателя блока в описатель канала LD BC,#10 LDIR LD C,#C ;#C-ый байт RST #28 LD A,(#5D1E) ;установка номера блока в каталоге LD (HL),A XOR A ;обнуление аккумулятора RET ;возврат ;Адрес #23FC. Запись текущего сектора файла данных. Откройте поток, связанный с файлом. x23FC CALL x2423 ;вычисление адреса текущего сектора файла на диске CALL x2321 ;вычисление адреса текущего фрагмента текста в описателе канала LD B,1 ;записывать 1 сектор CALL x1E4D ;запись сектора ;Внимание!!! После записи сектора надо снова открывать поток, связанный с файлом данных, так как при дисковой ошибке открывается поток 0. LD C,#F ;#F-ый байт описателя канала RST #28 LD A,(HL) ;файл прямого доступа? CP #7F RET Z ;если да, то возврат CALL x2321 ;вычисление адреса текущего фрагмента текста в описателе канала XOR A ;сектор заполнять нулями LD B,A ;длина его - #100 байтов x2413 LD (HL),A ;очистка байта INC HL ;следующий байт DJNZ x2413 ;повтор до конца RET ;возврат ;Адрес #2418. Загрузка текущего сектора в описатель канала. Откройте поток, связанный с файлом данных. x2418 CALL x2423 ;вычисление адреса текущего сектора на диске CALL x2321 ;вычисление адреса сектора в описателе канала LD B,1 ;загружать 1 сектор JP x1E3D ;загрузка сектора и возврат ;Внимание!!! После загрузки сектора надо снова открывать канал, связанный с файлом данных, так как при ошибках открывается поток 0. ;Адрес #2423. Вычисление адреса текущего сектора файла на диске. Откройте поток, связанный с файлом данных. На выходе в DE будет адрес сектора на диске. x2423 LD HL,(#5C51) ;берем адрес #1E-го байта описателя канала LD BC,#1E ADD HL,BC LD E,(HL) ;берем адрес файла на диске INC HL LD D,(HL) LD C,#E ;#E-ый байт RST #28 LD B,(HL) ;берем номер текущего сектора файла DEC B ;он равен 0? INC B PUSH AF ;сохранение AF LD A,#10 ;на дорожке #10 секторов JR Z,x2441 ;если номер текущего сектора файла pавен 0, то выход x2438 INC E ;следующий сектор CP E ;конец дорожки? JR NZ,x243F ;если да, то LD E,0 ;сектор 0 INC D ;и следующая дорожка x243F DJNZ x2438 ;повтор до конца x2441 POP AF ;восстановление AF RET ;возврат ;Адрес #2443. Установка дисковода для операций с файлом данных. Откройте поток, связанный с файлом. x2443 LD C,#B ;берем адрес #B-го байта описателя канала RST #28 LD A,(HL) ;берем номер дисковода, на котором находится файл JP x3DCB ;выбор дисковода ;Адрес #244A. Вывод символа в файл данных. Символ поместите в аккумулятор и откройте поток, связанный с файлом. x244A LD HL,#5CC2 ;адрес переключателя ПЗУ на бейсик PUSH HL ;помещение его на стек LD HL,x20F1 ;адрес подпрограммы изменения памяти PUSH HL ;помещение его на стек PUSH AF ;сохранение символа CALL x20F1 ;изменение памяти LD A,#A ;файл искать по #A байтам описателя LD (#5D06),A POP AF ;восстановление символа CALL x24A2 ;работа с файлом прямого доступа PUSH AF ;сохранение символа CALL x2650 ;файл открывался для чтения? JP Z,x249E ;если да, то ошибка POP AF ;восстановление символа CALL x2317 ;вычисление адреса текущего символа в текущем секторе LD (HL),A ;запись символа JP x232A ;проверка достижения конца сектора в описателе канала ;Адрес #246E. Проверка достижения конца блока. Используется также с адресов: ;#2492 - обработка ошибки END OF FILE через ПЗУ бейсика. ;#2494 - обработка ошибок через ПЗУ бейсика. Код ошибки поместите в аккумулятор. x246E LD C,#D ;берем адрес #D-го байта описателя канала RST #28 LD A,(HL) ;берем младший байт длины пройденной части файла LD BC,#E ;#1B-й байт ADD HL,BC CP (HL) ;сравнение младших байтов длин пройденной и записанной частей блока RET NZ ;если они не равны, то возврат LD C,#E ;аналогично со старшими байтами RST #28 LD A,(HL) LD BC,#E ADD HL,BC CP (HL) RET NZ LD HL,#5CB6 ;адрес переменной разpешения изменения памяти LD A,(HL) ;берем ее значение CP #F4 ;интерфейс-1 есть? JR Z,x2492 ;если нет, то ошибка BIT 4,(HL) ;выполняется команда LOAD интерфейса-1? JR Z,x2492 ;если да, то ошибка OR 1 ;сброс флага C POP HL ;снятие со стека адреса возврата RET ;возврат по следующему адресу x2492 LD A,7 ;код ошибки END OF FILE x2494 LD (#5C3A),A ;установка кода ошибки CALL x20E5 ;изменение памяти RST #20 ;обработка ошибки DW #0058 ;Адрес #249D. Команда RET. x249D RET ;Адрес #249E. Обработка ошибки INVALID I/O DEVICE через ПЗУ бейсика. x249E LD A,#17 ;код ошибки - #17 JR x2494 ;обработка ошибки чеpез ПЗУ бейсика ;Адрес #24A2. Работа с файлом произвольного доступа. Очередной символ поместите в A и откройте поток, связанный с файлом данных. Если окончен прием записи или файл последовательного доступа, то происходит простой возврат, иначе происходит возврат из программы, вызвавшей эту подпрограмму. x24A2 LD D,A ;сохранение символа LD C,#F ;берем адрес #D-го байта описателя канала RST #28 LD A,(HL) ;файл произвольного доступа? CP #7F LD A,D ;восстановление символа RET NZ ;если файл произвольного доступа, то возврат LD BC,#13 ;#22-ый байт ADD HL,BC LD A,(HL) ;принимаем номер записи? OR A LD A,D ;восстановление символа JR NZ,x24D5 ;если номер записи принят, то запись символа DEC HL ;#21-ий байт LD A,(HL) ;это 0? OR A JR NZ,x24C2 ;если нет, то рабочая область уже есть PUSH BC ;сохранение числа #13, PUSH HL ;адреса #21-го байта описателя канала и PUSH DE ;символа CALL x24F8 ;выделение #10 байтов в рабочей области POP DE ;восстановление символа, POP HL ;адреса #21-го байта описателя канала и POP BC ;числа #13 x24C2 LD C,(HL) ;берем относительный адрес символа LD A,D ;восстановление символа EX DE,HL LD HL,(#5CCF) ;берем адрес рабочей области ADD HL,BC ;вычисление адреса для символа CP 6 ;символ CHR$ 6? LD (HL),A ;помещение символа в рабочую область CALL Z,x2504 ;если символ CHR$ 6, то номер записи принят LD C,#21 ;#21-ий байт RST #28 INC (HL) ;записали 1 символ POP HL ;снятие со стека адреса возврата RET ;возврат по следующему адресу x24D5 DEC HL ;#21-ий байт LD A,(HL) ;берем относительный адрес символа DEC HL ;#20-й байт INC A ;место для символа ENTER CP (HL) ;конец записи? INC HL ;#21-ий байт INC (HL) ;записали 1 символ PUSH HL ;сохранение адреса #21-го байта описателя PUSH AF ;канала и результата проверки наличия места для символа LD C,#23 ;#23-ый байт RST #28 LD (HL),#FF ;сектор переписывать POP AF ;восстановление результата проверки наличия места POP HL ;для символа и адреса #21-го байта описателя канала JR C,x24EE ;если места для символа нет, то следующая запись LD A,D ;восстановление символа CP #D ;это ENTER? JR Z,x24F2 ;если да, то следующая запись POP BC ;снятие со стека адреса возврата RET ;возврат по следующему адресу x24EE LD A,D ;восстановление символа CP #D ;это ENTER? RET NZ ;если нет, то возврат x24F2 XOR A ;относительный адрес символа - 0 LD (HL),A INC HL ;#22-ый байт LD (HL),A ;будем принимать номер записи LD A,D ;восстановление символа RET ;возврат ;Адрес #24F8. Выделение #10 байтов в рабочей области памяти. Устанавливает #5CCF. x24F8 LD HL,(#5C61) ;берем адрес рабочей области памяти LD (#5CCF),HL ;установка его LD BC,#10 ;выделять #10 байтов JP x1E23 ;выделение области и возврат ;Адpес #2504. Обработка номера записи. Поместите в память номер записи в виде текста и поместите его адрес в #5CCF, а в HL поместите адрес последнего символа номера записи плюс 1. x2504 LD (HL),#D ;конец строки LD HL,(#5C5D) ;сохранение CH_ADD LD (#5CD7),HL LD HL,(#5CCF) ;установка CH_ADD на номер записи LD (#5C5D),HL LD HL,#5C3B ;проверка на синтаксис RES 7,(HL) CALL x1DC1 ;перевод числа в 5-байтную форму LD HL,#5C3B ;выполнение SET 7,(HL) LD HL,(#5CCF) ;установка CH_ADD на номер записи LD (#5C5D),HL CALL x1DC1 ;прием числа на стек калькулятора CALL x1DB9 ;снятие его оттуда PUSH BC ;перенос его в DE POP DE LD C,#20 ;берем адрес #D-го байта описателя канала RST #28 LD B,(HL) ;берем длину записи XOR A LD HL,0 ;вычисление относительного адреса записи в LD (#5CDB),HL ;секторе, номера сектора и номера блока x2538 ADD HL,DE ;извините, не понял, как это pаботает JR NC,x2544 PUSH HL LD HL,(#5CDB) INC HL LD (#5CDB),HL POP HL x2544 DJNZ x2538 LD (#5CD9),HL LD A,(#5CDB) ;в блоке всего 16 секторов LD HL,#5CDA RRD AND #F LD (#5CDB),A LD HL,(#5CD7) ;восстановление CH_ADD LD (#5C5D),HL CALL x2568 ;открытие записи LD C,#21 ;#21-ий байт RST #28 LD A,#FF ;относительный адрес текущего символа будет 0 LD (HL),A INC HL ;#22-ый байт LD (HL),A ;номер записи принят RET ;возврат ;Адрес #2568. Открытие записи. Установите #5CD7, #5CD9 и #5CDB. x2568 LD C,#19 ;берем адрес #19-го байта описателя канала RST #28 LD A,(#5CDA) ;берем номер открываемого блока CP (HL) ;блок уже открыт? JP NZ,x2584 ;если нет, то открытие блока LD C,#E ;#E-ый байт RST #28 LD A,(#5CDB) ;берем номер сектора в открываемом блоке CP (HL) ;сектор уже считан? JP NZ,x25A7 ;если нет, то загрузка сектора x257C LD C,#D ;#D-ый байт RST #28 LD A,(#5CD9) ;берем относительный адрес открываемой записи LD (HL),A ;установка его RET ;возврат x2584 CALL x25CA ;проверка и обнуление #23-го байта CALL NZ,x25C3 ;если надо, то запись сектора LD A,(#5CDA) ;берем номер открываемого блока LD C,#19 ;#19-ый байт RST #28 LD (HL),A ;установка номера блока LD C,#10 ;#10-ый байт RST #28 LD DE,#5CDD ;установка описателя блока LD BC,#10 LDIR CALL x1CB3 ;поиск блока ;Ошибка!!! После поиска файла надо снова открывать канал файла данных, так как при ошибке будет открыт поток 0. JP NZ,x25D2 ;если блок не найден, то создание блока CALL x23E4 ;открытие блока JR x25AD ;загрузка сектора из блока x25A7 CALL x25CA ;проверка и обнуление #23-го байта CALL NZ,x25C3 ;если надо, то запись сектора x25AD LD A,(#5CDB) ;берем номер считываемого сектора LD C,#E ;#E-ый байт RST #28 LD (HL),A ;установка номера сектора PUSH HL ;сохранение адреса #E-го байта CALL x2443 ;установка дисковода CALL x2418 ;загрузка сектора POP HL ;восстановление адреса #E-го байта DEC HL ;#D-ый байт LD A,(#5CD9) ;установка относительного адреса открываемой LD (HL),A ;записи JR x257C ;выход ;Адрес #25C3. Запись текущего сектора. Откройте канал файла данных. x25C3 CALL x2443 ;установка дисковода CALL x23FC ;запись сектора RET ;возврат ;Адрес #25CA. Проверка и обнуление #23-го байта описателя канала. Соответственно содержимому будет установлен флаг Z, а само содержимое будет в аккумуляторе. Откройте нужный канал. x25CA LD C,#23 ;берем адрес #23-го байта описателя канала RST #28 LD A,(HL) ;берем его содержимое OR A ;проверка его LD (HL),0 ;обнуление байта RET ;возврат ;Адрес #25D2. Создание блока файла данных. Установите #5CD7, #5CD9 и #5CDB. x25D2 LD HL,(#5CDA) ;берем номер блока LD H,#20 LD (#5CD7),HL ;установка его LD HL,(#5CD9) ;сохранение относительного адреса открываемой PUSH HL ;записи LD HL,(#5CDB) ;и номера сектора PUSH HL CALL x2381 ;создание блока POP HL ;восстановление номера сектора LD (#5CDB),HL POP HL ;и относительного адреса открываемой записи LD (#5CD9),HL JR x25AD ;загрузка сектора из блока ;Адрес #25EF. Ввод из файла данных. Откройте поток, связанный с файлом данных. При вызове из редактора вводит всю строку и производит выход из редактора, иначе возвращает символ из файла в A. x25EF CALL x20F1 ;изменение памяти LD HL,#5C3C ;pежим не менялся RES 3,(HL) LD HL,(#5C3D) ;берем адрес подпрограммы обработки ошибок LD E,(HL) INC HL LD D,(HL) OR A ;он pавен #107F? LD HL,#107F SBC HL,DE JR NZ,x2626 ;если нет, то подпрограмма вызвана не из редактора LD SP,(#5C3D) ;очистка стека редактора POP DE ;снятие адреса подпрограммы обработки ошибок POP DE ;восстановление адреса дна стека LD (#5C3D),DE ;установка его x260F CALL x262B ;ввод символа из файла JR C,x261D ;если был введен символ, то посылка его в буфер редактора x2614 LD HL,#5CC2 ;адрес переключателя ПЗУ на бейсик PUSH HL ;помещение его на стек LD HL,x20E5 ;адрес подпрограммы удаления буфера и изменения памяти PUSH HL ;помещение его на стек RET ;изменение памяти и возврат x261D CP #D ;символ ENTER? JR Z,x2614 ;если да, то выход RST #20 ;ввод символа в буфер редактора DW #0F85 JR x260F ;повтор x2626 CALL x262B ;ввод символа из файла JR x2614 ;возврат ;Адрес #262B. Ввод байта из файла данных. На выходе байт будет в аккумуляторе. Откройте поток, связанный с файлом данных. x262B LD A,#A ;файл искать по 10 байтам описателя LD (#5D06),A CALL x2650 ;файл открыт для чтения? JR Z,x2642 ;если да, то CP #7F ;файл произвольного доступа? JP NZ,x249E ;если нет, то ошибка LD BC,#13 ;берем адрес #22-го байта описателя канала ADD HL,BC LD (HL),0 ;подпрограмма вывода будет принимать номер записи JR x2645 x2642 CALL x246E x2645 CALL x2317 ;вычисление адреса текущего символа LD A,(HL) ;берем этот символ PUSH AF ;сохраняем его CALL x239B ;проверка достижения конца сектора POP AF ;восстановление символа SCF ;был введен символ RET ;возврат ;Адрес #2650. Проверка #F-го байта описателя текущего канала. Соответственно его содержимому установится флаг Z, а само содержимое будет в регистре A. x2650 LD C,#F ;берем адрес #F-го байта описателя канала RST #28 LD A,(HL) ;берем этот байт OR A ;проверка его на 0 RET ;возврат ;Адрес #2656. Выполнение команды CLOSE#. Установите #5D11 и #5C3B. x2656 LD HL,(#5D11) ;установка CH_ADD LD (#5C5D),HL CALL x1E0B ;прием номера потока CALL x1D75 ;если идет проверка на синтаксис, то возврат LD A,(#5CDB) ;берем номер потока RST #20 ;берем относительный адрес описателя канала DW #1727 LD A,B ;поток закрыт? OR C JP Z,x01D3 ;если да, то завершение PUSH HL ;сохранение адреса элемента STRMS LD HL,(#5C4F) ;берем адрес области описателей каналов ADD HL,BC ;вычисляем адрес первого байта описателя канала LD A,(HL) ;берем старший байт адреса подпрограммы вывода LD HL,x3D0E ;он равен #3D? CP H POP HL ;восстановление адреса элемента STRMS JP NZ,x2228 ;если старший байт адреса подпрограммы вывода не равен #3D, то сообщение NOT DISC FILE Дурацкая проверка!!! Мало ли что может изменить пользователь! LD (HL),0 ;закрытие потока INC HL LD (HL),0 LD (#5CD9),BC ;сохранение относительного адреса описателя канала LD HL,(#5C4F) ;вычисление адреса описателя канала ADD HL,BC DEC HL LD (#5CD7),HL ;сохранение его CALL x26CE ;запись остатка файла, если нужно LD HL,(#5CD7) ;восстановление адреса описателя канала LD BC,#124 ;его длина - #124 байта CALL x1E2E ;уничтожение области описателя канала LD HL,#5C10 ;берем начало таблицы STRMS LD B,#10 ;всего 16 потоков x269D PUSH BC ;сохранение количества потоков LD BC,(#5CD9) ;берем относительный адрес описателя канала LD E,(HL) ;берем адрес из таблицы INC HL LD D,(HL) EX DE,HL ;переносим его в HL SBC HL,BC ;он меньше нашего адреса? EX DE,HL ;переброска его в DE JR C,x26BC ;если он меньше нашего адреса, то следующий элемент LD D,(HL) ;снова берем адрес из таблицы DEC HL LD E,(HL) INC HL PUSH HL ;сохранение адреса текущего элемента таблицы EX DE,HL ;переброска адреса из таблицы в HL LD BC,#124 ;коррекция адреса SBC HL,BC EX DE,HL ;перенос его в DE POP HL ;восстановление адреса текущего элемента таблицы LD (HL),D ;установка нового адреса DEC HL LD (HL),E INC HL x26BC INC HL ;следующий элемент POP BC ;восстановление количества элементов DJNZ x269D ;повтор до конца LD HL,(#5D11) ;коррекция адреса командной строки LD BC,#124 SBC HL,BC LD (#5D11),HL JP x01D3 ;завершение ;Адрес #26CE. Запись текущего сектора файла данных. При записи открывает поток, связанный с файлом. Поместите в HL и #5CD7 адрес описателя канала. x26CE LD BC,#F ;берем адрес #F-го байта описателя канала ADD HL,BC LD A,(HL) ;файл открывался для чтения? OR A RET Z ;если да, то возврат LD HL,(#5CD7) ;открытие потока LD (#5C51),HL CALL x26E1 ;запись описателя блока JP x23FC ;запись текущего сектора и возврат ;Адpес #26E1. Запись описателя текущего блока файла данных. Откройте поток, связанный с файлом данных и поместите в HL адрес описателя канала. x26E1 LD BC,#D ;берем адрес #D-го байта описателя канала ADD HL,BC LD E,(HL) ;берем длину пройденной части блока INC HL LD D,(HL) LD BC,#D ;берем адрес #1A-го байта описателя канала ADD HL,BC LD (HL),E ;установка длины записанной части блока INC HL LD (HL),D LD C,#10 ;#10-ый байт RST #28 LD DE,#5CDD ;установка описателя блока LD BC,#10 LDIR CALL x2443 ;установка дисковода LD C,#C ;#C-ый байт RST #28 LD C,(HL) ;берем номер блока в каталоге CALL x166B ;замена описателя блока JP x1E43 ;запись сектора с описателем и возврат ;Внимание!!! После записи сектора надо снова открывать поток, связанный с файлом данных, так как при дисковой ошибке открывается поток 0. ;Адрес #2707. Печать строки. В HL поместите ее начало. Последний символ должен быть либо CHR$ 0, либо с поднятым седьмым битом. x2707 LD A,(HL) ;берем символ из строки OR A ;это CHR$ 0? RET Z ;если да, то возврат AND #7F ;сброс бита 7 RST #10 ;печать символа BIT 7,(HL) ;бит 7 установлен? RET NZ ;если да, то возврат INC HL ;берем адрес следующего символа JR x2707 ;повтор ;Адрес #2713. Сравнение областей памяти. В HL и DE поместите начала сравниваемых областей, а в B - их длину. При несовпадении флаг Z сброшен, иначе включен. x2713 LD A,(DE) ;сравнение байтов из областей CP (HL) RET NZ ;если они не совпали, то возврат INC DE ;следующие байты INC HL DJNZ x2713 ;повтор до конца RET ;возврат ;Адрес #271B. Обработка ошибки NO DISC без установки TAPE LOADING ERROR. x271B LD HL,x27FC ;адрес сообщения NO DISC LD A,6 ;код ошибки - 6 JP x1C4A ;обработка ошибки ;Адрес #2723. Обработка ошибки DIRECTORY FULL. x2723 LD HL,x27ED ;адрес сообщения DIRECTORY FULL LD A,4 ;код ошибки - 4 JP x1C4A ;обработка ошибки ;Адрес #272B. Установка кода ошибки TAPE LOADING ERROR для ПЗУ бейсика. x272B LD A,#1A ;код ошибки TAPE LOADING ERROR JR x2731 ;установка кода ошибки ;Адрес #272F. Установка кода ошибки INVALID I/O DEVICE для ПЗУ бейсика. Используется также с адреса: ;#2731 (установка кода ошибки для пзу бейсика; код ошибки поместите в A). x272F LD A,#12 ;код ошибки INVALID I/O DEVICE x2731 LD (#5C3A),A ;установка кода ошибки RET ;возврат ;Адрес #2735. Установка кода ошибки OUT OF MEMORY для ПЗУ бейсика. x2735 LD A,3 ;код ошибки OUT IF RAM JR x2731 ;установка кода ошибки ;Адрес #2739. Проверка дорожки. В регистре D задайте физический номер дорожки. По окончании в #5CD6 получите число битых секторов на дорожке. x2739 XOR A ;дорожку проверять LD (#5CD8),A LD (#5CD6),A ;дефектных секторов пока не нашли IN A,(#1F) ;сохраним состояние контроллера дисководов LD (#5CCD),A LD E,D ;перегрузка номера дорожки в E PUSH DE ;сохранение номера дорожки LD A,E ;помещение номера дорожки в регистр данных OUT (#7F),A LD A,#18 ;позиционирование CALL x3D9A LD A,(#5CCD) ;берем состояние контроллера до операции AND #80 ;дисковод был готов? CALL NZ,x3EA0 ;если нет, то задержка в 3135098 тактов POP DE ;восстановление номера дорожки CALL x207D ;проверка дорожки LD A,(#5CD6) ;битых секторов нет? OR A RET Z ;если да, то возврат LD A,7 ;дисковая ошибка LD (#5D0F),A RET ;возврат ;Адрес #2766. Сообщения TR-DOS. x2766 DB "O.K." DB 0 x276B DB "Verify Error." DB #8D x2779 DB "BACKUP DISK" DB #8D x2785 DB "Insert Destination disk" DB #D DB "then press Y" DB 0 x27AA DB "Insert Source disk then press Y" DB 0 x27CA DB "*BREAK*" DB #8D x27D2 DB "Out of RAM" DB #8D x27DD DB "Array not found" DB #8D x27ED DB "Directory full" DB #8D x27FC DB "No disk" DB #8D x2804 DB "Stream opened" DB #8D x2812 DB "Not disk file" DB #8D x2820 DB "File exists" DB #D DB "Over write?(Y/N" x283B XOR C ;Адрес #283C. Вызов подпрограмм TR-DOS из машинного кода. Вход: в регистре C код команды, остальное согласно описанию. На выходе в регистре BC код ошибки. x283C PUSH AF ;сохранение регистров PUSH BC LD (#5D04),DE LD (#5D02),HL CALL x20F1 ;если нужно, то изменение памяти LD A,#FF LD (#5D15),A ;сообщения не печатать LD (#5D1F),A ;команда поступила из машинного кода POP BC ;восстановление BC и AF POP AF LD HL,#201 ;по возврату пойдем в подпрограмму возврата в LD (#5D1A),HL ;бейсик LD HL,0 ;сохранение SP ADD HL,SP LD (#5D1C),HL DEC HL ;резервирование места для адреса возврата по DEC HL ;ошибке из подпрограмм бейсика LD SP,HL PUSH AF ;сохранение AF CALL x021D ;установка адреса возврата по ошибке из бейсика LD HL,x288C ;берем адрес начала таблицы команд x2869 LD A,(HL) ;берем код команды CP C ;он совпал с требуемым? JR NZ,x287F ;если нет, то берем код следующей команды POP AF ;восстановление AF INC HL ;берем адрес, по которому находится адрес подпрограммы LD E,(HL) ;берем адрес подпрограммы INC HL LD D,(HL) LD HL,x01D3 ;берем адрес подпрограммы завершения PUSH HL ;кладем его на стек PUSH DE ;кладем на стек адрес подпрограммы LD HL,(#5D02) ;восстановление HL и DE LD DE,(#5D04) RET ;переход к подпрограмме x287F CP #FF ;достигнут конец таблицы? JR NZ,x2887 ;если нет, то берем адрес номера следующей подпрограммы POP AF ;снятие AF со стека (этого можно было не делать) JP x01D3 ;переход на подпрограмму завершения x2887 INC HL ;пропуск двух байтов адреса подпрограммы INC HL INC HL JR x2869 ;повтор x288C DB 0 ;таблица номеров и адресов подпрограмм DW x08A7 ;new было x3D98 DB 1 DW x3DCB DB 2 DW x3E63 DB 3 DW x3F02 DB 4 DW x3F06 DB 5 DW x1E3D DB 6 DW x1E4D DB 7 DW x28D8 DB 8 DW x165C DB 9 DW x1664 DB #A DW x1CF0 DB #B DW x28FB DB #C DW x28F2 DB #D DW x01D3 DB #E DW x290F DB #F DW x01D3 DB #10 DW x01D3 DB #11 DW x01D3 DB #12 DW x2926 DB #13 DW x28E0 DB #14 DW x28E3 DB #15 DW x2739 DB #16 DW x1FEB DB #17 DW x1FF6 DB #18 DW x0405 DB #FF ;признак конца таблицы ;Адрес #28D8. Выдача каталога диска с настройкой. На входе в A задайте номер потока, в который будете выводить каталог. x28D8 PUSH AF ;сохранение номера потока CALL x0405 ;настройка на диск POP AF ;восстановление номера потока JP x0479 ;вывод каталога ;Адрес #28E0. Перемещение описателя файла из памяти в #5CDD. В HL задайте адрес описателя файла в памяти. x28E0 XOR A ;перемещаем из (HL) в #5CDD JR x28E5 ;перемещение описателя ;Адрес #28E3. Перемещение описателя файла из #5CDD в память по адресу, установленному в HL. Используется также с адреса #28E5 (перемещение описателя файла, в HL - адрес описателя в памяти, в A - направление перемещения: 0 - из памяти, иначе - в память). x28E3 LD A,#FF ;перемещаем в память x28E5 LD DE,#5CDD ;установка второго адреса для LDIR LD BC,#10 ;установка длины описателя OR A ;установка направления перемещения JR Z,x28EF EX DE,HL x28EF LDIR ;перемещение описателя файла RET ;возврат ;Адрес #28F2. Запись программы на бейсике. Установите #5CD1, #5CDD и #5CE5. x28F2 CALL x0405 ;настройка на диск CALL x1AC4 ;проверка свободного места в каталоге JP x1B27 ;запись программы ;Адрес #28FB. Запись файла. Имя с расширением поместите в #5CDD, длину в DE, начало в HL. x28FB LD (#5CD7),HL ;установка начала LD (#5CD9),DE ;установка действительной длины файла LD (#5CDB),DE ;установка длины файла для каталога CALL x0405 ;настройка на диск CALL x1AC4 ;проверка наличия свободного места в каталоге JP x1B53 ;запись файла ;Адрес #290F. Загрузка/верификация файла а также чтение/запись сектора файла. Установите #5CDD, #5CE5, #5CD7 (только для чтения/записи сектора) и #5CF9; в A поместите флаг загрузки согласно описанию команды #E в HL и DE - старт и длину (в зависимости от аккумулятора). x290F OR A LD (#5CD6),A ;установка флага загрузки LD (#5CD9),HL ;установка адреса загрузки LD (#5CDB),DE ;установка длины загрузки CALL x1CB3 ;поиск файла CALL x18A4 ;если файл найден, то чтение его описателя CALL x18AB ;обработка параметров загрузки JP x1921 ;загрузка файла ;Адрес #2926. Стирание файла. Установите #5CDD и #5CE5. На выходе будут установлены #5D07 и #5D08. x2926 CALL x0405 ;настройка на диск CALL x1CB3 ;поиск файла JP x07A0 ;стирание его ;Адрес #292F. Проверка наличия файла. Имя поместите на стек калькулятора и установите #5D06. Если файл найден, то в рег. C и в #5D1E и будет включен флаг Z, иначе флаг Z будет сброшен, а в C будет #FF. x292F CALL x1C57 ;установка имени файла CALL x0405 ;настройка на диск JP x1CB3 ;поиск файла и возврат ;Адрес #2938. Печать имени файла с расширением. В HL установите адрес имени с расширением. x2938 PUSH BC ;сохранение BC LD B,8 ;в имени файла 8 символов x293B LD A,(HL) ;берем символ из имени файла RST #10 ;печать его INC HL ;адрес следующего символа DJNZ x293B ;повтор до конца LD A,"<" ;печать "<" RST #10 LD A,(HL) ;печать расширения RST #10 LD A,">" ;печать ">" RST #10 POP BC ;восстановление BC RET ;возврат ;Адрес #294A. Создание буфера, если его нет. Установите #5D0C. x294A PUSH HL ;сохранение регистров PUSH DE PUSH BC PUSH AF LD HL,#5D0C ;буфер есть? LD A,(HL) OR A JR Z,x2992 ;если да, то восстановление регистров и возврат PUSH HL ;сохранение адреса флага наличия буфера LD BC,#101 ;длина буфера PUSH BC ;сохранение ее CALL x19FD ;проверка возможности выделения буфера POP BC ;восстановление длины буфера POP HL ;восстановление адреса его флага LD (HL),0 ;буфер есть LD HL,#5D25 ;начало буфера CALL x1E32 ;выделение буфера LD HL,(#5D11) ;командная строка переместилась на #101 байтов LD BC,#101 ADD HL,BC JR x298F ;установка нового адреса командной строки и возврат ;Адрес #2970. Удаление буфера, если он есть. Установите #5D0C. Используется также с адресов #298F и #2992 подпрограммой #294A. x2970 PUSH HL ;сохранение регистров PUSH DE PUSH BC PUSH AF LD HL,#5D0C ;буфера нет? LD A,(HL) OR A JR NZ,x2992 ;если да, то возврат LD (HL),#FF ;буфера нет LD HL,#5D25 ;начало буфера LD BC,#101 ;его длина CALL x1E2E ;удаление области памяти OR A ;командная строка переместилась на #101 байтов LD BC,#101 ;надо поменять ее адрес LD HL,(#5D11) SBC HL,BC x298F LD (#5D11),HL x2992 POP AF ;восстановление регистров POP BC POP DE POP HL RET ;возврат ;Адрес #2997. Выполнение команды "40". Установите #5D11 и #5C3B. Используется также с адреса: ;#2998 (выполнение команды установки типа дисковода; установите все для #2997 плюс в A тип дисковода). x2997 XOR A ;дисковод 40-дорожечный односторонний ;Ошибка!!! Во-первых, почему дисковод односторонний?; во-вторых, надо проверять возможность использования дисковода в требуемом режиме. x2998 LD (#5CD7),A ;сохранение типа дисковода CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x042B ;проверка второго символа строки JP Z,x1D1A ;если это ENTER, то *ERROR* CALL x3E11 ;берем адрес ячейки с типом дисковода LD A,(#5CD7) ;установка типа дисковода LD (HL),A JP x03E1 ;сообщение O.K. ;Адрес #29AE. Выполнение команды "80". Установите #5D11 и #5C3B. x29AE LD A,#80 ;дисковод 80-дорожечный односторонний ;Ошибка!!! Во-первых, почему дисковод односторонний?; во-вторых, надо проверять возможность использования дисковода в требуемом режиме. JR x2998 ;выполнение команды ;Адрес #29B2. Тексты сообщений TR-DOS. x29B2 DB #D DB "*ERROR*" DB #8D x29BB DB #D DB "No space" DB #8D x29C5 DB #D DB "File exists" DB #8D x29D2 DB " Free" DB #8D x29D8 DB #D DB "Read Onl" DB #F9 x29E2 DB #D DB "Disc Erro" DB #F2 x29ED DB #D DB "Rec. O/" DB #C6 x29F7 DB "Title:" DB #A0 x29FE DB #D DB "Retry,Abort,Ignore?" DB 0 x2A13 DB #D DB "Trk" DB #A0 x2A18 DB " sec" DB #A0 x2A1D DB " Del. File" DB #8D x2A28 DB #D DB "No" x2A2B DB " File(s)" DB #8D,#00 ;Адрес #2A35. Перенос подпрограммы определение текущего ПЗУ по адресу #4080. x2A35 LD HL,x2A41 ;адрес подпрограммы определение текущего ПЗУ LD DE,#4080 ;ее адрес в ОЗУ LD BC,#20 ;ее длина - #20 байта LDIR ;перенос подпрограммы RET ;возврат ;Адрес #2A41. Подпрограмма определения текущего ПЗУ. Устанавливает #5C01 и подключает ПЗУ 48-го бейсика. Для работы подпрограмма должна быть перемещена в любое место ОЗУ. Можно использовать также с адреса: ;#2A53 для прямого вывода в любой порт. x2A41 LD A,(#3B5) ;берем байт из ПЗУ CP #F3 ;это #F3? LD A,#10 ;если да, то это ПЗУ 48-го бейсика JR Z,x2A4B XOR A ;иначе это ПЗУ 128-го бейсика x2A4B LD (#5C01),A ;установка номера ПЗУ LD BC,#7FFD ;адрес порта конфигурации системы LD A,#10 ;ПЗУ 48-го бейсика x2A53 OUT (C),A ;установка ПЗУ RET ;возврат ;Адрес #2A56. Запись памяти на диск. x2A56 jp x0807 ;new ; PUSH AF ;сохранение регистров ; PUSH BC ; PUSH DE x2A59 PUSH HL PUSH IX PUSH IY EXX PUSH BC PUSH DE PUSH HL EX AF,AF' PUSH AF LD A,I PUSH AF LD A,R PUSH AF LD HL,0 ADD HL,SP ;сохранение SP PUSH HL LD A,#3C ;выбор дисковода A и верхней стороны диска OUT (#FF),A LD A,#3F ;установка регистра I LD I,A IN A,(#1F) ;берем состояние контроллера AND #80 RRCA RRCA RRCA LD (#5C01),A ;сохранение его ;Ошибка!!! Нельзя портить память. CALL x2F65 ;восстановление CALL x3EA0 ;задержка в 3135098 тактов CALL x3EA0 ;еще раз LD DE,#A ;сектор #A LD HL,#4000 ;записывать с адреса #4000 PUSH HL ;сохранение числа #4000 CALL x2D73 ;запись сектора LD HL,#4100 ;записывать с адреса #4100 LD DE,#B ;сектор #B CALL x2D73 ;запись сектора POP HL ;восстановление числа #4000 PUSH HL ;и снова сохранение LD DE,8 ;сектор 8 CALL x2F1B ;загрузка сектора LD HL,#40E3 ;берем тип диска LD A,(HL) LD (#5C00),A ;сохраняем его ;Ошибка!!! Опять порча памяти. INC HL ;берем количество файлов на диске LD A,(HL) INC (HL) ;записали еще 1 файл ;Внимание!!! Не проверяется наличие свободного места в каталоге диска. INC HL ;берем количество свободного места на диске LD E,(HL) INC HL LD D,(HL) OR A ;сброс флага C EX DE,HL LD DE,#C0 ;уменьшим количество места на диске на #C0 SBC HL,DE ;сектора LD (#40E5),HL ;установка нового количества свободного места на диске LD HL,#4000 ;записывать с адреса #4000 LD DE,8 ;сектор 8 CALL x2D73 ;запись сектора POP HL ;восстановление адреса #4000 LD DE,(#40E1) ;берем адрес свободного места на диске PUSH DE ;сохраняем его LD DE,#A ;сектор #A CALL x2F1B ;загрузка сектора POP DE ;восстановление адреса свободного места на диске CALL x2D4C ;запись секторов PUSH DE ;сохранение нового адреса свободного места на диске LD A,#3C ;выбор дисковода A и верхней стороны диска OUT (#FF),A CALL x2F65 ;восстановление LD HL,#4000 ;грузить с адреса #4000 LD DE,8 ;сектор 8 LD B,1 CALL x2F1B ;загрузка сектора POP DE ;восстановление нового адреса свободного места на диске LD HL,(#40E1) ;берем старый адрес свободного места на диске LD (#40E1),DE ;установка нового адреса PUSH HL ;сохранение старого адреса LD HL,#4000 ;записывать с адреса #4000 LD DE,8 ;сектор 8 LD B,1 CALL x2D73 ;запись сектора LD A,(#40E4) ;берем номер записанного файла DEC A CALL x2CE5 ;загрузка сектора с его описателем LD (HL),"@" ;имя файла - "@" INC HL LD B,7 ;7 пробелов x2B09 LD (HL)," " INC HL DJNZ x2B09 LD (HL),"C" ;расширение файла - "C" POP DE ;восстановление старого адреса свободного места на диске POP BC ;и значения SP после сохранения регистров INC HL ;установка значения SP после сохранения LD (HL),C ;в поле адреса загрузки файла INC HL LD (HL),B INC HL ;поле длины файла пропускаем INC HL INC HL LD (HL),#C0 ;длина файла - #C0 сектора INC HL LD (HL),E ;установка адреса файла на диске INC HL LD (HL),D LD HL,#4000 ;записывать с адреса #4000 LD DE,0 IN A,(#5F) ;берем номер сектора, в котором находится DEC A ;описатель файла LD E,A LD B,1 CALL x2D73 ;запись сектора LD HL,0 ;сохранение SP ADD HL,SP LD (#4140),HL LD SP,#41FF ;перенос стека в экран CALL x2A35 ;перенос в экран подпрограммы определения текущего ПЗУ LD HL,#C000 ;адрес страниц ОЗУ XOR A ;начало вычисления контрольной суммы страницы x2B3F ADD A,(HL) ;прибавление к сумме очередного байта INC HL ;адрес следующего байта LD B,A ;сохранение контрольной суммы LD A,H ;берем старший байт текущего адреса в странице OR A ;это 0? LD A,B ;восстановление контрольной суммы JR NZ,x2B3F ;если нет, то повтор LD HL,#4100 ;сохранение контрольной суммы текущей LD (HL),A ;страницы PUSH HL ;сохранение ее адреса LD HL,x2B58 ;адрес возврата - #2B58 PUSH HL ;помещение его на стек LD HL,x3D2F ;адрес переключателя ПЗУ на TR-DOS PUSH HL ;помещение его на стек DI ;запрет прерываний JP #4080 ;определение текущего ПЗУ x2B58 POP HL ;восстановление адреса контрольной суммы текущей страницы LD BC,#7FFD ;адрес порта конфигурации системы LD A,#AA ;контрольный байт LD (#4130),A ;помещение его в экран LD D,5 ;банк ОЗУ 5 LD A,(#5C01) ;выбор ПЗУ OR D LD D,A OUT (C),D ;выбор банка памяти LD A,(#C130) ;берем адрес контрольного байта CP #AA ;это #AA? JP NZ,x2C1B ;если нет, то выход LD A,D ;ОЗУ 0 AND #F8 LD D,A INC HL ;адрес переменной с кодом текущего банка памяти LD B,8 ;всего 8 страниц x2B79 LD (HL),D ;установка банка OUT (C),D ;выбор банка XOR A ;начало вычисления контрольной суммы страницы LD HL,#C000 ;адрес страниц ОЗУ x2B80 ADD A,(HL) ;прибавление к сумме очередного байта INC HL ;адрес следующего байта LD E,A ;сохранение контрольной суммы LD A,H ;берем старший байт текущего адреса в странице OR A ;это 0? LD A,E ;восстановление контрольной суммы JR NZ,x2B80 ;если нет, то повтор LD HL,#4100 ;адрес переменной с контрольной суммой текущей страницы CP (HL) ;суммы совпадают? INC HL ;адрес переменной с кодом текущего банка памяти JR Z,x2B93 ;если да, то все INC D ;следующая страница ОЗУ DJNZ x2B79 ;повтор до конца DEC D ;берем код текущего банка памяти x2B93 LD B,8 ;всего 8 страниц x2B95 PUSH BC ;сохранение числа страниц CALL x2C37 ;запись страницы POP BC ;восстановление числа страниц DJNZ x2B95 ;повтор до конца LD C,0 ;дорожка 0 CALL x2F3A ;позиционирование CALL x2D2A ;загрузка сектора 8 по адресу #4000 LD A,(#40E4) ;берем количество файлов на диске LD (#4102),A ;сохраняем его INC A ;записали еще 1 файл LD (#40E4),A ;установка нового количества файлов LD HL,(#40E5) ;берем количество свободного места на диске LD DE,1 ;уменьшаем его на 1 сектор SBC HL,DE LD (#40E5),HL ;установка нового количества свободного места на диске RET C ;если места на диске нет, то возврат ;Внимание!!! Куда возврат? Ведь на вершине стека находится сохраненные регистры R и F. LD HL,(#40E1) ;берем адрес свободного места на диске LD (#411E),HL ;сохраняем его CALL x2D1E ;установка имени файла LD A,"8" ;восьмой файл LD (#4111),A LD A,1 ;его длина - 1 сектор LD (#411D),A LD HL,#4100 ;адрес загрузки - #4100 LD (#4119),HL LD HL,#100 ;длина - #100 байтов LD (#411B),HL LD DE,(#40E1) ;берем адрес свободного места на диске CALL x2F65 ;восстановление LD C,D ;берем номер дорожки CALL x2F3A ;позиционирование LD HL,#4100 ;записывать с адреса #4100 LD B,1 ;1 сектор CALL x2D58 ;запись сектора LD (#40E1),DE ;установка нового адреса свободного места на диске LD C,0 ;дорожка 0 CALL x2F3A ;позиционирование CALL x2D34 ;запись сектора 8 с адреса #4000 LD A,(#4102) ;берем номер записанного файла CALL x2CE5 ;загрузка сектора с его описателем LD DE,#4110 ;замена описателя файла LD BC,#10 EX DE,HL LDIR IN A,(#5F) ;берем номер загруженного сектора DEC A LD E,A LD D,0 LD HL,#4000 ;записывать с адреса #4000 CALL x2D73 ;запись сектора LD BC,#7FFD ;адрес порта конфигурации системы LD A,(#4101) ;берем код текущего банка памяти OUT (C),A ;установка его x2C1B LD HL,(#4140) ;восстановление SP LD SP,HL LD HL,#4000 ;загружать с адреса #4000 LD DE,#A ;сектор #A CALL x2F1B ;загрузка сектора LD HL,#4100 ;загружать с адреса #4100 LD DE,#B ;сектор #B CALL x2F1B ;загрузка сектора LD A,#3C ;помещение на стек числа #3C PUSH AF JP x2EBC ;восстановление регистров и возврат ;Адрес #2C37. Запись страницы ОЗУ, если она не пустая. Поместите в B номер страницы плюс 1 и установите #5C00 и #4101. x2C37 LD A,B ;берем номер страницы DEC A LD (#4103),A ;установка его LD B,A ;сохранение его LD A,(#4101) ;берем номер текущей страницы AND 7 CP B ;записываем ее? RET Z ;если да, то возврат LD A,2 ;записываем страницу 2? CP B RET Z ;если да, то возврат LD A,(#4101) ;берем код текущего банка памяти AND 8 ;текущий экран 0? JR Z,x2C55 ;если да, то не записываем страницу 5 LD A,B ;записываем страницу 7? CP 7 RET Z ;если да, то возврат JR x2C59 ;запись страницы x2C55 LD A,B ;записываем страницу 5? CP 5 RET Z ;если да, то возврат x2C59 CALL x2C5D ;запись страницы RET ;возврат ;Адрес #2C5D. Запись страницы ОЗУ, если она не пустая. Поместите в B номер страницы и установите #5C00 и #4101. x2C5D LD HL,#4101 ;берем код текущего банка памяти LD A,(HL) AND #F8 ;оставляем экран и ПЗУ LD C,A LD A,B ;вычисление байта для порта конфигурации OR C ;системы PUSH BC ;сохранение кода текущего банка памяти LD BC,#7FFD ;адрес порта конфигурации OUT (C),A ;установка банка памяти POP BC ;восстановление кода текущего банка LD HL,#C000 ;адрес страницы x2C70 LD A,(HL) ;берем байт из страницы OR A ;это 0? JR NZ,x2C7A ;если нет, то запись страницы INC HL ;следующий байт LD A,H ;конец страницы? OR A JR NZ,x2C70 ;если нет, то повтор RET ;возврат x2C7A CALL x2C7E ;запись страницы RET ;возврат ;Адрес #2C7E. Запись страницы ОЗУ. Установите #4103 и #5C00. x2C7E LD C,0 ;дорожка 0 CALL x2F3A ;позиционирование CALL x2D2A ;загрузка сектора 8 по адресу #4000 LD A,(#40E4) ;берем количество файлов на диске LD (#4102),A ;сохраняем его INC A ;записали 1 файл LD (#40E4),A LD HL,(#40E5) ;берем количество свободного места на диске LD DE,#40 ;уменьшаем его на #40 секторов SBC HL,DE LD (#40E5),HL ;установка нового количества свободного места RET C ;если места нет, то возврат LD HL,(#40E1) ;берем адрес свободного места на диске LD (#411E),HL ;установка адреса файла на диске CALL x2D1E ;установка имени файла LD A,#40 ;размер файла - #40 секторов LD (#411D),A LD HL,#C000 ;адрес загрузки - #C000 LD (#4119),HL LD HL,#4000 ;длина - #4000 байта LD (#411B),HL LD DE,(#40E1) ;берем адрес свободного места на диске CALL x2D3E ;запись файла LD (#40E1),DE ;установка нового адреса свободного места LD C,0 ;дорожка 0 CALL x2F3A ;позиционирование CALL x2D34 ;запись сектора 8 с адреса #4000 LD A,(#4102) ;восстановление номера файла CALL x2CE5 ;загрузка сектора с описателем файла LD DE,#4110 ;замена описателя файла LD BC,#10 EX DE,HL LDIR IN A,(#5F) ;берем номер загруженного сектора DEC A LD E,A LD D,0 LD HL,#4000 ;записывать с адреса #4000 CALL x2D73 ;запись сектора RET ;возврат ;Адрес #2CE5. Загрузка по адресу #4000 Номер файла поместите в A. На выходе в HL будет адрес описателя файла. x2CE5 LD C,A ;сохранение номера файла AND #F0 ;вычисление номера сектора с описателем файла RRCA RRCA RRCA RRCA LD B,A PUSH BC LD E,B LD D,0 LD HL,#4000 ;загружать с адреса #4000 PUSH DE ;сохранение номера сектора CALL x2F1B ;загрузка сектора POP DE ;восстановление номера сектора POP BC ;и номера файла LD B,0 LD A,C ;вычисление относительного адреса описателя AND #F ;файла в секторе RLCA RLCA RLCA RLCA LD HL,#4000 ;вычисление абсолютного адреса ADD A,L LD L,A RET ;возврат ;Адрес #2D09. Помещение имени и расширения файла "@"CODE по адресу #4110. x2D09 LD HL,#4110 ;адрес имени файла LD B,9 ;длина области - 9 байтов x2D0E LD (HL)," " ;очистка области INC HL DJNZ x2D0E LD A,"@" ;имя файла - "@" LD (#4110),A LD A,"C" ;расширение файла - "C" LD (#4118),A RET ;возврат ;Адрес #2D1E. Установка имени файла страницы. Установите #4103. Имя файла будет находиться по адресу #4110. x2D1E CALL x2D09 ;установка имени главного файла LD A,(#4103) ;берем номер страницы ADD A,"0" ;преобразование его в символ LD (#4111),A ;установка номера страницы RET ;возврат ;Адрес #2D2A. Загрузка сектора 8 по адресу #4000. Спозиционируйте головку. x2D2A LD HL,#4000 ;грузить по адресу #4000 LD DE,8 ;сектор 8 CALL x2F1B ;загрузка сектора RET ;возврат ;Адрес #2D34. Запись сектора 8 с адреса #4000. Спозиционируйте головку. x2D34 LD HL,#4000 ;записывать с адреса #4000 LD DE,8 ;сектор 8 CALL x2D73 ;запись сектора RET ;возврат ;Адрес #2D3E. Запись #40-х секторов с адреса #C000. Установите все для #2D4C. x2D3E CALL x2F65 ;восстановление LD C,D ;берем номер первой дорожки CALL x2F3A ;позиционирование LD HL,#C000 ;записывать с адреса #C000 LD B,#40 ;#40 секторов JR x2D58 ;запись секторов и возврат ;Адрес #2D4C. Запись #C0 секторов с адреса #4000 для подпрограммы MAGIC. В DE поместите адрес на диске и установите #5C00. Используется также с адреса: ;#2D58 (запись секторов; в HL поместите адрес в памяти, в DE - адрес на диске, в B ? количество секторов, установите #5C00 и спозиционируйте головку на первую дорожку). x2D4C CALL x2F65 ;восстановление LD C,D ;берем номер первой дорожки CALL x2F3A ;позиционирование LD HL,#4000 ;записывать с адреса #4000 LD B,#C0 ;#C0 секторов x2D58 PUSH BC ;сохранение количества секторов PUSH DE ;и адреса на диске CALL x2D73 ;запись сектора LD DE,#100 ;адрес следующего сектора в памяти ADD HL,DE POP DE ;восстановление адреса на диске INC E ;следующий сектор LD A,E ;конец дорожки? CP #10 JR NZ,x2D6F ;если да, то LD E,0 ;текущий сектор 0, INC D ;следующая дорожка, LD C,D CALL x2F3A ;позиционирование x2D6F POP BC ;восстановление количества секторов DJNZ x2D58 ;повтор до конца RET ;возврат ;Адрес #2D73. Запись сектора для команды GO TO. В HL поместите адрес записи, в E - номер сектора. x2D73 LD A,E ;установка номера сектора INC A OUT (#5F),A PUSH HL ;сохранение адреса записи LD D,#14 ;20 попыток PUSH DE ;сохранение числа попыток x2D7B DI ;запрет прерываний LD C,#7F ;адрес регистра данных контроллера LD A,#A0 ;команда записи сектора OUT (#1F),A CALL x3FCA ;запись байтов POP DE ;восстановление количества попыток POP HL ;и адреса записи сектора IN A,(#1F) ;берем состояние контроллера AND #7F ;все в порядке? RET Z ;если да, то возврат DEC D ;следующая попытка PUSH HL ;сохранение адреса записи сектора PUSH DE ;и количества попыток JR NZ,x2D7B ;если попытки не кончились, то повтор ;Внимание!!! Самая большая ошибка!!! Диск с заклеенной прорезью защиты от записи будет, скорее всего, испорчен. Подробное объяснение вы найдете в ZX-PЕВЮ #5F/4 на странице #23. HALT ;остановка процессора ;Адрес #2D92. Загрузка секторов. Установите #5CE6, #5CEB и #5CEA. x2D92 LD HL,(#5CE6) ;берем адрес загрузки LD DE,(#5CEB) ;берем адрес секторов на диске LD A,(#5CEA) ;берем количество секторов LD B,A CALL x1E3D ;загрузка секторов RET ;возврат ;Адрес #2DA1. Выполнение команды GO TO. Установите #5D11 и #5C3B. Можно использовать также с адреса #2E27 (GO TO для 48К; параметры, как и для #2DA1). Используется также с адреса #2EBC для возврата из подпрограммы обработки немаскируемого прерывания. x2DA1 CALL x1DDF ;прием имени файла на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x102E ;прием расширения файла ;Зачем это нужно? Ведь MAGIC записывает файлы только с расширением C. CALL x1C57 ;установка имени файла LD (#4020),BC ;сохранение длины имени файла LD A,C ;она равна 8 символам? CP 8 JR NC,x2DD2 ;если да, то работа с 48К CALL x0405 ;настройка на диск CALL x1CB3 ;поиск файла JP NZ,x03D9 ;если не нашли, то NO FILE LD HL,#5CDD ;берем адрес имени файла LD BC,(#4020) ;и его длину ;Зачем портить экран без надобности? Ведь длину имени файла можно сохранять и в другом месте. ADD HL,BC ;вычисляем адрес конца имени файла LD (HL),"8" ;прибавление "8" к имени файла PUSH HL ;сохранение адреса этого символа CALL x1CB3 ;поиск файла POP HL ;восстановление последнего символа имени файла JR Z,x2DD8 ;если файл нашелся, то загрузка страниц LD (HL)," " ;восстановление имени главного файла x2DD2 CALL x1CB3 ;поиск файла JP x2E33 ;загрузка файла x2DD8 CALL x165D ;чтение описателя файла CALL x2D92 ;загрузка файла LD SP,#40FF ;перенос стека LD B,8 ;всего 8 страниц x2DE3 PUSH BC ;сохранение номера файла страницы LD A,B LD BC,#7FFD ;адрес порта конфигурации системы DEC A ;страницы считаем с 0 PUSH AF ;сохранение номера страницы OR #10 ;экран 0, ПЗУ 1 OUT (C),A ;установка страницы POP AF ;восстановление номера страницы ADD A,"0" ;вычисление последнего символа имени файла страницы LD HL,#5CDD ;вычисление адреса для этого символа LD BC,(#4020) ADD HL,BC LD (HL),A ;установка последнего символа имени файла страницы CALL x1CB3 ;поиск файла JR NZ,x2E05 ;если не нашли, то загрузка следующей страницы CALL x165D ;чтение описателя файла CALL x2D92 ;загрузка файла ;Внимание!!! При ответе A на вопpос "DISC ERROR. RETRY,ABORT,IGNORE?", может произойти что угодно, если значение ERR_SP больше #C000, так как старый стек будет затираться загружаемым файлом или находиться в другой странице. x2E05 POP BC ;восстановление номера файла страницы DJNZ x2DE3 ;повтор до конца LD A," " ;восстановление имени главного файла LD HL,#5CDD LD BC,(#4020) ADD HL,BC LD (HL),A CALL x1CB3 ;поиск файла CALL x165D ;чтение описателя файла PUSH BC ;сохранение номера файла PUSH AF ;и AF LD BC,#7FFD ;адрес порта конфигурации LD A,(#4101) ;берем его значение в момент записи файла (из восьмого файла) OUT (C),A ;установка рабочего состояния порта POP AF ;востановление номера файла и AF POP BC JR x2E39 ;загрузка главного файла x2E27 CALL x1DDF ;прием имени файла на стек калькулятора CALL x1D75 ;если идет проверка на синтаксис, то возврат CALL x102E ;прием расширения файла CALL x292F ;поиск файла x2E33 JP NZ,x03D9 ;если он не найден, то NO FILE CALL x165D ;чтение его описателя x2E39 LD A,(#5CDD) ;берем первый символ имени файла CP "$" ;это "$"? DI ;запрет прерываний JR NZ,x2E43 ;если да, то IM 2 ;установка второго режима прерываний x2E43 LD SP,#40F0 ;перенос стека CALL x3E11 ;берем тип дисковода LD (#4010),A ;сохраняем его LD A,(#5D16) ;сохранение копии системного регистра, LD (#4011),A LD HL,(#5CE6) ;адреса стека для программы, PUSH HL LD DE,(#5CEB) ;и адреса файла на диске PUSH DE INC E ;первый сектор файла пока не загружаем LD A,E CP #10 JR NZ,x2E64 LD E,0 INC D x2E64 LD C,D ;берем логический номер дорожки CALL x2F07 ;выбор верхней стороны диска LD A,(#4010) ;берем режим дисковода AND 2 ;дисковод двухсторонний? CALL NZ,x2F0F ;если да, то выбор стороны диска LD A,C ;берем физический номер дорожки CALL x2F50 ;позиционирование LD HL,#4100 ;загружать с адреса #4100 LD B,#BF ;#BF секторов x2E79 PUSH BC ;сохранение количества секторов PUSH DE ;и адреса текушего сектора на диске CALL x2F1B ;загрузка сектора LD DE,#100 ;вычисление адреса загрузки следующего сектора ADD HL,DE POP DE ;восстановление адреса текушего сектора на диске INC E ;следующий сектор LD A,E ;конец дорожки? CP #10 JR NZ,x2E9C ;если нет, то продолжение загрузки LD E,0 ;сектор 0 INC D ;следующая дорожка LD C,D CALL x2F07 ;позиционирование (смотрите выше) LD A,(#4010) AND 2 CALL NZ,x2F0F LD A,C CALL x2F50 x2E9C POP BC ;восстановление количества секторов DJNZ x2E79 ;повтор до конца POP DE ;восстановление адреса файла на диске POP HL ;и адреса стека LD SP,HL ;установка стека LD A,(#4011) ;берем копию системного регистра PUSH AF ;сохраняем ее LD C,D ;позиционирование (смотрите выше) CALL x2F07 LD A,(#4010) AND 2 CALL NZ,x2F0F LD A,C CALL x2F50 LD HL,#4000 ;адрес загрузки первого сектора файла CALL x2F1B ;загрузка сектора x2EBC POP AF ;востановление копии системного регистра EX AF,AF' ;и снова сохранение POP AF ;восстановление регистров R и I LD R,A POP AF LD I,A DI ;запрет прерываний LD A,#FF ;установка флага прерываний JP PO,x2ECC LD A,0 x2ECC LD (#5C00),A POP AF ;восстановление регистров POP HL POP DE POP BC EXX EX AF,AF' POP IY POP IX POP HL POP DE POP BC LD A,(#5C48) ;установка цвета бордюра AND #38 RRCA RRCA RRCA nop ;new nop ;new ; OUT (#FE),A LD A,(#5B08) ;берем байт из #5B08 CP #EE ;там #EE? JR NZ,x2EF7 ;если нет, то системных переменных 128К нет ;Ошибка!!! Число #EE по адресу #5B08 еще ни о чем не говоpит. PUSH BC ;сохранение BC LD BC,#7FFD ;адрес порта конфигурации LD A,(#5B5C) ;берем значение переменной BANK_M OUT (C),A ;установка рабочей страницы POP BC ;восстановление BC x2EF7 LD A,(#5C00) ;берем флаг прерываний OR A ;прерывания разрешать? LD A,#C9 ;установка переключателя ПЗУ на бейсик LD (#5C00),A JR NZ,x2F03 ;если в #5C00 был 0, то EI ;разрешение прерываний x2F03 POP AF ;восстановление AF JP #5C00 ;запуск программы ;Адрес #2F07. Выбор верхней стороны диска для команды GO TO. Установите #4011. Можно использовать также с адреса: ;#2F0C для прямого вывода в порт #FF. x2F07 LD A,(#4011) ;берем копию системного регистра OR #3C ;сторона - верхняя x2F0C OUT (#FF),A ;загрузка системного регистра RET ;возврат ;Адрес #2F0F. Выбор верхней стороны диска для команды GO TO. Вход: установите #4011, поместите в C логический номер дорожки и выберите верхнюю сторону диска. Выход: в C будет физический номер дорожки и выбрана сторона диска. x2F0F LD A,C ;деление номера дорожки на 2 OR A RRA LD C,A RET NC ;если дорожка четная, то возврат LD A,(#4011) ;берем копию системного регистра AND #6F ;сторона - нижняя JR x2F0C ;загрузка системного регистра и возврат ;Адpес #2F1B. Чтение сектора для команды GO TO. В HL поместите адрес загрузки, в E - номер сектора. x2F1B LD A,E ;установка номера сектора INC A OUT (#5F),A PUSH HL ;сохранение адреса загрузки LD D,#14 ;20 попыток PUSH DE ;сохранение числа попыток x2F23 DI ;запрет прерываний LD C,#7F ;адрес регистра данных контроллера LD A,#80 ;команда чтения сектора OUT (#1F),A CALL x3FE5 ;чтение байтов POP DE ;восстановление количества попыток POP HL ;и адреса загрузки сектора IN A,(#1F) ;берем состояние контроллера AND #7F ;все в порядке? RET Z ;если да, то возврат DEC D ;следующая попытка PUSH HL ;сохранение адреса загрузки сектора PUSH DE ;и количества попыток JR NZ,x2F23 ;если попытки не кончились, то повтор HALT ;остановка процессора ;Адрес #2F3A. Позиционирование для подпрограммы MAGIC. Логический номер дорожки поместите в C и установите #5C00. Используется также с адресов: ;#2F50 - позиционирование для команды GO TO. Поместите в A физический номер дорожки. ;#2F57 - выдача команды и ожидание INTRQ. Команду поместите в A. x2F3A LD A,#3C ;выбор верхней стороны диска OUT (#FF),A LD A,(#5C00) ;берем тип дисковода AND 8 ;он двухсторонний? JR NZ,x2F4F ;если нет, то позиционирование LD A,C ;деление номера дорожки на 2 OR A RRA LD C,A JR NC,x2F4F ;если дорожка четная, то позиционирование LD A,#2C ;выбор нижней стороны диска OUT (#FF),A x2F4F LD A,C x2F50 OUT (#7F),A ;загрузка номера дорожки в регистр данных CALL x3DFD ;задержка в 725779 тактов LD A,#18 ;new команда позиционирования x2F57 OUT (#1F),A x2F59 IN A,(#FF) ;ожидание сигнала INTRQ AND #80 JR Z,x2F59 PUSH BC ;сохранение BC CALL x3DFD ;задержка в 725779 тактов POP BC ;восстановление BC RET ;возврат ;Адрес #2F65. Восстановление для подпрограммы MAGIC. x2F65 LD A,#08 ;new команда восстановления JR x2F57 ;выдача команды, ожидание INTRQ и возврат ;Адрес #2F69. Подпрограмма обработки ошибок, поступающих из ПЗУ бейсика. Установите #5C3A и все для подпрограммы #1D3. x2F69 LD HL,(#5D1C) ;очистка стека DEC HL DEC HL LD SP,HL JP x1D2F ;выдача сообщения и завершение ;Адрес #2F72. Вызов подпрограмм из ПЗУ бейсика. Адрес задайте в двух байтах после CALL #2F72: ;CALL #2F72 ;DW #0D6B x2F72 LD (#5D02),HL ;сохранение HL и DE LD (#5D04),DE POP HL ;снятие со стека адреса двух байтов с адресом подпрограммы LD E,(HL) ;берем адрес подпрограммы INC HL LD D,(HL) INC HL PUSH HL ;помещение на стек адреса возврата в программу, вызвавшую #2F72 LD HL,x3D2F ;помещение на стек адреса переключателя ПЗУ на TR-DOS PUSH HL PUSH DE ;помещение на стек адреса вызываемой подпрограммы LD HL,#5CC2 ;помещение на стек адреса команды RET в ОЗУ PUSH HL LD HL,(#5D02) ;восстановление HL и DE LD DE,(#5D04) RET ;переход к команде RET в ОЗУ ;Адрес #2F90. Установка начальных значений системных пеpеменных TR-DOS. В переменные помещает: ;в #5CFA - #5CFD, #5CC8 - #5CCB, #5C3A, #5D16, #5D0C - #FF; #5D17 - #5D19, #5D1F - 0; #5CC2 - #C9; в системный регистр помещается #FF и выполняется команда прерывания. Подпрограмма может использоваться также с адреса: ;#2FC3 для прямого вывода в порт #1F. x2F90 LD HL,#0000 ;new было #FFFF LD (#5CFA),HL ;типы дисководов неизвестны LD (#5CFC),HL call x08CA ;new LD (#5CC8),HL ;время перемещения головок дисководов ; LD (#5CCA),HL ;неизвестно XOR A LD (#5D17),A ;заставку выводить LD (#5D19),A ;дисковод по умолчанию - A: LD (#5D18),A ;память не изменять LD (#5D0F),A ;pаботает командный процессор TR-DOS LD (#5D1F),A LD A,#FF ;загрузка системного регистра OUT (#FF),A LD (#5C3A),A ;ошибки нет LD (#5D16),A ;сохранение значения системного регистра LD (#5D0C),A ;буфера нет LD A,#C9 ;помещение в ОЗУ команды RET LD (#5CC2),A LD A,#D0 ;команда прерывания x2FC3 OUT (#1F),A ;выдача команды RET ;возврат ;Адрес #2FC6. Проверка достижения конца каталога при его печати. x2FC6 CALL x050C ;проверка и обработка достижения конца буфера LD A,(HL) ;берем первый символ имени файла OR A ;конец каталога? JP Z,x03AC ;если да, то окончание выдачи CP 1 ;файл стерт? CALL Z,x0507 ;если да, то пропуск его RET NZ ;иначе возврат JR x2FC6 ;повтор ;Адрес #2FD6. Загрузка сектора в буфер. В DE поместите адрес сектора на диске. x2FD6 LD B,1 ;загружать 1 сектор LD HL,#5D25 ;загружать в буфер JP x1E67 ;загрузка сектора ;Адрес #2FDE. Загрузка конца файла. В HL - адрес загрузки, в #5CDC - длина, в #5CF4 - откуда грузить. x2FDE PUSH HL ;сохранение адреса загрузки LD DE,(#5CF4) ;берем адрес сектора на диске CALL x2FD6 ;загрузка его в буфер LD A,(#5CDB) ;берем количество байтов для загрузки POP DE ;восстановление адреса загрузки OR A ;загружаем 0 байтов? RET Z ;если да, то возврат LD C,A ;перевод длины загружаемой части в двухбайтную форму LD HL,#5D25 ;перемещаем байты из буфера LDIR RET ;возврат ;Адрес #2FF3. Таблица команд TR-DOS. x2FF3 DB #CF,"*",#D0,#D1,#E6,#D2,#EF,#F8,#FE,#BE,#F4,#D5,#F7 DB #D3,#D4,#FF,"4",#EC,"8",#F0,#D6 ;Адрес #3008. Таблица адресов подпрограмм, выполняющих команды TR-DOS. x3008 DW x0433,x1018,x1EC2,x16AB,x053A,x0787,x1815,x1AD0,x1CFB,x19A5 DW x19A9,x19B1,x1D4D,x2182,x2656,x0690,x2997,x2DA1,x29AE,x11CE DW x1810 ;Адрес #3032. Сжатие командной строки. Строку поместите в буфер редактора. Помещает в #5CD6 #FF и устанавливает #5D11. x3032 LD HL,(#5C59) ;берем адрес буфера редактора LD (#5D11),HL ;установка адреса командной строки LD (#5CD9),HL ;установка адреса текущего символа LD A,#FF ;подана прямая команда LD (#5CD6),A LD HL,#5CDB ;любой адрес LD (#5CD7),HL JR x3057 ;сжатие строки и возврат ;Адрес #3048. Сжатие командной строки. В HL поместите адрес строки. Устанавливает #5CD6 и #5D11. Используется также с адреса: ;#3057 (сжатие строки; установите #5CD6, #5CD7 и #5CD9). x3048 LD (#5D11),HL ;установка адреса строки LD (#5CD9),HL ;и адреса текущего ключевого слова CALL x30E1 ;проверка, где находится строка RET NZ ;если строка не найдена, то возврат INC HL ;вычисление адреса поля длины строки INC HL LD (#5CD7),HL ;установка адреса поля длины строки x3057 CALL x30A9 ;определение номера ключевого слова JR NZ,x3087 ;если это не ключевое слово, то следующий символ EX DE,HL ;переброска адреса последнего символа ключевого слова в DE INC DE ;вычисление адреса символа после ключевого слова LD B,0 ;перевод номера ключевого слова в 2-х байтную форму LD HL,x31C8 ;адрес таблицы кодов ключевых слов ADD HL,BC ;вычисление адреса кода ключевого слова LD A,(HL) ;берем этот код LD HL,(#5CD9) ;берем адрес ключевого слова LD (HL),A ;замена его одним символом INC HL ;вычисление адреса второго символа ключевого слова EX DE,HL ;переброска его в DE RST #20 ;вычисление количества стираемых символов DW #19DD PUSH BC ;сохранение его RST #20 ;уничтожение ненужных символов DW #19E8 POP BC ;восстановление количества стертых символов LD A,(#5CD6) ;строка находится в программе на бейсике? OR A JR NZ,x3087 ;если нет, то ее длина нигде не обозначена LD HL,(#5CD7) ;берем адрес поля длины строки LD E,(HL) ;берем длину строки INC HL LD D,(HL) EX DE,HL ;перебросим ее в HL OR A SBC HL,BC ;скорректируем ее EX DE,HL ;перебросим в DE LD (HL),D ;и загрузим обратно DEC HL LD (HL),E x3087 LD HL,(#5CD9) ;берем адрес текущего символа LD A,(HL) ;берем этот символ CP #D ;это ENTER? RET Z ;если да, то возврат INC HL ;следующий символ LD (#5CD9),HL LD A,(HL) ;берем его CP #D ;это ENTER? RET Z ;если да, то возврат CP #22 ;это кавычки? JR NZ,x3057 ;если нет, то повтор x309A INC HL ;следующий символ LD A,(HL) ;берем его CP #D ;это ENTER? RET Z ;если да, то возврат CP #22 ;это кавычки? JR NZ,x309A ;если нет, то следующий символ INC HL ;следующий символ LD (#5CD9),HL JR x3057 ;повтор ;Адрес #30A9. Определение номера ключевого слова. Установите #5CD9. После возврата если флаг Z установлен, то в C будет номер ключевого слова, а в HL - адрес последнего символа ключевого слова; иначе ключевое слово не было опознано, а в HL будет адрес из #5CD9. x30A9 LD HL,(#5CD9) ;берем адрес ключевого слова в строке LD DE,x30FD ;адрес таблицы ключевых слов LD C,0 ;начнем со слова 0 x30B1 LD A,(HL) ;берем символ слова из нашей строки AND #DF ;буква заглавная LD B,A ;загрузка символа в B OR A ;это CHR$ 0? JR NZ,x30BB ;если да, то INC HL ;следующий символ JR x30B1 ;и повтор x30BB LD A,(DE) ;берем символ из таблицы AND #80 ;его бит 7 включен? JR NZ,x30C8 ;если да, то этот символ последний LD A,(DE) ;снова берем символ из таблицы CP B ;сравнение символов JR NZ,x30D9 ;если они не совпадают, то проверка следующего слова INC HL ;адреса следующих символов INC DE JR x30B1 ;повтор x30C8 LD A,(DE) ;берем символ из таблицы AND #7F ;сбрасываем бит 7 CP B ;сравниваем символы RET Z ;если они совпали, то возврат x30CD INC C ;номер следующего слова LD HL,(#5CD9) ;берем адрес ключевого слова в строке INC DE ;следующий символ из таблицы LD A,(DE) CP #FF ;конец таблицы? JR NZ,x30B1 ;если нет, то повтор OR A ;сброс флага Z RET ;возврат x30D9 INC DE ;следующий символ из таблицы LD A,(DE) AND #80 ;его бит 7 включен? JR Z,x30D9 ;если да, то следующий символ JR x30CD ;проверка достижения конца таблицы ;Адрес #30E1. Проверка местонахождения строки. Устанавливает #5CD6, а в HL помещает адрес поля длины строки минус 2. x30E1 LD HL,(#5C45) ;берем номер выполняющейся строки INC HL ;подана прямая команда? INC HL LD A,H OR L JR Z,x30F4 ;если да, то установка флага XOR A ;команда находится в строке программы на бейсике LD (#5CD6),A DEC HL ;восстановление номера строки DEC HL RST #20 ;определение адреса строки DW #196E RET ;возврат x30F4 LD A,#FF ;подана прямая команда LD (#5CD6),A LD HL,(#5C59) ;любой адрес RET ;возврат ;Адрес #30FD. Таблица ключевых слов TR-DOS. x30FD DB "SAVE" DB #80 DB "SAV" DB #C5 DB "LOAD" DB #80 DB "LOA" DB #C4 DB "RUN" DB #80 DB "RU" DB #CE DB "CAT" DB #80 DB "CA" DB #D4 DB "ERASE" DB #80 DB "ERAS" DB #C5 DB "NEW" DB #80 DB "NE" DB #D7 DB "MOVE" DB #80 DB "MOV" DB #C5 DB "MERGE" DB #80 DB "MERG" DB #C5 DB "PEEK" DB #80 DB "PEE" DB #CB DB "POKE" DB #80 DB "POK" DB #C5 DB "OPEN" DB #83 DB "CLOSE" DB #83 DB "CODE" DB #80 DB "COD" DB #C5 DB "RND" DB #80 DB "RN" DB #C4 DB "DATA" DB #80 DB "DAT" DB #C1 DB "SCREEN" DB 4,#84 DB "SCREEN" DB #84 DB "COPY" DB #80 DB "COP" DB #D9 DB "FORMAT" DB #80 DB "FORMA" DB #D4 DB "GOTO" DB #80 DB "GOT" DB #CF DB "LIST" DB #80 DB "LIS" DB #D4 DB "LINE" DB #80 DB "LIN" DB #C5 DB "VERIFY" DB #80 DB "VERIF" DB #D9 DB #FF,#FF ;Адрес #31C8. Таблица кодов ключевых слов TR-DOS. x31C8 DB #F8,#F8,#EF,#EF,#F7,#F7,#CF,#CF,#D2,#D2,#E6,#E6,#D1 DB #D1,#D5,#D5,#BE,#BE,#F4,#F4,#D3,#D4,#AF,#AF,#A5,#A5 DB #E4,#E4,#AA,#AA,#FF,#FF,#D0,#D0,#EC,#EC,#F0,#F0,#CA DB #CA,#D6,#D6,0 ;Адрес #31F3. Проверка наличия системных переменных TR-DOS. Если они есть, то флаг C будет сброшен, иначе установлен. x31F3 LD HL,(#5C4F) ;берем адрес области описателей каналов OR A ;для правильного вычитания LD BC,#5D25 ;адрес области описателей каналов при наличии системных переменных TR-DOS. SBC HL,BC ;установка флага C RET ;возврат x31FD DISPLAY "Free space at ",$,": ",/D,#3201-$," byte(s)" DS #3201-$,#FF x3201 ld hl,x3219 ld de,#FCA0 ld bc,#0318 ld a,#FF jr x3210 x320E inc hl inc hl x3210 cp l jr z,x320E ldi jp pe,x3210 ret ;шрифт x3219 db #00,#00,#00,#00,#00,#00,#00,#00 db #00,#20,#20,#20,#20,#20,#00,#20 db #00,#50,#50,#00,#00,#00,#00,#00 db #00,#00,#50,#F8,#50,#F8,#50,#00 db #00,#20,#70,#A0,#70,#28,#70,#20 db #00,#40,#48,#10,#20,#48,#08,#00 db #00,#20,#50,#50,#60,#A8,#90,#68 db #00,#20,#40,#00,#00,#00,#00,#00 db #00,#08,#10,#10,#10,#10,#10,#08 db #00,#40,#20,#20,#20,#20,#20,#40 db #00,#00,#50,#20,#F8,#20,#50,#00 db #00,#00,#20,#20,#F8,#20,#20,#00 db #00,#00,#00,#00,#00,#60,#20,#40 db #00,#00,#00,#00,#F8,#00,#00,#00 db #00,#00,#00,#00,#00,#00,#60,#60 db #00,#00,#08,#10,#20,#40,#80,#00 db #00,#70,#88,#98,#A8,#C8,#88,#70 db #00,#20,#60,#A0,#20,#20,#20,#F8 db #00,#70,#88,#08,#30,#40,#80,#F8 db #00,#70,#88,#08,#30,#08,#88,#70 db #00,#18,#28,#48,#88,#F8,#08,#08 db #00,#F8,#80,#F0,#08,#08,#08,#F0 db #00,#70,#80,#F0,#88,#88,#88,#70 db #00,#F8,#08,#10,#20,#40,#80,#80 db #00,#70,#88,#88,#70,#88,#88,#70 db #00,#70,#88,#88,#88,#78,#08,#70 db #00,#00,#60,#60,#00,#00,#60,#60 db #00,#00,#60,#60,#00,#60,#20,#40 x32F9 db #00,#00,#10,#20,#40,#20 x32FF dw #FFFF x3301 db #10,#00 x3203 db #00,#00,#00,#F8,#00,#F8,#00,#00 db #00,#00,#40,#20,#10,#20,#40,#00 db #00,#70,#88,#08,#10,#20,#00,#20 db #00,#70,#88,#B8,#A8,#B8,#80,#78 db #00,#70,#88,#88,#88,#F8,#88,#88 db #00,#F0,#88,#88,#F0,#88,#88,#F0 db #00,#70,#88,#80,#80,#80,#88,#70 db #00,#E0,#90,#88,#88,#88,#90,#E0 db #00,#F8,#80,#80,#F0,#80,#80,#F8 db #00,#F8,#80,#80,#F0,#80,#80,#80 db #00,#70,#88,#80,#B8,#88,#88,#70 db #00,#88,#88,#88,#F8,#88,#88,#88 db #00,#F8,#20,#20,#20,#20,#20,#F8 db #00,#38,#10,#10,#10,#90,#90,#60 db #00,#88,#90,#A0,#C0,#A0,#90,#88 db #00,#80,#80,#80,#80,#80,#80,#F8 db #00,#88,#D8,#A8,#88,#88,#88,#88 db #00,#88,#88,#C8,#A8,#98,#88,#88 db #00,#70,#88,#88,#88,#88,#88,#70 db #00,#F0,#88,#88,#88,#F0,#80,#80 db #00,#70,#88,#88,#88,#A8,#90,#68 db #00,#F0,#88,#88,#88,#F0,#90,#88 db #00,#70,#88,#80,#70,#08,#88,#70 db #00,#F8,#20,#20,#20,#20,#20,#20 db #00,#88,#88,#88,#88,#88,#88,#70 db #00,#88,#88,#88,#88,#88,#50,#20 db #00,#88,#88,#88,#88,#88,#A8,#50 db #00,#88,#88,#50,#20,#50,#88,#88 db #00,#88,#88,#50,#20,#20,#20,#20 db #00,#F8,#08,#10,#20,#40,#80,#F8 db #00,#38,#20,#20,#20,#20,#20,#38 x33FB db #00,#00,#80,#40 x33FF dw #FFFF x3401 db #20,#10,#08,#00 x3405 db #00,#E0,#20,#20,#20,#20,#20,#E0 db #00,#20,#70,#A8,#20,#20,#20,#20 db #00,#00,#00,#00,#00,#00,#00,#FC db #00,#40,#20,#00,#00,#00,#00,#00 db #00,#00,#60,#10,#70,#90,#90,#68 db #00,#80,#80,#80,#E0,#90,#90,#E0 db #00,#00,#60,#90,#80,#80,#90,#60 db #00,#10,#10,#10,#70,#90,#90,#70 db #00,#00,#60,#90,#90,#E0,#80,#70 db #00,#18,#20,#20,#70,#20,#20,#20 db #00,#00,#70,#90,#90,#70,#10,#60 db #00,#80,#80,#80,#E0,#90,#90,#90 db #00,#40,#00,#40,#40,#40,#40,#30 db #00,#20,#00,#20,#20,#20,#20,#C0 db #00,#80,#90,#A0,#C0,#A0,#90,#88 db #00,#40,#40,#40,#40,#40,#40,#30 db #00,#00,#D0,#A8,#A8,#A8,#A8,#A8 db #00,#00,#E0,#90,#90,#90,#90,#90 db #00,#00,#60,#90,#90,#90,#90,#60 db #00,#00,#E0,#90,#90,#E0,#80,#80 db #00,#00,#70,#90,#90,#70,#18,#10 db #00,#00,#90,#A8,#C0,#80,#80,#80 db #00,#00,#60,#80,#60,#10,#10,#E0 db #00,#40,#40,#E0,#40,#40,#40,#30 db #00,#00,#90,#90,#90,#90,#90,#60 db #00,#00,#88,#88,#88,#50,#50,#20 db #00,#00,#88,#88,#A8,#A8,#A8,#50 db #00,#00,#00,#88,#50,#20,#50,#88 db #00,#00,#90,#90,#90,#70,#10,#E0 db #00,#00,#F0,#10,#20,#40,#80,#F0 db #00,#20,#40,#40,#80,#40,#40,#20 x34FD db #00,#20 x34FF dw #FFFF x3501 db #20,#20,#20,#20,#20,#20 x3507 db #00,#20,#10,#10,#08,#10,#10,#20 db #00,#00,#A8,#50,#00,#00,#00,#00 db #00,#78,#84,#B4,#A4,#B4,#84,#78 db #00,#FC,#FC,#FC,#FC,#FC,#FC,#FC db #00,#00,#00,#00,#FC,#FC,#FC,#FC db #00,#60,#F0,#78,#3C,#78,#F0,#60 x3537 DISPLAY "Free space at ",$,": ",/D,#35FF-$," byte(s)" ds #35FF-$,#00 dw #FFFF x3601 DISPLAY "Free space at ",$,": ",/D,#36FF-$," byte(s)" ds #36FF-$,#00 dw #FFFF x3701 DISPLAY "Free space at ",$,": ",/D,#37FF-$," byte(s)" ds #37FF-$,#00 dw #FFFF x3801 DISPLAY "Free space at ",$,": ",/D,#38FF-$," byte(s)" ds #38FF-$,#00 dw #FFFF x3901 DISPLAY "Free space at ",$,": ",/D,#39FF-$," byte(s)" ds #39FF-$,#00 dw #FFFF x3A01 DISPLAY "Free space at ",$,": ",/D,#3AFF-$," byte(s)" ds #3AFF-$,#00 dw #FFFF x3B01 DISPLAY "Free space at ",$,": ",/D,#3BFF-$," byte(s)" ds #3BFF-$,#00 dw #FFFF ;Адрес #3C01. То же, что и #3D31. x3C01 JR x3C06 x3C03 DB #FF ;Адрес #3C04. То же, что и #3D1A x3C04 JR x3C09 ;Адрес #3C06. То же, что и #3D31. x3C06 JP x3D00 ;Адрес #3C09. То же, что и #3D1A. x3C09 JP x3D03 x3C0C ret x3C0D push af push hl push de call x3E08 ld b,a pop de pop hl pop af jp x3E44 x3C1A DISPLAY "Free space at ",$,": ",/D,#3C30-$," byte(s)" ds #3C30-$,#00 x3C30 in a,(#1F) ret x3C33 DISPLAY "Free space at ",$,": ",/D,#3CFA-$," byte(s)" ds #3CFA-$,#00 ;Адрес #3CFA. То же, что и #20F1. x3CFA JP x20F1 ;Адрес #3CFD. То же, что и #3D13, но не переключает ПЗУ. x3CFD JP x283C ;Адрес #3D00. Вход в TR-DOS. Переключает ПЗУ. x3D00 NOP JR x3D31 ;Адрес #3D03. Выполнение команд TR-DOS из бейсика. Установите CH_ADD на префикс :REM: перед командой. Возвращает в BC код ошибки. Переключает ПЗУ. x3D03 NOP JR x3D1A ;Адрес #3D06. Подпрограмма ввода из файла данных. Переключает ПЗУ. При вызове из редактора вводит всю строку и производит выход из редактора, иначе возвращает в A символ из файла. x3D06 NOP JP x25EF ;Адрес #3D0A. То же, что и #3D0D, но не переключает ПЗУ. x3D0A JP x244A ;Адрес #3D0D. Подпрограмма вывода в файл данных. Символ поместите в аккумулятор. Используется также с адреса #3D0E. Обе точки входа переключают ПЗУ. x3D0D NOP x3D0E JR x3D0A ;Адрес #3D10. То же, что и #20F1. Переключает ПЗУ. x3D10 NOP JR x3CFA ;Адрес #3D13. Переход на подпрограмму вызова подпрограмм TR-DOS из машинного кода. Адрес является переключателем. x3D13 NOP JR x3CFD ;Адрес #3D16. Переход на подпрограмму обработки ошибок. Адрес является переключателем. x3D16 NOP JP x2F69 ;Адрес #3D1A. То же, что и #3D03, но не переключает ПЗУ. x3D1A CALL x3D21 ;создание системных переменных TR-DOS PUSH HL ;помещение на стек адреса переключателя ПЗУ на бейсик JP x016C ;выполнение команды ;Адрес #3D21. Создание области системных переменных TR-DOS, если ее нет. В HL помещается #5CC2. x3D21 CALL x31F3 ;проверка наличия области системных переменных NOP NOP CALL C,x3D4C ;если ее нет, то создание ее LD HL,#5CC2 ;загрузка в HL адреса переключателя ПЗУ на бейсик RET ;возврат NOP NOP ;Адрес #3D2F. Переключение пзу на TR-DOS и переход на любой адрес. Адрес поместите на стек. x3D2F NOP RET ;Адрес #3D31. Вход в TR-DOS. x3D31 CALL x3D21 ;создание области системных переменных PUSH HL ;помещение на стек адреса переключателя ПЗУ на бейсик JP x0239 ;вход в TR-DOS ;Адрес #3D38. Проверка наличия интерфейса-1. В случае его обнаружения происходит создание его системных переменных и в #5CF1 помещается 1. Для работы подпрограмма должна быть перемещена в любое место ОЗУ. x3D38 XOR A ;интерфейс-1 есть? OUT (#F7),A IN A,(#F7) CP #1E JR Z,x3D44 ;если да, то создание его системных переменных CP #1F RET NZ ;если нет, то возврат x3D44 RST 8 ;создание системных переменных интерфейса-1 DB #31 LD A,1 ;по команде SAVE записывать 1 копию LD (#5CEF),A RET ;возврат ;Адрес #3D4C. Создание системных переменных TR-DOS. При наличии интерфейса-1 перед созданием переменных TR-DOS создаются его переменные и в #5CEF помещается 1. В переменные TR-DOS помещаются: в #5CFA - #5CFC, #5CC8 - #5CCA, #5C3A, #5D16 и #5D0C - #FF; в #5D17, #5D19, #5D18, #5D0F и #5D1F - 0; в #5CC2 - #C9. Также в системный регистр помещается #FF, а на ВГ93 выдается команда прерывания. Подпрограмма портит ячейки памяти калькулятора. x3D4C XOR A ;выбор дисковода A: и сброс ВГ93 OUT (#FF),A IN A,(#F6) ;это ничего не дает LD HL,x3D38 ;адрес подпрограммы проверки наличия интерфейса-1 LD DE,#5C92 ;любой свободный адрес, ОЗУ LD BC,#14 ;длина подпрограммы LDIR ;перенос подпрограммы в ОЗУ LD HL,x3D67 ;адрес возврата из подпрограммы PUSH HL ;помещение его на стек LD HL,x3D2F ;адрес переключателя ПЗУ на TR-DOS PUSH HL ;помещение его на стек JP #5CA5 ;new запуск подпрограммы (переход на ret) ;Адрес #3D67. Создание системных переменных TR-DOS. В переменные помещаются: в #5CFA - #5CFD, #5CC8 - #5CCB, #5C3A, #5D16 и #5D0C - #FF; в #5D17, #5D19, #5D18, #5D0F и #5D1F - 0; в #5CC2 - #C9. Также в системный регистр помещается #FF, а на ВГ93 выдается команда прерывания. x3D67 LD HL,x2F90 ;адрес возврата из пзу бейсика PUSH HL ;помещение его на стек LD HL,x3D2F ;адрес переключателя ПЗУ на TR-DOS PUSH HL ;помещение его на стек LD HL,#1655 ;адрес подпрограммы MAKE_ROOM из ПЗУ бейсика PUSH HL ;помещение его на стек LD HL,#5BFF ;адрес переключателя ПЗУ на бейсик PUSH HL ;помещение его на стек LD (HL),#C9 ;помещение в озу команды RET LD HL,#5CB5 ;начальный адрес области системных переменных LD BC,#70 ;длина ее RET ;запуск подпрограммы MAKE_ROOM ;Адрес #3D80. Перевод строки. Используется также с адреса #3D82 (печать символа из аккумулятора). Также эта подпрограмма ошибочно используется с адреса #3D8B подпрограммой #4F6. x3D80 LD A,#D ;символ ENTER x3D82 PUSH HL ;сохранение регистров PUSH BC PUSH DE PUSH AF ;сохранение символа CALL x20F1 ;изменение памяти POP AF ;восстановление символа x3D8A CALL x3D94 ;печать символа CALL x20F1 ;восстановление памяти POP DE ;восстановление регистров POP BC POP HL RET ;возврат ;Адрес #3D94. Печать символа без изменения памяти. Символ поместите в аккумулятор. x3D94 RST #20 DW #0010 RET ;Адрес #3D98. Восстановление с ожиданием INTRQ. Используется также с адреса #3D9A (отдача команды из рег.A с ожиданием INTRQ). x3D98 LD A,#08 ;new восстановление x3D9A OUT (#1F),A x3D9C PUSH HL ;сохранение HL RST #20 ;проверка нажатия BREAK DW #1F54 JR C,x3DA5 ;если нажато, то сообщение *BREAK* RST #20 DW #1B7B x3DA5 POP HL ;восстановление HL IN A,(#FF) ;INTRQ поступил? AND #80 JR Z,x3D9C ;если нет, то повтор RET ;возврат ;Адрес #3DAD. Проверка наличия диска в дисководе. Никаких установок не требуется. x3DAD LD A,#08 ;new команда восстановления CALL x3D9A ;выдача команды и ожидание INTRQ LD DE,0 ;за #10000 проходов индексный сигнал должен измениться IN A,(#1F) ;берем индексный сигнал для образца AND 2 LD B,A ;запоминаем его x3DBA IN A,(#1F) ;берем его снова AND 2 CP B ;он изменился? RET NZ ;если да, то возврат INC DE ;следующая попытка LD A,E ;попытки кончились OR D JR NZ,x3DBA ;если нет, то повтор JP x16F9 ;обработка ошибки NO DISC ;Адрес #3DC8. Выбор дисковода, определенного по умолчанию. Вход: можно установить время перемещения головки и режим дисковода согласно описанию команды #01. Выход: эти переменные могут быть изменены согласно этому описанию. Используется также с адресов: ;#3DCB - выбор дисковода. Номер задайте в рег.A, остальное как и для предыдущей подпрограммы. ;#3DFD - задержка в 725779 тактов. ;#3DFF - задержка любой нужной длительности. В рег.A установите число, определяющее длительность задержки. x3DC8 LD A,(#5D19) ;берем номер дисковода по умолчанию x3DCB call x0901 ; LD (#5CF6),A ;установка номера выбранного дисковода LD HL,#5D16 ;выбор дисковода LD C,A LD A,#3C OR C OUT (#FF),A LD (HL),A CALL x3E08 ;берем время перемещения головки дисковода AND #80 ;бит 7 выключен? JR Z,x3DFA ;если да, то инициализацию не проводим CALL x3DAD ;проверка наличия диска в дисководе CALL x3E16 ;определение времени перемещения головки дисковода CALL x3E11 ;берем тип дисковода CP #82 ;new в этой переменной #FF? JR Z,x3DFA ;new если да, то не определяем его PUSH HL ;сохраняем адрес переменной с типом дисковода CALL x1FCA ;определение количества дорожек дисковода POP HL ;восстановление адреса переменной типа CP #50 ;установка этой переменной LD A,0 JR NZ,x3DF9 LD A,#80 x3DF9 LD (HL),A ;Внимание, ошибка!!! Не проверяется количество сторон дисковода и предполагается, что он односторонний. x3DFA CALL x1E36 ;проверка индексной области диска x3DFD LD A,#50 ;задержка в 327842 тактов x3DFF LD C,#FF x3E01 DEC C JR NZ,x3E01 DEC A JR NZ,x3DFF RET ;возврат ;Адрес #3E08. Выборка времени перемещения головки текущего дисковода. Установите #5CF6. На выходе в A будет время перемещения головки дисковода, а в HL - адрес, по которому оно находится. Используется также с адреса #3E0B (выборка параметра дисковода; в DE поместите адрес таблицы параметров и установите #5CF6; На выходе в A будет параметр, в HL - адрес его ячейки). x3E08 LD DE,#5CFA ;берем адрес таблицы скоростей перемещения головок x3E0B LD HL,(#5CF6) ;смещение равно номеру дисковода ADD HL,DE ;вычисление адреса ячейки с параметром LD A,(HL) ;берем оттуда параметр RET ;возврат ;Адрес #3E11. Выборка типа дисковода. Вход: установите #5CF6. Выход: в A тип дисковода, в HL - адрес его ячейки. x3E11 LD DE,#5CC8 ;берем адрес таблицы типов дисководов JR x3E0B ;выборка параметра и возврат ;Адрес #3E16. Определение времени перемещения головки дисковода. x3E16 CALL x3E08 ;берем адрес ячейки со временем перемещения головки LD B,8 ;начнем с наименьшего LD C,4 ;4 попытки x3E1D LD (HL),B ;установка времени перемещения головки LD A,#08 ;new восстановление CALL x3D9A LD A,#20 ;позиционирование на дорожку #20 LD B,#B CALL x3E44 LD B,(HL) ;берем время перемещения головки LD A,1 ;позиционирование на дорожку 1 с заданным временем CALL x3E44 IN A,(#1F) ;головка на дорожке 0? AND 4 JR NZ,x3E3F ;если да, то ошибка XOR A ;позиционирование на дорожку 0 CALL x3E44 IN A,(#1F) ;головка на дорожке 0? AND 4 RET NZ ;если да, то возврат x3E3F INC B ;увеличение времени перемещения головки на 1 DEC C ;следующая попытка RET Z ;если попытки кончились, то возврат JR x3E1D ;повтор ;Адрес #3E44. Позиционирование. В A поместите физический номер дорожки, в B - время перемещения головки и выберите сторону. x3E44 OUT (#7F),A ;помещение номера дорожки в регистр данных LD A,B ;получение команды позиционирования OR #18 JP x0800 ;отдача команды из рег.A с ожиданием INTRQ ;Внимание!!! Здесь нужно JP #3D9A, т.к. #800 гасит биты скорости перемещения головки дисковода, следовательно позиционирование работает только с быстрой скоростью. ;Адрес #3E4C. Позиционирование. На входе в A должен быть физический номер дорожки, а в B - время перемещения головки дисковода. x3E4C OUT (#7F),A ;загрузка номера дорожки в регистр данных PUSH BC ;сохранение времени перемещения головки дисковода LD B,A ;головка уже спозиционирована? IN A,(#3F) CP B POP BC ;восстановление времени перемещения головки PUSH AF ;сохранение результата проверки LD A,B ;получение команды позиционирования OR #18 CALL x0800 ;отдача команды из рег.A с ожиданием INTRQ ;Внимание!!! Позиционирование осуществляется только с быстрой скоростью перемещения головки, т.к. в #800 используется AND #FC. Для исправления ситуации здесь нужно поставить JP #3D9A. POP AF ;восстановление результата проверки положения головки RET Z ;если головка была спозиционирована, то возврат PUSH BC ;сохранение времени перемещения головки? CALL x3DFD ;задержка в 725779 тактов POP BC ;восстановление времени перемещения головки RET ;возврат ;Адрес #3E63. Позиционирование головки дисковода. Вход: в рег.A установите логический номер требуемой дорожки и установите #5CCD. На выходе #5CCD обнуляется. Используется также с адреса: ;#3EA0 (задержка в 3135098 тактов). x3E63 LD C,A ;загрузка номера дорожки в регистр C CALL x0A01 ;выбор верхней стороны диска CALL x3E11 ;берем тип дисковода AND 2 ;дисковод двухсторонний? CALL NZ,x3EAA ;если да, то выбор стороны PUSH BC ;сохраним номер дорожки BIT 7,(HL) ;дисковод 40-дорожечный? JR Z,x3E83 ;если да, то номера дорожек не меняем BIT 0,(HL) ;используем только 40 дорожек? JR NZ,x3E83 ;если нет, то номера дорожек не меняем IN A,(#3F) ;берем номер текущей дорожки CP C ;головка уже спозиционирована? JR Z,x3E82 ;если да, то номера дорожек не меняем RLCA ;делим номер текущей дорожки на 2 OUT (#3F),A LD A,C ;делим номер требуемой дорожки на 2 RLCA x3E82 LD C,A x3E83 CALL x3E08 ;берем время перемещения головки дисковода LD B,A IN A,(#3F) ;головка уже спозиционирована? CP C PUSH BC ;сохраним номер требуемой дорожки CALL NZ,x3DFD ;если головка не спозиционирована, то задержка в 725779 тактов POP BC ;восстановление номера требуемой дорожки LD A,C CALL x3E4C ;позиционирование POP BC ;восстановление номера требуемой дорожки LD A,C ;установка регистра дорожки OUT (#3F),A LD A,(#5CCD) ;нужна задержка после операции? OR A RET Z ;если нет, то возврат XOR A ;в следующий раз задержка не понадобится LD (#5CCD),A x3EA0 LD B,3 ;задержка в 3135098 тактов x3EA2 LD A,#FF CALL x3DFF DJNZ x3EA2 RET ;возврат ;Адрес #3EAA. Выбор стороны при позиционировании. Вход: в C поместите логический номер дорожки и выберите верхнюю сторону диска. Выход: будет выбрана сторона, а в C будет физический номер дорожки. x3EAA LD A,C ;деление номера дорожки на 2 OR A RRA LD C,A RET NC ;если номер дорожки был четный, то возврат JP x1FF6 ;иначе выбор нижней стороны диска ;Адрес #3EB2. Проверка индексной области дорожки. Установите #5CD1 и поместите в B время перемещения головки дисковода. Выбирается верхняя сторона и при ошибке в #5D17 помещается #FF. В регистр H помещается номер текущей дорожки. Используется также с адреса: ;#3EE7 (обработка ошибки NO DISC). x3EB2 CALL x1FEB ;выбор верхней стороны диска x3EB5 IN A,(#1F) ;берем состояние контроллера AND #80 ;сохранение флага готовности LD (#5CCD),A IN A,(#3F) ;берем номер текущей дорожки LD H,A ;на случай возврата CALL x3C0D ;преобразование и выполнение команды из рег.B ;Внимание!!! Перед CALL #3E44 в регистр B надо поместить время перемещения головки дисковода, иначе команда, которая выполнится перед проверкой зависит от содержимого регистра B на входе в подпрограмму и последствия могут быть весьма плачевными. LD C,#7F ;адрес регистра данных LD D,1 ;число, определяющее количество попыток DI ;запрет прерываний LD A,#C0 ;чтение индексной области OUT (#1F),A PUSH BC ;сохранение адреса регистра данных LD B,3 ;определяем количество попыток x3ECE IN A,(#FF) ;берем состояние сигналов DRQ и INTRQ AND #C0 JR NZ,x3EF2 ;если какой-нибудь сигнал поступил, то начало чтения INC DE ;следующая попытка LD A,E OR D JR NZ,x3ECE DJNZ x3ECE ;повтор до конца попыток POP BC ;восстановление адреса регистра данных EI ;разрешение прерываний LD A,#D0 ;остановка контроллера OUT (#1F),A LD A,(#5CD1) ;ошибку игнорировать? ;Ошибка!!! Надо LD A,(#5D17). CP #FF RET Z ;если да, то возврат x3EE7 CALL x272B ;установка TAPE LOADING ERROR LD A,#FF ;в следующий раз ошибку игнорировать LD (#5D17),A JP x271B ;обработка ошибки NO DISC x3EF2 POP BC ;восстановление адреса регистра данных IN H,(C) ;чтение первого байта x3EF5 IN A,(#FF) ;ожидание какого-нибудь сигнала AND #C0 JR Z,x3EF5 EI ;на случай возврата ;Ошибка!!! Так можно потерять байт при чтении. RET M ;если поступил INTRQ, то возврат DI ;запрет прерываний IN A,(#7F) ;чтение байта JR x3EF5 ;повтор ;Адрес #3F02. В комментариях не нуждается. x3F02 LD (#5CFF),A RET ;Адрес #3F06. Похоже на предыдущее. x3F06 LD (#5D00),HL RET ;Адрес #3F0A. Запись сектора. Спозиционируйте головку и установите #5CFF и #5D00. x3F0A LD A,#A0 ;команда записи сектора JR x3F10 ;переход к подпрограмме чтения / записи сектора ;Адрес #3F0E. Загрузка сектора. Установите #5CFF и #5D00 и спозиционируйте головку. Используется также с адреса: ;#3F10 (загрузка/запись сектора; установите все для #3F0E плюс в A поместите команду чтения или записи сектора). x3F0E LD A,#80 ;команда чтения сектора x3F10 LD (#5CFE),A ;установка команды x3F13 LD D,#A ;10 попыток x3F15 PUSH DE ;сохранение счетчика попыток DI ;запрет прерываний LD A,(#5CFF) ;установка сектора INC A OUT (#5F),A call x0853 ; LD HL,(#5D00) ;берем адрес чтения/записи LD C,#7F ;берем адрес регистра данных LD A,(#5CFE) ;отдаем команду OUT (#1F),A CP #A0 ;была команда записи сектора? PUSH AF CALL Z,x3FBA ;если да, то запись данных POP AF CALL NZ,x3FD5 ;иначе чтение данных POP DE ;восстановление счетчика попыток EI ;разрешение прерываний IN A,(#1F) ;берем состояние контроллера LD B,A ;сохраняем его AND #7F ;все в порядке? RET Z ;если да, то возврат x3F39 LD HL,x29D8 ;адрес сообщения READ ONLY AND #40 ;запрещена запись? JR NZ,x3F4B ;если да, то переход на обработку ошибки LD A,B ;восстановление состояния контроллера AND 4 ;была потеря данных? JR Z,x3FA0 ;если нет, то обработка дисковых ошибок DEC D ;следующая попытка JR NZ,x3F15 ;если попытки не кончились, то повтор x3F48 LD HL,x29E2 ;адрес сообщения DISC ERROR x3F4B LD A,#D0 ;команда прерывания OUT (#1F),A LD A,B ;восстановление состояния контроллера AND 1 ;контроллер был занят? JP NZ,x3EE7 ;если да, то обработка ситуации NO DISC IN A,(#3F) ;если ошибка произошла в секторе #A дорожки OR A ;0, то возврат (игнорирование) JR NZ,x3F5F IN A,(#5F) CP #A RET Z x3F5F PUSH HL ;сохранение адреса сообщения CALL x1D97 ;очистка экрана POP HL ;восстановление адреса сообщения RST #18 ;печать сообщения LD HL,x2A13 ;печать TRK: RST #18 IN A,(#3F) ;печать номера дорожки CALL x1DA3 LD HL,x2A18 ;печать SEC: RST #18 IN A,(#5F) ;печать номера сектора CALL x1DA3 LD HL,x29FE ;печать RETRY,ABORT,IGNORE? RST #18 x3F7B CALL x1052 ;ввод клавиши CP "I" ;нажато I? RET Z ;если да, то возврат CP "R" ;нажато R? JR Z,x3F94 ;если да, то перепозиционирование и повтор CP "A" ;нажато A? JR NZ,x3F7B ;если нет, то повтор ввода клавиши CALL x272B ;установка TAPE LOADING ERROR LD A,7 ;дисковая ошибка LD (#5D0F),A JP x01D3 ;завершение x3F94 LD A,(#5CF5) ;перепозиционирование CALL x3E63 CALL x3EA0 ;задержка в 3135098 тактов JP x3F13 ;повтор ;Ошибка!!! Надо JP #3F13 для того, чтобы обновить число попыток. x3FA0 DEC D ;следующая попытка JP Z,x3F48 ;если попытки кончились, то обработка DISC ERROR PUSH DE ;сохранение счетчика попыток CALL x3E08 ;берем время перемещения головки дисковода AND 2 ;оно равно #A? JR NZ,x3FAD INC (HL) ;если нет, то увеличение его на 1 x3FAD CALL x08A7 ;восстановление LD A,(#5CF5) ;перепозиционирование CALL x3E63 POP DE ;восстановление счетчика попыток JP x3F15 ;повтор ;Адрес #3FBA. Запись данных на диск. Установите в HL адрес блока данных, в DE - число, определяющее количество циклов, за которое должна начаться запись, в C - адрес регистра данных контроллера и отдайте команду записи. Используется также с адреса #3FCA (то же, что и #3FBA, но без обработки NO DISC). x3FBA LD B,4 ;установка количества попыток x3FBC IN A,(#FF) ;поступил какой-нибудь сигнал? AND #C0 JR NZ,x3FD1 ;если да, то начинаем запись INC DE ;следующая попытка LD A,E OR D JR NZ,x3FBC DJNZ x3FBC RET ;если попытки кончились, то возврат x3FCA IN A,(#FF) ;поступил какой-нибудь сигнал? AND #C0 JR Z,x3FCA ;если нет, то ожидание его RET M ;если поступил INTRQ, то возврат x3FD1 OUTI ;вывод байта из вашей области в регистр данных JR x3FCA ;повтор ;Адрес #3FD5. Чтение данных с диска. Все установки аналогично подпрограмме #3FBA, но отдать нужно команду чтения. Используется также с адpеса #3FE5 (то же, что и #3FD5, но без обработки NO DISC). x3FD5 LD B,4 ;установка количества попыток x3FD7 IN A,(#FF) ;поступило что-нибудь? AND #C0 JR NZ,x3FEC ;если да, то начинаем читать INC DE ;следующая попытка LD A,E OR D JR NZ,x3FD7 DJNZ x3FD7 RET ;если попытки кончились, то возврат x3FE5 IN A,(#FF) ;поступил какой-нибудь сигнал? AND #C0 JR Z,x3FE5 ;если нет, то ждем его RET M ;если это INTRQ, то возврат x3FEC INI ;чтение байта JR x3FE5 ;повтор ;АДРЕС: #3FF0 вывод в порт x3FF0 out (c),a ret ;АДРЕС: #3FF3 чтение порта x3FF3 in a,(c) ret x3FF6 DISPLAY "Free space at ",$,": ",/D,#4000-$," byte(s)" ds #4000-$,#FF SAVEBIN "../Build/scorp/NewROM3_Tr-Dos.bin",#0000,#4000