//////////////////////////////////////////////////////////////////////// ; CHANGELOG ; [x] - загрузка с любого primary active раздела ; [x] - поддержка загрузки с FAT32 раздела ; [x] - загрузка с RAM диска ; [x] - bug fixes and optimizations))) //////////////////////////////////////////////////////////////////////// ; Программа записи на FDD/HDD boot-загрузчика и файлов системы. ; ; Загружает сист. файлы из корня диска, с которого была ; загружена система. ; Фитчи программы: ; В отличие от оригинального boot-инсталлятора, эта может ; переписывать уже установленный boot-загрузчик. ; Файлы системы (system.dos, system.exe) могут иметь ; любые размеры. ; При загрузке компьютера с дискеты, запрашивается новая ; дискета для создания из нее загрузочной. ; ; STRUCT _sysFatBuffer ;.DRIVE: BYTE #FF .FAT_TYPE: BYTE #00 ; TYPE FAT (12 - 12bit, 16 - 16bit, 32 - 32bit) ; fat32 .CacheBlock: WORD #0000 ;.CacheUpdated: BYTE #00 ;.SectorsPerBank: BYTE #00 .RootDirStartCluster_L: WORD #0000 .RootDirStartCluster_H: WORD #0000 ; fat32 .FAT1_SEC_L: WORD #0000 ; MSD_FAT_SEC first sector FAT (FAT_FRM) .FAT1_SEC_H: WORD #0000 ; fat32 ;.FAT2_SEC_L: WORD #0000 ;.FAT2_SEC_H: WORD #0000 ; fat32 ;.Number_Of_FATs BYTE #02 .SectorsPerFAT_L WORD #0000 .SectorsPerFAT_H BYTE #00 .RootDirFirstSector_L: WORD #0000 ; MSD_CAT_SEC first sector DIR .RootDirFirstSector_H: WORD #0000 ; MSD_CAT_SEC first sector DIR .DirSizeInSectors: BYTE #00 ; DIR_SEC_SIZE .FirstDataSector_L: WORD #0000 ; MSD_DAT_SEC low .FirstDataSector_H: WORD #0000 ; MSD_DAT_SEC high .BytesPerCluster: WORD #0000 ; CLUSTER_LEN ;.END_CHAIN_CLUSTER_L: WORD #FFFF ;.END_CHAIN_CLUSTER_H: WORD #0FFF ;.MaxClusterLow: WORD #0000 ; макс. число кластеров (без служ.) ;.MaxClusterHigh: WORD #0000 ; макс. число кластеров (без служ.) ;.BytesPerSector: WORD #0000 .SectorsPerCluster: BYTE #00 ;.FSINFO_Sector: WORD #01 ;.BPB_SERIAL_NUMBER: DWORD #00000000 ;.BPB_LABEL: BLOCK 11,' ' ; 11 для FAT, 31 для CDFS ;.UPD_FSINFO: BYTE 0 ;.FREE_CLUSTERS_COUNT_L: WORD #FFFF ;.FREE_CLUSTERS_COUNT_H: WORD #FFFF ;.FilesPerSector: BYTE #00 ; число файловых записей в секторе ;.ClustersPerBank: BYTE #00 ; A - Clusters per bank (16k) (число кластеров на блок ОЗУ) ;.READ_PG: BYTE #00 ;!TODO не используются некоторые значения, но задумка неплохая))) ;.S_X_H: DWORD #0000 ; количество секторов на цилиндре ENDS includelua 'Shared_includes/lua/Functions.lua' include 'shared_includes/constants/sp2000.inc' include 'shared_includes/constants/bios_equ.inc' include 'shared_includes/constants/dss_equ.inc' include 'shared_includes/macroses/accelerator.z80' include 'shared_includes/macroses/macros.z80' include 'shared_includes/structures/FileSystem.inc' ;include 'DSS/structures.inc' include '../DSS/defines.inc' LUA PASS1 local date, month, year = Get_date_RU(sj.get_define("__DATE__")) BuildDate = "'" .. date .. "." .. month .. "." .. year .. "'" sj.insert_define("SYS_BUILD_DATE", BuildDate) ENDLUA LUA ALLPASS sj.insert_define("SYS_BUILD_DATE", BuildDate) ENDLUA DEFINE EXEinfoMACRO 0 DEFINE App_EXE_Version 1 MACRO _mEXEinfo IF EXEinfoMACRO BLOCK 10,' ' ; Выравнивание для красивого отображения в HEX BYTE ' Bootloader ' BYTE ' installer ' BYTE ' for DSS. ' BYTE ' Vasil Ivanov, ' BYTE ' Anatoliy ' BYTE ' Belyanskiy. ' BYTE ' Sprinter Team, ' BYTE ' 2025 ' ENDIF ENDM ; версия программы major_version equ 3 ; ст. номер версии minor_version equ 0 ; мл. номер ;; SECTORS_OF_LOADER EQU 4 ; секторов загрузчика .IN_BPB EQU 1 .AFTER_BPB EQU 3 org_addr EQU #8000 + CLP_Buffer code_addr EQU BEGIN program_start EQU BEGIN stack_point EQU #BFFE Loader_length EQU 0 ; page_buffer equ #C000 ; буфер файлов ;; include 'Shared_Includes/constants/EXE_Header.z80' ORG org_addr BEGIN: ;di in a,(SLOT3) ld (port+1),a ; сохр. порт push ix call save_path ; сохр. тек. диск и путь ld c,Dss.Version ; узнать версию ДОС RST ToDSS ex de,hl ; hl=тек. версия ld de,#0146 ; 1.70.810 d=версия, e=модификация, bc - номер сборки. de = #0146, bc = 810 dos ver 1.70.810 and a sbc hl,de ;[x] 17.12.2023 загрузка с активного раздела, а не с первого ;jr nc,version_ok jr z,.check_build ; если номер версии 1.70 jr nc,version_ok ; если номер версии больше 1.70 ; .old_ver: pop hl ld a,11 ; индекс строки "Error: Need DSS version 1.70..." call print_string ld a,-1 jp exit ;[x] 17.12.2023 загрузка с активного раздела, а не с первого .check_build: ld hl,810 ; 1.70.810 d=версия, e=модификация, bc - номер сборки. de = #0146, bc = 810 dos ver 1.70.810 sbc hl,bc jr nc,BEGIN.old_ver ; version_ok: xor a ; индекс строки титла call print_string pop hl ; ком-строка ; выделить параметр ком-строки call get_drive_letter jp c,help ; нет параметров ld (disk),a ; заданный номер диска ; узнать номер boot-диска системы ld bc,Dss.BootDSK.Get RST ToDSS ld (boot_disk),a ; диск (A=0,B=1,..) ; проверить на совпадение дисков ld hl,disk cp (hl) jr nz,.next ld hl,confirm_flag ld (hl),1 ; уст. флаг ; ; Чтение в банки файлов системы ; .next: ld a,(boot_disk) ; диск загрузки ОС ld hl,root_path ; "X:\" корень диска add a,'A' ld (hl),a ld c,Dss.ChDir ; смена каталога RST ToDSS ;-------------------------------------------- ; Чтение файла system.exe ;-------------------------------------------- ld hl,name2 ; имя файла call read_file ; вся работа по загрузке файла в страницы ;jr nc,read_file1_ok ; освоб. блок памяти ;read_file_err: ld a,(FILE1_PARAMS.id_blck) ; идентиф. блока памяти ; ld c,Dss.FreeMem ; RST ToDSS ;ld a,DSS_Error.sys.DISK_FULL ; код ошибки jp c,exit ; сохр. раб. ячейки файла system.exe read_file1_ok: ld hl,FILE1_PARAMS ; откуда ld de,FILE2_PARAMS ; куда ld bc,FILE2_PARAMS.dataSize ldir ;-------------------------------------------- ; Чтение файла system.dos ;-------------------------------------------- ld hl,name1 ; имя файла call read_file ; вся работа по загрузке файла в страницы ;jr c,read_file_err ;ld a,DSS_Error.sys.DISK_FULL; код ошибки jp c,exit ;jr nc,read_file2_ok ; освоб. блок памяти system.exe ; file_err1: ld a,(FILE2_PARAMS.id_blck); идентиф. блока памяти ; ld c,Dss.FreeMem ; RST ToDSS ;jr read_file_err ; освоб. блок памяти system.dos confirm_flag+1: ld a,0 or a jr z,no_confirm ld a,(boot_disk) ; сист. диск cp 2 jr nc,no_confirm ; не дисководы ; запросить целевой диск ld a,(disk) ; заданный номер диска add a,'A' ld (messages.lett2),a ld a,5 ; индекс строки "Insert destination disk..." call print_string ld bc,Dss.K_CLEAR + Dss.WaitKey*256; ждем нажатия клавиши RST ToDSS no_confirm: ld a,2 ; индекс строки "Installing boot loader..." call print_string ; Уст. целевой диск/путь ld a,(disk) ; целевой диск ld hl,root_path ; "X:\" строка пути add a,'A' ld (hl),a ld c,Dss.ChDir ; смена тек. каталога RST ToDSS ;-------------------------------------------- ; Записать boot-загрузчик call write_boot_loader jr c,write_error ; ошибка работы с девайсом ; ld a,3 ; индекс строки "Writing system files..." call print_string ; Запись файла system.dos ld hl,name1 ; имя файла call write_file jr c,write_error ok_write1: ; освободить память ; ld a,(FILE1_PARAMS.id_blck) ; блок system.dos ; ld c,Dss.FreeMem ; RST ToDSS ; ; загр. раб. ячейки ld hl,FILE2_PARAMS ; откуда ld de,FILE1_PARAMS ; куда ld bc,FILE1_PARAMS.dataSize ldir ; Запись файла system.exe ld hl,name2 ; имя файла call write_file ; освободить память ; push af ; ld a,(FILE1_PARAMS.id_blck) ; блок system.exe ; ld c,Dss.FreeMem ; RST ToDSS ; pop af ; jr c,write_error ;jr c,exit ; ошибка ; ld a,(disk) ; заданный номер диска add a,'A' ld (messages.lett1),a ld a,1 ; индекс строки "System installed on disk " call print_string ld a,(confirm_flag) or a jr z,exit ; запросить системный диск ld a,(boot_disk) ; сист. диск cp 2 jr nc,.not_fdd ; не дисководы add a,'A' ld (messages.lett3),a ld a,6 ; индекс строки "Insert system disk..." call print_string ld bc,Dss.K_CLEAR + Dss.WaitKey*256; ждем нажатия клавиши RST ToDSS .not_fdd: xor a ; код "Ok" exit: push af call restore_path ; восст. тек. диск и путь port: ld a,-1 ; сохр. порт out (SLOT3),a pop af ld c,Dss.Exit ; выход в ДОС ld b,a RST ToDSS jr $ ; help: ld a,8 ; индекс строки "Invalid drive specification" call print_string ld a,4 ; индекс строки хэлпа err_mes: call print_string ld a,1 ; код ошибки jr exit write_error: ld a,7 ; индекс строки "Can't install boot on this disk" jr err_mes root_path: db 'X:\',0 ; путь name1: db "SYSTEM.DOS",0 name2: db "SYSTEM.EXE",0 ;------------------------------------------------- ; Записать boot-загрузчик на FDD/HDD ; вход: нет ; выход: CF - ошибка работы с девайсом ;------------------------------------------------- write_boot_loader: ld a,(disk) ; заданный номер диска ld c,Dss.DRV.Open ; open device rst ToDSS.DRV ret c ld hl,close_device ; точка выхода push hl ld a,(disk) ; заданный номер диска ld hl,0 ; ст. разряд лог. сектора ld ix,0 ; мл. разряд ld de,buffer ; куда ld bc,1*256 + Dss.DRV.Read ; прочитать 1 сектор (boot) rst ToDSS.DRV ret c ; ошибка чтения ld a,(buffer + _sBOOT_SECTOR_PARAMS.DRIVE_TYPE) cp #F0 ; 1.44Mb ret c ; незнакомый формат jr z,write_to_floppy cp #F9 ; 720kB jr z,write_to_floppy cp #FA ; RAM disk jr z,write_to_ram_disk cp #F8 ; винт jp z,write_to_hard_disk scf ; незнакомый формат ret ; закрыть девайс close_device: push af ; сохр. флаг ld a,(disk) ; заданный номер диска ld c,Dss.DRV.Close ; close device rst ToDSS.DRV pop af ret ;------------------------------------------------- ; Запись boot-загрузчика на дискету ; ; вход: данные из buffer ; выход: CF - при ошибке записи ;------------------------------------------------- write_to_floppy: ld a,(buffer + BOOT_SECTOR.Number_of_FATs) ; число копий FAT-ов or a scf ret z ; ошибка dec a ; --число копий jr z,overwrite_floppy ; загрузчик уже записан, перезаписать его ; настроить ячейки boot-сектора ld (buffer + BOOT_SECTOR.Number_of_FATs),a ; число копий FAT-ов ld hl,(buffer + BOOT_SECTOR.RESERVED_SECTORS) ; зарезерв. секторов ld bc,(buffer + BOOT_SECTOR.SectorsPerFAT16) ; секторов на FAT add hl,bc ld (buffer + BOOT_SECTOR.RESERVED_SECTORS),hl ; зарезерв. секторов dec hl ld de,SECTORS_OF_LOADER.AFTER_BPB and a sbc hl,de ret c overwrite_floppy: ; перекидывание части загрузчика в 0 сектор LD HL,DSS_Boot_Loader.ZERO_SECTOR_OF_BPB.physical LD DE,buffer + (_sBOOT_SECTOR.PARTITION_TABLE - DSS_Boot_Loader.ZERO_SECTOR_OF_BPB.Size) LD BC,DSS_Boot_Loader.ZERO_SECTOR_OF_BPB.Size LDIR ; ; записать boot-сектор назад ld a,(disk) ; заданный номер диска ld hl,0 ; ст. разряд лог. сектора ld ix,0 ; мл. разряд ld de,buffer ; откуда ld bc,1*256 + Dss.DRV.Write ; записать 1 сектор rst ToDSS.DRV ret c ; ошибка записи ; записать загрузчик ld a,(disk) ; заданный номер диска ld hl,0 ; ст. разряд лог. сектора ld ix,1 ; мл. разряд ld de,code_loader ; откуда (код загрузчика) ld bc,SECTORS_OF_LOADER.AFTER_BPB*256+Dss.DRV.Write; записать 3 сектора (размер загр.) rst ToDSS.DRV ret ;------------------------------------------------- ; Запись boot-загрузчика на драйв ; ; вход: нет ; выход: CF-ошибка записи ;------------------------------------------------- write_to_ram_disk: CALL write_no_BPB RET C ; buffer = sector 0 ; JR write_to_BPB write_to_hard_disk: ;[x] 17.12.2023 загрузка с активного раздела, а не с первого CALL write_no_BPB RET C ; buffer = sector 0 ; ; проверка на РАМ-диск (разделы на рамдиске пока не поддерживаются) LD A,B CP #80-1 ;!HARDCODE HDD number JR C,write_to_BPB ; PUSH BC CALL Read_MBR RET NZ POP BC PUSH BC ; set active in buffer INC C LD HL,buffer + _sBOOT_SECTOR.PARTITION_TABLE.Record_4 LD DE,_sMBR_PARTITION_RECORD ; размер одной записи MBR LD B,_sMBR_PARTITION_TABLE / _sMBR_PARTITION_RECORD; MBR: Number of entries in the partition table .loop: XOR A LD (HL),A ; LD A,C CP B JR NZ,.next ; LD A,#80 LD (HL),A PUSH HL INC HL INC HL INC HL INC HL LD A,(HL) POP HL CP PartitionSysTypes.FAT12 JR Z,.next CP PartitionSysTypes.FAT16_32Mb JR Z,.next CP PartitionSysTypes.FAT16 JR Z,.next CP PartitionSysTypes.FAT16_LBA JR Z,.next CP PartitionSysTypes.FAT32 JR Z,.next CP PartitionSysTypes.FAT32_LBA JR Z,.next ; NOT SUPPORTED FS POP BC SCF RET ; .next: AND A SBC HL,DE DJNZ .loop ; JR write_to_BPB.no_push write_to_BPB: PUSH BC ; перекидывание части загрузчика в 0 сектор .no_push: LD HL,DSS_Boot_Loader.ZERO_SECTOR_OF_BPB.physical LD DE,buffer + (_sBOOT_SECTOR.PARTITION_TABLE - DSS_Boot_Loader.ZERO_SECTOR_OF_BPB.Size) LD BC,DSS_Boot_Loader.ZERO_SECTOR_OF_BPB.Size LDIR ; запись в 0 сектор куска загрузчика pop af ; заданный номер диска ld hl,0 ; ст. разряд лог. сектора ld ix,0 ; мл. разряд ld de,buffer ; откуда (код загрузчика) ld bc,1*256 + BIOS.DRV_WRITE ; записать 1 сектор RST ToBIOS RET ; ; write_no_BPB: ld a,(disk) ; номер заданного диска ld de,Dss.DRV.GenIOCTL.Enter ld bc,Dss.DRV.GenIOCTL.GetParams rst ToDSS.DRV ex af,af' ;[x] 17.12.2023 загрузка с активного раздела, а не с первого ld b,a inc c scf ret z dec c CP #80 ;!HARDCODE тип драйва - HDD JR NC,.skip_FAT_check PUSH BC ; B - PHISICAL DRIVE NUMBER, C - PARTITION RECORD NUMBER IN DRIVE MBR ; A - PHISICAL DRIVE NUMBER ; [x] 02/02/2024 проверка на влезаемость загрузчика (чтоб не попортить фат) CALL Read_MBR RET NZ POP BC LD HL,(buffer + _sBOOT_SECTOR_PARAMS.RESERVED_SECTORS) ; минимальное расстояние на драйве от нулевого сектора до фата (длина загрузчика + 1) LD DE,SECTORS_OF_LOADER.AFTER_BPB + 1 AND A SBC HL,DE RET C ; .skip_FAT_check:; push bc ld a,b ld hl,0 ; ст. разряд лог. сектора ld ix,1 ; мл. разряд ld de,code_loader ; откуда (код загрузчика) ld bc,SECTORS_OF_LOADER.AFTER_BPB*256+BIOS.DRV_WRITE; записать 3 сектора (размер загр.) rst ToBIOS ;[x] 17.12.2023 загрузка с активного раздела, а не с первого pop bc ; ret ; in: a - drive ; out CF = 1. ; ZF = 1 - OK, ; ZF = 0 - error Read_MBR: LD HL,0 LD IX,0 LD DE,buffer LD BC,1*256 + BIOS.DRV_READ RST ToBIOS LD HL,(buffer + _sBOOT_SECTOR.MBR_SIGNATURE) LD DE,#AA55 AND A SBC HL,DE SCF RET ;------------------------------------------------- ; Выделить заданный диск из ком-строки ; ; вход: hl=буфер строки ; выход: a=номер диска ; CF-при ошибке ;------------------------------------------------- get_drive_letter: inc hl ; буфер строки ld de,buffer ; буфер для выдел. параметра ld c,Dss.GSwitch ; выделить параметр ком. строки RST ToDSS ld de,buffer ld a,(de) inc de ld c,a ; сохр. 'a' ld a,(de) inc de cp ':' jr nz,get_drive_err ; диск не задан ld a,(de) inc de or a jr nz,get_drive_err ; > 1 параметра ld a,c ; восст. 'a' cp 'A' jr c,get_drive_err cp 'z'+1 jr nc,get_drive_err and %1101'1111 sub 'A' or a ret ; get_drive_err: scf ; ошибка ret ;---------------------------------------------------- ; сохр. тек. системный диск и путь ;---------------------------------------------------- save_path: ld c,Dss.CurDisk ; узнать диск RST ToDSS ld (sys_disk),a ld hl,sys_path ld c,Dss.CurDir ; узнать путь RST ToDSS ret ;---------------------------------------------------- ; восст. тек. системный диск и путь ;---------------------------------------------------- restore_path: ld a,(sys_disk) ld c,Dss.ChDisk ; смена диска RST ToDSS ld hl,sys_path ld c,Dss.ChDir ; смена пути RST ToDSS ret ; ; disk: db 0 ; номер заданного диска boot_disk: db 0 ; номер boot-диска системы ; раб. ячейки тек. файла ; ; чтение: system.exe, далее system.dos ; запись: system.dos, далее system.exe FILE1_PARAMS: .handle: db -1 ; дескриптор файла .id_blck: db -1 ; идентиф. выдел. блока памяти ; .sizeLow: dw 0 ; мл.разряд размера файла .sizeHigh: dw 0 ; ст.разряд .dataSize EQU $-FILE1_PARAMS ; сохр. данные system.exe FILE2_PARAMS: .handle: db -1 ; дескриптор файла .id_blck: db -1 ; идентиф. выдел. блока памяти ; .sizeLow: dw 0 ; мл.разряд размера файла .sizeHigh: dw 0 ; ст.разряд .dataSize EQU $-FILE2_PARAMS ASSERT FILE1_PARAMS.dataSize = FILE2_PARAMS.dataSize, "Erorr! FILE1_PARAMS != FILE2_PARAMS" ; ; ; ; ; ; сообщения messages: db 0 db "\r\nBoot and System files Installer v" ;0 db major_version + '0','.' db (minor_version / 10) + '0',(minor_version % 10) + '0','.' db "\r\nBuild date ",SYS_BUILD_DATE ;db "\r\nCopyright (c) 2006 Vasil Ivanov." db "\r\nCopyright (c) Sprinter Team." db "\r\n\n",0 ; db "System successfully installed on disk " ;1 .lett1: db "X:\r\n\n",0 ; db "Installing boot loader...\r\n\n",0 ;2 db "Writing system files...\r\n\n",0 ;3 ; db "Syntax: SYS X:\r\n" ;4 db " where X: - drive letter (A..Z)\r\n\n",0 ; db "Insert destination disk in drive " ;5 .lett2: db "X:\r\n" db "and strike any key when ready ...\r\n\n",0 ; db "Insert system disk in drive " ;6 .lett3: db "X:\r\n" db "and strike any key when ready ...\r\n\n",0 ; db "Can't install boot on this disk\r\n\n",0 ;7 db "Invalid drive specification\r\n\n",0 ;8 db " Error: Can't open file\r\n\n",0 ;9 db " Error: Can't allocate memory\r\n\n",0 ;10 db " Error: Need DOS version 1.70.811 or higher\r\n\n",0 ;11 db " Error: Reading error\r\n\n",0 ;12 db " Error: Can't create file\r\n\n",0 ;13 db " Error: Writing error\r\n\n",0 ;14 .endmess: db 0 ; Вывести строку по индексу ; вход: a=индекс строки print_string: call get_string ; поиск строки по ее индексу в 'a' ld c,Dss.PChars ; вывод строки RST ToDSS ret ; поиск строки по ее индексу в 'a' get_string: ld hl,messages ; список мессаг для индекс. доступа ld bc,messages.endmess - messages ; размер списка inc a ex af,af' xor a ex af,af' get_loop: ex af,af' cpir ret po ret nz ex af,af' dec a jr nz,get_loop ret ;==================================================== ; Вся работа по загрузке файла в страницы ; вход: hl=имя файла ; выход: CF-при ошибке ;==================================================== read_file: ld a,Dss.Open.R ; на чтение ld c,Dss.Open ; открыть файл RST ToDSS jr nc,.ok ; без ошибок ; push af ld a,9 ; индекс "Can't open file" call print_string pop af ret ; .ok: ld (FILE1_PARAMS.handle),a ; дескр. файла ld hl,0 ld ix,0 ld bc,Dss.Move_FP.FrEnd ; указатель на конец файла RST ToDSS ld (FILE1_PARAMS.sizeHigh),hl ; ст.разряд размера файла ld (FILE1_PARAMS.sizeLow),ix ; мл.разряд call get_memory ; расч. и выдел. страницы под файл jr c,.not_enough ; не хватает памяти call file_to_bank ; загр. файл в страницы .close_file: push af ld a,(FILE1_PARAMS.handle) ; дескр. файла ld c,Dss.Close ; закрыть файл RST ToDSS pop af ret ; .not_enough: push af call .close_file ld a,10 ; индекс "Can't allocate memory" call print_string pop af or a scf ret nz ld a,DSS_Error.sys.NOT_ENOUGH_MEMORY ret ;---------------------------------------------------- ; По размеру файла рассчитать необходимое ; число страниц и выделить их. ; Выход: CF - при нехватке памяти ;---------------------------------------------------- get_memory: ld hl,(FILE1_PARAMS.sizeHigh) ; ст.разряд размера файла ld bc,(FILE1_PARAMS.sizeLow) ; мл.разряд ld de,#4000 ; делитель (размер страницы) xor a scf malloc1: rr d rr e jr c,malloc2 rr h rr l rr b rr c jr nc,malloc1 ld a,1 jr malloc1 ; malloc2: or a jr z,$+3 ;!FIXIT $ inc bc xor a cp b scf ret nz ; выделить блок памяти ld b,c ; b=число страниц ld c,Dss.GetMem RST ToDSS ld (FILE1_PARAMS.id_blck),a ; идентиф. блока ret ;---------------------------------------------------- ; Загрузить файл в страницы ;---------------------------------------------------- file_to_bank: ld hl,0 ld ix,0 ld a,(FILE1_PARAMS.handle) ; дескр. файла ld bc,Dss.Move_FP.FrStart ; указатель на начало файла RST ToDSS ld a,(FILE1_PARAMS.id_blck) ; идентиф. блока памяти ;ld b,0 ; лог. номер страницы в блоке ld bc,0*256 + BIOS.GetMemPage; получить физ. номер страницы в блоке rst ToBIOS ret c .loop: push af out (SLOT3),a ld hl,page_buffer ; #C000 куда ld de,#4000 ; сколько ld a,(FILE1_PARAMS.handle) ; дескр. файла ld c,Dss.Read ; читать файл RST ToDSS pop bc jr c,.error ; ok cp -1 ; прочитано меньшее число байт ? ret z ; да ld a,b ; a=физич. страница ld c,BIOS.GetMemPageNext ; получить номер след. физ. страницы блока rst ToBIOS ret c cp #FF jr nz,.loop ; не последняя страница ret ; error .error: ld a,12 ; индекс "Reading error" call print_string scf ret ;==================================================== ; Запись файла на диск ; вход: hl=имя файла ; выход: CF-при ошибке ;==================================================== write_file: ld a,FAT_ATTR.ARCHIVE ; атрибут "архивный" ld c,Dss.Create ; создать файл RST ToDSS jr nc,.create_ok ; без ошибок push af ld a,13 ; индекс "Can't create file" call print_string pop af ret ; .create_ok: ld (FILE1_PARAMS.handle),a ; дескр. файла ld hl,read_file.close_file ; закр. файл push hl ; точка выхода ; ; чтение файла из банок и запись на диск ld a,(FILE1_PARAMS.id_blck); идентиф. блока памяти ;ld b,0 ; лог. номер страницы в блоке ld bc,BIOS.GetMemPage ; получить физ. номер страницы в блоке rst ToBIOS ret c .loop: push af out (SLOT3),a ld hl,(FILE1_PARAMS.sizeLow) ; мл.разряд размера файла ld de,(FILE1_PARAMS.sizeHigh) ; ст.разряд ld bc,#4000 xor a sbc hl,bc ld b,a ex de,hl sbc hl,bc ex de,hl jr c,.write_end ; записать остаток ld (FILE1_PARAMS.sizeLow),hl ld (FILE1_PARAMS.sizeHigh),de ; ld hl,page_buffer ; #C000 откуда ld de,#4000 ; сколько ld a,(FILE1_PARAMS.handle) ; дескр. файла ld c,Dss.Write ; запись файла RST ToDSS pop bc jr c,.error ; write_ok ; [ ] Fixed 24/06/2024 какой-то пережиток прошлого ;cp -1 ; записано меньшее число байт ? ;ld a,DSS_Error.sys.DISK_FULL ;scf ;jr nz,.error ; да, на диске нет места ; ld a,b ; a=физич. страница ld c,BIOS.GetMemPageNext ; получить номер след. физ. страницы блока rst ToBIOS ret c cp #FF jr nz,.loop ; не последняя страница ret ; .write_end: pop af ; баланс стека ld de,(FILE1_PARAMS.sizeLow) ; сколько ld a,e or d ret z ; 0 байтов ld hl,page_buffer ; #C000 откуда ld a,(FILE1_PARAMS.handle) ; дескр. файла ld c,Dss.Write ; запись файла RST ToDSS ret nc ; .error: push af ld a,14 ; индекс "Writing error" call print_string pop af ret ; ДОС-загрузчик code_loader: include 'dssboot.asm' ; универсальный загрузчик для старого и нового доса code_loader.size EQU $-code_loader ASSERT SECTORS_OF_LOADER*512 >= (code_loader.size), "incorrect value of the SECTORS_OF_LOADER variable" DISPLAY " dssboot size: ", /D,code_loader.size, " bytes. Sectors: ",/D,(code_loader.size/512 + (code_loader.size mod 512)/(code_loader.size mod 512)) ; 512 байт, буфер boot-сектора buffer equ $ sys_disk equ buffer+512 ; диск системы sys_path equ sys_disk+1 ; путь системы