; _ ____ ____ __ ; | | | _ \ / ___|___ _ __ / _| ; | | | | | | | / _ \| '_ \| |_ ; | |___| |_| | |__| (_) | | | | _| ; |_____|____/ \____\___/|_| |_|_| ; _____ ____ _ _ ____ _ ; | ___|__ _ __ / ___| _ __ _ __(_)_ __ | |_ ___ _ __ / ___|___ _ __ ___ _ __ _ _| |_ ___ _ __ ; | |_ / _ \| '__| \___ \| '_ \| '__| | '_ \| __/ _ \ '__| | | / _ \| '_ ` _ \| '_ \| | | | __/ _ \ '__| ; | _| (_) | | ___) | |_) | | | | | | | || __/ | | |__| (_) | | | | | | |_) | |_| | || __/ | ; |_| \___/|_| |____/| .__/|_| |_|_| |_|\__\___|_| \____\___/|_| |_| |_| .__/ \__,_|\__\___|_| ; |_| |_| ;******************************************************* ; Тестовая сборка или нет? define debug 0 define sprinter 1 ; ; Макросы MACRO TraceMSG tr_mess LD HL,tr_mess CALL PrintStr ENDM MACRO iDontKnow ;-----------------; Тайные манипуляции DI LD A,CNF_3 OUT (SYS_PORT_OFF),A LD A,3 ; установка внутр.портов Z84C15 для перезагрузки OUT (#EE),A OUT (#EF),A ; CASH & ROM ;-----------------; ENDM ; ; Версия проги и инфо для понтов: DEFINE Ver_ID "0.1 alpha" DEFINE e_mail "Tolik.Trek@gmail.com" ; Подгрузка файла с константами BIOS и DSS: INCLUDE "EQU/SP2000.ASM" ; Подгрузка файла с ошибками))) INCLUDE "EQU/Errors_MSG.a80" ; ST_Point EQU #BFFE ; адрес стека SP_Win EQU 64 ; мнимый контроль пересечения стека с кодом ORG_Addr EQU #8100 ; адрес компиляции. DSS вставляет строку ; с параметрами запущенного EXE перед ; адресом загрузки START, поэтому ; грузимся не с начала страницы. ; _______ _______ ____ __ _ ; | ____\ \/ / ____| | _ \ _ __ ___ / _(_)_ __ ; | _| \ /| _| | |_) | '__/ _ \ |_| \ \/ / ; | |___ / \| |___ | __/| | | __/ _| |> < ; |_____/_/\_\_____| |_| |_| \___|_| |_/_/\_\ ;-----------------; ORG ORG_Addr-#200 ; Сначала в EXE файле идёт заголовок ; длинной в 1 сектор (512 байт) ;-----------------; DB 'EX' ; EXE Сигнатура DB 'E' ; Reserved (EXE type) DB 0 ; Version of EXE file DW #0200 ; С какого смещения в файле будет грузиться код в DW #0000 ; память по адресу (START) Low - 0200h, High - 0000. DW #0000 ; Размер первичного загрузчика или 0 DW #0000 ; Reserved DW #0000 ; Reserved DW #0000 ; Reserved DW START ; Адрес расположения кода в памяти DW START ; Адрес в памяти с которого запустится код (Reg. PC) DW ST_Point ; Адрес стека (Reg. SP) BLOCK 490 ; Reserved. Добивка до конца сектора (512 байт). Может использоваться в новых версиях DSS ;******************************************************* ; __ __ _ ; | \/ | __ _(_)_ __ ; | |\/| |/ _` | | '_ \ ; | | | | (_| | | | | | ; |_| |_|\__,_|_|_| |_| START: ; ; ;-----------------; Чистим буфер акселем DI LD HL,Buffer LD D,D ; Установить размер блока LD A,255 ; Размер блока LD C,C ; LD A,0 ; LD (HL),A LD B,B ; Выключаем аксель ; EI ;-----------------; Сохраняем текущие страницы IN A,(PAGE0) LD (page0_save),A IN A,(PAGE1) LD (page1_save),A IN A,(PAGE2) LD (page2_save),A IN A,(PAGE3) LD (page3_save),A ;-----------------; ;-----------------; Сохраняем настройки экрана ld c,51h rst 10h jp nc,1f LD HL,error_Vmode JP BadExit 1: ld (VMod),a ld a,b ld (VModPage),a ;-----------------; ;-----------------; LD (dss_line),IX ; Сохраняем указатель на строку запуска. ????? Нужна ли она в дальнейшем ????? LD A,(IX) ; тут DSS кладёт длину параметров ком.строки AND A ; проверяем на отсутствие параметров JP NZ,1F ; запуска в ком.строке. Если их нет, LD HL,Help_Msg ; то печатаем инструкцию и выходим CALL PrintStr ; из программы с нормальным кодом LD B,0 ; завершения. JP Exit ; ;-----------------; ;-----------------; Разбираем и активируем ключи 1: CALL Set_keys ; на выходе CF=0 - нет ошибки JR NC,1F ; СF=1 - есть ошибка LD HL,error_ComStr ; Если разобрали с ошибками JP BadExit ; то выход с ошибкой ;-----------------; ;-----------------; если норм. завершение set_keys 1: if debug : TraceMSG trace_msg1 : endif ; ld a,(x_key) and A ; если ключ X установлен, то проверку пропускаем jp nz,1F CALL TestConf ; проверка конфы. на выходе CF=0 - нет ошибк JR NC,1F ; СF=1 - есть ошибка LD HL,error_confFile ; Если косяк с файлом прошивки JP BadExit ; то выход с ошибкой ;-----------------; ;-----------------; если норм. завершение TestConf 1: if debug : TraceMSG trace_msg2 : endif ; CALL TakeMem ; Выделение памяти для конфы 65536 байт JR NC,1F LD HL,error_freeMem ; Если недостаточно памяти JP BadExit ; то выход с ошибкой ;-----------------; ;-----------------; если норм. завершение TakeMem 1: if debug : TraceMSG trace_msg3 : endif ; ; LD A,(ConfHandler) ; Выставляем хендлер прошивки ; LD (NowHandler),A ; с которой будем работать ; ; CALL Load_conf ; Читаем прошивку из файла (меняет PAGE3) LD A,(page3_save) ; восстанавливаем страницу OUT (PAGE3),A ; памяти после смены JR NC,1F LD HL,error_readConf ; Если ошибка при чтении прошивки из файла JP BadExit ; то выход с чем? Правильно, с ошибкой ;-----------------; ;-----------------; если норм. завершение Load_conf 1: if debug : TraceMSG trace_msg4 : endif ; if sprinter : iDontKnow : endif ; LD DE,ReloadRET ; Адрес ВОЗВРАТА после перезагрузки LD (SP_Save),SP ; сохраняем стек CALL Set_Ret ; установка данных для возврата ; if debug : TraceMSG trace_msg5 : endif ; CALL Set_Acex_Data ; перегрузка данных ACEX в FAST-RAM ; После этой процедуры хитрой ^^^^^^ начинаются глюки ; с вызовом процедур DSS. Чёт она там мудрит с портами ; или с памятью, не разобрался. Поэтому после неё лучше ; сразу в ресет с головой и не париться... ;-----------------; ;-----------------; 7 бед - 1 ресет RESET: DI IN A,(PAGE1) ; открытие порта сброса PUSH AF LD A,40h OUT (PAGE1),A ; set DCP page LD A,2Eh LD (04400h),A ; open for WR LD (04600h),A ; open for RD POP AF OUT (PAGE1),A ; Close PAGE1 ??????? RESET_LOOP: ; цикл сброса LD BC,100h OUT (C),C LD BC,000h OUT (C),C JR RESET_LOOP ; полностью зациклить! HALT ; пылеуловитель ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ; ____ _ _ ____ _ ; | _ \ _ __(_)_ __ | |_ / ___|| |_ _ __ ; | |_) | '__| | '_ \| __| \___ \| __| '__| ; | __/| | | | | | | |_ ___) | |_| | ; |_| |_| |_|_| |_|\__| |____/ \__|_| ; Печать строки. Адрес строки в HL ;-----------------; PrintStr: LD C,5Ch RST 10h RET ;******************************************************* ; ____ _ _ ____ _____ _____ ; | _ \ ___| | ___ __ _ __| | | _ \| ____|_ _| ; | |_) / _ \ |/ _ \ / _` |/ _` | | |_) | _| | | ; | _ < __/ | (_) | (_| | (_| | | _ <| |___ | | ; |_| \_\___|_|\___/ \__,_|\__,_| |_| \_\_____| |_| ; Место, куда будет возврат после ; перезагрузки новой прошивки ;-----------------; ReloadRET: DI LD SP,(SP_Save) LD A,CNF_0 ; конфигурация и отключение ПЗУ OUT (SYS_PORT_OFF),A LD A,(page0_save) ; SET PAGE DOS OUT (PAGE0),A LD A,(page3_save) ; возврат старой страницы PAGE3 OUT (PAGE3),A ;-----------------; ;-----------------; Работа программы с новой прошивкой ld a,(e_key) and a jp z,1F ld hl,EXEfileBuff ; Запуск EXE ld bc,0040h rst 10h ;-----------------; ;-----------------; 1: ld a,(a_key) ; Выход без восстановления дефолтной конфы? and a jp nz, NormExit LD DE,NextReloadRET ; LD (SP_Save),SP ; сохраняем стек CALL Set_Ret ; установка данных для возврата JP RESET ;******************************************************* ; _ _ _ ; | \ | | _____ _| |_ ; | \| |/ _ \ \/ / __| ; | |\ | __/> <| |_ ; |_| \_|\___/_/\_\\__| ; ____ _ _ ____ _____ _____ ; | _ \ ___| | ___ __ _ __| | | _ \| ____|_ _| ; | |_) / _ \ |/ _ \ / _` |/ _` | | |_) | _| | | ; | _ < __/ | (_) | (_| | (_| | | _ <| |___ | | ; |_| \_\___|_|\___/ \__,_|\__,_| |_| \_\_____| |_| ; Подготовка к завершению после ресета и ; возврата родной прошивки ;-----------------; NextReloadRET: DI LD SP,(SP_Save) LD A,CNF_0 ; конфигурация и отключение ПЗУ OUT (SYS_PORT_OFF),A LD A,(page0_save) ; SET PAGE DOS OUT (PAGE0),A LD A,(page1_save) OUT (PAGE1),A ; Глянуть, может не надо возвращать одну из страниц??? LD A,(page3_save) OUT (PAGE3),A JP NormExit ;******************************************************* ; _____ _ _ ____ _ ; | ____|_ _(_) |_ | _ \ _ __ ___ ___( )___ ; | _| \ \/ / | __| | |_) | '__/ _ \ / __|// __| ; | |___ > <| | |_ | __/| | | (_) | (__ \__ \ ; |_____/_/\_\_|\__| |_| |_| \___/ \___| |___/ ;-----------------; NormExit: LD HL,WellDone CALL PrintStr LD B,0 CALL Exit ;-----------------; BadExit: ; В HL строка с ошибкой CALL PrintStr LD B,1 ; код ошибки CALL Exit ;-----------------; ;-----------------; Exit: LD A,CNF_0 ;?????? OUT (SYS_PORT_OFF),A ; PUSH BC LD HL,FirstHandler LD C,12h LD B,(LastHandler-FirstHandler) .loop: ; Закрываем все открытые файлы, LD A,(HL) ; если есть. В цикле. AND A JR Z,1F PUSH HL PUSH BC RST 10h POP BC POP HL 1: INC HL DJNZ .loop ;-----------------; ;-----------------; освобождаем память, если клянчили ld c,#C3 ld a,(ram_blk_id) cp 0 jr z,1F rst 8 ;-----------------; ;-----------------; восстанавливаем экран ld c,53h rst 10h push de ld a,(VModPage) ld b,a ld a,(VMod) ld c,50h rst 10h ld c,52h pop de rst 10h ;-----------------; ;-----------------; Выход в DOS 1: POP BC LD C,41h RST 10h DI HALT ;-----------------; ;******************************************************* ; ____ _ _ ; / ___| ___| |_ | | _____ _ _ ___ ; \___ \ / _ \ __| | |/ / _ \ | | / __| ; ___) | __/ |_ | < __/ |_| \__ \ ; |____/ \___|\__| |_|\_\___|\__, |___/ ; |___/ ; Получаем ключи запуска, распихиваем их по углам, ; настраиваем начальные условия работы. ;-----------------; Set_keys: LD HL,(dss_line) INC HL .CheckChar: CALL .GetParam JP NC,1F CCF ; Если последний параметр в строке = 0 RET ; то выходим. Разбор окончен 1: LD A,(Buffer+1) ; В основном цикле CheckChar мы AND A ; ждём только один символ в JP Z,1F ; ключе. Поэтому если их больше, SCF ; то выходим с ошибкой. RET ; Выход с ошибкой. 1: ; Проверка/установка ключа LD C,A ; ТУТ ЖДЁМ, что в А лежит 0 и используем BC LD B,A ; как смещение в памяти, где хранятся ключи LD A,(Buffer) RES 5,A ; делаем маленький символ большим))) CP 'A' ; проверяем параметр на нужный JR Z,.set_keys_a CP 'C' JR Z,.set_keys_c CP 'E' JR Z,.set_keys_e CP 'X' JR Z,.set_keys_x SCF ; ошибка в параметре RET ; выход с ошибкой ;-----------------; ;-----------------; .set_keys_x: INC C .set_keys_e: INC C .set_keys_c: INC C .set_keys_a: EX DE,HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! LD HL,key_buff ; Вычисляем ячейку хранения ключа ADD HL,BC LD A,(HL) ; и проверяем нет ли там уже ключа. CP 0 ; если есть, значит ключ введён 2 раза SCF RET NZ ; ошибка - повтор ключа. выход OR C ; Тут ОЖИДАЕТСЯ, что А=0. Если С=0, то это ключ "A" LD A,3 LD (HL),A ; установили ключ EX DE,HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! JR Z,.CheckChar ; если ключ "A" то следующий круг цикла xor C ; Тут ОЖИДАЕТСЯ, что А=3. Если С=3, то это ключ "X" JR Z,.CheckChar ; если ключ "X" то следующий круг цикла PUSH BC CALL .GetParam ; получаем следующий параметр строки DOS к найденому ключу POP BC RET C ; выход, если ошибка EX DE,HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! LD HL,FirstHandler ; вычисляем ячейку хранения хендлера ADD HL,BC ; DEC HL ; LD (.fileHandler),HL ; и подставляем её прямо в код ".OpenFile" EX DE,HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! PUSH HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! CALL .OpenFile ; Открытие файла (или проверка наличия) по имени из буфера POP HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! RET C ; выход, если ошибка JP .CheckChar ; погнали на следующий виток разбора ключей ;-----------------; ;-----------------; .GetParam: ; в HL принимается след. пар. строки DOS LD C,43h ; тут выделяем параметр запуска LD DE,Buffer ; буфер для операций со строками RST #10 ; получаем в буфере следующий параметр CCF LD A,(Buffer) AND A RET NZ ; Нормальный возврат C = 0 SCF RET ; Возврат с ошибкой C = 1 ;-----------------; ;-----------------; .OpenFile: LD HL,key_save ; прописываем ключ в код для проверки на EXE LD (HL),C ; втыкаем значение ключа в код LD BC,#0045 ; проверяем буфер на корректность имени файл LD HL,Buffer ; ????? сделать проверку на корректность всего пути????? RST 10h RET C ; ошибка в строке AND %00000011 ; проверяем, что есть имя и XOR %00000011 ; расширение файла (0 и 1 биты) SCF RET NZ ; ошибка файла - выход LD A,0 LD C,11h LD HL,Buffer RST 10h ; открытие файла RET C ; ошибка файла - выход LD (.fileHandler),A ; сохраняем хендлер .fileHandler EQU $-2 ;-----------------; ;-----------------; Проверяем обрабатываемый ключ key_save EQU $+1 LD A,#FF ; сюда воткнётся значение из регистра C XOR 2 ; если 2, то это ключ "E" ret NZ ; если нет, то выход из процедуры. ;-----------------; ;-----------------; Проверка расширения файла LD BC,#0445 ; С ключом "E" проверяем файл LD HL,Buffer ; на расширение "EXE" выделив LD DE,BufferEXE ; из строки имени расширение RST 10h ; файла в отдельный буфер на 4 байта ;-----------------; ;-----------------; тестим буфер расширения посимвольно LD DE,IsEXE LD HL,BufferEXE LD BC,IsEXElength-IsEXE 2: LD A,(DE) RES 5,(HL) ; делаем маленький символ большим))) CPI INC DE JP PO,3F ; если последний символ проверен, то JP на проверку JP Z,2B ; если символ совпадает, то повтор 3: SCF ; сюда попадём когда BC=0 или символ не совпал RET NZ ; если вышли из цикла и символ не совпал - ошибка, xor A ; если всё ништяк (???- закрываем открытый EXE и???) выходим ex af,af' ld hl,Buffer ld de,EXEfileBuff ld bc, #00FF 1: ldi ex af,af' cp (hl) jr z,1F ex af,af' jp pe,1B 1: ld a,0 ld (de),a ld a,(ExeHandler) ld c,12h rst 10h RET ;******************************************************* ; _____ _ ____ __ ; |_ _|__ ___| |_ / ___|___ _ __ / _| ; | |/ _ \/ __| __| | | / _ \| '_ \| |_ ; | | __/\__ \ |_ | |__| (_) | | | | _| ; |_|\___||___/\__| \____\___/|_| |_|_| ; Проверяем размер и заголовок файла прошивки ; (???добавить ключ для отмены???) ;-----------------; TestConf: LD A,(ConfHandler) ; сохраняем хендлер на текущий LD (NowHandler),A ; файл с которым работаем. ??? убрать лишнее ??? AND A ; проверка на отсутствие хендлера SCF RET Z ; выход с ошибкой если файл не открыт CALL .testing /* RET C LD A,(ConfHandler2) ; выбираем текущим следующий файл LD (NowHandler),A AND A ; проверка на отсутствие хендлера RET Z ; выход без ошибки - второй прошивки может не быть в параметрах CALL .testing */ RET ;-----------------; ;-----------------; .testing: LD HL,Buffer LD DE,8 LD C,13h ; читаем в буфер первые 8 байт RST 10h ; для сравнения с шаблоном RET C ;-----------------; ;-----------------; ковыряем буфер посимвольно: LD DE,IsNormConf ; шаблон для сравнения LD HL,Buffer LD BC,IsNormConfLen-IsNormConf 2: LD A,(DE) CPI INC DE JP PO,3F ; если последний символ проверен, то JP на проверку JP Z,2B ; если символ совпадает, то повтор 3: SCF ; сюда попадём когда BC=0 или символ не совпал RET NZ ; если вышли из цикла и символ не совпал - ошибка, ;-----------------; ; если ОК, то сбрасываем указатель в файле на 0 ;-----------------; LD B,2 ; Ставим указатель на конец файла CALL .set_fp ; чтоб узнать его размер RET C LD A,H ; Размер файла в HL:IX. Нет смысла, если он больше OR L ; 65536 байт, поэтому проверяем, что в HL ноль. SCF RET NZ LD HL,(ConfSize) ; Сравниваем размер файла LD A,H ; с эталлоным (59215 или #E74F) SUB XL JP NZ,1F LD A,L SUB XH 1: SCF RET NZ ;-----------------; ;-----------------; LD B,0 ; Возвращаем указатель CALL .set_fp ; в файле на его начало RET ;-----------------; ;-----------------; .set_fp: LD A,(NowHandler) ; Хэндлер файла с которым сейчас работаем LD HL,0 LD IX,0 LD C,15h RST 10h ; установка указателя RET ;******************************************************* ; _____ _ __ __ ; |_ _|_ _| | _____ | \/ | ___ _ __ ___ ; | |/ _` | |/ / _ \ | |\/| |/ _ \ '_ ` _ \ ; | | (_| | < __/ | | | | __/ | | | | | ; |_|\__,_|_|\_\___| |_| |_|\___|_| |_| |_| ; Выделяем память под загрузку прошивки - 64 кб ;-----------------; TakeMem: LD BC,#04C2 ; Запрос на выделение 64 Кб памяти под конфу RST 8 RET C ; завершение - нехватка памяти LD (ram_blk_id),A ; LD C,#C5 ; запрос номеров выделенных страниц LD HL,ram_pages ; буфер для перечисления страниц RST 8 RET C ; завершение - ошибка в ID блока LD A,B CP 4 SCF RET NZ ; завершение - некорректное кол-во блоков CCF RET ;******************************************************* ; _ _ ____ __ ; | | ___ __ _ __| | / ___|___ _ __ / _| ; | | / _ \ / _` |/ _` | | | / _ \| '_ \| |_ ; | |__| (_) | (_| | (_| | | |__| (_) | | | | _| ; |_____\___/ \__,_|\__,_| \____\___/|_| |_|_| ; Загружаем прошивку в память ; Читает файл прошивки 59215 байт. ;Процедура щёлкает PAGE3 без сохранения/восстановления ; предыдущего состояния. ;-----------------; Load_conf: LD A,(ram_pages) OUT (PAGE3),A LD A,(ConfHandler) LD HL,#D000 LD DE,#3000 LD C,13h RST 10h ; RET C ; AND A ; JP NZ,2F LD A,(ram_pages+1) OUT (PAGE3),A LD A,(ConfHandler) LD HL,#C000 LD DE,#4000 LD C,13h RST 10h ; RET C ; AND A ; JP NZ,2F LD A,(ram_pages+2) OUT (PAGE3),A LD A,(ConfHandler) LD HL,#C000 LD DE,#4000 LD C,13h RST 10h ; RET C ; AND A ; JP NZ,2F LD A,(ram_pages+3) OUT (PAGE3),A LD A,(ConfHandler) LD HL,#C000 LD DE,#4000 LD C,13h RST 10h ; RET C ; and a JP 3F LD HL,#374F SBC HL,DE JP Z,3F 2: SCF 3: RET ;******************************************************* ; ____ _ _ ; / ___| ___| |_ / \ ___ _____ __ ; \___ \ / _ \ __| / _ \ / __/ _ \ \/ / ; ___) | __/ |_ / ___ \ (_| __/> < ; |____/ \___|\__| /_/ \_\___\___/_/\_\ ; Перекидываем прошивку в кэш и освобождаем память, ; если нет второй прошивки ; (???освобождение памяти недоделанно???) ;-----------------; Set_Acex_Data: DI IN A,(CASH_ON) ; Включение кэша LD BC,1FFDh XOR A OUT (C),A ; отключить RAM-0 LD A,4 OUT (SYS_PORT_ON),A ; DCP-PAGE 0 LD A,0 OUT (5Ch),A ; Страница КЭШ = 0 LD A,(ram_pages) OUT (PAGE1),A ; страница с данными файла LD HL,5000h ; перекидывание данных в страницу КЭШ = 0 LD DE,1000h LD BC,3000h LDIR LD A,1 OUT (5Ch),A ; Страница КЭШ = 1 LD A,(ram_pages+1) OUT (PAGE1),A ; следующая страница с данными файла ld h,d ; LD HL,4000h ld d,e ; LD DE,0000h ld b,h ; LD BC,4000h LDIR LD A,2 OUT (5Ch),A ; Страница КЭШ = 2 LD A,(ram_pages+2) OUT (PAGE1),A ; следующая страница с данными файла ex de,hl ; LD HL,4000h ld d,e ; LD DE,0000h ld b,h ; LD BC,4000h LDIR LD A,3 OUT (05Ch),A ; Страница КЭШ = 3 LD A,(ram_pages+3) OUT (PAGE1),A ; следующая страница с данными файла ld h,d ; LD HL,4000h ld d,e ; LD DE,0000h ; LD BC,37F4h ld b,h ; LD BC,4000h LDIR LD HL,Reload_String ; флаг перезагрузки из КЭШ-а LD DE,3EF0h LD C,10h ; LD BC, 16 LDIR LD A,0FFh LD (3EE0h),A ; no multiple ! перезагрузка только одна IN A,(CASH_OFF) ; Отключение кэша LD A,(page1_save) ; возврат страницы 1 OUT (PAGE1),A RET ;******************************************************* ; ____ _ ____ _____ _____ ; / ___| ___| |_ | _ \| ____|_ _| ; \___ \ / _ \ __| | |_) | _| | | ; ___) | __/ |_ | _ <| |___ | | ; |____/ \___|\__| |_| \_\_____| |_| ; Настройки перед ресетом ; Установка адреса возврата после reboot ; Сохранение активных страниц ; Адрес программы для возврата в регистре DE ;-----------------; Set_Ret: DI LD A,Spec_Page OUT (PAGE3),A ; открыть спец-страницу LD (#FFF4),DE ; адрес программы перезапуска LD A,'Z' LD (#FFFE),A LD A,'X' LD (#FFFF),A ; флаг перезапуска ld A,(page0_save) ; сохранять страницы LD (0FFF0h),A ; DOS-PAGE ld A,(page1_save) LD (0FFF1h),A ld A,(page2_save) LD (0FFF2h),A ; программы для возврата??? in A,(PAGE3) ; Сохраняем ТЕКУЩУЮ страницу 3 LD (0FFF3h),A ld A,(page3_save) ; Восстанавливаем начальную страницу 3 OUT (PAGE3),A ; EI RET ;******************************************************* ;(.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) ; Подгрузка файла с переменными, константами и буферами: INCLUDE "LDconf_Consts.ASM" ; the_end EQU $ ; IF (the_end>(ST_Point-SP_Win)) DISPLAY "the_end = ",/H,the_end DISPLAY "ST_Point-SP_Win = ",/H,(ST_Point-SP_Win) Stack_Error 0 ENDIF IF (LastHandler=FirstHandler) or ((LastHandler-FirstHandler) > 255) DISPLAY "FirstHandler = ",/H,FirstHandler DISPLAY "LastHandler = ",/H,LastHandler Handler_Error 0 ENDIF ;(.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.)