;!TODO: ; [ ] Dss.DRV.Open ; [ ] Dss.DRV.Close ; [ ] .SectorsPerFAT32 DWORD 0 error если старший байт !=0 ; [ ] .FAT.LABEL DB 'NO_LABEL ' дополнительно писать в корневую директорию /* BOOT_SECTOR EQU #00 .JMP EQU #00 ; BLOCK 3,0 BS_jmpBoot Jump to bootstrap (E.g. eb 3c 90; on i86: JMP 003E NOP. One finds either eb xx 90, or e9 xx xx. .ID_NAME EQU #03 ; TEXT 8 BS_OEMName DOS NAME - DB "DSS_1.70" ; Block Parameters BIOS .BytesPerSector GenIOCTL.GetParams EQU #0B ; WORD #200 BPB_BytsPerSec Размер сектора в байтах .SectorsPerCluster ;!TODO EQU #0D ; BYTE 2 BPB_SecPerClus Размер кластера в секторах .RESERVED_SECTORS !RESERVED_SECTORS EQU #0E ; WORD 1 BPB_ResvdSecCnt Размер системной области (включая этот сектор) RESERVE SECTORS .Number_of_FATs 2 EQU #10 ; BYTE 2 BPB_NumFATs Количество таблиц FAT .FilesInRootDIR 0 EQU #11 ; WORD 112 BPB_RootEntCnt Число описателей файлов в корневом каталоге (в FAT32 - 0) .SectorsPerDrive 0 EQU #13 ; WORD 1440 BPB_TotSec16 Общее число секторов на диске (если 0, то размер - в .BPB_BIG_TOTAL_SECTORS) .DRIVE_TYPE !DRV_TYPE EQU #15 ; BYTE #F0 BPB_Media Тип устройства .SectorsPerFAT16 0 EQU #16 ; WORD 2 BPB_FATSz16 Размер одной FAT в секторах (0 в FAT32) .SectorsPerTrack GenIOCTL.GetParams EQU #18 ; WORD 9 BPB_SecPerTrk Размер дорожки в секторах .HEADS GenIOCTL.GetParams EQU #1A ; WORD 2 BPB_NumHeads количество головок .HIDDEN EQU #1C ; DWORD 0 BPB_HiddSec количество скрытых секторов .BPB_BIG_TOTAL_SECTORS_L EQU #20 ; WORD 0 BPB_TotSec32 BIG TOTAL SECTOR Low word .BPB_BIG_TOTAL_SECTORS_H EQU #22 ; WORD 0 BPB_TotSec32 BIG TOTAL SECTOR High word ; FAT 32 .SectorsPerFAT32 EQU #24 ; DWORD 4 BPB_FATSz32 Размер одной FAT в секторах .MainFATnumber 0 EQU #28 ; WORD 0 BPB_ExtFlags Номер главной таблицы FAT .Version 0 EQU #2A ; WORD 0 BPB_FSVer Версия FAT32 (обычно 0) .RootDirStartCluster 2 EQU #2C ; DWORD 2 BPB_RootClus Первый кластер корневого каталога (обычно 2) .FSINFO_Sector 1 EQU #30 ; WORD 1 BPB_FSInfo Номер сектора структуры FSINFO (обычно 1) .CopyBootSector 6 EQU #32 ; WORD 6 BPB_BkBootSec Номер сектора - копии загрузочного (обычно 6) .reserved_block: 0 EQU #34 ; BLOCK 12 BPB_Reserved Зарезервировано .FDD_Number GenIOCTL.GetParams&#F0 EQU #40 ; BYTE 0 BS_DrvNum Номер дисковода для функций BIOS .reserved_2: 0 EQU #41 ; BYTE 0 BS_Reserved1 Зарезервировано .FAT32.EXT_BOOT_REC_SIGNATURE EQU #42 ; BYTE #29 BS_BootSig Сигнатура - #29 .FAT32.SERIAL_NUMBER EQU #43 ; DWORD 0 BS_VolID VOLUME SERIAL NUMBER .FAT32.LABEL EQU #47 ; TEXT 11 BS_VolLab Метка диска .ID_FAT32 EQU #52 ; TEXT 8 BS_FilSysType Аббревиатура файловой системы .BOOT_CODE_FAT32 EQU #5A ------------------------------------------------------------------------ !DRV_TYPE: GenIOCTL.GetParams - физический номер 0,1 - BIOS.DRV_GET_PAR - тип флопаря #8x - Hard Drive остальное подумать ;;;;;;;;;;;;;;;;; для смещения FAT до кратного 4096 значения: 1) tmp1 = ((.HIDDEN + min_last_sector) & #0F)>0 ) * #10 2) tmp2 = (.HIDDEN + min_last_sector) & #FFFF'FFF0 3) tmp3 = tmp2 + tmp1 4) error = (tmp3 >= #1000'0000) ; LBA28 reserved_sectors = ( ((.HIDDEN + min_last_sector) & #0F)>0 ) * #10) - .HIDDEN ;;;;;;;;;;;;;;;;; */ ; ┌════════════════════════════════════════════════┐ ; │ DSS Drive Formatter for Sprinter │ ; │ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ │ ; │ Tolik_Trek │ ; │ 2026 │ ; └════════════════════════════════════════════════┘ DEVICE ZXSPECTRUM4096 ; for debug DEFINE INCREASE_BUILD 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.ini' ; 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 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 ; MAKE_AUTO: CALL CALCULATE_FAT CALL FORMAT_DRIVE CALL MAKE_LABEL_IN_DIR ;!FIXIT ;CALL MAKE_ROOT_DIR_LABEL ; первая запись в root dir - метка, потом нули RET ;----------------------------------------------------------------------- ; Автоматическое пределение параметров носителя и выбор 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 BIOS.Error.InvalidSubFunction 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: 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 RET ; .it_is_fat32: LD (FAT_PARAMETERS.SectorsPerFAT32),HL LD HL,(CALC_TOTAL_CLUSTERS.fat_size_h) LD (FAT_PARAMETERS.SectorsPerFAT32 + 2),HL RET ;--------------; ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- STOP_ERROR: .Save_SP+1: LD SP,0 ;!TODO SCF ; RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; 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_sz32; fat_sz32 в кластерах .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_sz32 = 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_sz32 + 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 LD (VARIABLES.DataSectors_L),DE LD (VARIABLES.DataSectors_H),HL ; total_clusters LD A,(FAT_PARAMETERS.SectorsPerCluster) CALL HLDE_Div_A LD (VARIABLES.NotUsedSpace),A ; total_clusters = HL:DE ; 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 ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- 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.HDD 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 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 + 3) LD IX,TABLES.FAT_TYPES LD A,TABLES.FAT_TYPES.Records LD BC,TABLES.FAT_TYPES.LineSize .loop: LD L,(IX) LD H,(IX+1) AND A SBC HL,DE JR C,.found JR Z,.found ; 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 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 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 ;!FIXIT JP NZ,STOP_ERROR ; 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.SectorsPerFAT32) LD DE,(FAT_PARAMETERS.SectorsPerFAT32 + 2) JR Z,.its_fat32 ; LD BC,(FAT_PARAMETERS.SectorsPerFAT16) LD DE,0 .its_fat32: LD (.add_l),BC LD (.add_h),DE 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_l+1: LD BC,0 .add_h+1: LD DE,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: LD HL,FAT_PARAMETERS.PART2_FAT32 LD BC,FAT_PARAMETERS.PART2_FAT32_SIZE + FAT_PARAMETERS.PART3_SHARED_SIZE LDIR ; LD HL,#AA55 LD (SECTOR_BUFFER + BOOT_SECTOR.MBR_SIGNATURE),HL ; LD HL,0 LD IX,0 CALL WRITE_SECTOR_BUFFER LD HL,0 LD IX,(FAT_PARAMETERS.CopyBootSector) CALL WRITE_SECTOR_BUFFER ; LD A,(VARIABLES.FAT_TYPE) CP CONSTANTS.FAT32 RET NZ ; 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: HL:IX - rootdir's first sector MAKE_LABEL_IN_DIR: CALL CLEAN_SECTOR_BUFFER ;!FIXIT скорее всего, не нужно чистить ; 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) INC HL AND A JP Z,SHOW_VERSION ; CALL .MAIN JP C,STOP_ERROR RET ; .MAIN: PUSH HL LD BC,Dss.EX_Path.GET_ALL RST ToDSS RET C ; нам нужна строка в которой есть драйв, но нет пути AND %0000'1100 XOR %0000'1000 RET NZ ; достаём имя драйва (оно без ключа "/") POP HL PUSH HL LD DE,SECTOR_BUFFER LD BC,Dss.EX_Path.GET_DRIVE RST ToDSS RET C ; LD (VARIABLES.CurrentDrive),A ; только для того, чтоб обновить параметры драйва (вдруг дискету сменили?) LD C,Dss.ChDisk RST ToDSS JR NC,.no_err_drv ; CP DSS_Error.sys.MEDIA_CHANGED JP NZ,STOP_ERROR ; перебираем ключи "/" .no_err_drv: POP HL .loop: LD A,(HL) INC HL AND A RET Z ; CP '/' ; JR Z,.SET_KEY ; CP ' ' JR Z,.loop JP STOP_ERROR ; ; .SET_KEY: LD A,(HL) EX AF,AF' INC HL LD A,(HL) INC HL AND A JR Z,.cont_set ; CP ' ' JR Z,.cont_set JP 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 L,(IX + KEYS_PARAMETERS.KEYS_STR.Procedure) LD H,(IX + KEYS_PARAMETERS.KEYS_STR.Procedure + 1) LD A,L OR H 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 ; неправильный ключ ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- JP_HL: JP (HL) ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ;!FIXIT SHOW_VERSION: LD SP,(STOP_ERROR.Save_SP) LD HL,Version_Msg LD C,Dss.PChars RST ToDSS ; LD BC, 256*DSS_Error.sys.INVALID_DRIVE + Dss.Exit RST ToDSS ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ;!FIXIT SHOW_HELP: LD SP,(STOP_ERROR.Save_SP) DI HALT ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ;!FIXIT GET_KEY_FAT: DI HALT ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ;!FIXIT SET_LABEL: DI HALT ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- 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 ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; DEBUG_START: LD HL,.data ; CALL STRING_TO_WORD ; DI ; HALT ; ; ; .data: DZ "327670" ; IN: DE - (string decimal) ; OUT: HL - string to word ; DE - addr next after string decimal ;!FIXIT проверка на пустую строку STR_TO_WORD: LD HL,0 .loop: LD B,H LD C,L ; ADD HL,HL ;x2 RET C ADD HL,HL ;x4 RET C ADD HL,BC ;x5 RET C ADD HL,HL ;x10 RET C ; LD B,0 LD C,A ADD HL,BC RET C ; LD A,(DE) OR A RET Z CP ' ' RET Z ; CP '9'+1 CCF RET C SUB '0' RET C ; INC DE JR .loop ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; Enin Anton ;Процедура преобразования 8битовых чисел в шестнадц. текст ;На вход: ; HL - адрес буфера ; А - байт ;На выход: ; буфер с текст.числом IFUSED PutHexNumb PutHexNumb PUSH AF RRCA RRCA RRCA RRCA AND #0F ADD A,#90 DAA ADC A,#40 DAA LD (HL),A INC L POP AF AND #0F ADD A,#90 DAA ADC A,#40 DAA LD (HL),A INC L RET ENDIF ;----------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////// include 'math.asm' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// include 'data.z80' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// include 'messages.z80' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// ;!FIXIT include 'shared_includes/printf.asm' //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// 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" ;███████████████████████████████████████████████████████████████████████