;[BEGIN] ;//MODULE: EXECUTE ;//CREATE: 19-05-1998 AUTHOR: Denis Parinov ;//UPDATE: 24-10-1999 DNS Restore module ;--------------------------------------------------------------- ;Rev Date Name Description ;--------------------------------------------------------------- //;R12 20-07-2023 BAO При завершении приложения через функцию #41 или "аварийно" в возвращаемое приложение передаётся код ошибки и флаг CF=1 ;R11 17-04-2023 BAO OPTIMIZED BUFFERS, FREED UP 768 BYTES FOR CODE ;R10 13-04-2023 BAO FIX BUG WITH PARSING DIRECTORY BUFFER ;R09 -- 14-04-2003 DNS NOW EXEC DON'T FOLLOW TO PROGRAM'S DIR ;R08 05-12-2002 DNS FIX BUG WITH INCREMENT TASK ID AND OPEN *.EXE ERROR ;R07 05-12-2002 DNS FIX FOR EXECUTING IN CURRENT DIR WITHOUT PATH ;R06 02-12-2002 DNS FIX BUG WITH NULL-TERMINATED STRING ;R05 02-12-2002 DNS ADD APP_PATH TO THE PROGRAM PREFIX ;R04 26-11-2002 DNS TRY TO FIX EXEC WITH PATH ;R03 19-11-2002 DNS CHECK SUBFN. FOR FN. EXEC ;R02 24-05-1999 DNS FIX CREATE PSP AND ; MOVE EXEC STACK ;R01 14-05-1999 DNS DECREASE HEADER SIZE FOR EXE-FILE ;--------------------------------------------------------------- ////////////////////////////////////////////////////////////////////// ; !FIXIT тут одни затупы и дебилизм ; Функция #47. Получение информации приложения. ; ; вход: HL - буфер данных ; B - номер подфункции: ; B=0 - получение параметров командной строки ; B=1 - получение полного пути к каталогу программы ; B=2 - получение полного пути и имени файла программы ; выход: нет ; ; APPLICATION INFO ;==================== ; B = 0 - GET APP_PARAM ; B = 1 - GET APP_PATH ; B = 2 - GET APP_FULLNAME ////////////////////////////////////////////////////////////////////// ;LAST_PSP_PTR: DW 0 APPINFO: INC B ; DJNZ .FN1 ; получение параметров командной строки EX DE,HL XOR A LD (DE),A LD HL,(.LAST_PSP_PTR) LD C,(HL) INC C RET Z INC HL LDIR AND A RET .FN1: DJNZ .FN2 ; получение полного пути к каталогу программы EX DE,HL .LAST_PSP_PTR+1: LD HL,0 LD C,(HL) INC HL ADD HL,BC INC HL INC HL PUSH HL LD BC,#100 ;!HARDCODE длина коммандной строки XOR A CPIR DEC HL ;R10 ;[x] исправлен баг с парсингом буфера каталога DEC HL ;R10,5 - не тестил ;!!!!! LD BC,#100 ;R10 ;[x] не было этой команды, CPDR мог не прошерстить всё ;!HARDCODE длина коммандной строки LD A,'\' CPDR INC HL INC HL POP BC AND A SBC HL,BC ;R10 ;[x] могло всё в космос улететь LD A,DSS_Error.sys.COMMON_ERROR JR C,.error ; LD A,B ;EX HL,A,BC LD B,H LD H,A LD A,C LD C,L LD L,A LDIR XOR A LD (DE),A RET ; .FN2: DJNZ .FN3 ; получение полного пути и имени файла EX DE,HL LD HL,(.LAST_PSP_PTR) LD C,(HL) INC HL ADD HL,BC INC HL INC HL ; .loop LD A,(HL) LDI OR A JR NZ,.loop ; RET ; .FN3: ; ; ошибка LD A,DSS_Error.sys.INVALID_FUNCTION .error: SCF RET ////////////////////////////////////////////////////////////////////// ; Функция #45. Разбор командной строки. ; ; вход: HL - указатель командной строки ; DE - указатель на буфер пользователя ; B - номер подфункции: ; 0 - Разобрать строку ; 1 - Выделить имя диска ; 2 - Выделить директорию ; 3 - Выделить имя файла ; 4 - Выделить расширение файла ; 5 - Выделить имя диска, путь к файлу, имя файла и расш. файла ; 6 - Зарезервировано ; 7 - Выделить параметр командной строки ; 8 - Преобразовать из 11 символьного формата в формат ДОС ; 9 - Преобразовать из формата ДОС в 11 символьный формат ; выход: нет ////////////////////////////////////////////////////////////////////// GLOB_PR EQU 7 ;%10000000 DRIV_PR EQU 3 ;%00001000 PATH_PR EQU 2 ;%00000100 EXTN_PR EQU 1 ;%00000010 NAM_PR EQU 0 ;%00000001 EX_PATH: EXX LD HL,NM_PATH_A ;BUILT-IN BUFFER FOR PATH ;!!!!! используется общий буфер LD (NM_PATH),HL LD HL,NM_NAME_A LD (NM_NAME),HL LD HL,NM_EXTN_A LD (NM_EXTN),HL LD HL,NM_DRIVE_A LD (NM_DRIVE),HL EXX INC B DEC B ;JR Z,EX_GET_ALL JR Z,EX_FULL ;0 ; разобрать строку DEC B JR Z,EX_GET_DRIVE ;1 ; выделить имя диска DEC B JR Z,EX_GET_PATH ;2 ; выделить директорию DEC B JR Z,EX_GET_NAME ;3 ; выделить имя файла DEC B JR Z,EX_GET_TYPE ;4 ; выделить расширение файла DEC B JR Z,EX_GET_ALL_EX ;5 ; выделить диск, путь, файл и расш. DEC B JR Z,EX_RESR ;6 ; зарезервировано DEC B JP Z,GSWITCH ;7 ; выделить параметр ком-строки DEC B JP Z,GETNAME ;8 ; преобр. имя 11 -> 8.3 формат DEC B JP Z,MASK ;9 ; преобр. имя 8.3 -> 11 формат EX_RESR: LD A,DSS_Error.sys.INVALID_FUNCTION SCF RET ; Выделить имя диска EX_GET_DRIVE: LD (NM_DRIVE),DE CALL EX_FULL RET C LD DE,(NM_DRIVE) LD A,(DE) DEC A CP #FF RET Z CP "A"-1 JR C,ERGD001 CP "Z" JR NC,ERGD001 SUB "A"-1 RET ERGD001 LD A,DSS_Error.sys.INVALID_DRIVE SCF RET ; Выделить директорию EX_GET_PATH LD (NM_PATH),DE JR EX_FULL ; Выделить имя файла EX_GET_NAME LD (NM_NAME),DE JR EX_FULL ; Выделить расширение файла EX_GET_TYPE LD (NM_EXTN),DE JR EX_FULL ; Разобрать строку ; EX_GET_ALL ; JR EX_FULL ; Выделить диск, путь, файл и расш. EX_GET_ALL_EX: EX DE,HL LD C,(HL) INC HL LD B,(HL) INC HL LD (NM_DRIVE),BC LD C,(HL) INC HL LD B,(HL) INC HL LD (NM_PATH),BC LD C,(HL) INC HL LD B,(HL) INC HL LD (NM_NAME),BC LD C,(HL) INC HL LD B,(HL) LD (NM_EXTN),BC EX DE,HL ;JR EX_FULL ; Разобрать строку EX_FULL: EX AF,AF' EXX XOR A LD HL,(NM_PATH) LD (HL),A LD HL,(NM_NAME) ; адрес буфера под имя файла LD (HL),A LD HL,(NM_EXTN) LD (HL),A LD HL,(NM_DRIVE) LD (HL),A EXX EX AF,AF' EX_PAT0: LD DE,TMPBUF LD BC,#0D01 ;!HARDCODE счетчики EX_PAT1: LD A,(HL) CALL UPPER ; a..z -> A..Z LD (DE),A INC HL INC DE INC C ; ++счетчик CP '\' JR Z,PATH_YEP CP ":" JR Z,DRIVE_YEP CP "!" JR C,NAME_YEP CP "?" JR Z,GLOBP1 CP "*" JR Z,GLOBP1 EX_PAT2: DJNZ EX_PAT1 LD A,DSS_Error.sys.INVALID_NAME SCF RET GLOBP1: EX AF,AF' SET GLOB_PR,A EX AF,AF' JR EX_PAT2 NAME_YEP: LD A,2 CP C JR Z,NOFNAME PUSH HL LD HL,TMPBUF LD DE,(NM_NAME) ; адрес буфера под имя файла LD B,0 DEC C DEC C LD A,C LDIR LD C,A XOR A LD (DE),A LD HL,(NM_NAME) LD A,"." CPIR JR NZ,NOEXTN LD C,3 LD DE,(NM_EXTN) EXTSK0: LD A,(HL) OR A JR NZ,EXTSK1 LD A,' ' DEC HL EXTSK1: LD (DE),A INC HL INC DE DEC C JR NZ,EXTSK0 XOR A LD (DE),A EX AF,AF' SET EXTN_PR,A ; указано расш. файла EX AF,AF' NOEXTN: EX AF,AF' SET NAM_PR,A ; указано имя файла EX AF,AF' POP HL NOFNAME: EX AF,AF' AND A RET DRIVE_YEP: XOR A LD (DE),A PUSH HL LD HL,TMPBUF LD DE,(NM_DRIVE) LD B,0 LDIR POP HL EX AF,AF' SET DRIV_PR,A ; указано имя диска EX AF,AF' JP EX_PAT0 PATH_YEP: XOR A LD (DE),A PUSH HL PUSH BC LD HL,(NM_PATH) LD BC,#00FF ; !FIXIT глубина буфера не зависит от CurrentDirectory.DEPTH CPIR DEC HL EX DE,HL LD HL,TMPBUF ; 12 пробелов POP BC LD B,0 LDIR POP HL EX AF,AF' SET PATH_PR,A EX AF,AF' JP EX_PAT0 TMPBUF: DB " ",#00 ; 12 пробелов NM_DRIVE: DW NM_DRIVE_A NM_NAME: DW NM_NAME_A NM_EXTN: DW NM_EXTN_A NM_PATH: DW NM_PATH_A NM_DRIVE_A: BLOCK 9,0 NM_NAME_A: DB " ",#00 NM_EXTN_A: DB " ",0 NM_PATH_A EQU CORE_BUFFERS.BUFFER ;DS 256 ;!!!!! shared buffer ////////////////////////////////////////////////////////////////////// ; Функция #43. Выделить параметр командной строки. ; ; вход: HL - указатель командной строки ; DE - буфер для выдел. параметра ; выход: HL - указатель на след. параметр ком-строки ; CF=0 - конец строки не достигнут (есть другие параметры) ; CF=1 - конец строки (в буфер перенесён последний параметр или ноль) ; ;ENTRY: HL - COMMAND LINE ; DE - SWITCH BUFFER ;EXIT: BUFFER ////////////////////////////////////////////////////////////////////// GSWITCH: XOR A LD (DE),A GSWIT1: LD A,(HL) INC HL CP " " RET C JR Z,GSWIT1 GSWIT2: LD (DE),A LD A,(HL) INC HL INC DE CP " "+1 JR NC,GSWIT2 CP " " LD A,0 LD (DE),A RET ////////////////////////////////////////////////////////////////////// ; Функция #3C. Информация о памяти. ; ; вход: нет ; выход: HL - общее кол-во страниц ; BC - кол-во своб. страниц ////////////////////////////////////////////////////////////////////// FREEMEM: LD C,BIOS.GetMemSize RST ToBIOS RET ////////////////////////////////////////////////////////////////////// ; Функция #3D. Выделение блока памяти. ; ; вход: B - размер блока в страницах по 16kB ; выход: A - идентификатор блока памяти, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// GETMEM: LD C,BIOS.GetMem RST ToBIOS LD E,A LD A,DSS_Error.sys.NOT_ENOUGH_MEMORY RET C LD D,#00 LD HL,MEMTAB ; массив списка выдел. страниц ADD HL,DE LD A,(TASK) ; уровень текущей программы LD (HL),A LD A,E AND A RET ////////////////////////////////////////////////////////////////////// ; Функция #3E. Освобождение блока памяти. ; ; вход: A - идентификатор блока памяти ; выход: A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// RETMEM: LD E,A LD D,#00 LD HL,MEMTAB ; массив списка выдел. страниц ADD HL,DE LD A,(TASK) ; уровень текущей программы CP (HL) LD A,DSS_Error.sys.INVALID_MEMORY_HND SCF RET NZ PUSH DE LD A,E LD C,BIOS.FreeMem RST ToBIOS POP DE LD A,DSS_Error.sys.INVALID_MEMORY_HND RET C LD HL,MEMTAB ADD HL,DE XOR A LD (HL),A RET ////////////////////////////////////////////////////////////////////// ; Функция #3F. Изменение блока памяти. ; ; вход: A - идентификатор блока памяти ; B - новый размер блока ; выход: A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETMEM: LD E,A LD D,#00 LD HL,MEMTAB ADD HL,DE LD A,(TASK) CP (HL) LD A,DSS_Error.sys.INVALID_MEMORY_HND SCF RET NZ LD D,B PUSH DE LD A,E CALL SIZEBLK POP DE LD A,DSS_Error.sys.INVALID_MEMORY_HND RET C LD A,B CP D RET Z JR C,INCMEM DECMEM: LD B,D LD A,E LD C,BIOS.DivMemBlocks RST ToBIOS LD A,B LD C,BIOS.FreeMem RST ToBIOS XOR A RET ; Добавить страниц памяти к блоку INCMEM: LD A,D SUB B LD B,A LD C,E PUSH BC LD C,BIOS.GetMem RST ToBIOS POP BC LD B,A LD A,DSS_Error.sys.NOT_ENOUGH_MEMORY RET C LD A,C LD C,BIOS.MergeMemBlocks RST ToBIOS XOR A RET SIZEBLK: LD B,#FF LD C,A .loop: INC B PUSH BC LD A,C LD C,BIOS.GetMemPage RST ToBIOS POP BC JR NC,.loop OR A SCF RET Z XOR A RET LEAVMEM: LD HL,MEMTAB LD BC,256 ;!HARDCODE размер блока страниц ОЗУ .loop: LD A,(TASK) CPIR RET NZ PUSH HL PUSH BC DEC HL AND A LD DE,MEMTAB SBC HL,DE LD A,L CALL RETMEM ; освоб. блок памяти POP BC POP HL JP .loop ////////////////////////////////////////////////////////////////////// ; Функция #38. Подключение страницы памяти. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; H - биты 6 и 7 задают номер окна, в которое будет подкл. страница ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ; if B = 0FFh, then logical page number got from DE ////////////////////////////////////////////////////////////////////// SETWIN: BIT 7,H ; if #8000 or high? JR Z,SETWIN1 ; no, go to open in SLOT1 BIT 6,H ; if #C000 or high? JR Z,SETWIN2 ; no, go to open in SLOT2 //JR SETWIN3 ; yes, go to open in SLOT3 ////////////////////////////////////////////////////////////////////// ; Функция #3B. Подключение страницы памяти в третье окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETWIN3: LD C,BIOS.GetMemPage EX DE,HL RST ToBIOS EX DE,HL RET C LD C,SLOT3 IN B,(C) OUT (C),A LD A,B RET ////////////////////////////////////////////////////////////////////// ; Функция #39. Подключение страницы памяти в первое окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETWIN1: LD C,BIOS.GetMemPage EX DE,HL RST ToBIOS EX DE,HL RET C LD C,SLOT1 IN B,(C) OUT (C),A LD A,B RET ////////////////////////////////////////////////////////////////////// ; Функция #3A. Подключение страницы памяти во второе окно. ; ; вход: A - идентиф. блока памяти ; B - номер страницы в блоке (0,1,2,..) ; выход: A - номер страницы, если CF=0 ; A - код ошибки, если CF=1 ////////////////////////////////////////////////////////////////////// SETWIN2 LD C,BIOS.GetMemPage EX DE,HL RST ToBIOS EX DE,HL RET C LD C,SLOT2 IN B,(C) OUT (C),A LD A,B RET ;!TODO если надо будет сэкономить память, но привязаться к номерам слотов ; SETWIN1: LD H,SLOT1 : JR SETWIN.ALL ; SETWIN2: LD H,SLOT2 : JR SETWIN.ALL ; SETWIN3: LD H,SLOT3 : JR SETWIN.ALL ; SETWIN: LD C,A ; LD A,H ; AND %1100'0000 ; JR NZ,.no_error ; OR %0100'0000 ; .no_error: RRСA ; OR %100'0010 ; LD H,A ;SLOT number ; LD A,C ; .ALL: LD C,BIOS.GetMemPage ; EX DE,HL ; RST ToBIOS ; EX DE,HL ; RET C ; LD C,H ;SLOT number ; IN B,(C) ; OUT (C),A ; LD A,B ; RET ; ; // SLOT0 - #82 %1000'0010 ; // SLOT0 - #A2 %1010'0010 ; // SLOT0 - #C2 %1100'0010 ; // SLOT0 - #E2 %1110'0010 CHECKPATH: ; !TODO сделать проверку на количество циклов LD A,(HL) INC HL CP '\' RET Z CP '/' ;ALT SLASH RET Z CP '!' JR NC,CHECKPATH RET RELATIVE_DIR EQU 0 ABSOLUTE_DIR EQU 1 FINDPATH: SET_PAGE_X ENVPAGE PUSH AF ;!TEST ;CALL CURRDSK_FN ;ADD A,"A" ;LD HL,TMP_CURDIR ;LD (HL),A ;INC HL ;LD A,":" ;LD (HL),A ;INC HL ;CALL CURRDIR_FN ; CALL .MAKE_PATH_ARRAY LD HL,PATH_PNT_ARRAY .NEXTPATHI: LD E,(HL) INC HL LD D,(HL) INC HL BIT ABSOLUTE_DIR,(HL) INC HL PUSH HL PUSH BC EX DE,HL CALL Z,.GOTO_CURDIR CALL NZ,CHDIR JR C,.BADPATH LD HL,CORE_BUFFERS.EXEBUFF LD DE,MASKARE CALL MASK JR C,.BADPATH CALL TST_EXT JR C,.BADPATH CALL SEARCH .BADPATH: POP BC POP HL JR NC,.PATHFOUND DJNZ .NEXTPATHI SCF .PATHFOUND: POP BC LD A,B OUT (SLOT3),A LD A,DSS_Error.sys.PATH_NOT_FOUND RET .GOTO_CURDIR: PUSH AF PUSH HL ;LD HL,TMP_CURDIR LD HL,CurrentDirectory CALL CHDIR POP HL POP AF RET .MAKE_PATH_ARRAY: LD HL,PATH_PNT_ARRAY-1 ;R04 -1 LD DE,ENVTEMP-1 LD B,#00 .NEXTAR: LD (HL),C ;R04 INC HL ;R04 XOR A LD (DE),A LD C,A INC DE LD (HL),E INC HL LD (HL),D INC HL ;R04 LD (HL),C ;R04 INC HL INC B .NEXTRT: LD A,(DE) CP '\' JR NZ,.NEXTCH .NEXTDR: SET ABSOLUTE_DIR,C .NEXTRL: ;SET RELATIVE_DIR,C ;!TODO ???? .NEXTCH: LD A,(DE) CP ";" JR Z,.NEXTAR INC DE ; CP "." ; JR Z,NEXTRL CP ":" JR Z,.NEXTRT OR A JR NZ,.NEXTCH LD (HL),C ;R04 INC HL ;R04 LD (HL),A INC HL LD (HL),A RET ENVPATH DB "PATH=",0 ;;; ; !TODO СДЕЛАТЬ СТРУКТУРОЙ и обозначить страницу TMP_CURDIR_AUTO EQU #FB00 PATH_PNT_ARRAY EQU #FC80 ; !FIXIT не нужно если SAVE_PATH_MACRO = 1 TMP_CURDIR EQU #FD00 ENVTEMP EQU #FE00 INCTASK: LD HL,TASK ;R08 INC (HL) ;R08 RET ;R08 DECTASK: LD HL,TASK ;R08 DEC (HL) ;R08 RET ;R08 ;///////////////////////////////////////////////////////////////////// ; Функция #40. Выполнить файл. ; ; вход: HL - указатель на имя файла ; B=0 - загрузить и выполнить программу с коротким именем (без полного пути до программы) ; B=1 - загрузить и выполнить программу с полным путём до программы ; выход: A - код завершения, если CF=0 ; код ошибки, если CF=1 ;--------------------------------------------------------------------- ; Загрузить и выполнить программу. ; функ. #40, B=0. ; ; 1) Открывает exe-файл на чтение; ; 2) Считывает в рабочую область префикс exe-файла; ; 3) Выделяет блок памяти, требуемый для загрузки всего файла или первичного ; загрузчика, если его размер не равен нулю; ; 4) Сохраняет стек; ; 5) Подключает страницы из выделенного блока; ; 6) Строит префикс запуска программы и устанавливает на него регистр IX; ; 7) Считывает файл по адресу указанному в смещении 16 (Адрес расположения ; кода в памяти); ; 8) Закрывает exe-файл, если это не первичный загрузчик; ; 9) Устанавливает стек равным значению из смещения 20 (Адрес расп. стека); ; 10) Передает управление по адресу указанному в смещении 18 (Адрес запуска); ; ; Префикс запуска файла: ; ; -03 1 db ? ; Дескриптор файла, если exe-файл с первичным загрузчиком ; -02 1 db ? ; Идентификатор блока памяти ; -01 1 db ? ; Уровень текущей программы ; +00 1 db ? ; Длина ком-строки ; +01 127 ds ? ; Параметры ком-строки, заканчивается нулем ;///////////////////////////////////////////////////////////////////// EXEC: INC B ;R03 DEC B ;R03 JR Z,.VAR_1 ;R03 DEC B ;R03 JR Z,.VAR_2 ;R03 LD A,DSS_Error.sys.INVALID_FUNCTION ;R03 SCF ;R03 RET ;R03 ; .VAR_1: LD (CMDLINE),HL CALL CHECKPATH ;CHECK FOR '\' - SHORT/FULL NAME LD HL,(CMDLINE) JR C,EXEC0_SHORT .VAR_2: CALL EXEC_1 SCF RET ; File not found - exit ; при выходе с ошибкой, в регистре А - код ошибки EXEC_1: LD (CMDLINE),HL LD A,#01 ; %7600000R = !FAT_ATTR ;!HARDCODE LD (F_FIRST.ACCESS),A CALL GETWORD RET C LD HL,TMPNAME LD DE,MASKARE CALL MASK RET C CALL TST_EXT LD A,DSS_Error.sys.FILE_NOT_FOUND RET C CALL INCTASK ;R08 CALL OPEN.FILE JR NC,.noError CALL DECTASK ;R08 AND A RET ; .noError: POP HL ; убираем лишний адрес_возврата_в_вызвавшую_процедуру JP EXEC02 ;R07 CONTINUE EXECUTING PROGRAM ;SHORT NAME ;TRY TO FIND IN CURRENT DIRECTORY EXEC0_SHORT: CALL EXEC_1 RET C ;FILE NO FOUND, SEARCHING IN PATH ; GET PATH AND ETC. LD HL,ENVPATH LD DE,ENVTEMP LD B,Dss.Environ.Get CALL ENVIRON LD HL,(CMDLINE) LD DE,CORE_BUFFERS.EXEBUFF COPYEXN: LD A,(HL) LDI OR A JR NZ,COPYEXN CALL FINDPATH ;[x] 1/10/2023 RET C ; LD HL,(CMDLINE) JR EXEC.VAR_2 EXEC02: LD (EXE_FM),A LD HL,CORE_BUFFERS.EXEBUFF LD DE,#0080 ;!#0200(512) ;R02 LD A,(EXE_FM) CALL READ JP C,ERREXE LD IX,CORE_BUFFERS.EXEBUFF LD HL,(CORE_BUFFERS.EXEBUFF) LD DE,'E'+'X'*256 ;AND A ; не нужно, если бы был CF=1, то чуть выше мы бы ушли на JP C,ERREXE SBC HL,DE LD A,DSS_Error.sys.INVALID_EXE SCF JP NZ,ERREXE LD A,(IX+3) ;!HARDCODE OR A LD A,DSS_Error.sys.UNKNOWN_EXE SCF JP NZ,ERREXE LD DE,(CORE_BUFFERS.EXEBUFF.LOADER) LD A,E OR D JP NZ,PRELOAD ; A=0 LD H,A LD L,A LD XL,A LD XH,A ; LD B,#02 LD A,(EXE_FM) CALL MOVE_FP LD DE,(CORE_BUFFERS.EXEBUFF.LD_ADDR) LD A,D AND #3F LD D,A ADD IX,DE LD DE,#0000 ADC HL,DE LD A,XH SLA A RL L RL H SLA A RL L RL H OR XL JR Z,NOINK INC HL NOINK: LD A,H OR A JP NZ,ERREXE0 LD B,L LD HL,_RET_1 LD (_ret),HL JP _TST_PROC _RET_1: LD DE,(CORE_BUFFERS.EXEBUFF.LD_ADDR) XOR A LD H,A LD L,A SBC HL,DE EX DE,HL ; de=число чит. байт LD HL,(CORE_BUFFERS.EXEBUFF.LD_ADDR) ; буфер LD A,(EXE_FM) ; дескр. файла CALL READ ; чтение из файла LD A,(EXE_FM) ; дескр. файла CALL CLOSE ; закрыть файл JP _TST_PROC_2 RETFAR: LD B,DSS_Error.sys.UNEXPECTED_APP_TRMN JP LEAVE ; завершить программу (процесс) ;------------------------------------------------- ; Если расш. файла не задано, задать "exe". ; Если расш. файла задано, сравнить его с "exe". ;------------------------------------------------- TST_EXT: LD HL,EXE_EXT ; "EXE" LD DE,MASKARE+8 LD B,3 LD A,(DE) CP ' ' JR NZ,.loop ; задано расш. LDI LDI LDI XOR A RET ; сравнить расш. с "EXE" .loop: LD A,(DE) CP (HL) SCF RET NZ ; не совпадает INC HL INC DE DJNZ .loop XOR A ; Ok RET ERREXE0: LD A,DSS_Error.sys.NOT_ENOUGH_MEMORY ERREXE: PUSH AF LD A,(EXE_FM) CALL CLOSE CALL DECTASK POP AF RET PRELOAD: EX DE,HL LD DE,(CORE_BUFFERS.EXEBUFF.LD_ADDR) LD A,D AND #3F LD D,A ADC HL,DE XOR A SLA H RLA SLA H RLA LD B,A LD A,H OR L JR Z,NOINK2 INC B NOINK2: LD HL,_RET_2 LD (_ret),HL JR _TST_PROC _RET_2: LD HL,(CORE_BUFFERS.EXEBUFF.LD_ADDR) ; буфер LD DE,(CORE_BUFFERS.EXEBUFF.LOADER) ; число чит. байт LD A,(EXE_FM) ; дескр. файла CALL READ ; чтение из файла JP _TST_PROC_2 ;-------------------------------------------------------------------;[ ] _TST_PROC: CALL GETMEM JP C,ERREXE0 LD (EXE_MEM),A EXX POP DE ;снимаем со стека адрес возврата LD HL,#0000 ADD HL,SP LD SP,(EXSTACK) PUSH HL PUSH DE IN A,(SLOT3) LD D,A IN A,(SLOT2) LD E,A IN A,(SLOT1) PUSH DE PUSH AF ;!Test close EXE FM [x] 25/10/23 LD A,(EXE_FM) PUSH AF ; LD (EXSTACK),SP LD SP,HL EXX ; НЕ СОХРАНЯЕТСЯ DE перед вызовом BIOS, а биос пока его и не портит LD A,(EXE_MEM) LD DE,RAMMAP LD BC,0*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,1*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,2*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A INC DE LD A,(EXE_MEM) LD BC,3*256 + BIOS.GetMemPage RST ToBIOS LD (DE),A LD HL,(CMDLINE) LD DE,CORE_BUFFERS.SECBUF+1 CALL SCOPYS LD A,#80 ;!HARDCODE cmd line size SUB B LD (CORE_BUFFERS.SECBUF),A ;R02 LD SP,CORE_BUFFERS.EXEBUFF+510 ;Вставляется в SHARED_PAGE ; LD A,SHARED_PAGE OUT (SLOT1),A OUT (SLOT2),A OUT (SLOT3),A LD HL,(CORE_BUFFERS.EXEBUFF.LD_ADDR) LD DE,RAMMAP LD A,H AND #C0 CP #40 JR Z,FR4000 CP #80 JR Z,FR8000 CP #C0 JR Z,FRC000 FR4000: LD A,(DE) OUT (SLOT1),A INC DE FR8000: LD A,(DE) OUT (SLOT2),A INC DE FRC000: LD A,(DE) OUT (SLOT3),A CALL M_PSP LD HL,(CORE_BUFFERS.EXEBUFF.OFFCOD2) LD IX,(CORE_BUFFERS.EXEBUFF.OFFCOD1) LD B,Dss.Move_FP.FrStart LD A,(EXE_FM) CALL MOVE_FP ;R02 LD SP,#403F ;!HARDCODE STACK before start EXE. Устанавливается когда воткнуты SHARED_PAGE ; _ret+1: JP 0 _TST_PROC_2: LD SP,(CORE_BUFFERS.EXEBUFF.SP_REG) LD HL,(CORE_BUFFERS.EXEBUFF.LD_ADDR) LD DE,#0080 AND A SBC HL,DE EX DE,HL LD XH,D LD XL,E LD HL,(CORE_BUFFERS.EXEBUFF.PC_REG) LD DE,RETFAR ; адрес п/п "неожиданное завершение процесса" PUSH DE PUSH HL ;!Test Current Dir ;[x] 15/10/23 PUSH IX LD HL,CurrentDirectory CALL CHDIR_FN POP IX ; RET ; ;----------------------------------------------------------------------- ;///////////////////////////////////////////////////////////////////// ; Функция #41. Завершить программу (процесс). ; ; вход: B - код завершения ; выход: A - код ошибки, если CF=1 ; ; Выход из EXE-файла: ; ; 1) Освобождаются все блоки памяти которые выделялась данному приложению. ; 2) Восстанавливаются страницы которые были подключены до запуска EXE-файла. ; 3) Вспоминается стек. ; 4) В регистр A помещается код возврата и выполняется RET. ; ;///////////////////////////////////////////////////////////////////// LEAVE: LD A,B LD (ERLEVEL),A CALL LEAVMEM ;CALL DECTASK ;!Test close EXE FM [x] 25/10/23 LD SP,(EXSTACK) ;!Test close EXE FM [x] 25/10/23 POP AF CALL RES_FM CALL DECTASK ; POP AF POP HL OUT (SLOT1),A LD A,L OUT (SLOT2),A LD A,H OUT (SLOT3),A POP DE POP HL LD (EXSTACK),SP LD SP,HL EX DE,HL LD A,(ERLEVEL) ;R12 CP DSS_Error.sys.UNEXPECTED_APP_TRMN JR NZ,.exit SCF JP (HL) ; .exit: AND A JP (HL) ;///////////////////////////////////////////////////////////////////// ; Функция #42. Получить код завершения программы. ; ; вход: нет ; выход: A - код завершения ;///////////////////////////////////////////////////////////////////// WAIT: LD A,(ERLEVEL) AND A RET ;///////////////////////////////////////////////////////////////////// ;!TODO заменить тут CALL CURRDIR и CALL CURRDSK на другое, когда будет сохраняться current dir M_PSP: LD HL,(CORE_BUFFERS.EXEBUFF.LD_ADDR) DEC H LD D,H LD E,L INC DE LD BC,#00FF ;!HARDCODE LD (HL),B LDIR EX DE,HL DEC H LD DE,#0080 ADD HL,DE EX DE,HL LD XH,D LD XL,E LD HL,CORE_BUFFERS.SECBUF LD C,(HL) INC C LDIR EX DE,HL ;R06 LD (HL),B LD A,(TASK) LD (IX-1),A LD A,(EXE_MEM) LD (IX-2),A LD A,(EXE_FM) LD (IX-3),A ;R05 INC HL LD (HL),B INC HL ;!FIXIT тут восстанавливать правильный каталог CALL CURRDSK ADD A,'A' LD (HL),A INC HL LD A,':' LD (HL),A INC HL PUSH HL CALL CURRDIR ; POP HL XOR A LD BC,#0100 ;!FIXIT нет привязки к CurrentDirectory.DEPTH CPIR ;!FIXIT нет проверки на выход по BC=0 DEC HL DEC HL LD A,'\' CP (HL) INC HL JR Z,.YP_ESLA LD (HL),A INC HL .YP_ESLA: EX DE,HL LD HL,TMPNAME .loop: LD A,(HL) LDI CP ' '+1 JR NC,.loop DEC DE XOR A LD (DE),A LD (APPINFO.LAST_PSP_PTR),IX ; RET SCOPYS: LD BC,#80*256 + ' '+1 ;!HARDCODE cmd line size .loop: LD A,(HL) CP C JR C,.copy INC HL DJNZ .loop XOR A LD (DE),A LD B,#80 RET .copy: LD BC,#80*256 + ' ' ;!HARDCODE cmd line size .loop2: LD A,(HL) LD (DE),A INC HL INC DE CP C RET C DJNZ .loop2 RET EXE_EXT: DB "EXE" TASK: DB #01 ; уровень текущей программы RAMMAP: DB #00,#00,#00,#00 ERLEVEL: DB #00 ; код завершения программы (процесса) EXE_FM: DB #00 ; дескр. файла EXE_MEM: DB #00 ; идентификатор блока памяти CMDLINE: DW #0000 EXSTACK: DW CORE_BUFFERS.XSTACK ; адрес стека ;R11 \\\\\\\\\\\\\\\\\\\\\\\\\\\\ ;; ; EXEBUFF: ; DB "EXE" ; DB #00 ; OFFCOD1 DW #0000 ; OFFCOD2 DW #0000 ; LOADER DW #0000 ; DW #0000 ; DW #0000 ; DW #0000 ; LD_ADDR DW #0000 ; PC_REG DW #0000 ; SP_REG DW #0000 ; BLOCK 512-($-EXEBUFF),0 ; ;(!!!HERE STACK FOR EXEC!!!) ; BLOCK 255,0 ; XSTACK DB #00 ;R11 //////////////////////////// ;//MODULE: EXECUTE ;[END]