;Source code of TR-DOS 6.11Q for SjASMPlus ;07.03.2020 - modified by Mario Prato including support for 512K Pentagons ;16.1.2013 - modified memory paging routines for more ZX clones VELESOFT ( version 6.11Q ) ;Основано на книге "ПОЛHОЕ ОПИСАHИЕ + ПОЛHЫЙ ДИЗАССЕМБЛЕP ПЗУ TR-DOS 5.04T (5.03) ДЛЯ ПРОФЕССИОНАЛОВ, А ТАКЖЕ ДЛЯ ТЕХ, КТО ХОЧЕТ ИМИ СТАТЬ." ;Автор книги: Федин Павел Юрьевич, 04.04.1996. ;Перевод всех чисел в шестнадцатеричный формат, переформатирование: Spectre, 19.10.2005 ;Патчи до версии 6.11Е: 1999 CompoWellcome, 2006 Alone Coder ;Исправление, переформатирование, наложение патчей: Keeper, 2009 - 2010 :) ;Кодировка: CP-1251 DEVICE ZXSPECTRUM48 ;=========================================== SETUP ================================================== ;------- select only one memory model ------ ; DEFINE RAM_ZX_PROFI_1024 ; DEFINE RAM_PENTAGON_1024 DEFINE RAM_PENTAGON_512 ; DEFINE RAM_SCORPION_1024 ; DEFINE RAM_ZXM_PHOENIX ;------- select for autoboot tr-dos ------ ; DEFINE RUN_BOOT_B_ON_DOS_START ; BOOT_ON_CMD_8 ;------- select for enable testing drives ------- ; DEFINE TEST_DRIVES ;------- select for madrom support ------- ; DEFINE COMPILE_FOR_MADROM ;------- select for active patch for fix HL' register ------- DEFINE FIX_HL ;------- select for enable NMI code ------- ; DEFINE NMI_ENABLE ;------- number of ramdisc drive ------- RMD_DRIVE EQU #03 ;ramdisc on drive A(#00),B(#01),C(#02),D(#03) ;------- ramdisc size (free space) -------- RMD_SIZE EQU #05F0 ;ramdisc size(only free sectors = full capacity - 16 sectors) ;( #0DF0=896kB / #0BF0=768kB / #09F0=640kB / #07F0=512kB / #05F0=384kB / #03F0=256kB / #01F0=128kB ) ;==================================================================================================== ORG 0 IFDEF COMPILE_FOR_MADROM F_PAGE EQU #5C81 ELSE F_PAGE EQU #5B5C ENDIF ;Адрес 0. Полная инициализация системы. x0000 DI LD DE,#FFFF LD A,7 JR x0009 ;Адрес 8. Инициализация системы. В DE поместите адрес вершины памяти, в A - 7 и запретите прерывания. Используется также с адреса 9. x0008 NOP x0009 OUT (#FE),A LD A,#3F 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 NOP NOP NOP JR x0024 ;Адрес #20. Переход к подпрограмме вызова подпрограмм из ПЗУ бейсика. Адрес вызываемой подпрограммы поместите в двух байтах после команды RST #20. Например: x0020 JP x2F72 x0023 RET ;Адрес #24. Инициализация системы. В DE поместите адрес вершины памяти, установите белый бордюр, поместите в A старший байт низшего адреса памяти и запретите прерывания. x0024 LD H,D ;переброска адреса вершины памяти в HL LD L,E JR x002B ;инициализация системы ;Адрес #28. Выборка адреса текущего канала с учетом сдвига, заданного в регистре C. x0028 JP x2323 ;Адрес #2B. Инициализация системы. В DE и HL поместите адрес вершины памяти, установите белый бордюр, поместите в A старший байт низшего адреса памяти и запретите прерывания. x002B XOR A LD B,A LD C,A LD SP,HL JR x003A DISPLAY "Free space at ",$,": ",/D,#0038-$," byte(s)" DS #0038-$, #FF ;Адрес #38. Обработка маскируемого прерывания. x0038 EI RET ;Адрес #3A. Инициализация системы. В DE поместите адрес вершины памяти в HL - адрес дна, установите белый бордюр, заполните обозначенную область памяти байтом 2 и запретите прерывания. x003A PUSH BC,BC,BC,BC PUSH BC,BC,BC,BC LD HL,#A500 ADD HL,SP JR C,x003A 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 IFDEF NMI_ENABLE JP x2A56 ELSE RETN NOP ENDIF ;Адрес #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,#0540 ;установка 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,#0223 ;установка 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 RST #20 ;инициализация буфера принтера и экрана DW #0EDF LD HL,#5C6B ;буфер принтера использовался LD (HL),2 LD HL,#128B ;возвращаться в #128B PUSH HL IFDEF RUN_BOOT_B_ON_DOS_START LD A,#AA ;выполнять команду RUN "boot" ELSE LD A,#00 ENDIF IFDEF COMPILE_FOR_MADROM LD (#5B00),A ELSE LD (#5C81),A ENDIF 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 SETERRAD ;установка адреса подпрограммы обработки ошибок 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 TCH4 ;#399C (VELESOFT - removed to new code...) CALL SHOW_TXT ;(VELESOFT - show new text + jump to TCH4) NOP CALL TEST_R ;#3837 EI JR NZ,$+6 LD HL,TfndRD ;#1000 ;"Found R/D" RST #18 x0271 ;???? "boot" ?????????? IFDEF COMPILE_FOR_MADROM LD A,(#5B00) ELSE LD A,(#5C81) ;файл "boot" запускать? ENDIF 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,x1D1A ;если да, то выдача сообщения "*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 6.11Q*" DB #D,#D DB "2006 Alone,2013 Keeper,Velesoft,2020 Mario" DB #16,5,#B DB "Kharkiv" DB #16,7,5 DB " " 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 ;если да, то установка типа дисковода x040F 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 #10 ;он больше #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 ;проверка достижения конца каталога и возврат ;Адрес #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 JP NEWER L53D 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,x2723 ;если да, то 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 DOSSYM PUSH HL ;jp из #3D82 PUSH BC ;то,что раньше было в #3D82 PUSH DE PUSH AF CALL x20F1 POP AF CALL x3D94 CALL x20F1 POP DE POP BC POP HL RET ASKREPFORM LD A,(#5CF6) ;jp из #1FB6 CP RMD_DRIVE;#03 ;вместо #326B JR Z,LLc848 LD A,#0D RST #10 LD HL,TPressR ;#335E RST #18 CALL x1052 ;ввод клавиши с ожиданием CP #52 JR Z,LLc84b LLc848 JP x01D3 LLc84b RST #20 DW #0D6E ;CLS без чего-то LLc84e RST #20 DW #028E ;KEY_SCAN JR NZ,LLc84e RST #20 DW #31E ;K_TEST JR C,LLc84e JP wFORMAT ;продолжение... DISPLAY "Free space at ",$,": ",/D,#900-$," byte(s)" DS #900-$,#FF x900 DS 257,#FF ;родионовский вектор прерывания MAGSTOPDISK LD A,#3C ;call из #2A6F OUT (#FF),A ;вместо out (#ff),#3c LD A,#D0 ;надо JP #2FC1 OUT (#1F),A RET MAGregR LD (#5C01),A ;jp из #2EBF ;зачем 5C01?почему не коррекция сложением? POP AF JP x2EC2 MAGsetR LD A,(#5C01) ;jp из #2F03 LD R,A POP AF JP #5C00 MAGICER PUSH AF ;jp из #2A56 ;вместо push af,bc,de LD A,R BIT 7,A JR Z,LL8a27 SUB #1F SET 7,A JR LL8a2b LL8a27 SUB #1F RES 7,A LL8a2b PUSH AF LL8a45 LD A,#F7 IN A,(#FE) RRCA JR NC,MAG1 RRCA JR NC,MAG2 RRCA JR NC,MAG3 RRCA JR C,LL8a45 POP AF ;MAGIC+"4"=EXIT BIT 7,A ;надо RLCA:ADD A,#17*2:RRCA JR Z,LL8a60 ADD A,#17 SET 7,A JR LL8a64 LL8a60 ADD A,#17 RES 7,A LL8a64 LD R,A POP AF RETN MAG1 POP AF ;MAGIC+"1"=стандарт LD R,A POP AF JR LL8a78 MAG2 POP AF ;MAGIC+"2"=стек внизу экрана POP AF LD (#57FE),SP LD SP,#5800 LL8a78 PUSH AF PUSH BC PUSH DE JP x2A59 MAG3 POP AF ;MAGIC+"3"=STS#57 LD R,A PUSH HL LD HL,0 ADD HL,SP INC HL INC HL LD A,H POP HL CP #C0 JR NC,LL8ac4 LD A,R BIT 7,A ;надо RLCA:SUB 9*2:RRCA JR Z,LL8a9a SUB 9 SET 7,A JR LL8a9e LL8a9a SUB 9 RES 7,A LL8a9e LD R,A PUSH BC LD BC,#FFFD LD A,#07 OUT (C),A LD B,#BF LD A,#FF OUT (C),A ;глушит AY LD A,#57 LD BC,#7FFD OUT (C),A POP BC POP AF EX (SP),HL LD (#FEE4),HL LD (#FEFE),HL EX (SP),HL LL8abf INC SP INC SP JP #DB00 LL8ac4 LD A,R BIT 7,A ;надо RLCA:SUB #15*2:RRCA JR Z,LL8ad0 SUB #15 SET 7,A JR LL8ad4 LL8ad0 SUB #15 RES 7,A LL8ad4 LD R,A POP AF LD (#5800),SP EX (SP),HL LD (#5802),HL EX (SP),HL LD SP,#5808 PUSH AF PUSH BC LD BC,#FFFD LD A,#07 OUT (C),A LD B,#BF LD A,#FF OUT (C),A ;глушит AY LD A,#57 LD BC,#7FFD OUT (C),A POP BC POP AF LD SP,(#5800) LD (#C000),HL LD HL,(#5802) LD (#FEE4),HL LD (#FEFE),HL LD HL,(#C000) JR LL8abf IFDEF BOOT_ON_CMD_8 bootkus1 DISP #F500 DI ;его и #344D копирует #3AE7 PUSH AF PUSH HL PUSH DE PUSH BC EXX PUSH HL LD HL,(#5C3D) LD (#F632),HL LD A,(#5D19) LD (#5CF6),A ADD A,#3C LD (#5D16),A LD HL,#3C00 LD DE,#8000 PUSH DE LD (#5C36),DE LD BC,#0400 LDIR LD (IY+#47),#00 POP HL LD BC,#0080 LL0e30 PUSH BC INC HL INC HL INC HL LD B,#03 LL0e36 LD D,(HL) LD A,D RLA OR D LD (HL),A INC HL DJNZ LL0e36 POP BC DEC BC INC HL INC HL LD A,B OR C JR NZ,LL0e30 XOR A OUT (#FE),A LD A,#44 LD (#5C48),A DEC A DEC A LD (#5C8D),A CALL #0D6B LL0e56 DI XOR A LD (#F86E),A LD HL,#FA09 PUSH HL LD (#5C3D),SP LD (IY+#00),#FF LD A,(#5D19) LD C,#01 CALL #3D13 LD HL,#9000 LD DE,#0000 LD BC,#0805 CALL #3D13 LD A,(IY+#00) CP #FF JR NZ,LL0e56 LD HL,#F556 LD (#F55C),HL EXX LD DE,#A000 EXX LD HL,#9000 LD DE,#0008 LD A,(HL) OR A JP Z,#F887 LL0e98 LD DE,#0008 ADD HL,DE LD A,(HL) CP #42 CALL Z,#F836 ADD HL,DE LD A,(HL) OR A JR NZ,LL0e98 LD A,(#F86E) OR A JP Z,#F887 LD B,#3F SBC A,B JP NC,#F8A6 LD A,(#F86E) DEC A LD (#F86F),A CALL #F9BB LD (#F653),A CALL #0D6B DI CALL #F870 LD A,#02 CALL #F8CB LD A,#02 CALL #1601 LD (IY+#47),#00 LD DE,#A000 LD HL,#0008 LL0edc LD A,#20 RST #10 LD A,#20 RST #10 LD BC,#0008 PUSH DE CALL #203C POP DE EXD ADC HL,DE EXD LD A,(#F86E) DEC A LD (#F86E),A JR Z,LL0f35 LD A,#20 RST #10 LD A,#20 RST #10 LD BC,#0008 PUSH DE CALL #203C POP DE EXD ADC HL,DE EXD LD A,(#F86E) DEC A LD (#F86E),A JR Z,LL0f35 LD A,#20 RST #10 LD A,#20 RST #10 LD BC,#0008 PUSH DE CALL #203C POP DE EXD ADC HL,DE EXD LD A,(#F86E) DEC A LD (#F86E),A JR Z,LL0f35 LD A,#06 RST #10 JR LL0edc NOP NOP NOP LL0f35 LD HL,#5802 CALL #F816 LD DE,#000A LD IX,#F634 LD (IX+#00),#00 LL0f46 EI RES 5,(IY+#01) HALT PUSH HL PUSH IX CALL #F9BB CP #40 JP NZ,#F792 CALL #F989 POP IX POP HL BIT 5,(IY+#01) JR Z,LL0f46 LD A,(#5C08) CP 8 JP Z,#F6ED CP "o" JR Z,LL0fed CP "6" JR Z,LL0fed CP 9 JP Z,#F70C CP "p" JP Z,#F70C CP "7" JP Z,#F70C CP 11 JP Z,#F72E CP "q" JP Z,#F72E CP "9" JP Z,#F72E CP 10 JP Z,#F764 CP "a" JP Z,#F764 CP "8" JP Z,#F764 CP "d" JP Z,#FA1B CP "1" JR Z,LL0fd0 CP "2" JR Z,LL0fd0 CP "3" JR Z,LL0fd0 CP "4" JR Z,LL0fd0 PUSH AF LD A,#FE IN A,(#FE) RRA JR NC,LL0f46 POP AF CP 13 JP Z,#F79D CP "0" JP Z,#F79D CP 32 JP Z,#F79D JP #F646 LL0fd0 PUSH AF CALL #0D6B LD A,#03 CALL #F8CB POP AF SUB #31 LD C,#01 LD (#5CF8),A LD (#5CF9),A LD (#5D19),A CALL #3D13 JP #F556 LL0fed CALL #F870 CALL #F826 DEC (IX) bootst2 ENT bootln1=$-bootkus1 ENDIF ; DISPLAY "Free space at ",$,": ",/D,#1018-$," byte(s)" ; DS #1018-$,#FF DISPLAY "Free space at ",$,": ",/D,#1000-$," byte(s)" DS #1000-$,#FF TfndRD DB #16,#0A,5 DB "Found RAMDISK memory",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 ;установка атрибутов LD B,#E ;(VELESOFT - black attributes size) 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 HL,#40F2 ;(VELESOFT - new position for rainbow) 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 ;сохранение его 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 x040F ;иначе "Disk 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 номера файла x1665 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. ;быстрое MOVE x16AB CALL x042B ;проверка 2-го символа комстроки JP NZ,LL1775 ;не ENTER (а зачем эта ветка???) ;несовместимость:эта точка,указанная Фединым,теперь требует Z CALL x1D75 ;выйти,если проверка синтаксиса CALL x166F ;резервирование памяти в WORKSP LD HL,(#5CCF) LD (#5CE1),HL LD DE,#0900 ADD HL,DE LD (#5CCF),HL LD A,(#5D23) SUB D LD (#5D23),A LD HL,(#5CE1) LD B,D LD D,E CALL x1E3D ;LOAD SECTORS LD HL,(#5CE1) LD (#5CDF),HL LD HL,#0100 LD (#5CD7),HL LD (#5CDD),HL ;??? XOR A LD (#5CE3),HL LD (#5CE4),A CALL MOVEPP ;#3B00 LD HL,(#5CE1) LD DE,(#5CDF) LD BC,#0800 ADD HL,BC SCF SBC HL,DE LD C,L LD B,H LD H,D,L,E INC DE LD (HL),#00 LDIR LD HL,(#5CE1) LD DE,#08E1 ADD HL,DE LD E,(HL) INC HL LD D,(HL) LD BC,(#5CD7) LD (HL),B DEC HL LD (HL),C INC HL INC HL INC HL INC HL LD C,(HL) INC HL LD B,(HL) EXD LD A,L AND #0F LD L,H LD H,#00 ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD A,L LD L,A ADD HL,BC LD BC,(#5CD7) LD (#5CD7),HL LD L,B LD H,#00 ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD A,C AND #0F ADD A,L LD C,A LD B,H LD HL,(#5CD7) AND A SBC HL,BC EXD LD (HL),D DEC HL LD (HL),E DEC HL LD A,(#5CE3) LD (HL),A LD DE,#0010 ADD HL,DE LD (HL),D LD HL,(#5CE1) LD E,D LD B,#09 CALL x1E4D LD A,(#5D23) ADD A,#09 LD B,A LD C,#00 LD HL,(#5CCF) CALL x1E2E ;удаление обл.памяти HL=beg,BC=len JP x03E1 ;"O.K." LL1775 CALL x1DDF ;MOVE с параметром (имя диска) ;уст.CH_ADD и помещ.строки на стек кальк-ра CALL x1D75 ;выйти,если проверка синтаксиса CALL x1C57 ;установка имени файла CALL x03FD ;загрузка t0s8 в буфер LD HL,#5CDD LD DE,#5E1A LD BC,#0008 LDIR ;копируем имя диска CALL x1E43 ;запись только что юзанного сектора из буфера JP x03E1 ;"O.K." DISPLAY "Free space at ",$,": ",/D,#17A5-$," byte(s)" DS #17A5-$,#FF ;Адрес #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 CALL PARAMZAG ;#33CE 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 (#5D15),A ;флаг сост.раб.области 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 ;установка имени и поиск файла CALL Z,LL3343 ;перенос опис.из буф.в пам.и вкл.Overwr=ON 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 SAVER ;#33F5 ;запись файла 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 x1BBF 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 B ;проверка BC=0 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) IFDEF FIX_HL JP PATCH_HL ;(VELESOFT) - jump to new patch for fix value of register HL' ELSE JR NZ,x1D19 ;если нет, то возврат DEC HL ;установка ERR_SP на адрес ниже ENDIF 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 x3EB2 ;определение номера дорожки, на которой стоит головка 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 ;и адреса загрузки / записи JP TCH1 ;#3800 TCH1Q 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 TCH3 ;#3921 wFORMAT CALL SELFORMAT ;#3378 AND #80 ;дисковод 40-дорожечный? LD A,#28 ;форматировать 40 дорожек JR Z,x1EE8 ;если дисковод 80-дорожечный, LD A,#50 ;то форматировать 80 дорожек x1EE8 LD (#5CD7),A ;установка количества дорожек CALL x3D98 ;восстановление CALL x1FF6 ;выбор нижней стороны диска CALL x3EA0 ;задержка в 3135098 тактов CALL x1EBC ;SCF:(23766),0(команда не принята анализ-ром) LD A,(#5CDD) CP #24 JR Z,x1F1B JR x1F16 DISPLAY "Free space at ",$,": ",/D,#1F16-$," byte(s)" DS #1F16-$,#FF x1F16 LD A,#80 ;форматировать обе стороны диска LD (#5CDA),A x1F1B CALL FORMDISK ;#334C 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 x1FEB ;выбор верхней стороны диска 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 ASKREPFORM ;#833 ;Адрес #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,(#5CE6) ;берем адрес таблицы секторов для форматирования 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 CALL SUB14 ;#33BE ;HL=HL-14 (???) 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 LD HL,#5CD7 ;берем число форматируемых дорожек LD B,(HL) CALL CHECKON ;#32EA ;XOR A:(+HL)=(#5CE8) LD E,#FF ;начнем с дорожки 0 x20C6 PUSH BC ;сохранение количества дорожек INC E ;следующая дорожка LD A,E LD B,#1B ;позиционирование CALL POSIT ;#3224 CALL x1FEB ;выбор верхней стороны диска CALL PRHD0 ;#32F6 LD A,(#5CDA) ;берем флаг количества сторон CP #80 ;форматировать 2 стороны? JR NZ,x20E1 ;если да, то CALL x1FF6 ;выбор нижней стороны диска CALL PRHD1 ;#32F1 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 (IY),#FF EI JP GETCOM ;#3B80 ;Адрес #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 ;пров.дор.,если (#5CD8)=0 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 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 OUTDE ;#3C10 ;OUT (D),E DB #E DW x290F DB #F DW INED ;#3C14 ;IN E,(D) DB #10 DW JPWRITE ;#3C18 ;C=#7F:16314(WRITE) DB #11 DW JPREAD ;#3C1D ;C=#7F:16341(READ) 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 ;установка длины файла для каталога JP SVNASTRDSK ;#33E6 CALL x1AC4 ;проверка наличия свободного места в каталоге JP SAVEFIL ;запись файла ;Адрес #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 "Disk 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 MAGICER ;#A1A 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 CALL MAGSTOPDISK ;#A01 ;там еще OUT (#1F),#D0 NOP 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 ;адрес переменной с кодом текущего банка памяти x2B77 LD (HL),D ;установка банка OUT (C),D ;выбор банка XOR A ;начало вычисления контрольной суммы страницы LD HL,#C000 ;адрес страниц ОЗУ x2B7E ADD A,(HL) ;прибавление к сумме очередного байта INC HL ;адрес следующего байта LD E,A ;сохранение контрольной суммы LD A,H ;берем старший байт текущего адреса в странице OR A ;это 0? LD A,E ;восстановление контрольной суммы JR NZ,x2B7E ;если нет, то повтор LD HL,#4100 ;адрес переменной с контрольной суммой текущей страницы CP (HL) ;суммы совпадают? INC HL ;адрес переменной с кодом текущего банка памяти JR Z,x2B93 ;если да, то все INC D ;следующая страница ОЗУ BIT 3,D JR Z,x2B77 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 JP MAGregR ;#A0A ;LD (#5C01),A:POP AF x2EC2 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 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 JP MAGsetR ;#A11 ;R=(#5C01) NOP ;Адрес #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 x3D30 ;RET LD A,#18 ;команда позиционирования 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,8 ;команда восстановления 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,#FFFF LD (#5CFA),HL ;типы дисководов неизвестны LD (#5CFC),HL 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,KILLREZ,x2DA1 DW x29AE DW x11CE,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 ;возврат KILLREZ CALL CLEAR JP x03E1 ;"O.K." CLEAR LD A,#D7 LD BC,#7FFD OUT (C),A LD (#C000),A LD (#FFF0),A LD A,#10 OUT (C),A RET DISPLAY "Free space at ",$,": ",/D,#321C-$," byte(s)" DS #321C-$,#FF SETERRAD LD A,#0D ;call из #246 ;вместо #21D LD (#5D20),A JP x021D POSIT PUSH HL ;call из #20CC ;вместо #3E44 PUSH BC PUSH AF PUSH DE LD A,#ED LD (#5C86),A LD A,#0C LD (#5C8A),A LD A,E JR LL323d LL3235 LD A,(HL) CP #FF RET Z RST #10 INC HL JR LL3235 LL323d LD B,"0" LL323f SUB 10 JR C,LL3246 INC B JR LL323f LL3246 PUSH AF LD A,B RST #10 POP AF ADD A,"0"+10 RST #10 POP DE POP AF POP BC POP HL EI JP x3E44 ;позиционирование TFormTS DB "Format track Side",0 TFile DB #16,0,0 DB "File ",34 DB #13,1,#FF TExists DB #13,0 DB 34,#D DB "Exists!Overwrite?(Y/N/Add)" DB #FF TComplete DB "Complete" DB #D DB "Name:",0 TFORMAT DB "FORMAT: 1 - Normal " DB #D,#17,#A DB " 2 - Turbo" DB #D,#17,#A DB " 3 - Fast turbo" DB 0 CHECKON INC HL ;call из #20C1 ;вместо XOR A:INC HL:LD (HL),A ;#5CD8 LD A,(#5CE8) LD (HL),A XOR A RET PRHD1 PUSH AF ;call из #20DE ;вместо #330F LD A,"1" JR LL32f9 PRHD0 PUSH AF ;call из #20D2 ;вместо #32DD LD A,"0" LL32f9 PUSH AF LD A,#F8 LD (#5C86),A LD A,#17 LD (#5C8A),A POP AF RST #10 POP AF JP x1FFD ;форматирование дорожки LL330a CALL x1D9F ;кнопка для Overwrite ;очистка низа экрана LD HL,TFile CALL LL3235 CALL LL3329 LD HL,TExists CALL LL3235 LD HL,#4000 LL331f DEC HL LD A,H OR L JR NZ,LL331f CALL x1052 ;ввод клавиши с ожиданием JR LL3338 LL3329 LD A,(#5CF6) ADD A,"A" RST #10 LD A,":" RST #10 LD HL,#5CDD ;адрес имени JP x2938 ;печать имени с расширением LL3338 PUSH AF CALL x1D9F ;очистка низа экрана POP AF CP "Y" RET Z CP "A" ;#D RET LL3343 CALL x165D ;если при записи есть такой файл ;из 1AC1, SVNASTRDSK ;перенос описателя из буфера в память LD HL,#5CE5 SET 7,(HL) ;включает overwrite=ON RET FORMDISK CALL x1D9F ;call из #1F1B ;вместо #20BD ;очистка низа экрана LD HL,TFormTS RST #18 CALL x20BD ;форматирование диска CALL x1D9F ;очистка низа экрана LD HL,TComplete RST #18 RET TPressR DB "Press R to repeat",("."+#80),0 ;для ASKREPFORM SAVEFIL CALL x1D9F ;очистка низа экрана ;jp из #290C ;еще jr ниже ;вместо #1B53 CALL x3E11 ;выборка типа дисковода RET SELFORMAT CALL x1D9F ;очистка низа экрана ;call из #1EDD ;вместо #3200 LD HL,TFORMAT RST #18 LL337f CALL x1052 ;ввод клавиши с ожиданием CP #11 JR Z,LL3395 CP #12 JR Z,LL33a1 CP #13 JR Z,LL33a6 CP 0 JP Z,x01D3 ;п/п завершения JR LL337f LL3395 LD HL,x1FB9 ;табл.секторов SLOW диска LL3398 XOR A LL3399 LD (#5CE8),A LD (#5CE6),HL JR SAVEFIL LL33a1 LD HL,LL33ad ;табл.сект.FAST JR LL3398 LL33a6 LD A,#01 LD HL,LL33ad ;табл.сект.FAST JR LL3399 LL33ad DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1 ;надо #325A SUB14 LD A,L SUB #0E LD L,A RET NC DEC H RET PARAMZAG LD A,(#5CE5) ;call из #18AB ;вместо a,(#5CD6) ;якобы фикс PEEK, но заглючивает Wolfed CP "B" JR Z,LL33e2 CP "D" JR Z,LL33e2 CP "#" JR Z,LL33e2 LD A,"C" LL33e2 LD A,(#5CD6) RET SVNASTRDSK CALL x1CF0 ;поиск файла CALL Z,LL3343 ;перенос опис.из буф.в пам.и вкл.Overwr=ON LL33ec CALL x0405 ;настр.на диск.Меняет перем-ю с типом диск-да CALL x1AC4 ;проверка =128 файлов JP x1B53 ;запись файла и инфы о нем SAVER LD HL,#5CE5 ;тип файла + "file exist" flag ;call из #1B53 ;было #1B59 BIT 7,(HL) RES 7,(HL) JP Z,x1B59 LL33ff CALL LL330a ;Y/N JP NZ,x01D3 ;п/п завершения CP "A" JP Z,x1B59 LD DE,(#5CD9) DEC DE INC D LD A,(#5CEA) CP D JR Z,LL341b CALL x2926 ;стирание файла JR LL33ec LL341b LD B,D LD HL,(#5C59) LD (HL),#AA INC HL LD DE,(#5CD1) LD (HL),E INC HL LD (HL),D LD C,#06 LD HL,(#5CDB) LD (#5CE8),HL LD HL,(#5CD7) LD (#5CE6),HL LD DE,(#5CEB) CALL x1E4D LD BC,(#5D1E) CALL x1BBF CALL x1665 RET OBROSH EI ;jp из #3D17 ;вместо #2F69 JP x2F69 POSITPP PUSH AF ;jp из #3E4E LD A,(#5CCE) ;0=READ,#FF=WRITE OR A JR Z,POSppRD POP AF PUSH BC LD B,A IN A,(#3F) CP B ;в #3E52 это уже есть! POP BC JP POSITCONT ;#3E54 POSppRD POP AF IN A,(#1F) AND #80 JP POSITCONT ;#3E54 PPNORESC000 LD HL,#FFF0 ;если нет резидента #C000 ;jp из #3C48 ;проверка резидента #FFF0 XOR A LL379e XOR (HL) ADC A,H INC L JR NZ,LL379e CP #06 ;"RESIDENTPRESENT!" ;идиотизм - опять 8bit! JP Z,#C000 XOR A CALL MEMDRV_ LD B,#13 ;проверка недокументированного резидента #5B00 LD H,#5B XOR A LL37b1 XOR (HL) ADC A,L ADC A,(HL) INC L DJNZ LL37b1 CP #68 ;идиотизм - опять 8bit! LD A,7 JP NZ,x0009 XOR A LD (#5B04),A LD (#5B0D),A IFDEF COMPILE_FOR_MADROM LD HL,#FE00 ELSE LD HL,#00C7 ENDIF LD (#5B11),HL JP #5B00 USEmovSPD PUSH HL ;вместо #3E44 ;call из #3EBF PUSH AF CALL x3E08 ;взять время перемещ.головки тек.дисковода LD B,A POP AF POP HL JP x3E44 NEWER LD HL,(#5D11) ;вместо #1DCD INC HL LD A,(HL) CP #D JR Z,NEWRel CALL x1DCD ;NEW new,old JP L53D NEWRel LD HL,TRel RST #18 JP x01D3 ;п/п завершения TRel DB "Rel: 03.04.10",#D,0 TCH1 LD A,(#5CF6) ;1-ая основная точка входа CP RMD_DRIVE;#03 JR Z,L1 LD A,(#5CCE) CALL x1E36 ;загрузка регистра дорожки JP TCH1Q ;#1E70 L1 PUSH DE CALL TEST_R JP NZ,x3EE1 ;NO DISK POP DE,HL,BC XOR A OR B RET Z RD_SV PUSH BC,HL CALL SECTR POP HL INC H PUSH HL LD HL,#5CF4 LD A,#10 INC (HL) CP (HL) JR NZ,LL3838 LD (HL),#00 INC HL,(HL) LL3838 POP HL,BC DJNZ RD_SV RET ;Тест наличия Ram-Disk'а ;точнее, памяти под него ;для 128K - вроде как дисковод D TEST_R DI LD A,#08 LD B,#83 L2 PUSH AF LD (#5CFD),A LD A,B LD (#5CCB),A XOR A OUT (#FF),A LD A,(#5CF6) ADD A,#3C LD (#5D16),A OUT (#FF),A LD A,#D0 OUT (#1F),A POP AF EI RET SECTR LD DE,(#5CF4) LD A,H CP #BF JR C,RED_SAV LD A,#FF CALL LL38A6 LD A,(#5CCE) AND A JR Z,LL38C0 LD DE,#5D25,BC,#0100 LDIR LD HL,#5D25,DE,(#5CF4) CALL RED_SAV LL38A4 LD A,#00 LL38A6 EXA LD A,(#5CCE) EXA LD (#5CCE),A PUSH HL,DE LD HL,#5D25,DE,#000F CALL RED_SAV POP DE,HL EX AF,AF' LD (#5CCE),A RET LL38C0 PUSH HL LD HL,#5D25 CALL RED_SAV LD HL,#5D25 POP DE LD BC,#0100 LDIR JR LL38A4 RED_SAV DI ;Собственно чтение-запись из/в RAM-DISK CALL FPG ;ищем тек.страницу на каждом секторе... LD A,D ;лог.дорожка CPL ;растет сверху RRCA AND #FE LD C,A LD B,0 PUSH IX LD IX,PG_TAB ADD IX,BC ; LD BC,#1FFD ;(VELESOFT - zxm phoenix 2048 port 1FFD) IFDEF RAM_ZX_PROFI_1024 LD BC,#0DFFD ;(VELESOFT - ZX PROFI 1024 port DFFD) ENDIF IFDEF RAM_PENTAGON_1024 LD BC,#7FFD ;(VELESOFT - PENTAGON 1024 port 7FFD) ENDIF IFDEF RAM_PENTAGON_512 LD BC,#7FFD ;(MARIO - PENTAGON 512 port 7FFD) ENDIF IFDEF RAM_SCORPION_1024 LD BC,#1FFD ;(VELESOFT - SCORPION 1024 port 1FFD) ENDIF IFDEF RAM_ZXM_PHOENIX LD BC,#1FFD ;(VELESOFT - ZXM PHOENIX port 1FFD) ENDIF LD A,(IX) OUT (C),A INC IX ; LD B,#7F ;(VELESOFT - remove this instruction) LD BC,#7FFD ;(VELESOFT - BC = full 16bit adress) LD A,(IX) OUT (C),A LD A,D RLCA RLCA RLCA RLCA AND #30 ADD A,E OR #C0 LD D,A,E,#00 LD A,(#5CCE) AND A JR NZ,LL38F9 EX DE,HL LL38F9 LD BC,#0100 LDIR LD D,0 LD A,(#5C81) LD E,A LD HL,PG_TAB ADD HL,DE ; LD BC,#1FFD ;(VELESOFT - zxm phoenix 2048 port 1FFD) IFDEF RAM_ZX_PROFI_1024 LD BC,#0DFFD ;(VELESOFT - ZX PROFI 1024 port DFFD) ENDIF IFDEF RAM_PENTAGON_1024 LD BC,#7FFD ;(VELESOFT - PENTAGON 1024 port 7FFD) ENDIF IFDEF RAM_PENTAGON_512 LD BC,#7FFD ;(MARIO - PENTAGON 512 port 7FFD) ENDIF IFDEF RAM_SCORPION_1024 LD BC,#1FFD ;(VELESOFT - SCORPION 1024 port 1FFD) ENDIF IFDEF RAM_ZXM_PHOENIX LD BC,#1FFD ;(VELESOFT - ZXM PHOENIX port 1FFD) ENDIF LD A,(HL) OUT (C),A INC HL LD A,(HL) ; LD B,#7F ;(VELESOFT - remove this instruction) LD BC,#7FFD ;(VELESOFT - BC = full 16bit adress) OUT (C),A POP IX EI RET ;Драйвер памяти (используется HONEY резидентом /и не только/) ;6.05 %00abcdef ;6.11 %bca0?def MEMDRV_ OR #10 LD BC,#7FFD OUT (C),A RET TCH2 LD (#5CF6),A ;2-ая точка входа - инициализация CP RMD_DRIVE;#03 JP NZ,TCH2Q ;#3DCE CALL TEST_R JP NZ,x3EE1 ;ошибку игнорировать?etc RET TCH3 CALL x1C57 ;3-я точка входа - форматирование ;установка имени файла LD A,(#5CF6) CP RMD_DRIVE;#03 RET NZ POP AF CALL FILL LD DE,#0000 LD (#5CF4),DE LD BC,#0010 FORMT PUSH BC LD A,#FF LD (#5CCE),A,HL,#5D25,B,#01 CALL RD_SV POP BC DEC BC LD A,B OR C JR NZ,FORMT ;free=... ; LD HL,#0DF0 ;для 896К (#0DF0 = number of free 256B sectors in ramdisc = 892kB) LD HL,RMD_SIZE ; (VELESOFT - number of free 256B sectors in ramdisc) LD A,#16 JP x1F55 ;продолж.FORMAT после LD HL,2544 FILL LD HL,#5D25,DE,#5D26 LD BC,#00FF,(HL),B LDIR RET FPG PUSH DE,HL ;Определение текущей PAGE 0-128 памяти EX AF,AF PUSH AF LD DE,(#C000) LD HL,(#FFFD) PUSH HL LD BC,#7FFD LD (#C000),BC LD (#FFFD),BC XOR A FPG1 DEC A DEC A LD HL,PG_TAB LD B,0 LD C,A ADD HL,BC ; LD BC,#1FFD ;(VELESOFT - zxm phoenix 2048 port 1FFD) IFDEF RAM_ZX_PROFI_1024 LD BC,#0DFFD ;(VELESOFT - ZX PROFI 1024 port DFFD) ENDIF IFDEF RAM_PENTAGON_1024 LD BC,#7FFD ;(VELESOFT - PENTAGON 1024 port 7FFD) ENDIF IFDEF RAM_PENTAGON_512 LD BC,#7FFD ;(Mario - PENTAGON 1024 port 7FFD) ENDIF IFDEF RAM_SCORPION_1024 LD BC,#1FFD ;(VELESOFT - SCORPION 1024 port 1FFD) ENDIF IFDEF RAM_ZXM_PHOENIX LD BC,#1FFD ;(VELESOFT - ZXM PHOENIX port 1FFD) ENDIF EX AF,AF LD A,(HL) OUT (C),A INC HL LD A,(HL) ; LD B,#7F ;(VELESOFT - remove this instruction) LD BC,#7FFD ;(VELESOFT - BC = full 16bit adress) OUT (C),A EX AF,AF LD HL,(#C000) SBC HL,BC JR NZ,FPG1 LD HL,(#FFFD) SBC HL,BC JR NZ,FPG1 LD (#C000),DE LD (#5C81),A POP HL POP AF EX AF,AF LD (#FFFD),HL POP HL,DE RET ;Установка типов дисководов 80DS (а-ля 5.04) ;Убрать,если необходимо автоопределение (а-ля 5.03) TCH4 LD HL,#8383 LD (#5CC8),HL,(#5CCA),HL LD A,#F7 ;Выбор дисковода при сбросе IN A,(#FE) LD B,0 RRA JR NC,DRV11 INC B RRA JR NC,DRV11 INC B RRA JR NC,DRV11 INC B RRA JR NC,DRV11 JR L3 DRV11 LD A,B,(#5CF6),A,(#5D19),A OR #3C LD (#5D16),A OUT (#FF),A L3 JP x106E ;вывод цветных полос для заставки MOVEPP LD HL,(#5CE1) LL3b03 LD A,(HL) CP #00 RET Z CP #01 JR Z,LL3b0e CALL LL3b14 LL3b0e LD DE,#0010 ADD HL,DE JR LL3b03 LL3b14 PUSH HL LD DE,#000D ADD HL,DE LD C,(HL) INC HL LD E,(HL) INC HL LD D,(HL) LD HL,(#5CD7) AND A SBC HL,DE ADD HL,DE JR Z,LL3b56 LD (#5CD5),DE LD A,C LD (#5CD3),A CALL x17A5 ;перемещение файла LL3b32 POP HL PUSH HL LD DE,(#5CDF) LD BC,#0010 LDIR LD (#5CDF),DE EXD LD DE,(#5CDD) DEC HL LD (HL),D DEC HL LD (HL),E LD HL,(#5CD7) LD (#5CDD),HL LD HL,#5CE3 INC (HL) POP HL RET LL3b56 LD A,C AND #0F ADD A,E BIT 4,A RES 4,A LD E,A JR Z,$+3 INC D LD A,C RRC A RRC A RRC A RRC A AND #0F ADD A,D LD D,A LD (#5CD7),DE JR LL3b32 GETCOM RES 5,(IY+#01) ;jp из #2154 ;вместо #1D90 - зачем??? RST #20 DW #15D4 ;WAIT_KEY CP 7 JR NZ,LL3bad LD HL,#00C8 LD D,H LD E,(IY-#01) RST #20 DW #03B5 ;beep CALL x212A ;восстановление командной строки LD HL,(#5C59) LD A,#0D LD BC,0 CPIR DEC HL LD (#5C5B),HL INC HL INC HL LD (HL),#80 LL3baa RST #20 DW #15D4 ;WAIT_KEY LL3bad PUSH AF LD HL,#00C8 LD D,H LD E,(IY-#01) RST #20 DW #3B5 ;beep POP AF CP #18 JR NC,LL3bca CP #07 JR C,LL3bca CP #10 JR C,LL3bcf RST #20 DW #F58 ;в ED_LOOP: sym>=16 JR LL3baa LL3bca RST #20 DW #F81 ;ADD_CHAR JR LL3baa LL3bcf CP #07 JR Z,LL3baa CP #0D RET Z CP #0A JR Z,LL3baa CP #0B JR Z,LL3baa RST #20 DW #F92 ;ED_KEYS JR LL3baa WHOD CALL x1D9F ;вход в TR-DOS ;jp из #3D35 ;вместо #239 ;очистка низа экрана JP x0239 ;вход в командный процессор OUTDE LD C,D OUT (C),E RET INED LD C,D IN E,(C) RET JPWRITE LD C,#7F JP x3FBA JPREAD LD C,#7F JP x3FD5 ;Free space for new routines ;--- FIXED HL' BY VELESOFT --- IFDEF FIX_HL PATCH_HL EXX LD HL,#2758 EXX JR NZ,END_HL DEC HL LD (#5C3D),HL END_HL RET ENDIF ;--- END OF FIXED HL' --- ;--- tables for memory paging for ramdisc support --- IFDEF RAM_ZX_PROFI_1024 ;(VELESOFT) table of values for paging ports (DW #1000 = OUT #7FFD,#10 + OUT #DFFD,#00) - values for ZX PROFI 1024 kB PG_TAB DW #1000,#1100,#1200,#1300,#1400,#1500,#1600,#1700 DW #1001,#1101,#1201,#1301,#1401,#1501,#1601,#1701 DW #1002,#1102,#1202,#1302,#1402,#1502,#1602,#1702 DW #1003,#1103,#1203,#1303,#1403,#1503,#1603,#1703 DW #1004,#1104,#1204,#1304,#1404,#1504,#1604,#1704 DW #1005,#1105,#1205,#1305,#1405,#1505,#1605,#1705 DW #1006,#1106,#1206,#1306,#1406,#1506,#1606,#1706 DW #1007,#1107,#1207,#1307,#1407,#1507,#1607,#1707 DW #1000,#1100,#1200,#1300,#1400,#1500,#1600,#1700 DW #1001,#1101,#1201,#1301,#1401,#1501,#1601,#1701 DW #1002,#1102,#1202,#1302,#1402,#1502,#1602,#1702 DW #1003,#1103,#1203,#1303,#1403,#1503,#1603,#1703 DW #1004,#1104,#1204,#1304,#1404,#1504,#1604,#1704 DW #1005,#1105,#1205,#1305,#1405,#1505,#1605,#1705 DW #1006,#1106,#1206,#1306,#1406,#1506,#1606,#1706 DW #1007,#1107,#1207,#1307,#1407,#1507,#1607,#1707 ENDIF IFDEF RAM_ZXM_PHOENIX ;table of values for paging ports (DW #1000 = OUT #7FFD,#10 + OUT #1FFD,#00) - values for ZXM PHOENIX 2048 kB PG_TAB DW #1000,#1100,#1200,#1300,#1400,#1500,#1600,#1700 DW #1080,#1180,#1280,#1380,#1480,#1580,#1680,#1780 DW #1010,#1110,#1210,#1310,#1410,#1510,#1610,#1710 DW #1090,#1190,#1290,#1390,#1490,#1590,#1690,#1790 DW #9000,#9100,#9200,#9300,#9400,#9500,#9600,#9700 DW #9080,#9180,#9280,#9380,#9480,#9580,#9680,#9780 DW #9010,#9110,#9210,#9310,#9410,#9510,#9610,#9710 DW #9090,#9190,#9290,#9390,#9490,#9590,#9690,#9790 DW #1040,#1140,#1240,#1340,#1440,#1540,#1640,#1740 DW #10C0,#11C0,#12C0,#13C0,#14C0,#15C0,#16C0,#17C0 DW #1050,#1150,#1250,#1350,#1450,#1550,#1650,#1750 DW #1090,#1190,#1290,#1390,#1490,#1590,#1690,#1790 DW #9040,#9140,#9240,#9340,#9440,#9540,#9640,#9740 DW #90C0,#91C0,#92C0,#93C0,#94C0,#95C0,#96C0,#97C0 DW #9050,#9150,#9250,#9350,#9450,#9550,#9650,#9750 DW #90D0,#91D0,#92D0,#93D0,#94D0,#95D0,#96D0,#97D0 ENDIF IFDEF RAM_PENTAGON_1024 ;(VELESOFT) table of values for paging ports (DW #1000 = OUT #7FFD,#10 + next byte are ignored) - values for PENTAGON 1024 kB PG_TAB DW #1010,#1111,#1212,#1313,#1414,#1515,#1616,#1717 DW #5050,#5151,#5252,#5353,#5454,#5555,#5656,#5757 DW #9090,#9191,#9292,#9393,#9494,#9595,#9696,#9797 DW #D0D0,#D1D1,#D2D2,#D3D3,#D4D4,#D5D5,#D6D6,#D7D7 DW #3030,#3131,#3232,#3333,#3434,#3535,#3636,#3737 DW #7070,#7171,#7272,#7373,#7474,#7575,#7676,#7777 DW #B0B0,#B1B1,#B2B2,#B3B3,#B4B4,#B5B5,#B6B6,#B7B7 DW #F0F0,#F1F1,#F2F2,#F3F3,#F4F4,#F5F5,#F6F6,#F7F7 DW #1010,#1111,#1212,#1313,#1414,#1515,#1616,#1717 DW #5050,#5151,#5252,#5353,#5454,#5555,#5656,#5757 DW #9090,#9191,#9292,#9393,#9494,#9595,#9696,#9797 DW #D0D0,#D1D1,#D2D2,#D3D3,#D4D4,#D5D5,#D6D6,#D7D7 DW #3030,#3131,#3232,#3333,#3434,#3535,#3636,#3737 DW #7070,#7171,#7272,#7373,#7474,#7575,#7676,#7777 DW #B0B0,#B1B1,#B2B2,#B3B3,#B4B4,#B5B5,#B6B6,#B7B7 DW #F0F0,#F1F1,#F2F2,#F3F3,#F4F4,#F5F5,#F6F6,#F7F7 ENDIF IFDEF RAM_PENTAGON_512 ;(VELESOFT) table of values for paging ports (DW #1000 = OUT #7FFD,#10 + next byte are ignored) - values for PENTAGON 1024 kB ;(Mario modified for pentagon 512K) PG_TAB DW #1010,#1111,#1212,#1313,#1414,#1515,#1616,#1717 DW #5050,#5151,#5252,#5353,#5454,#5555,#5656,#5757 DW #9090,#9191,#9292,#9393,#9494,#9595,#9696,#9797 DW #D0D0,#D1D1,#D2D2,#D3D3,#D4D4,#D5D5,#D6D6,#D7D7 DW #1010,#1111,#1212,#1313,#1414,#1515,#1616,#1717 DW #5050,#5151,#5252,#5353,#5454,#5555,#5656,#5757 DW #9090,#9191,#9292,#9393,#9494,#9595,#9696,#9797 DW #D0D0,#D1D1,#D2D2,#D3D3,#D4D4,#D5D5,#D6D6,#D7D7 DW #1010,#1111,#1212,#1313,#1414,#1515,#1616,#1717 DW #5050,#5151,#5252,#5353,#5454,#5555,#5656,#5757 DW #9090,#9191,#9292,#9393,#9494,#9595,#9696,#9797 DW #D0D0,#D1D1,#D2D2,#D3D3,#D4D4,#D5D5,#D6D6,#D7D7 DW #1010,#1111,#1212,#1313,#1414,#1515,#1616,#1717 DW #5050,#5151,#5252,#5353,#5454,#5555,#5656,#5757 DW #9090,#9191,#9292,#9393,#9494,#9595,#9696,#9797 DW #D0D0,#D1D1,#D2D2,#D3D3,#D4D4,#D5D5,#D6D6,#D7D7 ENDIF IFDEF RAM_SCORPION_1024 ;(VELESOFT) table of values for paging ports (DW #1000 = OUT #7FFD,#10 + OUT #1FFD,#00) - values for SCORPION 1024 kB PG_TAB DW #1000,#1100,#1200,#1300,#1400,#1500,#1600,#1700 DW #1010,#1110,#1210,#1310,#1410,#1510,#1610,#1710 DW #1040,#1140,#1240,#1340,#1440,#1540,#1640,#1740 DW #1050,#1150,#1250,#1350,#1450,#1550,#1650,#1750 DW #1080,#1180,#1280,#1380,#1480,#1580,#1680,#1780 DW #1090,#1190,#1290,#1390,#1490,#1590,#1690,#1790 DW #10C0,#11C0,#12C0,#13C0,#14C0,#15C0,#16C0,#17C0 DW #10D0,#11D0,#12D0,#13D0,#14D0,#15D0,#16D0,#17D0 DW #1000,#1100,#1200,#1300,#1400,#1500,#1600,#1700 DW #1010,#1110,#1210,#1310,#1410,#1510,#1610,#1710 DW #1040,#1140,#1240,#1340,#1440,#1540,#1640,#1740 DW #1050,#1150,#1250,#1350,#1450,#1550,#1650,#1750 DW #1080,#1180,#1280,#1380,#1480,#1580,#1680,#1780 DW #1090,#1190,#1290,#1390,#1490,#1590,#1690,#1790 DW #10C0,#11C0,#12C0,#13C0,#14C0,#15C0,#16C0,#17C0 DW #10D0,#11D0,#12D0,#13D0,#14D0,#15D0,#16D0,#17D0 ENDIF ;--- end of table for memory paging (ramdisc) --- ;--- show new text info about memory mode --- SHOW_TXT LD HL,NEW_TEXT RST #18 JP TCH4 NEW_TEXT IFDEF RAM_ZX_PROFI_1024 DB #16,7,5 DB "ZX Profi 1024" ENDIF IFDEF RAM_PENTAGON_1024 DB #16,7,5 DB "Pentagon 1024" ENDIF IFDEF RAM_PENTAGON_512 DB #16,7,5 DB "Pentagon 512" ENDIF IFDEF RAM_SCORPION_1024 DB #16,7,5 DB "Scorpion 1024" ENDIF IFDEF RAM_ZXM_PHOENIX DB #16,7,5 DB "ZXM Phoenix" ENDIF DB #16,8,5 DB "Ramdisk on drive : " DB 65+RMD_DRIVE DB 0 ;--- end of text info ... --- ;end of free space for new routines DISPLAY "Free space for expansions ",$,": ",/D,#3C30-$," byte(s)" DS #3C30-$,#FF IN A,(#1F) RET NACALO LD SP,#5BFF ;проверка резидентов (3 разных) LD A,#C7 ;1F ;проверка недокументированного резидента #C000 CALL MEMDRV_ LD HL,#C000 LD A,(HL) CP #C3 NORESC000 JP NZ,PPNORESC000 XOR A LL3c61 ADD A,(HL) ADC A,0 INC HL BIT 7,H JR NZ,LL3c61 DEC A JR NZ,NORESC000 LD A,#AA DEC HL CP (HL) JR NZ,NORESC000 CPL DEC HL CP (HL) JR NZ,NORESC000 LD HL,#D000 LD DE,#5B00 LD BC,#2500 LDIR LD SP,#5F00 LD A,#C6 ;1E CALL LDIfrC0 LD A,#03 CALL LDItoC0 LD A,#C5 ;1D CALL LDIfrC0 LD A,#01 CALL LDItoC0 LD A,#C4 ;1C CALL LDIfrC0 XOR A CALL LDItoC0 LD A,#C3 ;1B CALL LDIfrC0 XOR A CALL MEMDRV_ LD SP,(#5B73) RET LDItoC0 CALL MEMDRV_ SCF JR LDIR40 LDIfrC0 CALL MEMDRV_ XOR A LDIR40 LD HL,#C000 LD DE,#8000 LD BC,#4000 JR NC,$+3 EXD LDIR RET DISPLAY "Free space at ",$,": ",/D,#3CFA-$," byte(s)" DS #3CFA-$,#FF ;Адрес #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 OBROSH ;#3449 ;Адрес #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 x3D30 RET ;Адрес #3D31. Вход в TR-DOS. x3D31 CALL x3D21 ;создание области системных переменных PUSH HL ;помещение на стек адреса переключателя ПЗУ на бейсик JP WHOD ;#3BF0 ;вход в 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 #5C92 ;запуск подпрограммы ;Адрес #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 JP DOSSYM ;#805 DS 9,#FF DB #FF,0,0,#FF,#FF,#FF ;Адрес #3D94. Печать символа без изменения памяти. Символ поместите в аккумулятор. x3D94 RST #20 DW #0010 RET ;Адрес #3D98. Восстановление с ожиданием INTRQ. Используется также с адреса #3D9A (отдача команды из рег.A с ожиданием INTRQ). x3D98 LD A,8 ;восстановление 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,8 ;команда восстановления 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 x3EE7 ;обработка ошибки NO DISC ;Адрес #3DC8. Выбор дисковода, определенного по умолчанию. Вход: можно установить время перемещения головки и режим дисковода согласно описанию команды #01. Выход: эти переменные могут быть изменены согласно этому описанию. Используется также с адресов: ;#3DCB - выбор дисковода. Номер задайте в рег.A, остальное как и для предыдущей подпрограммы. ;#3DFD - задержка в 725779 тактов. ;#3DFF - задержка любой нужной длительности. В рег.A установите число, определяющее длительность задержки. x3DC8 LD A,(#5D19) ;берем номер дисковода по умолчанию x3DCB JP TCH2 ;перехват выбора дисковода TCH2Q 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 #FF ;в этой переменной #FF? JR NZ,x3DFA ;если да, то не определяем его 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,8 ;восстановление CALL x3D9A IFDEF TEST_DRIVES LD A,#10 ;???????????????? ?? ??????? #10 ELSE RET DB #20 ;Мусор ENDIF 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 ;позиционирование с быстрой скоростью ;Внимание!!! Здесь нужно JP #3D9A, т.к. #800 гасит биты скорости перемещения головки дисковода, следовательно позиционирование работает только с быстрой скоростью. ;Адрес #3E4C. Позиционирование. На входе в A должен быть физический номер дорожки, а в B - время перемещения головки дисковода. x3E4C OUT (#7F),A ;загрузка номера дорожки в регистр данных JP POSITPP ;#3780 CCF CP B POP BC ;восстановление времени перемещения головки POSITCONT PUSH AF ;сохранение результата проверки LD A,B ;получение команды позиционирования OR #18 CALL x0800 ;преобразование и выдача команды и ожидание 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 x1FEB ;выбор верхней стороны диска 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,x3D30 ;RET(этот CALL теперь пустышка) 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 USEmovSPD ;#37CD 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 x3EE1 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 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 ;повтор x3FA0 DEC D ;следующая попытка JP Z,x3F48 ;если попытки кончились, то обработка DISC ERROR PUSH DE ;сохранение счетчика попыток CALL x3E08 ;берем время перемещения головки дисковода AND 2 ;оно равно #A? JR NZ,x3FAD INC (HL) ;если нет, то увеличение его на 1 x3FAD CALL x3D98 ;восстановление 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 ;повтор x3FF0 OUT (C),A ;"умника",который первый засунул сюда ЭТО, RET ;лечить бесполезно... x3FF3 IN A,(C) ;а вот ЭТО,если бы он думал правильным местом, RET ;он бы положил в #3DXX. но теперь поздно... DISPLAY "Free space at ",$,": ",/D,#4000-$," byte(s)" DS #4000-$,#FF IFDEF RAM_ZX_PROFI_1024 SAVEBIN "TR-DOS_6.11Q_ZX_PROFI1024.ROM",0,#4000 ENDIF IFDEF RAM_PENTAGON_1024 SAVEBIN "TR-DOS_6.11Q_PENTAGON1024.ROM",0,#4000 ENDIF IFDEF RAM_PENTAGON_512 SAVEBIN "TR-DOS_6.11Q_PENTAGON512.ROM",0,#4000 ENDIF IFDEF RAM_SCORPION_1024 SAVEBIN "TR-DOS_6.11Q_SCORPION1024.ROM",0,#4000 ENDIF IFDEF RAM_ZXM_PHOENIX SAVEBIN "TR-DOS_6.11Q_ZXM_PHOENIX.ROM",0,#4000 ENDIF