;!TODO: ; [ ] Dss.DRV.Open ; [ ] Dss.DRV.Close ; [ ] .SectorsPerFAT32 DWORD 0 error если старший байт !=0 ; ┌════════════════════════════════════════════════┐ ; │ DSS Drive Formatter for Sprinter │ ; │ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ │ ; │ Tolik_Trek │ ; │ 2026 │ ; └════════════════════════════════════════════════┘ DEVICE ZXSPECTRUM4096 ; for debug DEFINE INCREASE_BUILD DEFINE fdd_low_enabled 0 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/structures/FileSystem.inc' INCLUDE 'version.inc' ; Standart EQU section ;---------------------------------------------------------------------[] org_addr EQU #8000 + CLP_Buffer code_addr EQU DSS_DRIVE_FORMAT stack_point EQU STACK_BUFFER stack_buffer EQU 256 program_start EQU DSS_DRIVE_FORMAT Loader_length EQU 0 ;---------------------------------------------------------------------[] ; Code start section ;[]-------------------------------------------------------------------[] DEFINE EXE_HEADER 1 INCLUDE 'Shared_Includes/constants/EXE_Header.z80' ORG org_addr ;;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - [] ; DSS Drive Formatter ;███████████████████████████████████████████████████████████████████████ ;----------------------------------------------------------------------- DSS_DRIVE_FORMAT: ;----------------------------------------------------------------------- LD (STOP_ERROR.Save_SP),SP PUSH IX ; забираем текущую директорию LD C,Dss.CurDisk RST ToDSS ADD 'A' LD (Exit_Path),A LD HL,Exit_Path.Path LD C,Dss.CurDir RST ToDSS ; POP HL CALL PARSE_CMD ; ;!FIXIT ; ; LD A,(KEYS_PARAMETERS.FAT_TYPE + KEYS_PARAMETERS.KEYS_STR.Status) LD C,A ; проверка на затуп LD A,(KEYS_PARAMETERS.FilesInRootDIR + KEYS_PARAMETERS.KEYS_STR.Status) AND A JR Z,.no_zatup ; LD A,C OR A JR Z,.no_zatup ; LD A,(KEYS_PARAMETERS.FAT_TYPE + KEYS_PARAMETERS.KEYS_STR.Data) CP CONSTANTS.FAT32 JR NZ,.no_zatup ; LD A,KEYS_PARAMETERS.Status.Ignored LD (KEYS_PARAMETERS.FilesInRootDIR + KEYS_PARAMETERS.KEYS_STR.Status),A .no_zatup: ; проверка на авто-расчёт LD A,(KEYS_PARAMETERS.SectorsPerCluster + KEYS_PARAMETERS.KEYS_STR.Status) OR C JR Z,MAKE_AUTO ; ; !TODO другие варианты формата ; ; !TODO вывод сообщения, что формат не состоялся JP STOP_ERROR ; MAKE_AUTO: CALL CALCULATE_FAT CALL SHOW_FORMAT_PARAMETERS ;JP C,STOP_ERROR ; abort CALL FORMAT_DRIVE CALL MAKE_LABEL_IN_DIR ; первая запись в root dir - метка, потом нули JP C,STOP_ERROR LD B,DSS_Error.sys.NO_ERROR LD HL,DONE_MSG LD (EXIT.msg),HL JP EXIT ;----------------------------------------------------------------------- ; Автоматическое пределение параметров носителя и выбор FAT CALCULATE_FAT: CALL .STEP1 ; эта должна быть общей для заполнения геометрии диска ; Автоматический выбор FAT_TYPE, RESERVED_SECTORS, SectorsPerCluster CALL .STEP2 ; RESERVED_SECTORS, RootDir, дальше устанавливаем геометрию. Уже должен быть выбран тип FAT CALL .STEP3 CALL MAKE_SERIAL RET ;--------------; ;--------------; .STEP1: LD A,(VARIABLES.CurrentDrive) LD BC,Dss.DRV.GenIOCTL.GetMoreParams RST ToDSS.DRV JR NC,.set_hidden ; CP DSS_Error.drv.INVALID_COMMAND JP NZ,STOP_ERROR ; если нет такой подфункции в драйвере, то смещение = 0 LD HL,0 LD D,H LD E,L ; .set_hidden: LD (FAT_PARAMETERS.HIDDEN),DE LD (FAT_PARAMETERS.HIDDEN + 2),HL LD A,(VARIABLES.CurrentDrive) LD BC,Dss.DRV.GenIOCTL.GetParams RST ToDSS.DRV JP C,STOP_ERROR ;!TODO CHECK ERROR неподходящий диск ; LD (VARIABLES.DriveExtendedParameters),A EX AF,AF' AND #F0 LD (FAT_PARAMETERS.BPB_PHISICAL_DRIVE_NUMBER),A LD (FAT_PARAMETERS.FDD_Number),A EXX LD (FAT_PARAMETERS.SectorsPerTrack),BC LD (FAT_PARAMETERS.HEADS),DE EXX ; !FIXIT вариант для винта LD A,H OR L JR NZ,.BPB_BIG_TOTAL_SECTORS ; LD (FAT_PARAMETERS.SectorsPerDrive),DE JR .STEP1_2 ; .BPB_BIG_TOTAL_SECTORS: LD (FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_L),DE LD (FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_H),HL .STEP1_2: ; размер сектора XOR A SRL B RRA LD C,A LD (FAT_PARAMETERS.BytesPerSector),BC ; размер диска в байтах EDLHA CALL MUL32_POWER2 LD (VARIABLES.VOLUME_SIZE_BYTES),DE ; !FIXIT байт из E не используется LD (VARIABLES.VOLUME_SIZE_BYTES + 2),HL LD (VARIABLES.VOLUME_SIZE_BYTES + 4),A RET ;--------------; ;--------------; ; Автоматический выбор FAT_TYPE, SectorsPerCluster .STEP2: CALL AUTO_CHOOSE_FAT_PARAMS JR C,STOP_ERROR ; LD A,C LD (VARIABLES.FAT_TYPE),A ;CP CONSTANTS.FAT32 ;LD HL,CONSTANTS.FAT_ReservedSectors.FAT32 ;JR Z,.set_reserved_s ; ;!FIXIT проверка FDD/HDD ;LD HL,CONSTANTS.FAT_ReservedSectors.HDD ; .set_reserved_s: ;LD (FAT_PARAMETERS.RESERVED_SECTORS),HL LD HL,(FAT_PARAMETERS.BytesPerSector) DEC HL SBC HL,DE LD HL,(FAT_PARAMETERS.BytesPerSector) EX DE,HL JR C,.BPS_OK ; на случай, если табличный кластер меньше сектора LD A,1 .BPS_OK: LD (VARIABLES.ClusterSize),HL CALL C,DIV16_POWER2 JR C,STOP_ERROR ; LD (FAT_PARAMETERS.SectorsPerCluster),A RET ;--------------; ;--------------; ; дальше устанавливаем геометрию. Уже должен быть выбран тип FAT ;IN: ; FAT_PARAMETERS.BPB_PHISICAL_DRIVE_NUMBER ; FAT_PARAMETERS.SectorsPerDrive ; FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_L ; FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_H ;OUT: ; VARIABLES.NotUsedSpace ; VARIABLES.total_clusters_L ; VARIABLES.total_clusters_H ; CALC_TOTAL_CLUSTERS.fat_size_l ; CALC_TOTAL_CLUSTERS.fat_size_h ; FAT_PARAMETERS.DRIVE_TYPE ; FAT_PARAMETERS.SectorsPerFAT16 ; FAT_PARAMETERS.SectorsPerFAT32 ; FAT_PARAMETERS.RESERVED_SECTORS ; FAT_PARAMETERS.FilesInRootDIR .STEP3: CALL GET_DRIVE_TYPE JR C,STOP_ERROR ; LD A,B LD (FAT_PARAMETERS.DRIVE_TYPE),A ; CALL SET_RESERVED_AND_ROOTDIR ; LD HL,(FAT_PARAMETERS.SectorsPerDrive) LD A,H OR L JR NZ,.total_sectors ; LD HL,(FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_H) LD (CALC_TOTAL_CLUSTERS.t_sec_h),HL LD HL,(FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_L) .total_sectors: LD (CALC_TOTAL_CLUSTERS.t_sec_l),HL CALL CALC_TOTAL_CLUSTERS LD HL,(CALC_TOTAL_CLUSTERS.fat_size_l) LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT32 LD DE,"32" JR Z,.it_is_fat32 ; LD (FAT_PARAMETERS.SectorsPerFAT16),HL LD (VARIABLES.SectorsPerFAT_L),HL RET ; .it_is_fat32: LD (FAT_PARAMETERS.SectorsPerFAT32),HL LD (VARIABLES.SectorsPerFAT_L),HL LD HL,(CALC_TOTAL_CLUSTERS.fat_size_h) LD (FAT_PARAMETERS.SectorsPerFAT32 + 2),HL LD (VARIABLES.SectorsPerFAT_H),HL RET ;--------------; ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- STOP_ERROR: .Save_SP+1: LD SP,0 LD B,DSS_Error.sys.INVALID_FUNCTION LD HL,Error_Msg LD (EXIT.msg),HL ;!TODO EXIT: LD C,Dss.Exit PUSH BC LD HL,Exit_Path LD C,Dss.ChDir RST ToDSS ; ; POP BC ; LD A,B ; AND A ; JP Z,ToDSS ; ; PUSH BC .msg+1: LD HL,Error_Msg LD C,Dss.PChars RST ToDSS ; POP BC RST ToDSS ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; data_sectors = total_sectors - reserved_sectors - root_dir_sectors - (num_fats * fat_sz) ; IN: DE:HL = total_sectors ; OUT: (VARIABLES.NotUsedSpace) ; (VARIABLES.total_clusters_L) ; (VARIABLES.total_clusters_H) ; (CALC_TOTAL_CLUSTERS.fat_size_l) ; (CALC_TOTAL_CLUSTERS.fat_size_h) CALC_TOTAL_CLUSTERS: LD A,(VARIABLES.FAT_TYPE) SUB CONSTANTS.FAT32 JR Z,.no_root_dir ; calc rootdir sectors LD HL,(FAT_PARAMETERS.FilesInRootDIR) XOR A LD B,5 ; AHL<<5 = AHL*32 CALL AHL_RL_B ; B=0 PUSH HL POP IX LD H,B LD L,A LD BC,(FAT_PARAMETERS.BytesPerSector) ;HLIX/BC -> HLIX remainder DE CALL HLIX_div_BC LD A,D OR E JR Z,.no_plus_one ; LD BC,1 ADD IX,BC DEC C ADC HL,BC .no_plus_one: ; HL:IX - rootdir sectors LD (VARIABLES.RootDirSectors),IX LD A,L LD (VARIABLES.RootDirSectors + 2),A ; корректируем значение FilesInRootDIR LD BC,(FAT_PARAMETERS.BytesPerSector) LD DE,(VARIABLES.RootDirSectors) CALL MUL32_POWER2 LD A,L EX DE,HL LD B,5 ; AHL>>5 = AHL/32 CALL AHL_RR_B LD (FAT_PARAMETERS.FilesInRootDIR),HL .no_root_dir: ; .t_sec_h+1: LD DE,0 .t_sec_l+1: LD HL,0 ; data_sectors AND A ; total_sectors - reserved_sectors LD BC,(FAT_PARAMETERS.RESERVED_SECTORS) SBC HL,BC JR NC,.skip_dec_DE ; AND A DEC DE .skip_dec_DE: ; DE:HL = total_sectors - reserved_sectors .push_regs: PUSH DE PUSH HL ;num_fats * fat_size; fat_size в кластерах .fat_size_l+1: LD BC,0 .fat_size_h+1: LD DE,0 LD A,(FAT_PARAMETERS.Number_of_FATs) CALL DEBCxA ; LD B,H LD C,L PUSH IX POP DE ;num_fats * fat_size = BCDE ; LD HL,(VARIABLES.RootDirSectors) ADD HL,DE EX DE,HL LD HL,(VARIABLES.RootDirSectors + 2) LD H,0 ADC HL,BC LD B,H LD C,L ;num_fats * fat_size + root_dir_sectors = BC:DE ; POP HL SBC HL,DE EX DE,HL POP HL SBC HL,BC JP C,STOP_ERROR ; data_sectors = HL:DE 0x7FFA0000 ; ;CALL CHECK_MAX_DATA_SECTORS JP C,STOP_ERROR ; сменить FAT type? ; LD (VARIABLES.DataSectors_L),DE LD (VARIABLES.DataSectors_H),HL ; ; total_clusters LD A,(FAT_PARAMETERS.SectorsPerCluster) CALL HLDE_Div_A ; total_clusters = HL:DE, A - unused space in sectors ; LD B,0 LD C,A LD IX,(VARIABLES.NotUsedSpace) ADD IX,BC JP C,STOP_ERROR ; сменить FAT type? ; LD (VARIABLES.NotUsedSpace),IX LD (VARIABLES.total_clusters_L),DE LD (VARIABLES.total_clusters_H),HL ; fat_size LD B,D LD C,E EX DE,HL ; total_clusters = DE:BC ; LD A,(VARIABLES.FAT_TYPE) .call_calc: CALL DEBCxA ;DE:BC * A = HL:IX ; LD BC,(FAT_PARAMETERS.BytesPerSector) LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT12 JR NZ,.no_sla ; SLA C RL B .no_sla: DEC BC ADD IX,BC JR NC,.skip_inc_HL ; INC HL .skip_inc_HL: INC BC CALL HLIX_div_BC ; округление вперёд LD A,D OR E JR Z,.set_new_size ; LD BC,1 ADD IX,BC DEC C ADC HL,BC ; fat_size = HLIX .set_new_size: LD DE,(.fat_size_l) LD BC,(.fat_size_h) LD (.fat_size_l),IX LD (.fat_size_h),HL AND A SBC HL,BC JR NZ,.next_loop ; PUSH IX POP HL SBC HL,DE RET Z .next_loop: ; .counter+1: LD A,32 ; loop counter DEC A LD (.counter),A JP NZ,CALC_TOTAL_CLUSTERS JP STOP_ERROR ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- IFUSED CHECK_MAX_DATA_SECTORS ; IN: data_sectors = HL:DE ; OUT: CF=0 corrected data_sectors = HL:DE ; CF=1 слишком большая разница CHECK_MAX_DATA_SECTORS: LD BC,0 LD (VARIABLES.NotUsedSpace),BC LD A,(VARIABLES.FAT_TYPE) SUB CONSTANTS.FAT12 RET NC ; good sectors ; PUSH HL PUSH DE ; LD BC,CONSTANTS.MaxDataSectorsNumber.FAT12_H JR Z,.sectors_fat12 ; sectors_fat16 LD BC,CONSTANTS.MaxDataSectorsNumber.FAT16_H .sectors_fat12: PUSH BC LD BC,(FAT_PARAMETERS.BytesPerSector) CALL MUL32_POWER2 ; A:HL:DE ; POP BC AND A JR NZ,.too_mutch ; AND A SBC HL,BC JR C,.good_sectors ; JR NZ,.get_clu LD A,D OR E JR Z,.good_sectors ; .get_clu: PUSH DE POP IX PUSH BC LD BC,(FAT_PARAMETERS.BytesPerSector) CALL HLIX_div_BC POP BC ; HLIX remainder DE ; по идее, DE = 0 тут ; LD A,H OR L JR NZ,.too_mutch ; LD (VARIABLES.NotUsedSpace),IX LD IX,0 LD H,B LD L,C LD BC,(FAT_PARAMETERS.BytesPerSector) CALL HLIX_div_BC PUSH IX POP DE POP BC POP BC AND A RET ; .good_sectors: SCF .too_mutch: POP DE POP HL CCF RET ; ENDIF ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- SET_RESERVED_AND_ROOTDIR: LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT32 JR Z,.for_fat32 ; FAT12_16 ; Ставим дефолтные значения LD A,(FAT_PARAMETERS.DRIVE_TYPE) CP BOOT_SECTOR.Hard_Drive LD HL,CONSTANTS.FAT_ReservedSectors.FAT LD DE,CONSTANTS.FilesInRootDIR.HDD JR Z,.set_vars ; #F0 CP BOOT_SECTOR.Floppy_3x5_1x44 ;LD HL,CONSTANTS.FAT_ReservedSectors.FDD LD DE,CONSTANTS.FilesInRootDIR.FDD_HD JR Z,.set_vars ; #F9 LD A,(VARIABLES.DriveExtendedParameters) RLA JR C,.set_vars ; 5.25 / 1200 ; 720 LD DE,CONSTANTS.FilesInRootDIR.FDD_DD .set_vars: CALL .ChooseReserved EX DE,HL CALL .ChooseFilesInRootDIR ; LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT12 LD HL,'61' ; str FAT16 JR C,.set_type ; RET NZ ; не меняем - FAT32 ; LD H,'2' ; str FAT12 .set_type: LD (FAT_PARAMETERS.ID_FAT + 3),HL RET ; .for_fat32: LD A,(KEYS_PARAMETERS.FilesInRootDIR + KEYS_PARAMETERS.KEYS_STR.Status) DEC A JR NZ,.set_for_fat32 ; LD A,KEYS_PARAMETERS.Status.Ignored LD (KEYS_PARAMETERS.FilesInRootDIR + KEYS_PARAMETERS.KEYS_STR.Status),A .set_for_fat32: LD HL,CONSTANTS.FAT_ReservedSectors.FAT32 LD DE,CONSTANTS.FilesInRootDIR.HDD JR .set_vars ; ; .ChooseFilesInRootDIR: LD A,(KEYS_PARAMETERS.FilesInRootDIR + KEYS_PARAMETERS.KEYS_STR.Status) DEC A JR NZ,.noChangeRootDir ; LD HL,(KEYS_PARAMETERS.FilesInRootDIR + KEYS_PARAMETERS.KEYS_STR.Data) .noChangeRootDir: LD (FAT_PARAMETERS.FilesInRootDIR),HL RET ; ; .ChooseReserved: LD A,(KEYS_PARAMETERS.RESERVED_SECTORS + KEYS_PARAMETERS.KEYS_STR.Status) DEC A JR NZ,.noChangeReserved ; LD HL,(KEYS_PARAMETERS.RESERVED_SECTORS + KEYS_PARAMETERS.KEYS_STR.Data) .noChangeReserved: LD (FAT_PARAMETERS.RESERVED_SECTORS),HL RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- GET_DRIVE_TYPE: LD A,(FAT_PARAMETERS.BPB_PHISICAL_DRIVE_NUMBER) AND A ; DRIVE_CODES.SPRINTER.FDD LD B,BOOT_SECTOR.Hard_Drive RET NZ ; FDD LD A,(VARIABLES.DriveExtendedParameters) RLA LD B,BOOT_SECTOR.Floppy_3x5_720 RET NC ; AND %0000'1000 LD B,BOOT_SECTOR.Floppy_3x5_1x44 RET Z ; LD B,BOOT_SECTOR.Floppy_8_1x20 RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; -> должно быть установлено значение VOLUME_SIZE_BYTES. ; <- DE - CLUSTER SIZE. ; C - FAT TYPE. AUTO_CHOOSE_FAT_PARAMS: LD DE,(VARIABLES.VOLUME_SIZE_BYTES + 1) EXX LD DE,(VARIABLES.VOLUME_SIZE_BYTES + 3) ; 00:0000:0000 LD IX,TABLES.FAT_TYPES LD A,TABLES.FAT_TYPES.Records LD BC,TABLES.FAT_TYPES.LineSize .loop: LD L,(IX+2) LD H,(IX+3) AND A SBC HL,DE JR C,.found JR NZ,.next ; EXX LD L,(IX) LD H,(IX+1) SBC HL,DE EXX JR C,.found JR Z,.found ; .next: ADD IX,BC DEC A JR NZ,.loop ; у нас FAT12 c кластером в 512 ; надо проверить раздел на минимальный размер для FAT ; sec_bpb + sec_fat + sec_root_dir + sec_for_data ; LD A,D ; OR E ; JR NZ,.found ; ; ; LD HL,(VARIABLES.VOLUME_SIZE_BYTES + 1) ; LD DE,8 ; SBC HL,DE RET C ; раздел слишком мал для FAT12 (<2048) .found: ; достаём параметры из таблицы DI LD (.restore_SP),SP LD SP,IX POP HL ; холостое POP HL ; холостое POP DE ; CLUSTER SIZE POP BC ; C - FAT TYPE LD A,C .restore_SP+1: LD SP,0 EI AND A RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- MAKE_SERIAL: LD C,Dss.SysTime RST ToDSS ; EX DE,HL ADD IX,DE LD (FAT_PARAMETERS.SERIAL_NUMBER_2),IX ; LD A,D LD D,B XOR C .loop: RRA DJNZ .loop ; LD E,H LD H,L LD L,E ; LD E,A ADD HL,DE LD (FAT_PARAMETERS.SERIAL_NUMBER_1),HL RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- FORMAT_DRIVE: CALL MAKE_SYS_SECTORS CALL CLEAN_SECTOR_BUFFER ; clean all fat tables at drive ;LD A,(VARIABLES.FAT_TYPE) ;CP CONSTANTS.FAT32 ;LD BC,(FAT_PARAMETERS.SectorsPerFAT16) ;JR NZ,.its_not_fat32 ; LD BC,(VARIABLES.SectorsPerFAT_L) LD DE,(VARIABLES.SectorsPerFAT_H) LD (.add_h),DE ;.its_not_fat32: LD (.add_l),BC LD A,(FAT_PARAMETERS.Number_of_FATs) CALL DEBCxA ; HL:IX - всего секторов для записи PUSH HL PUSH IX EXX POP DE POP HL EXX ; HL':DE' - всего секторов для записи ; LD IX,(FAT_PARAMETERS.RESERVED_SECTORS) LD HL,0 EXX .write_loop: PUSH HL PUSH DE EXX PUSH HL PUSH IX ; HL:IX - текущий сектор FAT CALL WRITE_SECTOR_BUFFER ; POP IX POP HL LD BC,1 ADD IX,BC DEC C ADC HL,BC EXX LD BC,1 POP HL SBC HL,BC POP DE EX DE,HL DEC C SBC HL,BC JR NZ,.write_loop ; LD A,D OR E JR NZ,.write_loop EXX ; HL:IX - rootdir's first sector ; LD (VARIABLES.RootDirFirstSector_L),IX LD (VARIABLES.RootDirFirstSector_H),HL ; ; make fat table LD HL,SECTOR_BUFFER LD A,(FAT_PARAMETERS.DRIVE_TYPE) LD (HL),A INC HL LD (HL),#FF INC HL LD (HL),#FF LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT12 JR Z,.write_fat ; fat12 ; INC HL LD (HL),#FF JR C,.write_fat ; fat16 ; ; LD HL,(FAT_PARAMETERS.DRIVE_TYPE) ; LD H,#FF ; LD (SECTOR_BUFFER),HL ; LD L,H ; LD (SECTOR_BUFFER + 2),HL ; LD A,(VARIABLES.FAT_TYPE) ; CP TABLES.FAT12 ; JR C,.write_fat ; fat16 ; JR NZ,.fat32 ; ; fat12 ; XOR A ; LD (SECTOR_BUFFER + 3),A ; JR .write_fat ; .fat32: ; fat32 LD DE,#0FFF LD B,7 LD (HL),D .loop32: INC HL LD (HL),E DJNZ .loop32 INC HL LD (HL),D ; EX DE,HL ; ;LD DE,SECTOR_BUFFER + 3 ; LD HL,.Fat32Data ; LD BC,.Fat32Data.Size ; LDIR ; .write_fat: LD A,(FAT_PARAMETERS.Number_of_FATs) LD HL,0 LD D,H LD E,L PUSH HL POP IX LD BC,(FAT_PARAMETERS.RESERVED_SECTORS) ; .write_tbl_fat: ADD IX,BC ADC HL,DE PUSH AF PUSH HL PUSH IX ; HL:IX - текущий сектор FAT ; CALL WRITE_SECTOR_BUFFER ; .add_h+1: LD DE,0 .add_l+1: LD BC,0 POP IX POP HL POP AF DEC A JR NZ,.write_tbl_fat RET ; ;.Fat32Data: DB #0F,#FF,#FF,#FF,#FF,#FF,#FF,#FF,#0F ;.Fat32Data.Size EQU $-.Fat32Data ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- MAKE_SYS_SECTORS: CALL CLEAN_SECTOR_BUFFER LD HL,FAT_PARAMETERS.PART1 LD DE,SECTOR_BUFFER LD BC,FAT_PARAMETERS.PART1_SIZE LDIR ; LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT32 JR Z,.set_32 ; LD HL,(FAT_PARAMETERS.PART2_FAT12_16) LD (SECTOR_BUFFER + FAT_PARAMETERS.PART1_SIZE),HL INC DE INC DE LD HL,FAT_PARAMETERS.PART3_SHARED LD BC,FAT_PARAMETERS.PART3_SHARED_SIZE JR .ldir ; .set_32: LD HL,FAT_PARAMETERS.PART2_FAT32 LD BC,FAT_PARAMETERS.PART2_FAT32_SIZE + FAT_PARAMETERS.PART3_SHARED_SIZE .ldir: LDIR ; LD HL,#AA55 LD (SECTOR_BUFFER + BOOT_SECTOR.MBR_SIGNATURE),HL ; LD HL,0 LD IX,0 CALL WRITE_SECTOR_BUFFER ; LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT32 RET NZ ; LD HL,0 LD IX,(FAT_PARAMETERS.CopyBootSector) CALL WRITE_SECTOR_BUFFER CALL CLEAN_SECTOR_BUFFER LD HL,#AA55 LD (SECTOR_BUFFER + _sFSinfo.SECTOR_SIGNATURE),HL ; LD HL,#5252 LD (SECTOR_BUFFER + _sFSinfo.LEAD_SIGNATURE),HL LD HL,#4161 LD (SECTOR_BUFFER + _sFSinfo.LEAD_SIGNATURE + 2),HL ; LD HL,#7272 LD (SECTOR_BUFFER + _sFSinfo.DATA_SIGNATURE),HL LD HL,#6141 LD (SECTOR_BUFFER + _sFSinfo.DATA_SIGNATURE + 2),HL ; LD HL,(VARIABLES.FAT32_RootDirClusters) LD DE,(FAT_PARAMETERS.RootDirStartCluster) ; FIXED! ADD HL,DE LD DE,(FAT_PARAMETERS.RootDirStartCluster + 2) JR NC,.no_inc_de ; INC DE .no_inc_de: LD (SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER),HL LD (SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER + 2),DE ; LD B,H LD C,L LD HL,(VARIABLES.total_clusters_L) LD IX,(VARIABLES.total_clusters_H) SBC HL,BC LD (SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT),HL PUSH IX POP HL SBC HL,DE LD (SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT + 2),HL ; LD IX,(FAT_PARAMETERS.FSINFO_Sector) LD HL,0 CALL WRITE_SECTOR_BUFFER ; LD HL,#FFFF LD (SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER),HL LD (SECTOR_BUFFER + _sFSinfo.FIRST_FREE_CLUSTER + 2),HL LD (SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT),HL LD (SECTOR_BUFFER + _sFSinfo.FREE_CLUSTERS_COUNT + 2),HL INC HL LD IX,(FAT_PARAMETERS.CopyBootSector) LD DE,(FAT_PARAMETERS.FSINFO_Sector) ADD IX,DE PUSH IX CALL WRITE_SECTOR_BUFFER ; CALL CLEAN_SECTOR_BUFFER LD HL,#AA55 LD (SECTOR_BUFFER + _sFSinfo.SECTOR_SIGNATURE),HL LD HL,0 LD IX,(FAT_PARAMETERS.FSINFO_Sector) INC IX CALL WRITE_SECTOR_BUFFER POP IX INC IX LD HL,0 CALL WRITE_SECTOR_BUFFER RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- CLEAN_SECTOR_BUFFER: LD HL,SECTOR_BUFFER LD DE,SECTOR_BUFFER + 1 LD BC,4096 - 1 ; на будущее, для секторов больше 512 LD (HL),0 LDIR RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ;!FIXIT check error WRITE_SECTOR_BUFFER: LD A,(VARIABLES.CurrentDrive) .sectors+2: LD BC,256*1 + Dss.DRV.Write LD DE,SECTOR_BUFFER JP ToDSS.DRV ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; IN: (VARIABLES.RootDirFirstSector_H), (VARIABLES.RootDirFirstSector_L) MAKE_LABEL_IN_DIR: CALL CLEAN_SECTOR_BUFFER ; make directory record LD HL,FAT_PARAMETERS.LABEL LD DE,SECTOR_BUFFER LD BC,FAT_PARAMETERS.LABEL.Size LDIR ; EX DE,HL LD (HL),#08 LD HL,#0233 LD (SECTOR_BUFFER+22),HL LD HL,#5C85 LD (SECTOR_BUFFER+24),HL ; LD HL,.RootLabel ; LD BC,.RootLabel.Size ; LDIR ; write sector LD HL,(VARIABLES.RootDirFirstSector_H) LD IX,(VARIABLES.RootDirFirstSector_L) JR WRITE_SECTOR_BUFFER ; ; root dir entry for label and 0 for "end of catalog" without label ; .RootLabel: ;BYTE 'NO_LABEL ' ; BYTE #08,#00,#00,#00,#00,#00,#00,#00,#00,#00,#00 ; BYTE #33,#02,#85,#5C,#00,#00,#00,#00,#00,#00,#00 ; .RootLabel.Size EQU $-.RootLabel ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- PARSE_CMD: LD A,(HL) AND A JP Z,SHOW_VERSION ; длина CMD строки нулевая ; INC HL INC HL CALL .MAIN RET NC JP STOP_ERROR ; .MAIN: LD A,(HL) INC HL AND %1101'1111 SUB 'A' JP C,SHOW_HELP_NO_DISK ; LD (VARIABLES.CurrentDrive),A LD D,A LD A,(HL) INC HL LD E,A LD A,(HL) AND ~' ' ADD A,E SUB ':' JP NZ,SHOW_HELP_NO_DISK ; только для того, чтоб обновить параметры драйва (вдруг дискету сменили?) PUSH HL LD A,D LD C,Dss.ChDisk RST ToDSS POP HL JR NC,.loop ; CP DSS_Error.sys.UNKNOWN_FORMAT JP NZ,STOP_ERROR ; перебираем ключи "/" .loop: CALL .skip_space RET Z ; CP '/' JP NZ,STOP_ERROR ; .SET_KEY: ;INC HL LD A,(HL) EX AF,AF' INC HL LD A,(HL) AND A JR Z,.cont_set CP ' ' JP NZ,STOP_ERROR ; .cont_set: EX AF,AF' LD IX,KEYS_PARAMETERS.TABLE LD B,KEYS_PARAMETERS.TABLE.Elements LD DE,KEYS_PARAMETERS.KEYS_STR ; .loop_key: CP (IX + KEYS_PARAMETERS.KEYS_STR.Key) JR NZ,.next ; ;EX DE,HL LD E,(IX + KEYS_PARAMETERS.KEYS_STR.Procedure) LD D,(IX + KEYS_PARAMETERS.KEYS_STR.Procedure + 1) LD A,E OR D CALL NZ,JP_HL ;EX DE,HL LD A,KEYS_PARAMETERS.Status.On JR NC,.set_stat ; LD A,KEYS_PARAMETERS.Status.Ignored .set_stat: LD (IX + KEYS_PARAMETERS.KEYS_STR.Status),A JR .loop ; .next: ADD IX,DE DJNZ .loop_key JP STOP_ERROR ; неправильный ключ ; .skip_space: LD A,(HL) AND A RET Z INC HL CP ' ' RET NZ JR .skip_space ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- JP_HL: EX DE,HL JP (HL) ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ;!FIXIT SHOW_FORMAT_PARAMETERS: ;.disk LD A,(VARIABLES.CurrentDrive) ADD 'A' LD (PARAMS_MSG.disk),A ;.unused LD BC,(FAT_PARAMETERS.BytesPerSector) LD DE,(VARIABLES.NotUsedSpace) LD HL,0 CALL MUL32_POWER2 XOR A LD BC,PARAMS_MSG.unused CALL PRINT_5BYTES ;.fullSize LD DE,(VARIABLES.VOLUME_SIZE_BYTES) LD HL,(VARIABLES.VOLUME_SIZE_BYTES + 2) LD A,(VARIABLES.VOLUME_SIZE_BYTES + 4) LD BC,PARAMS_MSG.fullSize CALL PRINT_5BYTES ;.dataSize LD HL,(VARIABLES.total_clusters_H) LD DE,(VARIABLES.total_clusters_L) LD BC,(VARIABLES.ClusterSize) CALL MUL32_POWER2 LD BC,PARAMS_MSG.dataSize CALL PRINT_5BYTES ;.Clusters LD DE,(VARIABLES.total_clusters_L) LD HL,(VARIABLES.total_clusters_H) XOR A LD BC,PARAMS_MSG.Clusters CALL PRINT_5BYTES ;.Clu_size LD DE,(VARIABLES.ClusterSize) XOR A LD H,A LD L,A LD BC,PARAMS_MSG.Clu_size CALL PRINT_5BYTES ;.FATtxt LD HL,(FAT_PARAMETERS.ID_FAT+3) LD (PARAMS_MSG.FATtxt + 3),HL ;.Serial LD HL,FAT_PARAMETERS.SERIAL_NUMBER_2 + 1 LD DE,PARAMS_MSG.Serial CALL .make_Serial INC DE CALL .make_Serial ;.LabelTxt LD HL,FAT_PARAMETERS.LABEL LD DE,PARAMS_MSG.LabelTxt LD BC,FAT_PARAMETERS.LABEL.Size LDIR ; LD HL,PARAMS_MSG LD DE,SECTOR_BUFFER PUSH DE CALL SKIP_DUBLESPACES EX DE,HL LD (HL),0 POP HL LD C,Dss.PChars RST ToDSS ; .loop: LD C,Dss.EchoKey RST ToDSS ; позиционный код Y/y/н/Н - #95/#15 LD A,D AND %0111'1111 CP #15 JR NZ,SHOW_CANCELED ; LD HL,FORMATING_MSG LD C,Dss.PChars RST ToDSS RET ; ; .make_Serial: LD B,2 .serialLoop: LD A,(HL) DEC HL PUSH HL PUSH DE EX DE,HL ; HL - адрес буфера ; А - байт CALL PutHexNumb POP DE POP HL INC DE INC DE DJNZ .serialLoop RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- SHOW_VERSION: LD HL,Version_Msg ;----------------------------------------------------------------------- PRINT_AND_EXIT: LD SP,(STOP_ERROR.Save_SP) LD C,Dss.PChars RST ToDSS LD BC,Dss.Exit RST ToDSS ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- SHOW_DONE: LD HL,DONE_MSG LD (EXIT.msg),HL JP EXIT ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- SHOW_CANCELED: LD HL,CANCELED_MSG LD (EXIT.msg),HL JP EXIT ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- SHOW_HELP: LD HL,Version_Msg LD C,Dss.PChars RST ToDSS LD HL,HELP_MSG LD (EXIT.msg),HL JP EXIT ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- SHOW_HELP_NO_DISK: LD HL,Version_Msg LD C,Dss.PChars RST ToDSS LD HL,HELP_MSG JR PRINT_AND_EXIT ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- SET_LABEL: LD HL,SECTOR_BUFFER ; создаём метку тут, если символы в порядке EX DE,HL ; LD A,(HL) INC HL CP ' ' JR NZ,.skip_label ; нет пробела между ключом и меткой ; LD A,(HL) INC HL CP '"' JR NZ,.skip_label ; метка начинается не с кавычки ; ;LD DE,SECTOR_BUFFER ; создаём метку тут, если символы в порядке LD C,FAT_PARAMETERS.LABEL.Size LD B,C LD A,(HL) CP ' ' JR Z,.skip_label ; no_name ; CALL .loop1 RET NC JR .skip_label ; .loop1: LD A,(HL) AND A JR Z,.skip_label ; no_name ; CP #80 JR NC,.sym_ok ; CP #22 JR Z,.end_label CP #7C JR Z,.skip_label ; no_name ; CP #2A JR C,.check_3A CP #30 JR NC,.check_3A CP #2D JR Z,.sym_ok JR .skip_label ; no_name ; .check_3A: CP #3A JR C,.check_5B CP #40 JR C,.skip_label ; no_name ; .check_5B: CP #5B JR C,.sym_ok CP #5E JR C,.skip_label ; no_name ; .sym_ok: LD (DE),A INC HL INC DE DJNZ .loop1 LD A,(HL) CP '"' SCF RET NZ ; .end_label: LD A,B CP C SCF RET Z ; стандартная метка ; INC B ; чтоб не тратить байты на проверку на ноль EX DE,HL .loop2: LD (HL)," " INC HL DJNZ .loop2 INC DE PUSH DE ; B=0, C=FAT_PARAMETERS.LABEL.Size LD HL,SECTOR_BUFFER LD DE,FAT_PARAMETERS.LABEL LDIR POP HL AND A RET ; .skip_label: LD A,(HL) AND A SCF RET Z ; INC HL CP '"' SCF RET Z JR .skip_label ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- STRING_TO_WORD: CALL STR_TO_WORD JP C,STOP_ERROR ; LD (IX + KEYS_PARAMETERS.KEYS_STR.Data),L LD (IX + KEYS_PARAMETERS.KEYS_STR.Data + 1),H RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ;!FIXIT GET_KEY_FAT: DI HALT ;----------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////// IF fdd_low_enabled include 'fdd_low.asm' ENDIF //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// include 'math.asm' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// include 'Strings.asm' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// include 'data.z80' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// include 'messages.z80' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// ;!FIXIT ; include 'shared_includes/printf.asm' //////////////////////////////////////////////////////////////////////// Exit_Path: DB 'A:\' .Path: BLOCK 256-3+1 //////////////////////////////////////////////////////////////////////// STACK_BUFFER EQU $ + stack_buffer //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// SECTOR_BUFFER EQU STACK_BUFFER .SIZE EQU 4096 ASSERT SECTOR_BUFFER + SECTOR_BUFFER.SIZE < #C000, "ERROR: SECTOR_BUFFER" //////////////////////////////////////////////////////////////////////// ;███████████████████████████████████████████████████████████████████████ DISPLAY "PROGRAMM SIZE: ", /D, $ - DSS_DRIVE_FORMAT, " bytes" ;███████████████████████████████████████████████████████████████████████