FORMAT/format/format.asm
2026-04-03 22:40:08 +10:00

813 lines
17 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
////////////////////////////////////////////////////////////////////////
include 'new_format.asm'
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
DISPLAY "programm size: ",$-EXEHeader
Loader_End:
DISPLAY "last address: ",$
////////////////////////////////////////////////////////////////////////