; ; ; !TODO ; ; [ ] - ключ для загрузки образа в новый рам-диск "/i имя_файла" ; [ ] - ключ для загрузки образа в существующий рам-диск "/i имя_файла /d буква диска" ; [ ] - ключ для сохранения рам-диска в образ "/s буква диска" ; [ ] - ключ для закрытия рам-диска "/с буква диска" ; ; ; Compilation parameters ;-------------[] ;DEVICE SPRINTER ;MMU 2 e, 0 ; нулевая страница в банку 2 и проверка на границы ;OUTPUT './Build/new.bin' ;-------------[] ; Defines section ;-------------[] define NEED_LOADER 0 ; define NeedSafePort_Y 0 ;-------------[] ; Included LUA section ;-------------[] includelua ;-------------[] ; Included constants section ;-------------[] include 'Shared_Includes/constants/sp2000.inc' include 'Shared_Includes/constants/dss_equ.inc' include 'Shared_Includes/constants/BIOS_equ.inc' ;-------------[] ; Included macroses section ;-------------[] include 'Shared_Includes/macroses/macros.z80' include 'Shared_Includes/macroses/accelerator.z80' ;-------------[] ; Standart EQU section ;-------------[] org_addr EQU #8000 + CLP_Buffer code_addr EQU BEGIN stack_point EQU #C000 stack_buffer EQU 64 program_start EQU BEGIN ;-------------[] ; Program EQU section ;-------------[] ; IMG_File: ; .Sectors EQU 2880 ; .RamPages EQU 90 ; STRUCT MEM_BUFFER_BLOCK ; FileID BYTE ; BlockID BYTE ; SavePage BYTE ; PagesBuffer BLOCK IMG_File.RamPages+1 ; ENDS ;-------------[] ; Code start section ;[]-------------------------------------------------------------------[] include 'Shared_Includes/constants/EXE_Header.z80' ORG org_addr BEGIN: ; LD C,BIOS.LP_GET_PLACE ; RST ToBIOS ; PUSH DE ; LD HL,EXIT.messages.test ; LD C,Dss.PChars ; RST ToDSS ; POP DE ; LD E,0 ; LD C,BIOS.LP_SET_PLACE ; RST ToBIOS ; LD HL,EXIT.messages.help ; LD C,Dss.PChars ; RST ToDSS ; di : halt LD (dss_line),IX ; Сохраняем указатель на строку запуска. LD A,(IX) ; тут DSS кладёт длину параметров ком.строки AND A ; проверяем на отсутствие параметров JP Z,EXIT.help ; запуска в ком.строке. Если их нет - выход с инструкцией CALL Set_keys JP C,EXIT.error.UNDEFINED ; проверка ключей на несовместимость)) LD HL,key_buff LD A,(HL) INC HL XOR (HL) JR NZ,.not_saveRMD INC HL OR (HL) JP Z,EXIT.error.WrongKeys CALL RMD_SAVE JP EXIT.good .not_saveRMD: AND (HL) JR NZ,RMD_MOUNT RMD_UNMOUNT: ;LD A,(key_buff.DRVsave) ;INC A ;CALL NZ,RMD_SAVE ;!TODO check error? LD A,(key_buff.DRV) LD C,BIOS.FreeMemRMD RST ToBIOS ;!TODO check error? LD C,Dss.RescanDrives RST ToDSS JP EXIT.good ;!TODO ;-------------[] ;-------------[] ;Сохранение образа рамдиска в файл RMD_SAVE: IN A,(SLOT3) LD (.SavePage),A LD A,(key_buff.DRVsave) LD C,BIOS.GET_RAMD_ST RST ToBIOS LD HL,PagesBuffer LD C,BIOS.GetMemBlkPages RST ToBIOS ;LD HL,PagesBuffer LD C,Dss.Write .loop: PUSH BC PUSH HL LD A,(HL) OUT (SLOT3),A LD A,(key_buff.FM) LD HL,#C000 LD DE,#4000 ;LD C,Dss.Write RST ToDSS ; A - файловый манипулятор ; HL - адрес в памяти ; DE - количество читаемых байт POP HL POP BC ;!TODO удалять файл если ошибка записи JP C,EXIT.error.writeFile INC HL DJNZ .loop .SavePage+*: LD A,0 OUT (SLOT3),A LD C,Dss.RescanDrives RST ToDSS LD A,(key_buff.FM) LD C,Dss.Close RST ToDSS RET ;-------------[] ;-------------[] RMD_MOUNT: LD A,(key_buff.FM) LD HL,0 LD IX,0 LD B,Dss.Move_FP.FrEnd LD C,Dss.Move_FP RST ToDSS ; узнаём размер файла ; A - файловый манипулятор ; HL:IX - смещение указателя в файле ; B - способ перемещения: ; 0 - от начала файла ; 1 - от текущего значения указателя ; 2 - от конца файла XOR A OR H JP NZ,EXIT.error.noRAM LD A,L CP #39 JP NC,EXIT.error.noRAM PUSH IX POP HL DUP 2 ; превращаем размер файла в байтах в страницы SLA L RL H RLA EDUP LD B,A LD A,H OR L JR Z,.skipINK INC B ; необходимое число страниц ;-------------[] .skipINK: LD A,B LD (.RamPagesNum),A LD C,BIOS.GetMem RST ToBIOS ;LD B,num_pages ; запрашиваемое число страниц ОЗУ ;LD C,0C2h ; номер функции ;CALL 3D13h ; NC -> А - идентификатор блока ; CF -> A=1 - нет памяти JP C,EXIT.error.noRAM LD (.BlockID),A ;-------------[] ;-------------[] LD HL,PagesBuffer LD C,BIOS.GetMemBlkPages RST ToBIOS ; LD A,id_blk ; идентификатор блока ; LD HL,bufer ; буфер длиной 256 байт для размещения списка ; ; буфер должен быть длиной на единицу больше числа ; ; страниц в блоке ; LD C,0C5h ; номер функции ; RST ToBIOS ; NC -> HL - тот же буфер, B - число страниц в блоке ; ; данные по адресу HL - список физических страниц по ; ; порядку. Список заканчивается байтом FF ; ; CF -> неверный идентификатор блока. Старая ; ; информация в буфере может быть затерта JP C,EXIT.error.wrongMEMblkID ;-------------[] ;-------------[] XOR A .loop: PUSH AF LD C,BIOS.GET_RAMD_ST RST ToBIOS ; получение идентификатора блока, назначенного на RAM-Disk AND A JR Z,.loopExit POP AF INC A CP 16 JP NZ,.loop JP EXIT.error.noFreeRAMdsk .loopExit: POP AF ;-------------[.] ; . ; . ;-------------[.] ; A = ram_disk number from BIOS.GET_RAMD_ST .BlockID+*: LD HL,0 LD B,L LD C,BIOS.BLK_TO_RAMD RST ToBIOS ; ; любой блок памяти может содержать данные ; ; RAM-Disk-а в формате TR-DOS для подключения этих ; ; данных в качестве диска и служит эта функция ; LD A,ram_disk ; номер RAM-Disk-а 0..15 - соответствует ; ; RAM-Disk-ам от e: до t: ; LD B,id_blk ; идентификатор блока ; LD C,0C9h ; номер функции ; RST ToBIOS ; NC -> нормальное завершение ; ; CF -> ошибка: неверный номер RAM-Disk-а или ; ; RAM-Disk занят JR C,EXIT.error.wrongRAMdrv ;-------------[] ;Чтение образа в память рамдиска ;-------------[] LD A,(key_buff.FM) LD HL,0 LD IX,0 LD B,Dss.Move_FP.FrStart LD C,Dss.Move_FP RST ToDSS IN A,(SLOT3) LD (.SavePage),A .RamPagesNum+*: LD B,0 LD HL,PagesBuffer LD C,Dss.Read ;;;;!TODO сделать общей процедурой .LOOP: PUSH BC PUSH HL LD A,(HL) OUT (SLOT3),A LD A,(key_buff.FM) LD HL,#C000 LD DE,#4000 ;LD C,Dss.Read RST ToDSS ; A - файловый манипулятор ; HL - адрес в памяти ; DE - количество читаемых байт POP HL POP BC JR C,EXIT.error.readFile INC HL DJNZ .LOOP ;;;; .SavePage+*: LD A,0 OUT (SLOT3),A LD C,Dss.RescanDrives RST ToDSS LD A,(key_buff.FM) LD C,Dss.Close RST ToDSS ;!TODO check error? ; JP EXIT.good ;-------------[] ;-------------[] MODULE EXIT good: LD B,DSS_Error.sys.NO_ERROR LD HL,messages.good printANDexit: PUSH BC LD C,Dss.PChars RST ToDSS POP BC .loop: LD C,Dss.Exit RST ToDSS JR .loop help: LD HL,messages.help LD B,DSS_Error.sys.NO_ERROR JP printANDexit error: .writeFile: LD B,DSS_Error.sys.WRITE_ERROR LD HL,messages.writeFile JP printANDexit .WrongKeys: LD B,DSS_Error.sys.GENERAL_FAILURE LD HL,messages.WrongKeys JP printANDexit .UNDEFINED: LD B,DSS_Error.sys.GENERAL_FAILURE LD HL,messages.UNDEFINED JP printANDexit .noRAM: LD B,DSS_Error.sys.NOT_ENOUGH_MEMORY LD HL,messages.noRAM JP printANDexit .wrongMEMblkID: LD B,DSS_Error.sys.INVALID_MEMORY_HND LD HL,messages.wrongMEMblkID JP printANDexit .wrongRAMdrv: LD B,DSS_Error.sys.INVALID_DRIVE LD HL,messages.wrongRAMdrv JP printANDexit .readFile: LD B,DSS_Error.sys.READ_ERROR LD HL,messages.readFile JP printANDexit .noFreeRAMdsk: LD B,DSS_Error.sys.GENERAL_FAILURE LD HL,messages.noFreeRAMdsk JP printANDexit ; messages: .good: DZ "\r\n All Done. Good luck)))\r\n" .noRAM: DZ "\r\n ERROR! No enough memory.\r\n" .wrongMEMblkID: DZ "\r\n ERROR! Invalid Memory block ID.\r\n" .wrongRAMdrv: DZ "\r\n ERROR! Invalid RAM disk ID or RAM disk busy.\r\n" .readFile: DZ "\r\n ERROR! Unable to read disk image file.\r\n" .writeFile: DZ "\r\n ERROR! Unable to write disk image to file.\r\n" .noFreeRAMdsk: DZ "\r\n ERROR! The number of RAM disks in use has reached its maximum.\r\n" .WrongKeys: DZ "\r\n ERROR! Wrong key combination.\r\n" .help: DZ "\r\n HELP MESSAGE IN PROGRESS\r\n" ;!TODO .UNDEFINED: DZ "\r\n Undefined error: SET_KEYS\r\n" ;!TODO ;.test DZ "1234567890-1234567890-1234567890-1234567890" ;.help: DZ " HELP MESSAGE IN PROGRESS\r\n" ;!TODO ENDMODULE ;-------------[] dss_line: DW 0 ;******************************************************* ; ____ _ _ ; / ___| ___| |_ | | _____ _ _ ___ ; \___ \ / _ \ __| | |/ / _ \ | | / __| ; ___) | __/ |_ | < __/ |_| \__ \ ; |____/ \___|\__| |_|\_\___|\__, |___/ ; |___/ ; Получаем ключи запуска, распихиваем их по углам, ; настраиваем начальные условия работы. ;-----------------; key_buff: .U: DB 0 ; unmount .M: DB 0 ; mount .S: DB 0 ; save ramdisk .FM: DB 0 ; File Manipulator .DRV: DB #FF ; номер рамдиска для unmount .DRVsave: DB #FF ; номер рамдиска для SAVE ;-----------------; Set_keys: LD HL,(dss_line) INC HL LD (.NextParam),HL .CheckChar: CALL .GetParam ;JR NC,.next CCF RET NC ; Разбор окончен. .next: LD A,(Buffer+2) ; В основном цикле CheckChar мы ждём только два ADD #FF ; символа в ключе. Поэтому если их больше, RET C ; то выходим с ошибкой. LD A,(Buffer) SUB '/' SCF RET NZ ; Проверка/установка ключа LD HL,key_buff ; начало хранения ключей LD E,L ; для проверки на ключ U LD A,(Buffer+1) AND %11011111 ; делаем маленький символ большим))) CP 'U' ; проверяем параметр mount image JR Z,.set_key INC HL ; следующий ключ CP 'M' ; проверяем параметр unmount image JR Z,.set_key INC HL ; следующий ключ CP 'S' ; проверяем параметр save image JR Z,.set_key SCF ; ошибка в параметре RET ; выход с ошибкой ;-----------------; ;-----------------; .set_key: LD A,(HL) ; проверяем не установлен ли ключ. ADD #FF ; если есть, значит ключ введён 2 раза RET C ; ошибка - повтор ключа. выход INC (HL) ; Признак установки ключа - не ноль. Установили ключ. LD A,L SUB E ; для проверки на ключ U LD (.save_a),A CALL .GetParam ; получаем следующий параметр строки DOS к найденому ключу RET C ; выход, если ошибка XOR A .save_a+*: OR 0 JR NZ,.file_key CALL .GetDRVnum RET C LD (key_buff.DRV),A ; сохраняем номер рамдиска для BIOS.FreeMemRMD JP .CheckChar ; погнали на следующий виток разбора ключей /* .save_a+*: LD A,0 XOR 2 JR Z,.key_save XOR 2 JR NZ,.file_key ;unmount key CALL .GetDRVnum ;!TODO error number RET C LD (key_buff.DRV),A ; сохраняем номер рамдиска для BIOS.FreeMemRMD ;-------------------- JP .CheckChar ; погнали на следующий виток разбора ключей .key_save: CALL .GetDRVnum RET C LD (key_buff.DRVsave),A ; сохраняем номер рамдиска для BIOS.FreeMemRMD */ ;!FIXIT .file_key: LD HL,Buffer LD A,(key_buff.M) AND A JR Z,.noRD CALL .OpenRDfile ; Открытие файла (или проверка наличия) по имени из буфера RET C ; выход, если ошибка JP .CheckChar ; погнали на следующий виток разбора ключей .noRD: CALL .OpenWRfile RET C ; выход, если ошибка LD A,(key_buff.DRVsave) INC A JP NZ,.CheckChar LD HL,(.NextParam) INC HL LD A,(HL) CP ':' JP NZ,.CheckChar CALL .GetParam CCF RET NC CALL .GetDRVnum RET C LD (key_buff.DRVsave),A ; сохраняем номер рамдиска для save ram drive JP .CheckChar ; погнали на следующий виток разбора ключей ;-----------------; ;-----------------; .GetParam: .NextParam+1: LD HL,0 LD DE,Buffer ; буфер для операций со строками LD C,Dss.GSwitch ; тут выделяем параметр запуска RST #10 ; получаем в буфере следующий параметр LD (.NextParam),HL LD A,(Buffer) AND A RET NZ ; Нормальный возврат C = 0 SCF RET ; Возврат с ошибкой C = 1 ;-----------------; ;-----------------; .OpenRDfile: LD BC,Dss.EX_Path.GET_ALL * 256 + Dss.EX_Path ; проверяем буфер на корректность имени файла RST ToDSS RET C ; ошибка в строке AND %00000011 ; проверяем, что есть имя и XOR %00000011 ; расширение файла (0 и 1 биты) SCF RET NZ ; ошибка файла - выход LD A,Dss.Open.R LD HL,Buffer LD C,Dss.Open RST 10h ; открытие файла LD (key_buff.FM),A ; сохраняем файловый манипулятор RET ; .OpenWRfile: XOR A ;LD A,FileAttrib.Normal LD C,Dss.Create RST ToDSS LD (key_buff.FM),A ; сохраняем файловый манипулятор RET ;-----------------; .GetDRVnum: LD HL,Buffer+2 LD (HL),'\' INC HL LD (HL),0 EX DE,HL LD HL,Buffer LD B,Dss.EX_Path.GET_DRIVE LD C,Dss.EX_Path ; тут определяем имя диска ли в буфере RST ToDSS ; получаем в А логический номер диска RET C LD BC,0*256 + 8 LD DE,#55AA RST #18 ; из логического в физический номер диска EX AF,AF' LD C,A AND #F0 XOR #60 SCF RET NZ LD A,C AND #0F RET ;-----------------; ;******************************************************* Loader_length EQU $-BEGIN ;!FIXIT PagesBuffer EQU $ Buffer EQU PagesBuffer+256 ;----------------------------------------------[End Code section] STACK_CHECK_MACRO stack_point, (stack_buffer+256) ;----------------------------------------------[Data after Loader] /* ;-----------------------------------------------------------------------; Test: LD (dss_line),IX ; Сохраняем указатель на строку запуска. LD A,(IX) ; тут DSS кладёт длину параметров ком.строки AND A ; проверяем на отсутствие параметров JP NZ,1F ; запуска в ком.строке. Если их нет, LD HL,Help_Msg ; то печатаем инструкцию и выходим CALL PrintStr ; из программы с нормальным кодом LD B,0 ; завершения. JP Exit ; ;-----------------------------------------------------------------------; ;-----------------------------------------------------------------------; 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 ;-----------------------------------------------------------------------; LD HL,COMLINE ;HL указывает на командную строку .loop: LD DE,BUFFER ;DE указывает на буфер для параметров LD C,43h ;Функция выделения параметра RST 10h ;Выполнение функции PUSH AF PUSH HL POP HL POP AF JP NC,.loop LD A,(BUFFER) AND A JR NZ,NEXTP */