From 5f125190892f05bb312b8e09878a978ab8d62143 Mon Sep 17 00:00:00 2001 From: Anatoliy Belyanskiy Date: Thu, 15 Jun 2023 03:12:54 +1000 Subject: [PATCH] Setup --- .gitmodules | 4 + Consts.inc | 93 +++++ Errors_MSG.mac | 11 + LDCONF.ASM | 980 ++++++++++++++++++++++++++++++++++++++++++++++++ LDCONF50.ASM | 856 ++++++++++++++++++++++++++++++++++++++++++ LDCONFW.ASM | 855 ++++++++++++++++++++++++++++++++++++++++++ LDConf.txt | 12 + SP2000.inc | 588 +++++++++++++++++++++++++++++ Shared_Includes | 1 + game conf.txt | 75 ++++ 10 files changed, 3475 insertions(+) create mode 100644 .gitmodules create mode 100644 Consts.inc create mode 100644 Errors_MSG.mac create mode 100644 LDCONF.ASM create mode 100644 LDCONF50.ASM create mode 100644 LDCONFW.ASM create mode 100644 LDConf.txt create mode 100644 SP2000.inc create mode 160000 Shared_Includes create mode 100644 game conf.txt diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..7355856 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "Shared_Includes"] + branch = main + path = Shared_Includes + url = https://github.com/Tolik-Trek/Shared_Includes.git diff --git a/Consts.inc b/Consts.inc new file mode 100644 index 0000000..9b84b30 --- /dev/null +++ b/Consts.inc @@ -0,0 +1,93 @@ +;================================================================================================================== +; + IFDEF debug : if debug +trace_msg1: db 'Set_keys OK',13,10,0 +trace_msg2: db 'TestConf OK',13,10,0 +trace_msg3: db 'take_mem OK',13,10,0 +trace_msg4: db 'read_conf OK',13,10,0 +trace_msg5: db 'Set_Ret OK',13,10,0 +trace_msg6: db 'Set_Acex_Data OK',13,10,0 ; Чудо - увидеть это сообщение на железе + endif : ENDIF +; +; +; +; ; Тут сидят переменные, константы и буферы +; +Spec_Page equ 41h +; +Help_Msg: + DB 13,10 + DB 'LDConf ver. ',Ver_ID,' ',__DATE__,13,10 + DB 'Программа для загрузки и тестирования конфигураций Sprinter 2000',13,10,13,10 + DB 'Параметры через пробел:',13,10 + DB 'a - оставить загружаемую конфу после выхода',13,10 + DB 'c - после этого ключа должен идти файл конфы',13,10 + DB 'e - EXE файл для запуска после ресета в конфу',13,10 + DB 'x - не проверять файл конфы на валидность заголовка и размер',13,10 + DB 'l - страшный ключ, залитая конфа останется до перезаливки или выключения ПК',13,10,13,10 + DB 'Если указано только имя конфы, то: загрузка конфы -> ресет ->',13,10 + DB 'восстановление дефолтной конфы -> ресет -> выход. Пока так.',13,10,13,10 + DB 'Программа была зачем-то написана Анатолием Белянским. ',13,10 + DB 'Не пишите мне сюда: ',e_mail,' ))))',13,10,13,10 + DB 0 +; ; Сообщения об ошибках +error_Vmode: DB 'Ошибка определения режима экрана!',13,10,0 +error_ComStr: DB 'Ошибка в параметрах коммандной строки!',13,10,0 +error_confFile: DB 'Ошибка файла прошивки!',13,10,0 +error_freeMem: DB 'Ошибка выделения памяти!',13,10,0 +error_readConf: DB 'Ошибка чтения файла прошивки!',13,10,0 +WellDone: DB 'Well done!)))',13,10,0 +; +;-----------------; Эти указатели должны идти друг за другом +ConfSize: DB #4F,#E7 ; #E74F - правильный размер прошивки 59215 (обратный порядок!) 12288+16384+16384+14159 +MaxConfSize: DB #E0,#EE ; #EEE0 - максимальный размер прошивки 61152 (обратный порядок!) для загрузчика конфы в биос. + +IsEXE: DB 'EXE',0 ; Расширение запускаемого файла по ключу 'E' +IsEXElength EQU $ + +IsNormConf: DB #FF,#FF,#62,#7B,#39,#00,#FF,#FF ; 8 байт заголовка конфы +IsNormConfLen EQU $ + +; ; Тут ключи запуска +key_buff EQU $ +c_key: DB 0 ; ConfHandler1 +e_key: DB 0 ; ExeHandler +x_key: DB 0 ; ключ отмены теста заголовка прошивки и привязки к размеру 1K30 +a_key: DB 0 ; ключ отмены загрузки дефолтной конфы после выхода +l_key: db 0 ; ключ для разных тестов +key_buff_end EQU $-1 + +; ; тут хендлеры открытых файлов +FirstHandler EQU $ ; ??? убрать лишнее ??? +ConfHandler: DB 0 ; тестируемая конфа (c_key) +ExeHandler: DB 0 ; запускаемый EXE (e_key) +LastHandler EQU $ ; ??? убрать лишнее ??? +;NowHandler: DB 0 ; хендлер текущего файла +ConfMultKeys: DB #FF,#FF,'I','M' ; Если воткнуть сюда строку 'IM', то что-то будет + +;-----------------; + +Reload_String: DB 'ACEX_30K_LOADING' ; флаг заливки конфы из кеша +VMod: db 0 ; Режим экрана +VModPage: db 0 ; Страница экрана +ram_blk_id: DB 0 ; Идентификатор блока памяти +SP_Save: DB 0,0 ; Тут храним стек для перезагрузки +dss_line: DB 0,0 ; указатель на DOS строку запуска LDConf +NextParameter: dw 0000 ; Следующий параметр для .GetParam +; +; +; ; Разные буффера (.)(.) +BufferEXE: DB 0,0,0,0 +ram_pages: DB 0,0,0,0,0 ; Выделенные BIOS'ом блоки памяти (последний #FF) +page0_save: DB 0 ; Тут храним текущую страницу PAGE0 (должна идти после ram_pages) +page1_save: DB 0 ; Тут храним текущую страницу PAGE1 +page2_save: DB 0 ; Тут храним текущую страницу PAGE2 (должна идти после ram_pages) +page3_save: DB 0 ; Тут храним текущую страницу PAGE3 +port_1ffd_save: DB 0 ; Состояние порта 1FFD до всяких манипуляций +page0_def db 0 +page1_def db 0 +page2_def db 0 +page3_def db 0 +EXEfileBuff equ $ ; Тут храним путь до запускаемого после ресета EXE +Buffer EQU EXEfileBuff+256 ; BLOCK 255,0 +; \ No newline at end of file diff --git a/Errors_MSG.mac b/Errors_MSG.mac new file mode 100644 index 0000000..41c81fc --- /dev/null +++ b/Errors_MSG.mac @@ -0,0 +1,11 @@ + MACRO Stack_Error true + ENCODING "WIN" + ASSERT true, "╩юф чрыхч эр юсырёЄ№ ёЄхър!!!" + ENCODING "DOS" + ENDM + + MACRO Handler_Error true + ENCODING "WIN" + ASSERT true, "╩юё ъ т сыюъх їЁрэхэш  їхэфыхЁют!!!" + ENCODING "DOS" + ENDM \ No newline at end of file diff --git a/LDCONF.ASM b/LDCONF.ASM new file mode 100644 index 0000000..50b313d --- /dev/null +++ b/LDCONF.ASM @@ -0,0 +1,980 @@ +; _ ____ ____ __ +; | | | _ \ / ___|___ _ __ / _| +; | | | | | | | / _ \| '_ \| |_ +; | |___| |_| | |__| (_) | | | | _| +; |_____|____/ \____\___/|_| |_|_| + +; _____ ____ _ _ ____ _ +; | ___|__ _ __ / ___| _ __ _ __(_)_ __ | |_ ___ _ __ / ___|___ _ __ ___ _ __ _ _| |_ ___ _ __ +; | |_ / _ \| '__| \___ \| '_ \| '__| | '_ \| __/ _ \ '__| | | / _ \| '_ ` _ \| '_ \| | | | __/ _ \ '__| +; | _| (_) | | ___) | |_) | | | | | | | || __/ | | |__| (_) | | | | | | |_) | |_| | || __/ | +; |_| \___/|_| |____/| .__/|_| |_|_| |_|\__\___|_| \____\___/|_| |_| |_| .__/ \__,_|\__\___|_| +; |_| |_| +;******************************************************* +; +; Макросы + 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.3 alpha" + DEFINE e_mail "Tolik.Trek@gmail.com" +; Подгрузка файла с константами BIOS и DSS: + INCLUDE "SP2000.inc" +; Подгрузка файла с ошибками))) + INCLUDE "Errors_MSG.mac" +; +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 +;-----------------; + +;-----------------; Сохраняем настройки экрана + push ix + ld c,51h + rst 10h + pop ix + jp nc,1f + LD HL,error_Vmode + JP BadExit +1: + ld (VMod),a + ld a,b + ld (VModPage),a +;-----------------; + +;-----------------; Сохраняем значение порта #1FFD + LD BC,1FFDh + IN A,(C) + ld (port_1ffd_save),a +;-----------------; + +;-----------------; Сохраняем дефолтные страницы + DI + LD A,Spec_Page + OUT (PAGE3),A ; открыть спец-страницу + ld hl,#FFF0 + ld de,page0_def + ldi + ldi + ldi + ldi + LD A,(page3_save) + OUT (PAGE3),A ; вернуть страницу + EI +;-----------------; + +;-----------------; + 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: + IFDEF debug : if debug : TraceMSG trace_msg1 : endif : endif +; + CALL TestConf ; проверка конфы. на выходе CF=0 - нет ошибк + JR NC,1F ; СF=1 - есть ошибка + LD HL,error_confFile ; Если косяк с файлом прошивки + JP BadExit ; то выход с ошибкой +;-----------------; + +;-----------------; если норм. завершение TestConf +1: + IFDEF debug : if debug : TraceMSG trace_msg2 : endif : endif +; + CALL TakeMem ; Выделение памяти для конфы 65536 байт + JR NC,1F + LD HL,error_freeMem ; Если недостаточно памяти + JP BadExit ; то выход с ошибкой +;-----------------; + +;-----------------; если норм. завершение TakeMem +1: + IFDEF debug : if debug : TraceMSG trace_msg3 : endif : endif +; + CALL Load_conf ; Читаем прошивку из файла (меняет PAGE3) + LD A,(page3_save) ; восстанавливаем страницу + OUT (PAGE3),A ; памяти после смены + JR NC,1F + LD HL,error_readConf ; Если ошибка при чтении прошивки из файла + JP BadExit ; то выход с чем? Правильно, с ошибкой +;-----------------; + +;-----------------; если норм. завершение Load_conf +1: + IFDEF debug : if debug : TraceMSG trace_msg4 : endif : endif +; +; IFDEF sprinter : if sprinter : iDontKnow : endif : endif +; + LD DE,ReloadRET ; Адрес ВОЗВРАТА после перезагрузки + LD (SP_Save),SP ; сохраняем стек + CALL Set_Ret ; установка данных для возврата +; + IFDEF debug : if debug : TraceMSG trace_msg5 : endif : endif +; + CALL Set_Acex_Data ; перегрузка данных ACEX в FAST-RAM +; После этой процедуры хитрой ^^^^^^ начинаются глюки +; с вызовом процедур DSS. Чёт она там мудрит с портами +; или с памятью, не разобрался. Поэтому после неё лучше +; сразу в ресет с головой и не париться... +;-----------------; + IFDEF debug : if debug : TraceMSG trace_msg6 : endif : endif +;-----------------; 7 бед - 1 ресет +RESET: + + DI + LD A,16 + LD BC,1FFDh + OUT (C),A + LD A,0A0h + OUT (PAGE3),A + LD (0C000h),A ; в этот момент подается RESET + DI ; глюкоуловитель + HALT + +/* + DI + + IN A,(PAGE1) ; открытие порта сброса + PUSH AF + LD A,40h + OUT (PAGE1),A ; set DCP page + LD A,2Eh + LD (#4400),A ; open for WR + LD (#4600),A ; open for RD + POP AF + OUT (PAGE1),A ; Close PAGE1 ??????? + +RESET_LOOP: ; цикл сброса + LD BC,#0100 + OUT (C),C + LD BC,#0000 + OUT (C),C + JR RESET_LOOP ; полностью зациклить! + + HALT ; пылеуловитель +*/ +;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + +; ____ _ _ ____ _ +; | _ \ _ __(_)_ __ | |_ / ___|| |_ _ __ +; | |_) | '__| | '_ \| __| \___ \| __| '__| +; | __/| | | | | | | |_ ___) | |_| | +; |_| |_| |_|_| |_|\__| |____/ \__|_| +; Печать строки. Адрес строки в HL + +;-----------------; +PrintStr: + LD C,#5C + 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: + di + + ld a,(a_key) ; Выход без восстановления дефолтной конфы? + and a + + jp nz,1F +; jp nz,NormExit +; jp nz,NextReloadRET + + LD DE,NextReloadRET ; + LD (SP_Save),SP ; сохраняем стек + CALL Set_Ret ; установка данных для возврата + JP RESET + +1: + ; ld a,(l_key) + ; and a + ; jr nz, NextReloadRET + + DI + IN A,(CASH_ON) ; Включение кэша + + LD BC,1FFDh + XOR A + OUT (C),A ; отключить RAM-0 + + LD A,CNF_0 + OUT (SYS_PORT_ON),A ; DCP-PAGE 0 + + LD A,3 + OUT (CASH_PAGE),A ; Страница КЭШ = 3 + + LD A,#FF + ld (#3ef0),a ; затирание ACEX_K30_LOADING + LD (#3EE0),a ; затирание "IM" флага + + call page0_restore ; Возврат на место нулевой страницы + + jp NextReloadRET + +;******************************************************* + +; _ _ _ +; | \ | | _____ _| |_ +; | \| |/ _ \ \/ / __| +; | |\ | __/> <| |_ +; |_| \_|\___/_/\_\\__| +; ____ _ _ ____ _____ _____ +; | _ \ ___| | ___ __ _ __| | | _ \| ____|_ _| +; | |_) / _ \ |/ _ \ / _` |/ _` | | |_) | _| | | +; | _ < __/ | (_) | (_| | (_| | | _ <| |___ | | +; |_| \_\___|_|\___/ \__,_|\__,_| |_| \_\_____| |_| +; Подготовка к завершению после ресета и +; возврата родной прошивки +;-----------------; +NextReloadRET: + DI + ; +;-----------------; Затираем следы нестоковой конфы + LD A,Spec_Page + OUT (PAGE3),A ; открыть спец-страницу + + ld h,#FF + ld l,h + ld sp,hl + push hl + push hl + push hl + push hl + push hl + push hl + push hl + push hl + + ; LD (0FFF3h),A ; сохраняем страницы + ; ld A,(page0_save) + ; LD (0FFF0h),A ; DOS-PAGE + ; ld A,(page1_save) + ; LD (0FFF1h),A + ; ld A,(page2_save) + ; LD (0FFF2h),A ; программы для возврата??? +/* + xor a ; выставляем страницы, которые ставятся при ресете + LD (0FFF0h),A ; page 0 + ld A,5 + LD (0FFF1h),A ; page 1 + ld A,2 + LD (0FFF2h),A ; page 2 + ld A,40h + LD (0FFF3h),A ; page 3 + + xor a + LD d,a + LD e,a + LD (#FFF4),DE ; адрес программы перезапуска + LD (#FFFE),DE ; флаг перезапуска + + LD A,'Z' + LD (#FFFE),A + LD A,'X' + LD (#FFFF),A ; флаг перезапуска +*/ +;-----------------; +; + 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 + ld (NextParameter),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 + CP 'L' + JR Z,.set_keys_l + SCF ; ошибка в параметре + RET ; выход с ошибкой +;-----------------; + +;-----------------; +.set_keys_l: + inc c +.set_keys_a: + INC C +.set_keys_x: + INC C +.set_keys_e: + INC C +.set_keys_c: +; EX DE,HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! + LD HL,key_buff ; Вычисляем ячейку хранения ключа + ADD HL,BC + LD A,(HL) ; и проверяем нет ли там уже ключа. + and a ; если есть, значит ключ введён 2 раза + SCF + RET NZ ; ошибка - повтор ключа. выход + +; OR C ; Тут ОЖИДАЕТСЯ, что А=0. Если С=0, то это ключ "A" + LD A,1 ; Признак установки ключа - не ноль. + LD (HL),A ; установили ключ +; EX DE,HL ; НЕ ТЕРЯТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ ПАРАМЕТР! +; JR Z,.CheckChar ; если ключ "A" то следующий круг цикла + sub C ; Тут ОЖИДАЕТСЯ, что А=1. Если С>1, то это ключ без параметров +; JR Z,.CheckChar ; если ключ "X" то следующий круг цикла + JR c,.CheckChar ; если ключ больше ключа 'e', то следующий круг цикла + + 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: + LD HL,(NextParameter) + LD C,43h ; тут выделяем параметр запуска + LD DE,Buffer ; буфер для операций со строками + RST #10 ; получаем в буфере следующий параметр + ld (NextParameter),hl + 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 1 ; если 1, то это ключ "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) + AND A ; проверка на отсутствие хендлера + SCF + RET Z ; выход с ошибкой если файл не открыт + + ex af,af' ; сохраняем хендлер, экономим такты))) + ld a,(x_key) ; если проверка (ключ X) на хедер и размер + and a ; файла отключена, то пропускаем .TestConfHeader + jr nz,1F + + ex af,af' ; восстановили хендлер, сэкономили такты))) + CALL .TestConfHeader + ret c +1: + CALL .TestConfSize + RET +;-----------------; + +.TestConfHeader: + 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: ; сюда попадём когда BC=0 или символ не совпал. + RET Z ; если BC=0 и последний символ совпал (Z=1) + SCF ; если BC=0 и символ не совпал - ошибка + RET + +;-----------------; + +.TestConfSize: + LD B,2 ; Ставим указатель на конец файла + CALL .set_fp ; чтоб узнать его размер + RET C + LD A,H ; Размер файла в HL:IX. Нет смысла, если он больше + OR L ; 61152 байта, поэтому проверяем, что в HL ноль. + SCF + RET NZ + + ld a,(x_key) ; Сравниваем размер файла с эталлоным для 1K30 (59215 или #E74F) + and a ; либо (при установленном ключе X) с максимально возможным + jr nz,2F ; для текущего загрузчика в BIOS (61152 или #EEE0) +; +; Тут проверка на точное соответствие для 1K30 + LD HL,(ConfSize) + LD A,H + SUB XH + JR NZ,1F + LD A,L + SUB XL +1: SCF + RET NZ + jp 3F +; +; Тут проверка на непривышение 61152 байта +2: + LD HL,(MaxConfSize) + push ix + pop bc + sbc hl,bc + ret c + +3: + LD B,0 ; Возвращаем указатель + CALL .set_fp ; в файле на его начало + RET +;-----------------; + +.set_fp: ; Входное значение в регистре B + LD A,(ConfHandler) ; Хэндлер файла с которым сейчас работаем + 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 +;******************************************************* + +; _ _ ____ __ +; | | ___ __ _ __| | / ___|___ _ __ / _| +; | | / _ \ / _` |/ _` | | | / _ \| '_ \| |_ +; | |__| (_) | (_| | (_| | | |__| (_) | | | | _| +; |_____\___/ \__,_|\__,_| \____\___/|_| |_|_| +; Загружаем прошивку в память +;Процедура щёлкает PAGE3 без сохранения/восстановления +; предыдущего состояния. + +;-----------------; +Load_conf: + ld DE,#3000 + ld hl,ram_pages + ld b,4 +1: + ld a,(hl) + out (PAGE3),a + push hl + push bc +; call .loopRead +; ; Параметры: DE - сколько считать в страницу + LD A,(ConfHandler) ; а куда грузить - рассчитывается (#0000 - DE) + ld hl,#0000 + sbc hl,de ; Тут будет в HL адрес куда, а в DE сколько загружать + LD C,13h + RST 10h + + pop bc + pop hl + ret c + and a ; достигнут конец файла? + ret nz ; если A<>0, то да. Выход + + inc hl + LD DE,#4000 + djnz 1B + RET +;******************************************************* + +; ____ _ _ +; / ___| ___| |_ / \ ___ _____ __ +; \___ \ / _ \ __| / _ \ / __/ _ \ \/ / +; ___) | __/ |_ / ___ \ (_| __/> < +; |____/ \___|\__| /_/ \_\___\___/_/\_\ +; Перекидываем прошивку в кэш и освобождаем память, +; если нет второй прошивки +; (???освобождение памяти недоделанно???) + +;-----------------; +Set_Acex_Data: + DI + + IN A,(CASH_ON) ; Включение кэша + + LD BC,1FFDh + XOR A + OUT (C),A ; отключить RAM-0 + + LD A,CNF_0 + OUT (SYS_PORT_ON),A ; DCP-PAGE 0 + + LD A,(ram_pages) + OUT (PAGE1),A ; страница с данными файла + + xor a + OUT (CASH_PAGE),A ; Страница КЭШ = 0 + + LD HL,5000h ; перекидывание данных в страницу КЭШ = 0 + LD DE,1000h + LD BC,3000h + LDIR + + inc a + OUT (CASH_PAGE),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 (CASH_PAGE),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 (CASH_PAGE),A ; Страница КЭШ = 3 + LD A,(ram_pages+3) + OUT (PAGE1),A ; следующая страница с данными файла + + ld h,d ; LD HL,4000h + ld d,e ; LD DE,0000h + LD BC,#3EDF + LDIR + + LD HL,Reload_String ; флаг перезагрузки из КЭШ-а + LD DE,3EF0h + LD C,10h ; LD BC, 16 + LDIR + + LD HL,(ConfMultKeys) ; Если тут устанавливаем не 'IM' ключи + ld a,(l_key) ; то "no multiple! перезагрузка только одна", + and a ; иначе - хз, ещё не пробовал. + jr z,1F + LD HL,(ConfMultKeys+2) + +1: + LD (#3EE0),HL + + LD A,(page1_save) ; возврат страницы 1 + OUT (PAGE1),A + + call page0_restore ; Возврат на место нулевой страницы + + RET +;******************************************************* + +;-----------------; +;Восстановление 0-ой страницы +page0_restore: + xor a ; Отключение кэша + OUT (CASH_PAGE),A ; пишем в CASH_PAGE ноль, иначе в + IN A,(CASH_OFF) ; нулевое окно биос или ДСС не воткнутся + + LD A,CNF_0 + OUT (SYS_PORT_OFF),A + + LD BC,1FFDh + ld a,(port_1ffd_save) + OUT (C),A + ret +;-----------------; + + +; ____ _ ____ _____ _____ +; / ___| ___| |_ | _ \| ____|_ _| +; \___ \ / _ \ __| | |_) | _| | | +; ___) | __/ |_ | _ <| |___ | | +; |____/ \___|\__| |_| \_\_____| |_| +; Настройки перед ресетом +; Установка адреса возврата после reboot +; Сохранение активных страниц +; Адрес программы для возврата в регистре DE + +;-----------------; +Set_Ret: + DI + LD A,Spec_Page + OUT (PAGE3),A ; открыть спец-страницу + + LD (0FFF3h),A ; сохраняем в спецстраницу номер Spec_Page + LD (#FFF4),DE ; адрес программы перезапуска + + ld de,#FFF0 ; сохраняем страницы 0-2 в спецстранице + ld hl,page0_save + ldi + ldi + ldi + + LD A,'Z' ; флаги перезапуска + LD (#FFFE),A + LD A,'X' + LD (#FFFF),A + + ld A,(page3_save) ; Восстанавливаем начальную страницу 3 + OUT (PAGE3),A + EI + RET +;******************************************************* + + +;(.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) +; Подгрузка файла с переменными, константами и буферами: + INCLUDE "Consts.inc" +; +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 +;(.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) diff --git a/LDCONF50.ASM b/LDCONF50.ASM new file mode 100644 index 0000000..1586e7d --- /dev/null +++ b/LDCONF50.ASM @@ -0,0 +1,856 @@ +; _ ____ ____ __ +; | | | _ \ / ___|___ _ __ / _| +; | | | | | | | / _ \| '_ \| |_ +; | |___| |_| | |__| (_) | | | | _| +; |_____|____/ \____\___/|_| |_|_| + +; _____ ____ _ _ ____ _ +; | ___|__ _ __ / ___| _ __ _ __(_)_ __ | |_ ___ _ __ / ___|___ _ __ ___ _ __ _ _| |_ ___ _ __ +; | |_ / _ \| '__| \___ \| '_ \| '__| | '_ \| __/ _ \ '__| | | / _ \| '_ ` _ \| '_ \| | | | __/ _ \ '__| +; | _| (_) | | ___) | |_) | | | | | | | || __/ | | |__| (_) | | | | | | |_) | |_| | || __/ | +; |_| \___/|_| |____/| .__/|_| |_|_| |_|\__\___|_| \____\___/|_| |_| |_| .__/ \__,_|\__\___|_| +; |_| |_| +;******************************************************* +; Тестовая сборка или нет? + 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 +;(.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) diff --git a/LDCONFW.ASM b/LDCONFW.ASM new file mode 100644 index 0000000..f5129dc --- /dev/null +++ b/LDCONFW.ASM @@ -0,0 +1,855 @@ +; _ ____ ____ __ +; | | | _ \ / ___|___ _ __ / _| +; | | | | | | | / _ \| '_ \| |_ +; | |___| |_| | |__| (_) | | | | _| +; |_____|____/ \____\___/|_| |_|_| + +; _____ ____ _ _ ____ _ +; | ___|__ _ __ / ___| _ __ _ __(_)_ __ | |_ ___ _ __ / ___|___ _ __ ___ _ __ _ _| |_ ___ _ __ +; | |_ / _ \| '__| \___ \| '_ \| '__| | '_ \| __/ _ \ '__| | | / _ \| '_ ` _ \| '_ \| | | | __/ _ \ '__| +; | _| (_) | | ___) | |_) | | | | | | | || __/ | | |__| (_) | | | | | | |_) | |_| | || __/ | +; |_| \___/|_| |____/| .__/|_| |_|_| |_|\__\___|_| \____\___/|_| |_| |_| .__/ \__,_|\__\___|_| +; |_| |_| +;******************************************************* +; Тестовая сборка или нет? + 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,#374F + LD C,13h + RST 10h + RET C + CP #FF + JP Z,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 + 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 +;(.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) (.)(.) diff --git a/LDConf.txt b/LDConf.txt new file mode 100644 index 0000000..b55cf8e --- /dev/null +++ b/LDConf.txt @@ -0,0 +1,12 @@ +╨Ч╨░╨┐╤Г╤Б╨║ ╨▒╨╡╨╖ ╨┐╨░╤А╨░╨╝╨╡╤В╤А╨╛╨▓ - ╨┐╨╡╤З╨░╤В╤М ╨┐╨╛╨╝╨╛╤Й╨╕ ╨┐╨╛ ╨┐╨░╤А╨░╨╝╨╡╤В╤А╨░╨╝ ╨╖╨░╨┐╤Г╤Б╨║╨░. + +╨Я╨░╤А╨░╨╝╨╡╤В╤А╤Л ╤З╨╡╤А╨╡╨╖ ╨┐╤А╨╛╨▒╨╡╨╗: +a - ╨╜╨╡ ╨╖╨░╤В╨╕╤А╨░╤В╤М Acex Loading ╨┐╨╛╤Б╨╗╨╡ ╤А╨╡╤Б╨╡╤В╨░ ╨▓ ╨║╨╛╨╜╤Д╤Г +c - ╨┐╨╛╤Б╨╗╨╡ ╤Н╤В╨╛╨│╨╛ ╨║╨╗╤О╤З╨░ ╨┤╨╛╨╗╨╢╨╡╨╜ ╨╕╨┤╤В╨╕ ╤Д╨░╨╣╨╗ ╨║╨╛╨╜╤Д╤Л +e - EXE ╤Д╨░╨╣╨╗ ╨┤╨╗╤П ╨╖╨░╨┐╤Г╤Б╨║╨░ ╨┐╨╛╤Б╨╗╨╡ ╤А╨╡╤Б╨╡╤В╨░ ╨▓ ╨║╨╛╨╜╤Д╤Г +x - ╨┐╨╛╤Б╨╗╨╡ ╤Н╤В╨╛╨│╨╛ ╨║╨╗╤О╤З╨░ ╨┤╨╛╨╗╨╢╨╡╨╜ ╨╕╨┤╤В╨╕ ╤Д╨░╨╣╨╗ ╨║╨╛╨╜╤Д╤Л, + ╨║╨╛╤В╨╛╤А╤Л╨╣ ╨░╨║╤В╨╕╨▓╨╕╤А╤Г╨╡╤В╤Б╤П ╨┐╨╡╤А╨╡╨┤ ╨╖╨░╨▓╨╡╤А╤И╨╡╨╜╨╕╨╡╨╝ ╤А╨░╨▒╨╛╤В╤Л. + ╨┐╨░╤А╨░╨╝╨╡╤В╤А 'a' ╨╕╨│╨╜╨╛╤А╨╕╤А╤Г╨╡╤В╤Б╤П. + +╨Х╤Б╨╗╨╕ ╤Г╨║╨░╨╖╨░╨╜╨╛ ╤В╨╛╨╗╤М╨║╨╛ ╨╕╨╝╤П ╨┐╤А╨╛╤И╨╕╨▓╨║╨╕ - ╨╖╨░╨│╤А╤Г╨╖╨║╨░ ╨┐╤А╨╛╤И╨╕╨▓╨║╨╕, ╤А╨╡╤Б╨╡╤В, +╨╖╨░╤В╨╕╤А╨░╨╜╨╕╨╡ ╨┐╨░╤А╨░╨╝╨╡╤В╤А╨░ Acex loading, ╨▓╤Л╤Е╨╛╨┤ ╨▓ ╨┤╨╛╤Б. \ No newline at end of file diff --git a/SP2000.inc b/SP2000.inc new file mode 100644 index 0000000..4eed334 --- /dev/null +++ b/SP2000.inc @@ -0,0 +1,588 @@ +/* Всякие директивы для какого - то компилятора + .LION EQU 0 + .FLEX EQU 1 + .IBMK EQU 1 + .PROJ1 EQU 0 + .PROJ2 EQU 0 + .PROJ3 EQU 1 + .PROJ4 EQU 1 + .PAL EQU 1 +*/ +;ELCOM256 EQU 1 ; режим ELCOM-256 +;IF ELCOM256 EQ 1 + +D_TBON EQU 3 ; данные для включения TURBO +D_TBOFF EQU 2 ; данные для включения TURBO +D_ROM16ON EQU 1 +D_ROM16OFF EQU 0 +CNF_0 EQU 04h ; карта портов 0 +CNF_1 EQU 0Ch ; карта портов 1 +CNF_2 EQU 14h ; карта портов 2 +CNF_3 EQU 1Ch ; карта портов 3 +CNF_512 EQU 80h ; включение Pentagon 128 + +CBL_DIR EQU 78 ; порт управления COVOX-Blaster +; bit 7 - 1 включить CBL +;ELSE +;D_TBON EQU 03h ; данные для включения TURBO +;D_TBOFF EQU 02h ; данные для включения TURBO +;D_ROM16ON EQU 40h +;D_ROM16OFF EQU 00h +;CNF_0 EQU 04h +;CNF_1 EQU 0Ch +;CNF_2 EQU 14h +;CNF_3 EQU 1Ch +;ENDIF + +SPRINTER EQU 4 ; ВЕРСИЯ !!! +ISD_WARM EQU 3 +ISD_COLD EQU 0 +IS_KEY EQU 40h ; ДАННЫЕ ДЛЯ ВЫВОДА В ПОРТ ПРИ ВКЛЮЧЕНИИ IS-DOS +IS_RAM_ADR EQU 5BC0h ; АДРЕС ЗАГРУЗКИ ПРОГРАММЫ ПЕРЕХОДА В IS-DOS +TB_WAITES EQU 00H ; WAITы для TURBO-MODE +NTB_WAITES EQU 00H ; WAITы для neTURBO-MODE +IS_WAITES EQU 00H ; WAITы для IS-DOS +;**************************************** +;SYS_PORT_ON EQU 07DH +;SYS_PORT_OFF EQU 03DH +SYS_PORT_ON EQU 07CH +SYS_PORT_OFF EQU 03CH + +CASH_ON EQU #FB ;Включение кэша IN A,(CASH_ON) +CASH_OFF EQU #7B ;Отключение кэша IN A,(CASH_OFF) +CASH_PAGE EQU #5C ;Переключение страниц кэша + +PAL_V_PAGE EQU 09EH +PAL_SCP EQU 01EH + +CNF_PAGE EQU 040H ; страница портов +SYS_PAGE EQU 0FEH +MODE_PAGE EQU 0FCH +;SCR_PAGE EQU 0FDH +;PAL_PAGE EQU 0FDH + +KBD_COM EQU 1Bh +KBD_DAT EQU 1Ah + +COM_B EQU 1Bh +DAT_B EQU 1Ah +COM_A EQU 19h +DAT_A EQU 18h + +LPT1_D EQU 1CH +LPT1_C EQU 1DH +LPT2_D EQU 1EH +LPT2_C EQU 1FH + +STC0_C EQU 10H +STC1_C EQU 11H +STC2_C EQU 12H +STC3_C EQU 13H + +RAMD_LET EQU ('R' - 'A') + +P_KBD_OUT EQU 0F8H +P_KBD_IN EQU 0FEH +;*************************************** +;HD_HEADS EQU 5 +HD_CS EQU 0A0H + +;HD_S_P_T EQU 17 +;HD_S_X_H EQU (HD_S_P_T * HD_HEADS) ; ??? число секторое на цилиндре + +P_DATS EQU 050H ; READ/WRITE INIR/OTIR + +P_ERR EQU 051H ; READ +P_PREC EQU 151H ; WRITE + +P_S_CNT EQU 152H ; +P_S_NUM EQU 153H +P_C_LOW EQU 154H +P_C_HIG EQU 155H ;<-\ +P_HD_CS EQU 4152H ;<-/ + +P_HDST EQU 4053H ; READ +P_CMD EQU 4153H ; WRITE + +P_HD3F6 EQU 4154H ; WRITE 3F6 +P_HD3F7 EQU 4055H ; READ 3F7 + +;*************************************** +CMOS_DRD EQU 0FFBDh +CMOS_DWR EQU 0BFBDh +CMOS_AWR EQU 0DFBDh +ISA_PORT EQU 09FBDh + +;*************************************** +SEC_SIZE EQU 11 +CLAST_SIZE EQU 13 +RESERV_SECS EQU 14 +FATS_NUM EQU 16 +FLS_NUM EQU 17 +S_P_D EQU 19 +FORM_CODE EQU 21 +S_P_F EQU 22 +S_P_T EQU 24 +H_P_S EQU 26 +SPECIAL_SECS EQU 28 +FAT_ID EQU 36H +;*************************************** + +SYSTEM_ID EQU 0C020H + +SYS_SP EQU 0C0FEH ; ДОПОЛНИТЕЛЬНЫЙ СТЕК +DISK_TYPE EQU 0C100H ; переадресация дисков +COPY_PAGE0 EQU 0C104H ; копии значений портов страниц +COPY_PAGE1 EQU 0C105H +COPY_PAGE2 EQU 0C106H +COPY_PAGE3 EQU 0C107H +RAMD_VARS EQU 0C108H ; переменные RAM-дисков +A_RAMD_VARS EQU 0C118H ; текущий RAM-Disk +SP_SAVE EQU 0C11AH ; место для сохранения адреса стека +ERR_SAVE EQU 0C11CH +COPY_RGADR EQU 0C11DH +RAM_MSD EQU 0C11EH ; страница для работы в MS-DOS +MSD_SECS EQU 0C11FH ; Число секторов в MS-DOS +MSD_NAME EQU 0C120H ; Адрес имени найденного файла +;MSD_FAT_SEC EQU 0C122H ; начальный сектор FAT +INT_ADRESS EQU 0C124H ; начальный сектор CAT +INT_PAGE EQU 0C126H ; начальный сектор DAT +DS_1440 EQU 0C128H ; флаги переключения 720/1440 +F_P_S EQU 0C129H ; число файловых записей в секторе +S_P_C EQU 0C12AH ; число секторов каталога +COUNT_FL EQU 0C12BH ; счетчик файлов в секторе +COUNT_SEC EQU 0C12CH ; счетчик секторов в каталоге +C_P_B EQU 0C12DH ; число кластеров на блок ОЗУ +;CLASTER_LEN EQU 0C12EH ; длина кластера в байтах +FAT_FLAG EQU 0C130H ; FAT флаг + FAT sector +MSD_CONT_SEC EQU 0C132H ; текущий сектор для MS-DOS +MSD_CONT_SEC2 EQU 0C134H +S_X_H EQU 0C136H ; количество секторов на цилиндре +CONFIG_ALL EQU 0C138H ; описатель конфигурации +CONFIG_DE EQU 0C13AH ; описатель конфигурации +CONFIG_BYTE EQU 0C13EH ; байт конфигурации + +WIN_MAP_SC EQU 0C140H +WIN_TAB_SC EQU 0C142H +WIN_SAV_HL EQU 0C144H +WIN_SAV_DE EQU 0C146H +WIN_SAV_BC EQU 0C148H +WIN_ZG EQU 0C14AH +WIN_PLACE_WIN EQU 0C14CH +WIN_GR_MAP EQU 0C14EH + +SYS_WORK1 EQU 0C150H +SYS_WORK2 EQU 0C152H +SYS_WORK3 EQU 0C154H +SYS_WORK4 EQU 0C156H + +WIN_MAP_LAB1 EQU 0C158H +WIN_MODE_SH EQU 0C15CH +WIN_MODE_SC EQU 0C15EH + +MSD_FAT_SEC EQU 0C160H ; начальный сектор FAT +MSD_FAT_SEC2 EQU 0C162H ; начальный сектор FAT +MSD_CAT_SEC EQU 0C164H ; начальный сектор CAT +MSD_CAT_SEC2 EQU 0C166H ; начальный сектор CAT +MSD_DAT_SEC EQU 0C168H ; начальный сектор DAT +MSD_DAT_SEC2 EQU 0C16AH ; начальный сектор DAT +CLASTER_LEN EQU 0C16CH ; длина кластера в байтах +CLASTER_LEN2 EQU 0C16EH ; длина кластера в байтах + +;CMOS_FLAG_1 EQU 0C170H + +GR_BIT_END EQU 7 + +S_BIT_END EQU 7 +S_BIT_LIN EQU 6 +S_BIT_MOD EQU 5 + +BIT_1440 EQU 1 +BIT_MASK_1440 EQU 00000010B + +RAMD_KEYS EQU 0C180H ; ключи RAM-Disks +RAMD_KEY_NUM EQU 16 + +LIB_TABLE EQU 0C1A0H ; таблицы librares 32 байта +; +0 библиотека DOS + +HDD_INI_TABLE EQU 0C1C0H ; таблицы для ide устройств 32 байта +; 0 - копия DRV_HEAD +; 1 - секторов на дорожке +; 2 - число головок +; 3 - количество цилиндров мл. +; 4 - количество цилиндров старший. +; 5 - секторов на цилиндр мл. +; 6 - секторов на цилиндр старш. +; 7 - reserv - type + +FDD_INI_TABLE EQU 0C1E0H ; таблицы для FDD устройств 32 байта + +RAMD_FAT EQU 0C200H ; расположение блоков RAM-Disk-ов + +MS_BPB EQU 0C400H ; буфер BPB +MS_DIR EQU 0C800H ; буфер DIR sector +MS_FAT EQU 0CC00H ; буфер FAT sector +MS_BUF EQU 0D000H ; буфер DAT sector +HD_IDF_ADR EQU 0C600H + + +WIN_MAP_IX EQU 0E000H ; данные карт окон + +TASK_DATA EQU 0EC00H ; данные для задач + +; ***** - Оконные переменные - ***** + +WIN_SIZE_H EQU 0 ; горизонтальный размер в знакоместах +WIN_SIZE_V EQU 1 ; вертикальный размер в знакоместах +WIN_PLACE_H EQU 2 ; положение по горизонрали, в знакоместах +WIN_PLACE_V EQU 3 ; положение по вертикали в знакоместах +WIN_MODE EQU 4 ; режим знакоместа +WIN_MODE_S EQU 5 ; дополнительный режим +; бит 0 - Sp-SCR, +WIN_GR_X EQU 6 ; положение по X в поле графики (по знакомест) +WIN_GR_Y EQU 7 ; положение по Y в поле графики (по знакомест) + +WIN_HL EQU 8 ; сохранение HL +WIN_BC EQU 10 ; сохранение BC +WIN_DE EQU 12 ; сохранение DE +WIN_V_BEG EQU 14 ; начало окна по вертикали +WIN_V_END EQU 15 ; конец окна по вертикали +WIN_H_BEG EQU 16 ; начало окна по горизонтали +WIN_H_END EQU 17 ; конец окна по горизонтали +WIN_SIZE_REL EQU 18 ; реальный размер в символах +WIN_MODE_E EQU 19 ; дополнительный режим экрана +WIN_WORK_1 EQU 20 ; рабочая переменная 1 +WIN_WORK_2 EQU 21 ; рабочая переменная 2 +WIN_GRAF_X EQU 24 ; начальная координата по X +WIN_GRAF_Y EQU 26 ; начальная координата по Y + +USER_VARS EQU 0F000h ; переменные пользователей + +;SW_ROM EQU 3CF9H + +; IF .PROJ4 +;RGADR EQU 0D0H +;RGSCR EQU 0D1H +;RGMOD EQU 0D2H +;RGACC EQU 0D3H +;PGACC EQU 0FCH + +;PAGE0 EQU 0C0H +;PAGE1 EQU 0C5H +;PAGE2 EQU 0C2H +;PAGE3 EQU 0C0H + +; ELSE + +; ENDIF + +PAGE0 EQU 082H ; номер банки 0 +PAGE1 EQU 0A2H ; номер банки 1 +PAGE2 EQU 0C2H ; номер банки 2 +PAGE3 EQU 0E2H ; номер банки 3 + +;RGADR EQU 089H +;RGSCR EQU 0A9H +;RGMOD EQU 099H +;RGACC EQU 0B9H +PORT_Y EQU 089H +RGADR EQU 089H +RGSCR EQU 0E9H +RGMOD EQU 0C9H +;RGACC EQU 0A9H +;PGACC EQU 0FCH +CNF_PORT EQU 7Ch + +ALTERA EQU 1400H + +WG_COM EQU 00FH +WG_TRK EQU 03FH +WG_SEC EQU 05FH +WG_DATA EQU 07FH +P_DOS_FF EQU 0FFH + +BUFER_RD EQU 5D25H + +PR_BUFER EQU 05B00H +AUTO_5B08 EQU 05B08H +AUTO_5B5C EQU 05B5CH +COPY_P128 EQU 05B5CH +AUTO_5BFF EQU 05BFFH +K_STATE EQU 05C00H +KEY_TIME EQU 05C09H +REP_K_TYME EQU 05C10H +ZG EQU 05C36H +ERR_BEEP EQU 05C38H +KEY_BEEP EQU 05C39H +ERR_NR EQU 05C3AH +FLAGS EQU 05C3BH +TV_FLAG EQU 05C3CH +ERR_SP EQU 05C3DH +LIST_SP EQU 05C3FH +MODE EQU 05C41H +NEW_PPC EQU 05C42H +NEW_S_PPC EQU 05C44H +PPC EQU 05C45H +SUB_PPC EQU 05C47H +BORDER EQU 05C48H +EDIT_PPC EQU 05C49H +BAS_VARS EQU 05C4BH +WORK_VAR EQU 05C4DH +CHANS EQU 05C4FH +CUR_CHL EQU 05C51H +BAS_PROG EQU 05C53H +NEXT_LINE EQU 05C55H +DATA_ADR EQU 05C57H +E_LINE EQU 05C59H +K_CUR EQU 05C5BH +CH_ADR EQU 05C5DH +SINT_ER_AD EQU 05C5FH +WORK_SP EQU 05C61H +STK_BOT EQU 05C63H +STK_END EQU 05C65H +B_REG EQU 05C67H +MEM_CALC EQU 05C68H +FLAGS_2 EQU 05C6AH +L_SCR_SIZE EQU 05C6BH +AUTO_LST_L EQU 05C6CH +OLD_PPC EQU 05C6EH +OLD_S_PPC EQU 05C70H +FLG_INPUT EQU 05C71H +S_VAR_LEN EQU 05C72H +SINT_TB_ADR EQU 05C74H +RAND_SEED EQU 05C76H +FRAMES EQU 05C78H +UDG EQU 05C7BH +X_Y_COORD EQU 05C7DH +PRN_POS EQU 05C7FH +ADR_PR_BUF EQU 05C80H +ECHO_E EQU 05C82H +SCR_PL_M EQU 05C84H +SCR_PL_L EQU 05C86H +SCR_POS_M EQU 05C88H +SCR_POS_L EQU 05C8AH +SCROLL_ST EQU 05C8CH +ATTR_P EQU 05C8DH +MASK_P EQU 05C8EH +ATTR_T EQU 05C8FH +MASK_E EQU 05C90H +FLAGS_ATR EQU 05C91H +MEM_BOT EQU 05C92H +AUTO_5C9A EQU 05C9AH +NMI_ADR EQU 05CB0H +TOP_CLEAR EQU 05CB2H +P_RAMTOP EQU 05CB4H +BEG_ADRESS EQU 05CB6H +RET_INS EQU 05CC2H +AUTO_5CC3 EQU 05CC3H +DISK_A EQU 05CC8H +DISK_B EQU 05CC9H +DISK_C EQU 05CCAH +DISK_D EQU 05CCBH +CAT_SEC EQU 05CCCH +DRV_READY EQU 05CCDH +RD_WR_COM EQU 05CCEH +VAR_1 EQU 05CCFH +AUTO_5CD1 EQU 05CD1H +AUTO_5CD2 EQU 05CD2H +AUTO_5CD3 EQU 05CD3H +AUTO_5CD5 EQU 05CD5H +DOS_ERROR EQU 05CD6H +MED_START EQU 05CD7H +DOS_CH_ADR EQU 05CD9H +MED_LEN EQU 05CDBH +FL_NAME EQU 05CDDH +FL_N_2 EQU 05CDFH +FL_N_4 EQU 05CE1H +FL_N_6 EQU 05CE3H +FL_N_7 EQU 05CE4H +FL_TYPE EQU 05CE5H +FL_START EQU 05CE6H + +FL_LEN EQU 05CE8H +START_CLASTER EQU FL_LEN + +FL_SIZE EQU 05CEAH +FL_PLACE EQU 05CEBH +VAR_2 EQU 05CEDH +INTERF_I EQU 05CEFH +VAR_2_0 EQU 05CF1H +VAR_2_1 EQU 05CF2H +CONT_SEC EQU 05CF4H +CONT_TRK EQU 05CF5H +OPER_DISK EQU 05CF6H +DOS_FLAG EQU 05CF7H +DISK_1_FLG EQU 05CF8H +DISK_2_FLG EQU 05CF9H +TIME_A EQU 05CFAH +TIME_B EQU 05CFBH +TIME_C EQU 05CFCH +TIME_D EQU 05CFDH +COMAND_WG EQU 05CFEH +SEC_NUM EQU 05CFFH +CONT_BUF_ADR EQU 05D00H +WORK_2 EQU 05D02H +WORK_4 EQU 05D04H +S_NAME_NUM EQU 05D06H +N_DEL_FLS EQU 05D07H +FST_SYM_NAME EQU 05D08H +VAR_3 EQU 05D09H +BUF_FLAG EQU 05D0CH +BAS_DOS_FLG EQU 05D0EH +DOS_ERR_2 EQU 05D0FH +ERR_3D00 EQU 05D10H +ADR_DOS_COM EQU 05D11H +ERR_SP_COPY EQU 05D13H +MSG_FLAG EQU 05D15H +PDOS_COPY EQU 05D16H +FLAG_BOOT EQU 05D17H +INT_1_VAR EQU 05D18H +CONT_DISK EQU 05D19H +ADR_RET EQU 05D1AH +DOS_SP EQU 05D1CH +FL_NUMBER EQU 05D1EH +COM_LN_COPY EQU 05D20H +L_5D23 EQU 05D23H +BUFER EQU 05D25H +AUTO_5D33 EQU 05D33H +CLEAR_SEC EQU 05E06H +CLEAR_TRK EQU 05E07H +TYPE_DISK EQU 05E08H +N_FILES EQU 05E09H +FREE_SEC EQU 05E0AH +CODE_10H EQU 05E0CH +DISK_MRK_1 EQU 05E0FH +DISK_ALT_NM EQU 05E10H +N_DEL_FL EQU 05E19H +DISK_NAME EQU 05E1AH + + + +;RET_PAGE0 MACRO +; LD A,0 +; OUT (PAGE0),A +; ENDM +;RET_PAGE1 MACRO +; LD A,5 +; OUT (PAGE1),A +; ENDM +;RET_PAGE2 MACRO +; LD A,2 +; OUT (PAGE2),A +; ENDM +; + MACRO RET_PAGE3 + LD A, 0 + OUT (PAGE3), A + ENDM +; + MACRO DSS adr, dt + IF (adr >= $) + DUP ((adr - $) / 16) + DB dt,dt,dt,dt,dt,dt,dt,dt,dt,dt,dt,dt,dt,dt,dt,dt + EDUP + DUP (adr - $) + DB dt + EDUP + ELSE + ASSERT 0, "Error memory relocation." + ENDIF + ENDM + + MACRO CALL_48 adr + LOCAL ADR_R + PUSH HL + LD HL, ADR_R + PUSH HL + LD HL, SW_ROM + PUSH HL + LD HL, adr + JP JP_HL_48 +ADR_R: POP HL + ENDM + + MACRO CALL_48X adr + LOCAL ADR_R + PUSH HL + LD HL, ADR_R + EX (SP), HL + PUSH HL + LD HL, SW_ROM + EX (SP), HL + PUSH HL + LD HL, adr + EX (SP), HL + JP SW_ROM +ADR_R: + ENDM + + MACRO RAMD_KEY + SUB 4 + DI + LD B, SYS_PAGE + LD C, PAGE3 + OUT (C), B + LD HL, RAMD_KEYS + ADD A, L + LD L, A + DEC L + LD (A_RAMD_VARS), HL + INC L + LD L, (HL) + RET_PAGE3 + EI + LD A, L + ENDM + + + + +; Поpты Sprinter. (байты PORT_X)<< +; 0 - port FF<< +; 1 - port keyboard<< +; 2 - port BORDER<< +; 3 - port 1FFDh<< +; 4 - port 7FFDh<< +; 5 - port 3FFDh<< +; 6 - port Start-ROM<< +; 7 - port Start-ROM-ALT<< +; 8 - port ROM-BASIC48<< +; 9 - port ROM-BASIC128<< +; 10 - port ROM-TR-DOS<< +; 11 - port ROM-EXPANSION<< +; 12 - port ROM-BASIC48-ALT<< +; 13 - port ROM-BASIC128-ALT<< +; 14 - port ROM-TR-DOS-ALT<< +; 15 - port ROM-EXPANSION-ALT<< +; 16 ─┐<< +; .. ─┤<< +; 31 ─┴─ports RAM-PAGES - поpты указывающие, какая стpаница ОЗУ<< +; подключена в качестве стpаницы 0..F в конфигуpации Scorpion.<< +; 33 - port RAM-0 стpаница ОЗУ подключаемая в нулевое окно пpоцессоpа<< +; 34 - port RAM-5 стpаница ОЗУ подключаемая в пеpвое окно пpоцессоpа<< +; 35 - port RAM-2 стpаница ОЗУ подключаемая во втоpое окно пpоцессоpа<< +; 36 - port CONFIG<< +; 37 - port COVOX-1<< +; 38 - port COVOX-2<< +; 39 - port AY-3-8910-adr<< +; 40 - port AY-3-8910-dat<< +; 41 - port KEMPSTON<< +; 42 - port ISA-interface<< +; 43 ─┐reserv<< +; .. ─┤<< +; 47 ─┘<< +; 48 - 51 поpты ВГ93<< +; 52 - поpт DOS-1<< +; 53 - поpт DOS-2<< +; 54 ─┐ служебные поpты<< +; .. ─┤<< +; 63 ─┘<< +; 64 ─┐ поpты IDE interface<< +; .. ─┤<< +; 79 ─┘<< +; 80..127 - pезеpв.<< +; 128..143 - поpты идентификатоpа машины ( только для чтения.)<< +; 144..254 - pезеpв<< +; 255 - нуль-поpт - отключенное состояние.<< +; diff --git a/Shared_Includes b/Shared_Includes new file mode 160000 index 0000000..6e27011 --- /dev/null +++ b/Shared_Includes @@ -0,0 +1 @@ +Subproject commit 6e27011b6259b0256ce65d91a53ef1185223eafa diff --git a/game conf.txt b/game conf.txt new file mode 100644 index 0000000..d9c3856 --- /dev/null +++ b/game conf.txt @@ -0,0 +1,75 @@ +╨╖╨░╨│╤А╤Г╨╖╨║╨░ ╨▓ 0C000h ╨┐╨╛ 16384 (4000h) + +0: 1 +hl 4100h +de 1000h +bc 3000h + +1: 1 +hl 7100h +de 0000h +bc 0f00h + +1: 2 +hl 4000h +de 0f00h +bc 3100h + +2: 2 +hl 7100h +de 0000h +bc 0f00h + +2: 3 +hl 4000h +de 0f00h +bc 3100h + +3: 3 +hl 7100h +de 0000h +bc 0f00h + +3: 4 +hl 4000h +de 0f00h +bc 3100h + +3: exe +hl ╤Б╤В╤А╨╛╨║╨░ +de 3EF0 +bc 16 + +╨╕╤В╨╛╨│╨╛ ╨╖╨░╨│╤А╤Г╨╢╨░╨╡╤В╤Б╤П 0F000h (61440) + +╨▓ ╤Б╤В╤А╨░╨╜╨╕╤Ж╨╡ ╤Б╨╝. ╨▓ ╤Б╤В╤А. ╨Ъ╨н╨и ╤А╨░╨╖╨╝╨╡╤А ╤Б╨╝╨╡╤Й╨╡╨╜╨╕╨╡ ╨▓ ╤Д╨░╨╣╨╗╨╡ +4100-70FF, 1x0100-30FF 0x1000-3FFF 3000 0100-30FF +7100-7fff, 1x3100-3FFF 1x0000-0EFF 0F00 3100-3FFF +4000-70FF, 2x0000-30FF 1x0F00-3FFF 3100 4000-70FF +7100-7FFF, 2x3100-3FFF 2x0000-0EFF 0F00 7100-7FFF +4000-30FF, 3x0000-30FF 2x0F00-3FFF 3100 8000-B0FF +7100-7FFF, 3x3100-3FFF 3x0000-0EFF 0F00 B100-BFFF +4000-70FF, 4x0000-30FF 3x0F00-3FFF 3100 C000-F0FF (EFDF) + 3x3EE0-3EE0 0001 FF - ╨╛╨┤╨╜╨░ ╨┐╨╡╤А╨╡╨╖╨░╨│╤А╤Г╨╖╨║╨░ +XXXX-XX16. XxXXXX-XX16 3x3EF0-3EFF 0010 Acex_Loading + + +0 0100-30FF 3000 +1 3100-70FF 4000 +2 7100-B0FF 4000 +3 B100- + +╨║╤Н╤И +0000 - 1000 - ╨┐╤Г╤Б╤В╨╛ +1000 - E74F - ╨║╨╛╨╜╤Д╨░ +3000 1 ╨▒╨╗╨╛╨║ +4000 2 ╨▒╨╗╨╛╨║ +4000 3 ╨▒╨╗╨╛╨║ +374f 4 ╨▒╨╗╨╛╨║ + + +╨│╤А╤Г╨╖╨╕╨╝ ╨▓ 1 ╤Б╤В╤А╨░╨╜╨╕╤Ж╤Г 3000h ╨▒╨░╨╣╤В ╤Б ╨░╨┤╤А╨╡╤Б╨░ ╨б000 ╨╕╨╗╨╕ D000 +╨│╤А╤Г╨╖╨╕╨╝ ╨▓╨╛ 2 ╤Б╤В╤А╨░╨╜╨╕╤Ж╤Г 4000h ╨▒╨░╨╣╤В +╨│╤А╤Г╨╖╨╕╨╝ ╨▓ 3 ╤Б╤В╤А╨░╨╜╨╕╤Ж╤Г 4000h ╨▒╨░╨╣╤В +╨У╤А╤Г╨╖╨╕╨╝ ╨▓ 4 ╤Б╤В╤А╨░╨╜╨╕╤Ж╤Г 374Fh ╨▒╨░╨╣╤В ╨╕ ╨▓╤В╤Л╨║╨░╨╡╨╝ ╨▓ ╨╜╨╡╤С ╨▓╤Б╨╡ ╨┐╨╡╤А╨╡╨╝╨╡╨╜╨╜╤Л╨╡ ╤В╨╕╨┐╨░ Acex_Loading +