FORMAT/format/format.asm
2026-03-27 01:11:17 +10:00

1094 lines
25 KiB
NASM
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;ÚÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¿
;³ 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
;
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) 4ÿ193ÿ152 + 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: 131ÿ072 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
; ;<Vadim> 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
; ;</Vadim>
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 $)<?1) ) * 256
; ALIGN 256
; buff:
; equ ($/80h)*80h+80h
DISPLAY "programm size: ",$-EXEHeader
Loader_End:
DISPLAY "last address: ",$
; SAVEBIN "format.exe",EXEHeader,$-EXEHeader
IFUSED FAT32_FORMAT
/*
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 <09> §¬¥à ᥪâ®à  ¢ ¡ ©â å
.SectorsPerCluster ;!TODO EQU #0D ; BYTE 2 BPB_SecPerClus <09> §¬¥à ª« áâ¥à  ¢ ᥪâ®à å
.RESERVED_SECTORS !RESERVED_SECTORS EQU #0E ; WORD 1 BPB_ResvdSecCnt <09> §¬¥à á¨á⥬­®© ®¡« á⨠(¢ª«îç ï íâ®â ᥪâ®à) 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 <09> §¬¥à ®¤­®© FAT ¢ ᥪâ®à å (0 ¢ FAT32)
.SectorsPerTrack GenIOCTL.GetParams EQU #18 ; WORD 9 BPB_SecPerTrk <09> §¬¥à ¤®à®¦ª¨ ¢ ᥪâ®à å
.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 <09> §¬¥à ®¤­®© FAT ¢ ᥪâ®à å
.MainFATnumber 0 EQU #28 ; WORD 0 BPB_ExtFlags <09>®¬¥à £« ¢­®© â ¡«¨æë FAT
.Version 0 EQU #2A ; WORD 0 BPB_FSVer ‚¥àá¨ï FAT32 (®¡ëç­® 0)
.RootDirStartCluster 2 EQU #2C ; DWORD 2 BPB_RootClus <09>¥à¢ë© ª« áâ¥à ª®à­¥¢®£® ª â «®£  (®¡ëç­® 2)
.FSINFO_Sector 1 EQU #30 ; WORD 1 BPB_FSInfo <09>®¬¥à ᥪâ®à  áâàãªâãàë FSINFO (®¡ëç­® 1)
.CopyBootSector 6 EQU #32 ; WORD 6 BPB_BkBootSec <09>®¬¥à ᥪâ®à  - ª®¯¨¨ § £à㧮筮£® (®¡ëç­® 6)
.reserved_block: 0 EQU #34 ; BLOCK 12 BPB_Reserved ‡ à¥§¥à¢¨à®¢ ­®
.FDD_Number GenIOCTL.GetParams&#F0 EQU #40 ; BYTE 0 BS_DrvNum <09>®¬¥à ¤¨áª®¢®¤  ¤«ï ä㭪権 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
®áâ «ì­®¥ ¯®¤ã¬ âì
;;;;;;;;;;;;;;;;;
!RESERVED_SECTORS: predefined (¯®ª )
.FAT12_FDD EQU 1
.FAT12_HDD
.FAT16_HDD
.FAT32_HDD EQU 32
CALCULATED_FAT_PARAMETERS:
.FAT_TYPE BYTE TABLES.FAT12 ; [x]
.BytesPerSector: WORD #200 ; predefined ; [x]
.SectorsPerCluster: BYTE 32 ; predefined ; [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: WORD 0 ; ; [x] +-
.SectorsPerFAT16: WORD 0 ; FAT32 constant ;
.HEADS WORD 0 ;
.HIDDEN WORD 0 ; ®â ­ ç «  MBR, extMBR ;
.BPB_BIG_TOTAL_SECTORS_L WORD 0 ; [x] +-
.BPB_BIG_TOTAL_SECTORS_H WORD 0 ; [x] +-
; FAT 12, FAT 16
.BPB_PHISICAL_DRIVE_NUMBER BYTE #80 ; [x]
.reserved_1 BYTE 0 ;
.FAT.EXT_BOOT_REC_SIGNATURE BYTE #29 ;
.FAT.SERIAL_NUMBER DWORD 0 ;
.FAT.LABEL TEXT 11 ;
.ID_FAT TEXT 8 ;
; FAT32
.SectorsPerFAT32 DWORD 0 ;
.MainFATnumber WORD 0 ; BPB_ExtFlags ;
.Version WORD 0 ; constant ;
.RootDirStartCluster DWORD 2 ;
.FSINFO_Sector WORD 1 ; constant ;
.CopyBootSector WORD 6 ; constant ;
.reserved_block: BLOCK 12 ; constant ;
.FDD_Number BYTE 0 ;
.reserved_2: BYTE 0 ; constant ;
.FAT32.EXT_BOOT_REC_SIGNATURE BYTE #29 ; constant ;
.FAT32.SERIAL_NUMBER DWORD 0 ;
.FAT32.LABEL TEXT 11 ;
.ID_FAT32 TEXT 8 ; constant ;
; #5A ;
¤«ï ᬥ饭¨ï 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
;;;;;;;;;;;;;;;;;
*/
////////////////////////////////////////////////////////////////////////
FORMAT_FAT32: LD (.Save_SP),SP
; Ž¯à¥¤¥«¥­¨¥ ¯ à ¬¥â஢ ­®á¨â¥«ï ¨ ¢ë¡®à FAT
.STEP1: ; íâ  ¤®«¦­  ¡ëâì ®¡é¥© ¤«ï § ¯®«­¥­¨ï £¥®¬¥âਨ ¤¨áª 
LD A,VARIABLES.CurrentDrive
LD BC,Dss.DRV.GenIOCTL.GetParams
RST ToDSS.DRV
JR C,.ERROR
;!TODO CHECK ERROR ­¥¯®¤å®¤ï騩 ¤¨áª
;
EX AF,AF'
AND #F0
LD (CALCULATED_FAT_PARAMETERS.BPB_PHISICAL_DRIVE_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 (VOLUME_SIZE_BYTES),DE
LD (VOLUME_SIZE_BYTES + 2),HL
LD (VOLUME_SIZE_BYTES + 4),A
LD E,H
LD D,A
CALL AUTO_CHOOSE_FAT_PARAMS
JR C,.ERROR
;
LD A,C
LD (CALCULATED_FAT_PARAMETERS.FAT_TYPE),A
CP TABLES.FAT32
LD A,(RESERVED_SECTORS.FAT32)
JR Z,.set_reserved_s
;
LD A,(RESERVED_SECTORS.FAT)
.set_reserved_s:
LD (CALCULATED_FAT_PARAMETERS.RESERVED_SECTORS),A
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,.ERROR
;
LD (CALCULATED_FAT_PARAMETERS.SectorsPerCluster),A
;
CALL GET_DRIVE_TYPE
JR C,.ERROR
;
LD A,B
LD (CALCULATED_FAT_PARAMETERS.DRIVE_TYPE),A
.ERROR: ;
.Save_SP+1: LD SP,0
;!TODO
;
RET
////////////////////////////////////////////////////////////////////////
;!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
;
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,(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
RET
; -> HLDE * BC. BC = á⥯¥­ì ¤¢®©ª¨
; <- AHLDE
; CF=1 - error
MUL32_POWER2: 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 FAT_TYPES_LINE (vol_size, clu_size, fat_type)
WORD vol_size, clu_size : BYTE fat_type
ENDM
MODULE TABLES
FAT12 EQU 0
FAT16 EQU 1
FAT32 EQU 2
; 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
;
;
ENDIF