;斃様様様様様様様様様様様様様様様様様様様様様様様与 ; DSS Drive Formatter for Sprinter ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; Tolik_Trek ; 2026 ;斥様様様様様様様様様様様様様様様様様様様様様様様踊 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" ;斃様様様様様様様様様様様様様様様様様様様様様様様与 ; FORMAT - Disk Format Utility for Sprinter ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; by Sayman 2021 ;斥様様様様様様様様様様様様様様様様様様様様様様様踊 DEVICE ZXSPECTRUM128 Start_addr = 0x8100 INCLUDE "include/estex_h.asm" INCLUDE "include/head_short.inc" INCLUDE "include/macro.s" INCLUDE "build.inc" LoaderStart: JP main ;=================================================== INCLUDE "console.asm" INCLUDE "printf.asm" INCLUDE "muldiv.asm" ;=================================================== ;[]=========================================================================[] ;[] Converting latin symbols a...z to upper registry [] ;[] IN: A - symbol for convert [] ;[] OUT: A - converted symbol [] ;[]=========================================================================[] CapsLetter: CP "a" ;<"a" JR C,.not_lat CP "z"+1 ;>"z" JR NC,.not_lat AND %11011111 ;set D5 for upper registry RET .not_lat: AND A SCF RET ;=================================================== main: DI PUSH IX LD A,(ix-3) SYS ESTEX_fclose CALL Check_Vmode ;check text mode and (if not) set it CALL GetXY LD DE,about_Msg.ptr CALL cPrint POP HL CALL ParseCL CALL confirmation LD DE,Process_Msg.ptr CALL cPrint CALL prepare JR NC,.ok_drive ; CALL FAT32_FORMAT ; LD A,"\a" ; bell SYS ESTEX_pchar LD DE,ProcessErr_Msg.ptr CALL cPrint LD B,#0D ;.UNKNOWN_FORMAT JP quit0 ; .ok_drive: CALL calc_bpb CALL gen_serial LD BC,0x0105 ;read 1 sector LD HL,0 LD IX,0 LD A,(FMTDISK) LD DE,buff RST 0x18 ;get start sector via read (drv) LD D,IXH ;this function return next sector LD E,IXL LD A,D OR E JR NZ,.next0 DEC HL .next0: DEC DE ;and correct it (-1) ;!FIXIT 苟 牀痳え? モ 皋, 艪 ぎ <ぅ 襪碎 甄イ竡薑 瓮皰 甄イ竡薑 ▲珀閻 LD (BPB.hide_sectors+2),HL LD (BPB.hide_sectors),DE LD HL,buff PUSH HL LD DE,buff+1 LD BC,512 XOR A LD (HL),A LDIR SYS ESTEX_getver PUSH DE LD A,D LD DE,BPB.OEM+4 CALL ConvNumTxt8 POP DE LD A,E LD DE,BPB.OEM+6 CALL ConvNumTxt8 ;write boot sector, init first FAT sector, write it ;clear buff (zeroed), write other FAT sectors ;repeat for FAT copy ;write zeroed ROOT directory LD IX,0 LD HL,0 ;boot sector LD A,(FMTDISK) LD BC,0x0106 ;save boot sector LD DE,BPB RST 0x18 CALL init_fat LD IX,(BPB.reserved_secs) LD HL,0 PUSH IX PUSH HL CALL wr_fat0 ;write first sector of FAT CALL clear_buff POP HL POP IX INC IX ;next FAT sector CALL wr_fat1 ;write other FAT sectors CALL init_fat LD IX,(BPB.reserved_secs) ;low bits LD DE,(BPB.fat_sectors) ADD IX,DE LD HL,0 PUSH HL PUSH IX CALL wr_fat0 CALL clear_buff POP IX POP HL PUSH HL PUSH IX INC IX CALL wr_fat1 POP IX POP HL LD DE,(BPB.fat_sectors) ADD IX,DE LD A,(BPB.root_handles) LD B,A CALL wr_fat1.loop0 LD DE,ProcessOK_Msg.ptr CALL cPrint CALL showInfo ; CALL Return_Vmode ; XOR A LD B,0 JP quit0 wr_fat0: LD A,(FMTDISK) LD BC,0x0106 ;save FAT sector LD DE,buff RST 0x18 ;next sector not returned!!! RET wr_fat1: LD A,(BPB.fat_sectors) LD B,A DEC B ;-first FAT sector .loop0: PUSH BC PUSH HL PUSH IX LD BC,0x0106 LD A,(FMTDISK) LD DE,buff RST 0x18 POP IX POP HL POP BC INC IX ;next sector (low) DJNZ .loop0 RET init_fat: LD HL,buff LD (HL),0xf8 ;init FAT INC HL LD (HL),0xff ;first 2 reserved clusters INC HL LD (HL),0xff INC HL LD A,(fat12_flg) RET NZ LD (HL),0xff ;0xfff8, 0xffff for FAT16 RET clear_buff: LD HL,buff LD DE,buff+1 LD BC,512 XOR A LD (HL),A LDIR RET showInfo: LD HL,(sectors+2) LD DE,(sectors) PUSH HL PUSH DE LD (DskInfo_Msg.sectors),DE LD (DskInfo_Msg.sectors+2),HL LD A,(BPB.cluster_size) RRA LD B,0 LD C,A JR NC,.next0 LD BC,512 LD A,"B" LD (DskInfo_Msg.u_sym),A .next0: LD (DskInfo_Msg.u_size),BC POP DE POP HL LD C,E ;/256 LD E,D LD D,L LD H,0 LD B,H SRL D ;/8 RR E SRL D RR E SRL D RR E LD (DskInfo_Msg.mb),DE LD HL,(BPB.serial_id) LD DE,(BPB.serial_id+2) LD (DskInfo_Msg.serial),DE LD (DskInfo_Msg.serial+2),HL LD A,(fat12_flg) OR A JR Z,.next1 LD A,"2" LD (DskInfo_Msg.FS+20),A .next1: LD DE,DskInfo_Msg.ptr CALL cPrint ;bugfix with last printed line with colors ;scrolling in console set color column... CALL GetXY ;get YX in DE LD HL,0x0150 LD B,D LD C,E CALL winClearScr RET ;=================================================== ;need to get the size of the disk in sectors and check for FAT12 limitation prepare: LD A,(FMTDISK) ; CP 2 JR NC,.begin ; PUSH AF SYS ESTEX_diskinfo JP C,Usage POP AF ; .begin: LD BC,0x0008 ;B = subcommand, C = IOCTL func. LD DE,0x55aa ;IOCTL requires Magic num RST 0x18 ;HLDE = disk size in sectors ; LD (cfg),A EX AF,AF AND #F0 LD (BPB.drv_code),A ; EX AF,AF ; LD A,H ; OR L CALL testDskSize ; CF = 0, 爼讚 ▲琥キ┘ ; CF = 1, 荐! ; EXX LD (BPB.sec_per_trk),BC LD (BPB.heads),DE EXX RET ;calculate boot sector (BPB) parameters calc_bpb: LD DE,(BPB.root_handles) LD B,5 .loop0: RL D RL E DJNZ .loop0 ;root_size (256) * 32 (element size) LD HL,0 CALL div512 ;root_size/512 (sector size) LD (rootSectors),DE ;root size in sectors LD HL,(sectors) LD DE,(sectors+2) LD BC,(BPB.reserved_secs) SBC HL,BC EX DE,HL LD BC,0 SBC HL,BC LD BC,(clusters) PUSH HL PUSH DE CALL div32 ;(sectors-reserved_sectors) / max_clusters AND A ;clear flags LD BC,0x0780 ;max 64 sectors for cluster LD A,E .loop1: RLC C ;128 sectors (64kb) not supported CP C JR C,.next_calc0 DJNZ .loop1 .next_calc0: LD A,C LD (BPB.cluster_size),A ;cluster size in sectors POP DE POP HL LD B,0 CALL div32 PUSH DE LD DE,(BPB.reserved_secs) ADD HL,DE ;+reserverd sectors LD (BPB.reserved_secs),HL POP DE LD A,(fat12_flg) OR A JR Z,.calc_fat16 LD H,D LD L,E ADD HL,HL ADD HL,DE ;*3 SRL H RR L ;/2 EX DE,HL LD HL,0 JR .next_calc1 .calc_fat16: LD HL,0 RL E RL D RL L RL H .next_calc1: CALL div512 LD A,B OR C JR Z,.next_calc2 INC DE .next_calc2: LD (BPB.fat_sectors),DE EX DE,HL ADD HL,HL LD B,H LD C,L EX DE,HL LD HL,(sectors) LD DE,(sectors+2) SBC HL,BC EX DE,HL LD BC,0 SBC HL,BC EX DE,HL LD BC,(BPB.reserved_secs) SBC HL,BC EX DE,HL LD BC,0 SBC HL,BC EX DE,HL LD BC,(rootSectors) SBC HL,BC LD BC,0 EX DE,HL SBC HL,BC LD A,(BPB.cluster_size) LD B,0 LD C,A CALL div32 LD (DskInfo_Msg.units),DE LD DE,(BPB.reserved_secs) ADD HL,DE LD (BPB.reserved_secs),HL RET testDskSize: ;EX AF,AF LD A,H OR L LD (sectors),DE LD (sectors+2),HL ;save temporary sectors JR NZ,.bigdsk ; PUSH HL .tstsmall: LD BC,0xf800+1 ;else, check for fat16 <32M LD H,D ;save in DE small sectors LD L,E SBC HL,BC POP HL JR NC,.bigdsk ;>32M (set Flag) LD BC,0x7800+1 ;else check for limit for fat12 EX DE,HL ;15M LD (BPB.small_sectors),HL SBC HL,BC RET NC ;>15M XOR A INC A LD (fat12_flg),A LD A,'2' LD (BPB.fat_id+4),A LD BC,0x0fef LD (clusters),BC RET ; .bigdsk: ;EX AF,AF ;LD (BigDskFlg),A LD (BPB.big_sectors),DE LD (BPB.big_sectors+2),HL ; check max size for fat16 #3FFD00 sectors (512b) 4193152 + 512 + 1+16? ; PC - 7F600000 The FAT file system is limited to 65,525 clusters /* The FAT file system is limited to 65,525 clusters - 0x3FFD40 sectors FAT TABLES SIZE: 131072 x 2 = 262 144 = #200 ROOT DIR SIZE: 8 192 #10 RESERVED SECTORS SIZE: 5 x 512 = 2 560 5 HIDDEN SECTORS SIZE */ LD BC,#FD00 + 1 EX DE,HL SBC HL,BC EX DE,HL LD BC,#003F SBC HL,BC CCF RET ; 諷き襯 Л腑: ; D - ぅ ; E - メ閹 ; IX - ; H - ; L - ┃竄 ; B - 瓮祗る ; C - ぅ イカ gen_serial: ld c,#21 ;!HARDCODE Dss.SysTime rst #10 ;!HARDCODE ToDSS ; ex de,hl add ix,de ld (BPB.serial_id + 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 e,l ; ld l,h ; ld h,e ld (BPB.serial_id),hl ret ; gen_serial: CALL Randomize ; CALL GetRnd ; LD (BPB.serial_id),A ;first 8bit (2 bits sec. 6 bits min.) ; LD L,A ; CALL GetRnd ; LD H,A ; PUSH HL ; .year: LD L,0 ; LD A,R ; RRA ; XOR L ; LD (BPB.serial_id+1),A ; CALL Rand16 ; POP BC ; ADD HL,BC ; LD (BPB.serial_id+2),HL ; RET ; ; from PQ-DOS formatter ; Randomize: SYS ESTEX_systime_get ; LD A,B ;seconds ; LD (rand1),A ; LD A,L ;minutes ; LD (rand2),A ; LD A,IXL ; LD (gen_serial.year+1),A ; LD A,R ; RRA ; LD (rand3),A ; CALL GetRnd ; LD L,A ; CALL GetRnd ; LD H,A ; LD (seed),HL ; RET ; GetRnd: LD A,(rand1) ; LD D,A ; LD A,(rand2) ; LD (rand1),A ; ADD A,D ; LD D,A ; LD A,(rand3) ; LD (rand2),A ; ADD A,D ; RRCA ; LD (rand3),A ; RET ; Rand16: LD DE,(seed) ;Seed is usually 0 ; LD A,D ; LD H,E ; LD L,253 ; OR A ; SBC HL,DE ; SBC A,0 ; SBC HL,DE ; LD D,0 ; SBC A,D ; LD E,A ; SBC HL,DE ; JR NC,Rand ; INC HL ; Rand: LD (Rand16+1),HL ; RET ; ; ParseCL: LD A,(HL) ;cmd line size OR A ;0 = no params JP Z,Usage ;goto help message INC HL INC HL ;first param LD A,(HL) LD C,A INC HL LD A,(HL) CP ':' ;must be dsk: (like C:) JP NZ,Usage ;if not, goto help message LD A,C CALL CapsLetter JP C,Usage ;drive letter is not a letter LD (warn_Msg.dsk),A ;store it in messages LD (Process_Msg.dsk),A ;* LD (ProcessErr_Msg.dsk),A ;* SUB 'A' ; .set_A: LD (FMTDISK),A .loop_x: INC HL LD A,(HL) OR A RET Z CP space JR NZ,.loop_x .loop1: CP "/" JR Z,.next0 CP "-" JR Z,.next0 JP Usage .next0: INC HL LD A,(HL) CP "?" JP Z,Usage POP HL JP Usage confirmation: CALL GetXY LD DE,warn_Msg.ptr CALL cPrint EI HALT SYS ESTEX_waitkey DI RES 5,A CP "Y" LD B,0 ;.NO_ERROR JP NZ,quit0 ;exit to DOS CALL PrintLF RET PrintLF: PrintChar cr PrintChar lf RET ;--------------- ;from FN ;Convert 8bit num to text ;IN: ; A - 8 bit num ; DE - buffer ;--------------- ConvNumTxt8: PUSH IX PUSH BC LD IX,ConvertFlg RES 7,(IX+#00) LD C,100 CALL ConNumb8 LD C,10 CALL ConNumb8 ADD A,"0" LD (DE),A INC DE POP BC POP IX RET ConNumb8: LD B,#2F INC B SUB C JR NC,$-2 ADD A,C EX AF,AF' LD A,B CP #30 JR Z,$+6 SET 7,(IX+#00) BIT 7,(IX+#00) JR Z,$+4 LD (DE),A INC DE EX AF,AF' RET ConvertFlg: DB #0 ;------------------------------------------------------------------------------- badClustErr: PrintChars badClust_Msg ;LD B,-2 LD B,#0D ; .UNKNOWN_FORMAT JR quit0 Usage: LD DE,usage_Msg.ptr CALL cPrint ; PrintChars usage_Msg LD B,0 quit0: PUSH BC CALL Return_Vmode POP BC SYS ESTEX_exit JP $ ;=================================================== FMTDISK: DB 0 ;formatting disk BigDskFlg: DB 0 ;big disk (>32Mb) flag cfg: DB 0 rootSectors: DW 0 sectors: DS 4 ;tmp value of sectors on the disk clusters: DW 0xffef fat_sectors: DW 0 system_sectors: DW 0 fat12_flg: DB 0 serial: DW 0,0 ;Volume Serial Number ; rand1: DB 0 ; rand2: DB 0 ; rand3: DB 0 ; seed: DB 0 ALIGN 256 BPB: .JMP: DB 0xeb,0xfe,0x00 ; 薑 ├ (珮И 轤 え瓷 PC 爬▲ぅ ※. JMP $) .OEM: DB "DSS . " .sector_size: DW 512 ;+11 ; sector size in bytes .cluster_size: DB 0 ;+13 ; cluster size in sectors .reserved_secs: DW 5 ;+14 ; reserved sector .fat_ncopy: DB 2 ;+16 ; # copy`s of FAT .root_handles: DW 256 ;+17 ; root size (records on root) .small_sectors: DW 0 ;+19 ; # of sectors (<32Mb) .media_id: DB 0xf8 ;+21 ; Media ID .fat_sectors: DW 0 ;+22 ; # sectors for one copy of FAT .sec_per_trk: DW 0 ;+24 ; sectors per track .heads: DW 0 ;+26 ; # of heads ; extended boot-record .hide_sectors: DWORD 0 ;+28 ; # of hidden sectors .big_sectors: DWORD 0 ;+32 ; # of sectors (>32Mb) .drv_code: DW 0x80 ;+36 ; drive code (0x80 for HDD) .eboot_sig: DB 0x29 ;+38 ; extended boot signature (?) .serial_id: DS 4 ;+39 ; Volume serial .vol_name: DB "NO NAME " ;+43 ; Volume label .fat_id: DB "FAT16 " ;+54 ; FAT id (FAT12 or FAT16) BPBsize = $-BPB INCBIN "x86_boot.bin" ; !FIXIT 磧碎 /* about_Msg: db cr,lf,"Format utility version 0.3.",BUILD_COUNT_T," (",BUILD_DAY_T,".",BUILD_MONTH_T,".",BUILD_YEAR_T,")" db cr,lf,"by Miroshnichenko Alexander aka Sayman@SprinterTeam",cr,lf,0 .ptr: dw about_Msg */ ;=================================================== about_Msg: DB cr,lf,"Format utility version 0.3.",BUILD_COUNT_T," (",BUILD_DAY_T,".",BUILD_MONTH_T,".",BUILD_YEAR_T,")" DB cr,lf,"by Miroshnichenko Alexander aka Sayman, (c) 2021.\r\nBug fixes by Anatoliy Belyanskiy, Sprinter Team, 2026.",cr,lf,0 .ptr: DW about_Msg usage_Msg: DB cr,lf,"This utility performs logical formatting and initializes the file system on the disks." DB cr,lf,col_cmd,col_red,"WARNING!!!",col_cmd,col_white," This version is limited for ",col_cmd,col_green,"2Gb",col_cmd,col_white," for FAT16 FS!" DB cr,lf,cr,"usage:" DB cr,lf,"FORMAT volume [key1] [key2] [keyN]" DB cr,lf," keys are:" DB cr,lf,tab,"in this version supported only /? key for help." DB cr,lf,cr,lf,0 .ptr: DW usage_Msg warn_Msg: DB cr,lf,cr,lf,col_cmd,col_red,"WARNING: ALL DATA ON YOR HARD DISK DRIVE ",col_cmd,col_violet,"%c:",col_cmd,col_red," WILL BE LOST!",col_cmd,col_white,cr,lf DB cr,lf,"Proceed with Format [Y/N]?",0 .ptr: DW warn_Msg .dsk: DB 0 Process_Msg: DB cr,lf DB cr,lf,"Quick formatting disk %c:...",0 .ptr: DW Process_Msg .dsk: DB 0 ProcessErr_Msg: DB cr,lf,cr,lf,col_cmd,col_red,"ABORTED: CAN'T FORMAT DRIVE ",col_cmd,col_violet,"%c:",cr,lf,col_cmd,col_yellow,"FAT16 does not support drives larger than 2GB.",cr,lf,cr,lf,0 .ptr: DW ProcessErr_Msg .dsk: DB 0 ProcessOK_Msg: DB "Done.",cr,lf,cr,lf,0 .ptr: DW ProcessOK_Msg DskInfo_Msg: DB "Formatted disk parameters:",cr,lf DB "Total sectors: ",tab,col_cmd,col_magenta,"%lu",col_cmd,col_white,cr,lf DB "Total size: ",tab,col_cmd,col_magenta,"%uMb",col_cmd,col_white,cr,lf DB "Units: ",tab,tab,col_cmd,col_magenta,"%u",col_cmd,col_white,cr,lf DB "Unit size: ",tab,col_cmd,col_magenta,"%u%c",col_cmd,col_white,cr,lf .FS: DB "File system: ",tab,col_cmd,col_magenta,"FAT16",col_cmd,col_white,cr,lf DB "Serial: ",tab,col_cmd,col_magenta,"%02x-%02x",col_cmd,col_white,cr,lf DB "Label: ",tab,tab,col_cmd,col_magenta,"NO LABEL",col_cmd,col_white,cr,lf,cr,lf,0 .ptr: DW DskInfo_Msg .sectors: DS 4 .mb: DW 0 .units: DW 0 .u_size: DW 0 .u_sym: DB "K",0 .serial: DS 4 badClust_Msg: DB cr,lf,"Bad cluster size.",cr,lf,cr,lf,0 ;WARNING: ALL DATA ON YOR HARD DISK DRIVE Z: WILL BE LOST! buff EQU ( high $ + ((low $)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 ;;;;;;;;;;;;;;;;; */ ;!TODO: ; Dss.DRV.Open ; Dss.DRV.Close ; DSS Drive Formatter FAT32_FORMAT: //////////////////////////////////////////////////////////////////////// MAKE_AUTO: LD (STOP_ERROR.Save_SP),SP ;!FIXIT LD A,(FMTDISK) LD (VARIABLES.CurrentDrive),A ; CALL CALCULATE_FAT CALL FORMAT_DRIVE ;!FIXIT ;CALL MAKE_ROOT_DIR_LABEL ; ム 瘡 root dir - モ, 皰 祀 RET ;----------------------------------------------------------------------- CALCULATE_FAT: ;LD (STOP_ERROR.Save_SP),SP ; ッ爛ぅキ┘ モ牀 瓱皀 襦 FAT .STEP1: ; 轤 ぎΝ °碎 ♂ォ か キ ギモ爬 え瓷 LD A,(VARIABLES.CurrentDrive) LD BC,Dss.DRV.GenIOCTL.GetMoreParams RST ToDSS.DRV JR NC,.set_hidden ; CP BIOS.Error.InvalidSubFunction JR Z,.GetParams ; メ モ や祗罔 む▲爛, 皰 甃ラキ┘ = 0 SCF JP STOP_ERROR ; .set_hidden: LD (CALCULATED_FAT_PARAMETERS.HIDDEN),DE LD (CALCULATED_FAT_PARAMETERS.HIDDEN + 2),HL .GetParams: LD A,(VARIABLES.CurrentDrive) LD BC,Dss.DRV.GenIOCTL.GetParams RST ToDSS.DRV JP C,STOP_ERROR ;!TODO CHECK ERROR クゅわ薑 え瓷 ; EX AF,AF' AND #F0 LD (CALCULATED_FAT_PARAMETERS.BPB_PHISICAL_DRIVE_NUMBER),A LD (CALCULATED_FAT_PARAMETERS.FDD_Number),A ; !FIXIT 爬 か ※ LD A,H OR L JR NZ,.BPB_BIG_TOTAL_SECTORS ; LD (CALCULATED_FAT_PARAMETERS.SectorsPerDrive),DE ;!TODO 竅※碎 筰, 艪 カ┤ え瓷 か FAT32 爬 ≒皀 JR .STEP1_2 ; .BPB_BIG_TOTAL_SECTORS: LD (CALCULATED_FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_L),DE LD (CALCULATED_FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_H),HL .STEP1_2: ; Кム 瓮皰 XOR A SRL B RRA LD C,A LD (CALCULATED_FAT_PARAMETERS.BytesPerSector),BC ; Кム え瓷 CALL MUL32_POWER2 LD (VARIABLES.VOLUME_SIZE_BYTES),DE LD (VARIABLES.VOLUME_SIZE_BYTES + 2),HL LD (VARIABLES.VOLUME_SIZE_BYTES + 4),A LD E,H LD D,A CALL AUTO_CHOOSE_FAT_PARAMS JR C,STOP_ERROR ; LD A,C LD (CALCULATED_FAT_PARAMETERS.FAT_TYPE),A CP TABLES.FAT32 LD HL,RESERVED_SECTORS.FAT32 JR Z,.set_reserved_s ; ;!FIXIT 牀▲爲 FDD/HDD LD HL,RESERVED_SECTORS.FAT_HDD ; .set_reserved_s: LD (CALCULATED_FAT_PARAMETERS.RESERVED_SECTORS),HL LD HL,(CALCULATED_FAT_PARAMETERS.BytesPerSector) DEC HL SBC HL,DE LD HL,(CALCULATED_FAT_PARAMETERS.BytesPerSector) EX DE,HL JR C,.BPS_OK ; 甄竍, メ ゛膈覃 痰ム キ跏 瓮皰 LD A,1 .BPS_OK: CALL C,DIV16_POWER2 JR C,STOP_ERROR ; LD (CALCULATED_FAT_PARAMETERS.SectorsPerCluster),A ; CALL GET_DRIVE_TYPE JR C,STOP_ERROR ; LD A,B LD (CALCULATED_FAT_PARAMETERS.DRIVE_TYPE),A LD HL,(CALCULATED_FAT_PARAMETERS.SectorsPerDrive) LD A,H OR L JR NZ,.total_sectors ; LD HL,(CALCULATED_FAT_PARAMETERS.BPB_BIG_TOTAL_SECTORS_H) LD (CALC_TOTAL_CLUSTERS.t_sec_h),HL LD HL,(CALCULATED_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,(CALCULATED_FAT_PARAMETERS.FilesInRootDIR) AND A JR Z,.it_is_fat32 ; LD (CALCULATED_FAT_PARAMETERS.SectorsPerFAT16),HL RET ; .it_is_fat32: LD (CALCULATED_FAT_PARAMETERS.SectorsPerFAT32),HL LD HL,(CALC_TOTAL_CLUSTERS.fat_size_h) LD (CALCULATED_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 CALC_TOTAL_CLUSTERS: .t_sec_h+1: LD DE,0 .t_sec_l+1: LD HL,0 ; data_sectors AND A ; total_sectors - reserved_sectors LD BC,(CALCULATED_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 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,(CALCULATED_FAT_PARAMETERS.Number_of_FATs) CALL DEBCxA ; LD B,H LD C,L PUSH IX POP DE ;num_fats * fat_sz32 = BCDE ; LD HL,(CALCULATED_FAT_PARAMETERS.RootDirSectors) ; !FIXIT 碎 牀罐ゃ珮 諛甄キ RootDirSectors ぎ 襷 轤 ADD HL,DE JR NC,.skip_inc ; AND A INC BC .skip_inc: EX DE,HL ;num_fats * fat_sz32 + root_dir_sectors = BC:DE ; POP HL SBC HL,DE EX DE,HL POP HL SBC HL,BC JR C,STOP_ERROR ; data_sectors = HL:DE ; ; total_clusters LD A,(CALCULATED_FAT_PARAMETERS.SectorsPerCluster) CALL HLDE_Div_A LD (CALCULATED_FAT_PARAMETERS.NotUsedSpace),A ; total_clusters = HL:DE ; LD (CALCULATED_FAT_PARAMETERS.total_clusters),DE LD (CALCULATED_FAT_PARAMETERS.total_clusters + 2),HL ; fat_size LD B,D LD C,E EX DE,HL ; total_clusters = DE:BC ; LD A,(CALCULATED_FAT_PARAMETERS.FAT_TYPE) .call_calc: CALL DEBCxA ;DE:BC * A = HL:IX ; LD BC,(CALCULATED_FAT_PARAMETERS.BytesPerSector) LD A,(CALCULATED_FAT_PARAMETERS.FAT_TYPE) CP TABLES.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 DIV_by_Shifts ; HL:DE / A => DE:BC, H=0, L - 痰皰 DIV_by_Shifts: LD C,A DEC A JR Z,.exit ; AND E LD B,A ; 痰皰 LD A,C RRCA .loop: SRL H RR L RR D RR E RRCA JP NC,.loop ; LD A,B .exit: LD B,D LD C,E EX DE,HL LD H,0 LD L,A RET ENDIF ;----------------------------------------------------------------------; ;----------------------------------------------------------------------- ; IN: ; DEBC, A ; OUT: ; HLIX = DEBC*A DEBCxA: LD HL,0 LD IX,0 AND A RET Z ; .loop: ADD IX,BC ADC HL,DE JP C,STOP_ERROR ; ぎ絅 ; DEC A JR NZ,.loop RET ;----------------------------------------------------------------------- /* total_sectors DWORD 0x10000000 reserved_sectors WORD data_sectors DWORD total_clusters 3 bytes 0x400000 total_clusters * 4 4 bytes fat_sz32 max 3 bytes Кム ゛肓 瓮皰 data_sectors = total_sectors - reserved_sectors - (num_fats * fat_sz32) total_clusters = data_sectors / sectors_per_cluster fat_sz32 = (total_clusters * 4 + (bytes_per_sector - 1)) / bytes_per_sector */ ;----------------------------------------------------------------------- ;HLIX/BC -> HLIX remainder DE HLIX_div_BC: EX DE,HL ; Negate BC to allow add instead of sbc XOR A ; Need to set HL to 0 anyways, so save 2cc and a byte LD H,A LD L,A SUB C LD C,A SBC A,A SUB B LD B,A LD A,D CALL .sub8 RLA LD D,A LD A,E CALL .sub8 RLA LD E,A LD A,XH CALL .sub8 RLA LD XH,A LD A,XL CALL .sub8 RLA LD XL,A EX DE,HL RET ; .sub8: CALL .iter1 .iter1: CALL .iter2 .iter2: CALL .sub .sub: RLA ADC HL,HL JR C,.skip ; ADD HL,BC RET C ; SBC HL,BC RET ; .skip: ADD HL,BC SCF RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- FORMAT_DRIVE: CALL CLEAN_SECTOR_BUFFER ; LD HL,CALCULATED_FAT_PARAMETERS.PART1 LD DE,SECTOR_BUFFER LD BC,CALCULATED_FAT_PARAMETERS.PART1_SIZE LDIR ; LD A,(CALCULATED_FAT_PARAMETERS.FAT_TYPE) CP TABLES.FAT32 ;!FIXIT JP NZ,STOP_ERROR ; CALL MAKE_SYS_SECTORS CALL CLEAN_SECTOR_BUFFER ; clean all fat tables at drive LD A,(CALCULATED_FAT_PARAMETERS.FAT_TYPE) CP TABLES.FAT32 LD BC,(CALCULATED_FAT_PARAMETERS.SectorsPerFAT32) LD DE,(CALCULATED_FAT_PARAMETERS.SectorsPerFAT32 + 2) JR Z,.its_fat32 ; LD BC,(CALCULATED_FAT_PARAMETERS.SectorsPerFAT16) LD DE,0 .its_fat32: LD (.add_l),BC LD (.add_h),DE LD A,(CALCULATED_FAT_PARAMETERS.Number_of_FATs) CALL DEBCxA ; HL:IX - ≡ィ 瓮皰牀 か 瓱 PUSH HL PUSH IX EXX POP DE POP HL EXX ; HL':DE' - ≡ィ 瓮皰牀 か 瓱 ; LD IX,(CALCULATED_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 ; make fat table LD HL,(CALCULATED_FAT_PARAMETERS.DRIVE_TYPE) LD H,#FF LD (SECTOR_BUFFER),HL LD L,H LD (SECTOR_BUFFER + 2),HL LD A,(CALCULATED_FAT_PARAMETERS.FAT_TYPE) CP TABLES.FAT12 JR NZ,.not_fat12 ; fat12 XOR A LD (SECTOR_BUFFER + 3),A JR .write_fat ; .not_fat12 CP TABLES.FAT16 JR Z,.write_fat ;fat32 ; LD HL,.Fat32Data LD DE,SECTOR_BUFFER + 3 LD BC,.Fat32Data.Size LDIR ; .write_fat: LD A,(CALCULATED_FAT_PARAMETERS.Number_of_FATs) LD HL,0 LD D,H LD E,L PUSH HL POP IX LD BC,(CALCULATED_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,CALCULATED_FAT_PARAMETERS.PART2_FAT32 LD BC,CALCULATED_FAT_PARAMETERS.PART2_FAT32_SIZE + CALCULATED_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,(CALCULATED_FAT_PARAMETERS.CopyBootSector) CALL WRITE_SECTOR_BUFFER ; LD A,(CALCULATED_FAT_PARAMETERS.FAT_TYPE) CP TABLES.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,(CALCULATED_FAT_PARAMETERS.FAT32_RootDirClusters) LD DE,(CALCULATED_FAT_PARAMETERS.RootDirStartCluster) ; FIXED! ADD HL,DE LD DE,(CALCULATED_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,(CALCULATED_FAT_PARAMETERS.total_clusters) LD IX,(CALCULATED_FAT_PARAMETERS.total_clusters + 2) 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,(CALCULATED_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,(CALCULATED_FAT_PARAMETERS.CopyBootSector) LD DE,(CALCULATED_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,(CALCULATED_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 ;----------------------------------------------------------------------- //////////////////////////////////////////////////////////////////////// ;----------------------------------------------------------------------- ;!TODO ぎぅ碎 か え瓷モ GET_DRIVE_TYPE: LD A,(CALCULATED_FAT_PARAMETERS.BPB_PHISICAL_DRIVE_NUMBER) CP DRIVE_CODES.SPRINTER.ATA LD B,BOOT_SECTOR.Hard_Drive RET Z ; え瓷モ -─磴 ATAPI SCF RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; -> DE - 4 5 硅 Кム Гカ. ; ぎΝ °碎 竅←キ Л腑┘ VOLUME_SIZE_BYTES. ; <- DE - CLUSTER SIZE. ; C - FAT TYPE. AUTO_CHOOSE_FAT_PARAMS: 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) 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 ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; -> HLDE * BC. BC = 痰クキ あ ; <- AHLDE ; CF=1 - error MUL32_POWER2: SRL B RR C LD A,B OR C RET Z ; XOR A .loop: EX DE,HL ADD HL,HL EX DE,HL ADC HL,HL ADC A,0 RET C ; SRL B RR C JR NC,.loop ; ;EX DE,HL AND A RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- ; -> HL / DE. DE = 痰クキ あ ; <- A = HL / DE ; CF=1 - error DIV16_POWER2: XOR A .loop: INC A SBC HL,DE JR NC,.loop DEC A RET Z ; error: ぅ━ < ぅ皀 CCF RET ;----------------------------------------------------------------------- ;----------------------------------------------------------------------- MACRO DIV_RL RL H RLA ADD A,C JR C,.exit SUB C .exit: ENDM ; ;Input: HLDE is numerator, A<129 is the divisor. ;Output: HLDE is quotient, A is remainder, C is negated HLDE_Div_A: NEG LD C,A XOR A CALL .div LD B,H LD H,L CALL .div LD L,H LD H,D CALL .div LD D,H LD H,E CALL .div LD E,H LD H,B RL E RL D ADC HL,HL RET ; .div: DIV_RL DIV_RL DIV_RL DIV_RL DIV_RL DIV_RL DIV_RL RL H RLA ADD A,C RET C SUB C RET ;----------------------------------------------------------------------- MACRO FAT_TYPES_LINE vol_size, clu_size, fat_type WORD vol_size, clu_size BYTE fat_type ENDM MODULE TABLES FAT12 EQU 3 FAT16 EQU 2 FAT32 EQU 4 ; VOL SIZE CLUSTER SIZE FAT TYPE FAT_TYPES: FAT_TYPES_LINE #0800, 32768, FAT32 ; > 32768 FAT_TYPES_LINE #0400, 16384, FAT32 ; 16384..32768 Mb FAT_TYPES_LINE #0200, 8192, FAT32 ; 8192..16384 Mb FAT_TYPES_LINE #0100, 4096, FAT32 ; 4096..8192 Mb FAT_TYPES_LINE #0080, 32768, FAT16 ; 2048..4096 Mb FAT_TYPES_LINE #0040, 16384, FAT16 ; 1023..2048 Mb FAT_TYPES_LINE #0020, 8192, FAT16 ; 511..1023 Mb FAT_TYPES_LINE #0010, 4096, FAT16 ; 256..511 Mb FAT_TYPES_LINE #0008, 2048, FAT16 ; 128..256 Mb FAT_TYPES_LINE #0004, 1024, FAT16 ; 64..128 Mb FAT_TYPES_LINE #0002, 512, FAT16 ; 32..64 Mb ; メ キ跏, 皰 FAT12 .LineSize EQU 5 .Records EQU ($ - FAT_TYPES)/.LineSize ENDMODULE ; ; RESERVED_SECTORS: ;predefined () .FAT_FDD EQU 1 .FAT_HDD EQU 8 .FAT32 EQU #2032 ;32 ; ; VARIABLES EQU $ .CurrentDrive DB 0 .VOLUME_SIZE_BYTES BLOCK 5,0 ; ; root_dir_sectors = ((root_dir_entries * 32) + (bytes_per_sector - 1)) / bytes_per_sector CALCULATED_FAT_PARAMETERS: .FAT_TYPE BYTE TABLES.FAT12 ; [x] .RootDirSectors WORD 0 .NotUsedSpace BYTE 0 ; in sectors .total_clusters: DWORD 0 .FAT32_RootDirClusters WORD 1 .PART1 EQU $ ; .JMP: BYTE #EB,#FE,#00 ; [x] opcode jmp $ .ID_NAME BYTE "DDF " ; DSS Drive Formatter .ID_NAME_VER BYTE "0." .ID_NAME_MOD BYTE "00" .BytesPerSector: WORD #200 ; predefined ; [x] .SectorsPerCluster: BYTE 0 ; [x] .RESERVED_SECTORS: WORD 0 ; [x] .Number_of_FATs: BYTE 2 ; predefined ; [ ] .FilesInRootDIR: WORD 0 ; FAT32 constant ; [ ] FAT ; [x] FAT32 .SectorsPerDrive: WORD 0 ; FAT32 constant ; [x] +- .DRIVE_TYPE: BYTE 0 ; ; [x] +- .SectorsPerFAT16: WORD 0 ; FAT32 constant ; [x] .SectorsPerTrack WORD 9 ; BPB_SecPerTrk ; [ ] Кム ぎ牀Κ 瓮皰 .HEADS WORD 2 ; [ ] .HIDDEN DWORD 0 ; MBR, extMBR ; [x] .BPB_BIG_TOTAL_SECTORS_L WORD 0 ; [x] +- .BPB_BIG_TOTAL_SECTORS_H WORD 0 ; [x] +- .PART1_SIZE EQU $ - .PART1 ; FAT 12, FAT 16 .PART2_FAT12_16 EQU $ ; .BPB_PHISICAL_DRIVE_NUMBER BYTE #80 ; [x] .reserved_1 BYTE 0 ; predefined ; ; .FAT.EXT_BOOT_REC_SIGNATURE BYTE #29 ; constant ; ; .FAT.SERIAL_NUMBER DWORD 0 ; ; .FAT.LABEL DB 'NO_LABEL ' ; ; .ID_FAT DB 'FAT16 ' ; .PART2_FAT12_16_END EQU $ ; FAT32 .PART2_FAT32 EQU $ ; .SectorsPerFAT32 DWORD 0 ; [x] ;!TODO error メ 痰琥┤ !=0 .MainFATnumber WORD 0 ; BPB_ExtFlags ; .Version WORD 0 ; constant ; .RootDirStartCluster DWORD 2 ; FIXED! 甎讌礇矚 筮爼祀 .FSINFO_Sector WORD 1 ; constant ; .CopyBootSector WORD 6 ; constant ; .reserved_block: BLOCK 12 ; constant ; .FDD_Number BYTE 0 ; [x] .reserved_2: BYTE 0 ; constant ; ; .FAT32.EXT_BOOT_REC_SIGNATURE BYTE #29 ; constant ; ; .FAT32.SERIAL_NUMBER DWORD 0 ; ; .FAT32.LABEL DB 'NO_LABEL ' ; ; .ID_FAT32 DB 'FAT32 ' ; .PART2_FAT32_SIZE EQU $ - .PART2_FAT32 ; SHARED .PART3_SHARED EQU $ ; .FAT.EXT_BOOT_REC_SIGNATURE BYTE #29 ; constant ; .FAT.SERIAL_NUMBER DWORD 0 ; [ ] .FAT.LABEL DB 'NO_LABEL ' ; [ ] ;!TODO ぎ皀讚 碎 爿ア竡 え爛皰爬 .ID_FAT DB 'FAT32 ' ; .PART3_SHARED_SIZE EQU $ - .PART3_SHARED ; ; SECTOR_BUFFER EQU $ ; ENDIF DISPLAY "programm size: ",$-EXEHeader Loader_End: DISPLAY "last address: ",$