FORMAT/format/format.asm
2026-04-03 00:50:52 +10:00

1731 lines
39 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.

;ÚÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¿
;³ 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) 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
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
®áâ «ì­®¥ ¯®¤ã¬ âì
;;;;;;;;;;;;;;;;;
¤«ï ᬥ饭¨ï 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
;;;;;;;;;;;;;;;;;
*/
;!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 <EFBFBD> §¬¥à â ¡«¨æë ¢ ᥪâ®à å
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 ; [ ] <20> §¬¥à ¤®à®¦ª¨ ¢ ᥪâ®à å
.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: ",$