' Uses FAT32 structure to calculate free/total disk space beyond 2 GB.

Type RegTypeX
 AX AS Integer
 BX AS Integer
 CX AS Integer
 DX AS Integer
 BP AS Integer
 SI AS Integer
 DI AS Integer
 Flags AS Integer
 DS AS Integer
 ES AS Integer
End Type

TYPE FAT32StrucType
 Size1 AS STRING * 2
 Version AS STRING * 2
 SectorsPerCluster AS STRING * 4
 BytesPerSector AS STRING * 4
 FreeClusters AS STRING * 4
 TotalClusters AS STRING * 4
 FreeSectors AS STRING * 4
 TotalSectors AS STRING * 4
 FreeUnits AS STRING * 4
 TotalUnits AS STRING * 4
 Reserved AS STRING * 8
END TYPE

DECLARE SUB InterruptX(N AS Integer,I AS RegTypeX,O AS RegTypeX)

DIM FAT32Struc AS FAT32StrucType, ASCIIZ AS STRING * 4
DIM InregsX AS RegTypeX, OutregsX AS RegTypeX

'--------D-2136-------------------------------
'INT 21 - DOS 2+ - GET FREE DISK SPACE
'        AH = 36h
'        DL = drive number (00h = default, 01h = A:, etc)
'Return: AX = FFFFh if invalid drive

IF Command$ <> "" THEN
   D$ = LEFT$(Command$, 1)
ELSE
   LINE INPUT "Disk drive letter? ", D$
   D$ = UCASE$(D$)
END IF

' check control break
DEF SEG = &H40
IF PEEK(&H71) THEN
   Flag = -1
END IF
POKE &H71, &H0
DEF SEG
IF Flag THEN
   END
END IF

' check drive
InregsX.AX = &H3600
InregsX.DX = ASC(D$) - 64
CALL InterruptX(&H21, InregsX, OutregsX)
IF OutregsX.AX = &HFFFF THEN
   PRINT "Invalid drive.": END
END IF

'INT 21 - Windows95 - FAT32 - GET EXTENDED FREE SPACE ON DRIVE
'        AX = 7303h
'        DS:DX -> ASCIIZ string for drive ("C:\" or "\\SERVER\Share")
'        ES:DI -> buffer for extended free space structure (see #01789)
'        CX = length of buffer for extended free space

ASCIIZ = D$ + ":\" + CHR$(0)
InregsX.AX = &H7303
InregsX.DS = VARSEG(ASCIIZ)
InregsX.DX = VARPTR(ASCIIZ)
InregsX.ES = VARSEG(FAT32Struc)
InregsX.DI = VARPTR(FAT32Struc)
InregsX.CX = LEN(FAT32Struc)
CALL InterruptX(&H21, InregsX, OutregsX)

'Return: CF clear if successful
'            ES:DI buffer filled
'        CF set on error
'            AX = error code
'        on DOS versions which do not support the FAT32 calls, this function
'          returns CF clear/AL=00h (which is the DOS v1+ method for reporting
'          unimplemented functions)

IF (OutregsX.AX AND &HFF) = 0 THEN
   PRINT "Unsupported call."
   END
END IF
IF (OutregsX.Flags AND &H1) = &H1 THEN
   IF OutregsX.AX = 15 THEN
      PRINT "Invalid drive."
   ELSE
      PRINT "Error"; OutregsX.AX
   END IF
   END
END IF

'Format of extended free space structure:
'Offset  Size    Description     (Table 01789)
' 00h    WORD    (ret) size of returned structure
' 02h    WORD    (call) structure version (0000h)
'                (ret) actual structure version (0000h)
' 04h    DWORD   number of sectors per cluster (with adjustment for compression)
' 08h    DWORD   number of bytes per sector
' 0Ch    DWORD   number of available clusters
' 10h    DWORD   total number of clusters on the drive
' 14h    DWORD   number of physical sectors available on the drive, without
'                  adjustment for compression
' 18h    DWORD   total number of physical sectors on the drive, without
'                  adjustment for compression
' 1Ch    DWORD   number of available allocation units, without adjustment
'                  for compression
' 20h    DWORD   total allocation units, without adjustment for compression
' 24h  8 BYTEs   reserved

 Bytes# = CLNG(ASC(MID$(FAT32Struc.BytesPerSector, 1, 1)))
 Bytes# = Bytes# + CLNG(ASC(MID$(FAT32Struc.BytesPerSector, 2, 1))) * 256#
 Bytes# = Bytes# + CLNG(ASC(MID$(FAT32Struc.BytesPerSector, 3, 1))) * 65536#
 Bytes# = Bytes# + CLNG(ASC(MID$(FAT32Struc.BytesPerSector, 4, 1))) * 16777216#
 Sectors# = CLNG(ASC(MID$(FAT32Struc.FreeSectors, 1, 1)))
 Sectors# = Sectors# + CLNG(ASC(MID$(FAT32Struc.FreeSectors, 2, 1))) * 256#
 Sectors# = Sectors# + CLNG(ASC(MID$(FAT32Struc.FreeSectors, 3, 1))) * 65536#
 Sectors# = Sectors# + CLNG(ASC(MID$(FAT32Struc.FreeSectors, 4, 1))) * 16777216#
 FreeSpace# = Bytes# * Sectors#
 PRINT "Free Disk Space:"; FreeSpace#
 Total# = CLNG(ASC(MID$(FAT32Struc.TotalSectors, 1, 1)))
 Total# = Total# + CLNG(ASC(MID$(FAT32Struc.TotalSectors, 2, 1))) * 256#
 Total# = Total# + CLNG(ASC(MID$(FAT32Struc.TotalSectors, 3, 1))) * 65536#
 Total# = Total# + CLNG(ASC(MID$(FAT32Struc.TotalSectors, 4, 1))) * 16777216#
 TotalSpace# = Bytes# * Total#
 PRINT "Total Disk Space:"; TotalSpace#
 END
