Metropoli BBS
VIEWER: sdl32.asm MODE: TEXT (ASCII)
page	80,132
title	SDL 3.2 - Sorted Directory List
sdl	segment
sdlp	proc	far
	assume	cs:sdl,ds:sdl,es:sdl
;
; SORTED DIRECTORY LIST 3.2
;
; SDL [d:][path][filename[.ext]][/options]
;
; Options:  General
;		 E	erase screen
;		 P	pause when screen full
;		 W	4 column format (2 if width 40)
;	    Sort options (sort on filename.ext is the default)
;		 N	do not sort entries
;		 S	sort by file size
;		 D	sort by date and time
;		 X	sort by file type (ext)
;	    Sub-directories
;		 T	list sub-directory names
;		 F	use with T to list file names by directory
;		 I	use with TF to indent file lists (not supported on
;			width 40 screens)
;		 A	use with T to list all file names together
;
; Default:  *.* sorted by name.ext, 2 cols wide (1 on width 40 screen), no
;	    screen erase or pause at end of page, using current directory.
;
; Notes:
;   1. Path specifications:
;      a. paths must end with \.
;      b. specifying a leading \ starts the path search at the root directory.
;	  No leading \ will start the path at the current directory.
;      c. not specifying a path starts the operation at the current directory.
;   2. The space used by sub-directories is not accounted for.
;   3. Directory listings do not include the '.' or '..' entries.
;   4. The specified filename.ext may include ? and/or *.
;
; Output formats:  Width 80 - 2 or 4 columns   (option TFI - 1 or 2 columns)
;		   Width 40 - 1 or 2 columns
;
; Filename in listing may be preceeded by one of the following char.:
;		r - read-only file
;		h - hidden file
;		s - system file
;		\ - sub-directory name
;   If a file has more than 1 attribute, only the last is shown.
;
; Written by W. C. Bodycomb
;	    Version 1.0 - original version, runs under DOS 1.0 and 1.1
;	    Version 2.0 - support for DOS 2.0, runs under DOS 1.0, 1.1, 2.0
;	    Version 3.0 - support for paths and sub-directories, runs under
;			  DOS 2.0.
;	    Version 3.2 - Sort in descending order for date and file size 
;	    options.  Make file extension ".*" by default.  Fix MASM 3 errors. 
;	    Reversed test for 80 column display because some MS-DOS systems do 
;	    not use the fixed address that PC-DOS does. Print the directory 
;	    name instead of "<curr>". Ted Shapin, 11/21/85.
;
	org	100h		;set up for COM
subp	proc	near
;
; get current or specified drive
;
bgn:	call	clear		;clear ctrs
	cld			;set direction
	mov	si,offset init	;init.
	mov	di,offset dxfcb ;  the
	mov	cx,19		;    dummy
	repz movsb		;      FCB
	mov	ah,19h		;get
	int	21h		;  current
	add	al,65		;    disk
	mov	si,offset path	;      and
	mov	[si],al 	;	 save
	mov	di,80h		;get
	mov	ch,0		;  lth of
	mov	cl,[di] 	;    of param
	jcxz	vol1		;br if no parms
	inc	di		;start of parms
	mov	al,' '          ;scan off
	repe scasb		;  blanks
	je	vol1		;br if no parm
	dec	di		;adj
	inc	cx		;  values
	cmp	cx,2		;long enough
	jb	vol1		;br no
	cmp	byte ptr [di]+1,':' ;is drive specified
	jne	vol1		;br no
	mov	al,[di] 	;save
	and	al,0dfh 	;  drive
	mov	[si],al 	;    letter
	inc	di		;incr
	inc	di		;  adr
	dec	cx		;decr
	dec	cx		;  count
;
; get volume label
;
vol1:	push	di		;save
	push	cx		;  regs
	mov	dx,offset da	;set
	mov	ah,1ah		;  dta
	int	21h		;    adr
	mov	al,[si] 	;put drive
	mov	tia+9,al	;  in header
	sub	al,64		;set
	mov	byte ptr dfcb,al 	;  drive
	mov	di,offset svvol ;save area
	mov	ah,11h		;set get first
	mov	dx,offset dxfcb ;look for
	int	21h		;  vol label
	or	al,al		;any vol label
	jnz	fpth		;br no
	mov	si,offset da+8	;label adr
	mov	cx,11		;save
	repz movsb		;  label
;
; save specified path
;
fpth:	mov	byte ptr [di],' ' ;mark end
	pop	cx		;restore
	pop	di		;  regs
	jcxz	fopt1		;br if no path/fnm
	mov	dx,cx		;save count
	mov	bp,di		;  and adr
	add	di,cx		;start
	dec	di		;  at
	std			;    end
	mov	al,'\'          ;find end
	repne scasb		;  of path
	cld			;set direction
	jne	fopt		;br-not found
	inc	cx		;adj count
	mov	si,bp		;copy start adr
	sub	dx,cx		;save non-path lth
	mov	di,offset path+2 ;move
	repz movsb		;  path
	mov	fspca,di	;save path end adr
	mov	bp,si		;set new start adr
;
; get options
;
fopt:	mov	di,bp		;get start adr
	mov	cx,dx		;  and lth
fopt1:	jcxz	eopt		;br-no options or filename
	mov	al,'/'          ;find
	repne scasb		;  options
	jne	gfspc		;br-no options
	dec	di		;adj
	inc	cx		;  values
	mov	si,di		;copy adr
	push	di		;  and save
	sub	dx,cx		;save filespec size
opt:	cmp	byte ptr [si],'/' ;is it /
	je	opt3		;keep looking
	mov	al,byte ptr [si] ;get char
	and	al,0dfh 	;force upper case
	mov	di,offset swn	;set adr
	mov	bx,400h 	;  and flag
opt1:	scasb			;option found
	je	opt2		;br yes
	shr	bx,1		;check next
	jnz	opt1		;  option
	jz	opt3		;not valid option
opt2:	or	word ptr sw,bx	;set option
opt3:	inc	si		;check
	loop	opt		;  all char
	pop	di		;restore reg
;
; get specified filespec
;
gfspc:	mov	byte ptr [di],' ' ;set delimiter
	mov	cx,dx		;get count
	mov	si,bp		;  and adr
	jcxz	eopt		;br-no filespec
	cmp	byte ptr [si],' ' ;any filespec
	je	eopt		;br no
	push	di		;save end ptr
	std	;look for filename extension
	mov	al,'.'		;by scanning for
	repne	scasb		;a period
	cld		;reset to up
	pop	di		;restore pointer
	je	gfspc2		;we found one
	mov	si,offset wild	;point to ".*"
	movsb		;and move
	movsb		;it
	mov	byte ptr [di],' ' ; add delimiter again
	mov	si,bp		;restore ptr to filespec
gfspc2:	mov	di,offset dfcb	;let DOS
	mov	ax,2900h	;  parse
	int	21h		;    filespec
;
; initialize options
;
eopt:	mov	di,fspca	;move dir.
	call	mvfs		;  filespec
	test	byte ptr sw1,4		;T option
	jnz	eopt1		;br yes
	and	byte ptr sw1,0fch	;clear A and F
eopt1:	test	byte ptr sw1,1		;A option
	jz	eopt2		;br no
	and	byte ptr sw1,0fdh	;clear F option
	mov	cx,19		;set count
	mov	si,offset dirm	;change
	mov	di,offset h2+25 ;  hdrs
	repz movsb		;    to dir#
eopt2:	test	byte ptr sw,8		;wide
	jz	eopt3		;br no
	mov	coln,4		;set cols to 4
	mov	si,offset h3	;hdr adr
	mov	di,offset h2+15 ;change
	mov	cx,5		;  bytes to
	repz movsb		;    sector
eopt3:	push	ds		;save data segment
	mov	ax,40h		;point to
	mov	ds,ax		;  data area
	mov	ax,ds:4ah	;get screen cols
	pop	ds		;restore data segment
	cmp	ax,40		;40 col
	jne	eopt4		;br no
	or	byte ptr sw1,128 	;set 40 col
	shr	coln,1		;cols
	jnz	fa		;  /2
eopt4:	test	byte ptr sw1,2		;option F
	jz	fa		;br no
	test	byte ptr sw,1		;I option
	jz	fa		;br no
	shr	coln,1		;cols/2
	mov	colp,40 	;set offset
;
; get FAT info
;
fa:	mov	dl,path 	;get
	sub	dl,64		;  drive no
	mov	ah,36h		;get DOS 2
	int	21h		;  fat info
	cmp	ax,0ffffh	;br if
	jne	fa1		;  drive ok
	int	20h		;give up
fa1:	mov	word ptr bpsc,cx 	;save bytes/sec
	mov	ah,0		;clear high byte
	mov	word ptr scpf,ax 	;save sec/fat
	xchg	cx,dx		;find bytes per
	mul	dx		;  alloc. unit
	mul	bx		;free bytes
	mov	word ptr free,ax 	;save low
	mov	word ptr free+2,dx	;  and high
;
; clear screen
;
clr:	test	byte ptr sw,128		;screen clear
	jz	sdlh		;br no
	sub	cx,cx		;col 0, row 0
	mov	dx,184fh	;last row, col
	test	byte ptr sw1,128 	;80 cols
	jz	clr1		;br yes
	mov	dx,1827h	;set 40 col
clr1:	mov	bh,7		;color
	mov	ax,600h 	;scroll
	int	10h		;  screen
	sub	dx,dx		;set
	mov	ah,2		;  cursor
	mov	bh,0		;    to
	int	10h		;      0
;
; print SDL header
;
sdlh:	mov	dx,offset h1	;print
	call	prt		;  header
	mov	si,offset svvol ;label adr
sdlh1:	lodsb			;get char
	cmp	al,' '          ;end of label
	je	sdlh2		;br yes
	mov	dl,al		;print
	call	prtc		;  char
	jmp	sdlh1		;next char
sdlh2:	mov	ah,2ah		;get
	int	21h		;  date
	mov	si,offset mth	;field start
	mov	al,dh		;convert
	call	x2		;  month
	mov	al,dl		;convert
	call	x2		;  day
	mov	ax,cx		;adjust
	sub	ax,1900 	;  year
	call	x2		;convert year
	mov	ah,2ch		;get
	int	21h		;  time
	mov	si,offset ti	;field start
	mov	al,ch		;convert
	call	x2		;  hour
	mov	al,cl		;convert
	call	x2		;  minutes
	mov	dx,offset h1evl ;print
	call	prt		;  hdr
	test	byte ptr sw1,128 	;width 40
	jz	sdlh3		;br no
	call	ckpg		;print cr
sdlh3:	mov	dx,offset h1a	;print
	call	prt		;  hdr
	mov	si,word ptr free 	;convert
	mov	di,word ptr free+2	;  free
	call	w0		;    bytes
	mov	dx,offset h1b	;print
	call	prt		;  hdr
; Note: DOS 4.0 and disks larger than 32 megabytes gives overflow
; so sectors are not printed.
;	mov	ax,word ptr free 	;convert
;	mov	dx,word ptr free+2	;  free
;	call	v0		;    sectors
;	call	v3		;      and print
;	mov	dx,offset h1c	;print
;	call	prt		;  hdr
	call	ckpg		;print cr
	call	ckpg		;print cr
	mov	mtha+8,'$'      ;set end of field
	mov	tia+5,'$'       ;set end of field
	test	byte ptr sw1,4		;T option
	jnz	tinit		;br yes
;
; list one directory
;
	call	prtb		;print a blank
	call	dirnam		;print the dir name
	call	prtcr		;and a CRLF
	call	dir		;get directory
	call	sr		;process entries
	jmp	return		;all done
;
; get current directory full name and print it
;
dirnam:	mov	ah,47h		;get name of current directory
	mov	dl,byte ptr path	;has the disk drive
	and	dl,0fh		;mask off binary part
	mov	si,nx		;put it in the table area
	int	21h
	mov	di,nx		;point to the name
	mov	cx,64		;max possible name length
	mov	al,0		;look for the end
	repne	scasb		;of the string
	dec	di		;and change the
	mov	byte ptr [di],'$' ;delimiter
	mov	dx,nx		;and then print
	call	prt		;the dir name
	ret		;return
;
; initialize for sub-directories
;
tinit:	mov	di,fspca	;get fspec adr
	mov	si,offset path+2 ;path adr
	cmp	byte ptr [si],'\' ;start at root
	je	tinit1		;br yes
	push	si		;save 
	push	di		;regs
	call	dirnam		;print current dir name
	pop	di		;restore
	pop	si		;regs
	cmp	si,di		;any path
	je	tinit3		;br no
tinit1: mov	dl,byte ptr [si] ;get path byte
	cmp	dl,61h		;force
	jb	tinit2		;  upper
	sub	dl,20h		;    case
tinit2: call	prtc		;print
	inc	si		;  name
	cmp	si,di		;end of path
	jb	tinit1		;br no
tinit3: test	byte ptr sw1,1		;option A
	jz	tinit4		;br no
	push	di		;save reg
	xor	si,si		;print
	call	v3		;  dir no
	pop	di		;restore reg
tinit4: call	ckpg		;print cr
	jmp	tre7		;get 1st dir
;
; list sub-directories
;
tre:	test	byte ptr [si]+15,16 ;sub-dir
	jnz	tre2		;br yes
tre1:	add	si,26		;next entry
	cmp	si,[di]+10	;end of dir
	jb	tre		;br no
	cmp	word ptr [di]+6,0 ;any previous dir.
	je	tred		;br no
	mov	di,[di]+6	;prev dir.
	mov	prvt,di 	;save adr
	mov	si,[di]+8	;curr. entry
	sub	col,2		;decr col
	jnz	tre1		;step to next
tre2:	mov	cx,[di]+4	;space
tre3:	call	prtb		;  to
	loop	tre3		;    col
	mov	[di]+8,si	;save curr entry
	inc	dirn		;incr dir no
	inc	si		;step to
	inc	si		;  filename
	mov	cx,12		;print
	mov	di,[di]+2	;  sub
tre4:	lodsb			;    dir
	cmp	al,' '          ;blank
	je	tre5		;br yes
	stosb			;move char
	mov	dl,al		;print
	call	prtc		;  char
tre5:	loop	tre4		;next char
	test	byte ptr sw1,1		;A option
	jz	tre6		;br no
	mov	si,dirn 	;print
	push	di		;  out
	call	v3		;    dir
	pop	di		;      no.
tre6:	call	ckpg		;print cr
	mov	byte ptr [di],'\' ;end
	inc	di		;  path
	mov	fspca,di	;save adr
tre7:	call	mvfs		;move fspec
	add	col,2		;incr col
	call	dir		;get directory
	test	byte ptr sw1,2		;F option
	jz	tre		;br no
	push	si		;save
	push	di		;  regs
	call	sr		;process entries
	pop	di		;restore
	pop	si		;  regs
	jmp	tre		;process table
tred:	test	byte ptr sw1,1		;A option
	jz	return		;br no
	mov	di,offset tb	;table start
	call	sr		;process entries
return: call	ckpg1		;allow for DOS cr
	int	20h		;all done
;
; get directory entries and build table
;
dir:	mov	di,nx		;get
	push	di		;  start
	add	di,26		;save
	mov	nx,di		;  end
	pop	di		;restore
	push	di		;  start
	inc	di		;+
	inc	di		;  2
	mov	si,offset fspca ;set up
	mov	cx,3		;  fspec adr, col
	repz movsw		;    and prev table
	pop	di		;restore
	push	di		;  start
	mov	byte ptr [di]+15,8 ;mark control
	mov	prvt,di 	;save as prev
	mov	[di]+8,di	; and curr sub-dir
	mov	ah,4eh		;get 1st
dir1:	mov	cx,16h		;get
	mov	dx,offset path	;  directory
	int	21h		;    entry
	or	al,al		;br if entry
	jz	dir2		;  found
	mov	ax,nx		;save
	pop	si		;  tbl
	mov	[si]+10,ax	;    end
	mov	di,si		;copy table adr
	ret			;return
dir2:	cmp	byte ptr dan,'.' ;path
	je	dir6		;br yes
	mov	bx,nx		;set next
	lea	di,[bx+2]	;  entry adr
	push	di		;save reg
	push	di		;  twice
	mov	si,offset blnk	;blanks
	mov	cx,13		;blank$
	repz movsb		;  fname
	pop	di		;restore reg
	mov	si,offset dan	;returned fn adr
dir3:	cmp	byte ptr [si],0 ;end of name
	je	dir5		;br yes
	cmp	byte ptr [si],'.' ;separator
	jne	dir4		;br no
	lea	di,[bx+2]	;position
	add	di,8		;  file type
dir4:	movsb			;move char
	jmp	dir3		;repeat
dir5:	pop	di		;restore reg
	add	di,13		;re-position
	mov	si,offset daa	;save
	movsb			;  attribute
	movsw			;save time
	movsw			;  and date
	movsw			;move file
	movsw			;  size
	mov	si,offset dirn	;move
	movsw			;  dir. no
	inc	word ptr ct	;incr file count
	mov	nx,di		;incr table adr
	cmp	di,sp		;more
	jb	dir6		;  room
	mov	dx,offset max	;print
	call	prt		;  msg
	int	20h		;give up
dir6:	mov	ah,4fh		;get next
	jmp	dir1		;  directory entry
;
; insertion sort
;
sr:	cmp	di,nx		;more entries
	jb	sr1		;br yes
	jmp	dcl		;set up columns
sr1:	test	byte ptr [di]+15,8 ;control entry
	jnz	sr2		;br yes
	mov	bp,di		;save reg
	lea	si,[di+2]	;compare
	mov	di,offset fspc	;  dir
	mov	cx,8		;    entry
	call	cknm		;check
	jcxz	sr3		;  filename
sr2:	jmp	snx		;skip entry
sr3:	inc	si		;step over .
	mov	cx,3		;check
	call	cknm		;  ext
	jcxz	sr4		;br ok
	jmp	snx		;skip entry
sr4:	mov	di,bp		;restore reg
	mov	si,offset t1	;start of chain
sr5:	mov	bx,si		;get next
	mov	si,[bx] 	;  chain entry
	or	si,si		;br if end
	jz	sch		;  of chain
	test	byte ptr sw,4		;no sorting
	jnz	sr5		;br yes
	mov	ax,si		;save
	mov	dx,di		;  adrs
	mov	bp,22		;size offset
	test	byte ptr sw,64		;sort size
	jnz	sz		;br yes
	mov	bp,18		;date offset
	test	byte ptr sw,32		;sort date
	jnz	sz		;br yes
	test	byte ptr sw,16		;sort type
	jnz	sx		;br yes
sn:	mov	bp,2		;compare
	mov	cx,8		;  file
	call	ssn		;    names
	jb	sr5		;try again
	ja	sch		;chain in entry
	test	byte ptr sw,16		;type sort
	jnz	sr5		;br yes
	call	ssx		;compare file types
	jbe	sr5		;try again
	jg	sch		;chain in entry
sx:	call	ssx		;compare
	jb	sr5
	jmp	sz1		;  file type
sz:	add	si,bp		;compare
	add	di,bp		;  the
	mov	cx,2		;    size
	std			;      or
	repz cmpsw		;	 date
	cld			;restore direction
	mov	di,dx		;restore
	mov	si,ax		;  regs
	ja	sr5		;try again
sz1:	je	sn		;check name
sch:	mov	[di],si 	;chain in
	mov	[bx],di 	;  entry
snx:	add	di,26		;check next
	jmp	sr		;  entry
;
; sort file name or type sub-rout.
;
ssx:	mov	bp,11		;type offset
	mov	cx,3		;  and lth
ssn:	add	si,bp		;sort
	add	di,bp		;  file name
	repz cmpsb		;    or type
	mov	di,dx		;restore
	mov	si,ax		;  regs
	ret			;return
;
; set up columns
;
dcl:	mov	ax,word ptr ct		;# of files
	cmp	ax,0		;any entries
	je	dcl4		;br no
	cmp	coln,1		;only 1 col
	je	hr		;br yes
	cmp	ax,2		;0 or 1
	jb	hr		;br yes
	xor	dx,dx		;clear reg
	div	coln		;/# of cols
	mov	word ptr fcrm,dx 	;save remainder
	mov	bp,1		;set col ctr
	mov	si,offset t1	;1st chain
dcl1:	mov	bx,si		;copy adr
	call	dcl2		;get 1 col entries
	dec	si		;next col
	dec	si		;  adr
	mov	[si],dx 	;save start of next chain
	inc	bp		;incr col ctr
	cmp	bp,coln 	;done
	jb	dcl1		;br no
	jge	hr		;print header
dcl2:	mov	cx,ax		;copy count
	cmp	bp,word ptr fcrm 	;need 1 more
	ja	dcl3		;br no
	inc	cx		;add 1 more
dcl3:	mov	bx,[bx] 	;count out
	loop	dcl3		;  entries for col
	mov	dx,[bx] 	;start of next chain
	mov	[bx],cx 	;end this chain
dcl4:	ret			;return
;
; print file headers
;
hr:	call	fsp		;option F spacing
	mov	cx,coln 	;# of cols
	jmp	hr2		;skip blank
hr1:	call	prtb		;blank
hr2:	mov	dx,offset h2	;hdr adr
	call	prt		;print hdr
	loop	hr1		;do all cols
	call	ckpg		;print cr
;
; process table entries
;
pr:	mov	bp,coln 	;# of cols
	mov	si,offset t1	;1st col adr
	cmp	word ptr [si],0 ;end of entries
	je	trlr		;br yes
pr1:	call	fsp		;option F
	jcxz	pr3		;  spacing
pr2:	call	prtb		;blank
pr3:	mov	bx,[si] 	;next in chain
	or	bx,bx		;end of chain
	jz	pr4		;br yes
	mov	ax,[bx] 	;save next
	mov	[si],ax 	;  in chain
	push	si		;save reg
	call	pf		;process entry
	pop	si		;restore reg
	dec	si		;next
	dec	si		;  col
	dec	bp		;decr
	jnz	pr2		;do next chain
pr4:	call	ckpg		;print cr
	jmp	pr		;repeat to end of 1st chain
;
; print no. of files
;
trlr:	call	fsp		;option F
	mov	si,word ptr ct		;convert file
	call	v3		;  count
	mov	dx,offset h1d	;print
	call	prt		;  hdr
	mov	si,word ptr dused	;convert
	mov	di,word ptr dused+2	;  used
	call	w0		;    bytes
	mov	dx,offset h1b	;print
	call	prt		;  hdr
	mov	si,word ptr sused	;convert
	call	v3		;    sectors
	call	clear		;clear ctrs
	mov	dx,offset h1c	;print
	call	prt		;  hdr
	jmp	ckpg		;print cr
;
; print file entry
;
pf:	mov	cx,4		;set count
	mov	dl,' '          ;blank
	mov	di,offset atr	;attr table
pf1:	mov	al,byte ptr [di] ;test
	inc	di		;  for
	test	byte ptr [bx+15],al ;attr
	jz	pf2		;br no
	mov	dl,byte ptr [di] ;get
pf2:	inc	di		;  attr
	loop	pf1		;try again
	call	prtc		;print attr
	lea	di,[bx+2]	;file name adr
	mov	cx,12		;print
pfn:	mov	dl,byte ptr [di] ; file
	call	prtc		;    name
	inc	di		;      and
	loop	pfn		;	 ext
	clc			;clear carry
	mov	ax,[bx+20]	;sum
	add	word ptr dused,ax	;  up
	mov	dx,[bx+22]	;    file
	adc	word ptr dused+2,dx	;      sizes
	call	v0		;get sectors
	add	word ptr sused,si	;add to sum
	test	byte ptr sw,8		;wide
	jz	pf5		;br no
	test	byte ptr sw1,1		;option A
	jz	pf3		;br no
	mov	si,[bx+24]	;print
	call	v3		;  dir#
	jmp	prtb		;blank
pf3:	test	byte ptr [bx+15],16 ;sub-dir
	jz	pf4		;br no
	mov	dx,offset b8+2	;print
	jmp	prt		;  blanks
pf4:	call	v3		;convert sectors
	jmp	prtb		;blank
pf5:	test	byte ptr [bx+15],16 ;sub-dir
	jz	pf6		;br no
	mov	dx,offset b8	;print
	call	prt		;  blanks
	jmp	pf7		;skip size
pf6:	push	bx		;save reg
	mov	si,[bx+20]	;convert
	mov	di,[bx+22]	;  file
	call	w0		;    size
	pop	bx		;restore reg
pf7:	call	prt2b		;2 blank
	mov	ax,[bx+18]	;convert
	call	x0		;  date
	call	prtb		;blank
	test	byte ptr sw1,1		;option A
	jz	pf8		;br no
	mov	si,[bx+24]	;print
	call	v3		;  dir#
	jmp	prt2b		;2 blanks
pf8:	mov	ax,[bx+16]	;convert
	call	y0		;  time
	jmp	prt2b		;2 blank
;
; convert bytes to sectors
;
v0:	div	word ptr bpsc		;bytes/sector
	or	dx,dx		;any remainder
	jz	v1		;br no
	inc	ax		;add 1 sector
v1:	xor	dx,dx		;clear reg
	div	word ptr scpf		;/ by sec/fat
	or	dx,dx		;any remainder
	jz	v2		;br no
	inc	ax		;add 1 fat
v2:	mul	word ptr scpf		;find no. of sectors
	mov	si,ax		;copy value
	ret			;return
v3:	xor	di,di		;clear reg
	call	sum		;convert to BCD
	mov	cx,1410h	;left zero supp. for 4 digits
	mov	dl,al		;convert
	call	w3		;  one digit
	mov	ax,bx		;convert
	jmp	w1		;  4 digits
;
; convert file size
;
w0:	call	sum		;convert to BCD
	mov	cx,1710h	;left zero supp. for 7 digits
	call	w1		;convert 4
	mov	ax,bx		;last 4
w1:	push	ax		;save reg
	mov	dl,ah		;convert
	call	w2		;  left 2
	pop	dx		;convert right 2
w2:	mov	dh,dl		;save right digit
	shr	dl,1		;shift
	shr	dl,1		;  over
	shr	dl,1		;    left
	shr	dl,1		;      digit
	call	w3		;print digit
	mov	dl,dh		;convert right digit
w3:	and	dl,0fh		;isolate digit
	jz	w4		;br if 0
	mov	cl,0		;kill zero suppress
w4:	dec	ch		;zero
	and	cl,ch		;  suppress
	or	dl,'0'          ;convert to
	sub	dl,cl		;  digit
	jnz	prtc		;    or blank
prt2b:	call	prtb		;print 2 blanks
prtb:	mov	dl,' '          ;print blank
prtc:	mov	ah,2		;print
	int	21h		;  char
	ret			;return
;
; convert to 8 BCD digits
;
sum:	xor	ax,ax		;clear
	mov	bx,ax		;  regs
	mov	cx,32		;set dble word shift
sum1:	shl	si,1		;shift
	rcl	di,1		;  dble word
	xchg	bx,ax		;double
	call	sum2		;  all
	xchg	bx,ax		;    and add
	call	sum2		;      in
	loop	sum1		;	 bit
	ret			;return
sum2:	adc	al,al		;double
	daa			;  each
	xchg	al,ah		;    digit
	adc	al,al		;      in
	daa			;	 word
	xchg	al,ah		;	   accumulator
	ret			;return
;
; convert time
;
y0:	mov	dx,offset b8+3	;blanks
	or	ax,ax		;any time
	jz	prt		;br no
	mov	si,offset tia	;field start
	push	ax		;save time
	and	ax,0f800h	;isolate
	mov	cl,11		;  hours
	call	x1		;convert hours
	pop	ax		;restore time
	and	ax,7e0h 	;isolate
	mov	cl,5		;  minutes
	call	x1		;convert minutes
	mov	dx,offset tia	;print
	jmp	prt		;  time
;
; convert date
;
x0:	mov	dx,offset b8	;blanks
	or	ax,ax		;is date 0
	jz	prt		;br yes
	mov	si,offset mth	;field start
	push	ax		;save date
	and	ax,1e0h 	;isolate
	mov	cl,5		;  month
	call	x1		;convert
	pop	ax		;get and
	push	ax		;  save date
	and	ax,1fh		;convert
	call	x2		;  day
	pop	ax		;restore date
	and	ax,0fe00h	;isolate and
	mov	cl,9		;  position
	shr	ax,cl		;    year
	add	ax,80		;add 80
	call	x2		;convert year
	mov	dx,offset mth	;print
	jmp	prt		;  date
x1:	shr	ax,cl		;position
x2:	aam			;convert
	or	ax,'00'         ;  2 digits
	xchg	al,ah		;add to
	mov	[si],ax 	;  field
	add	si,3		;next field
	ret			;return
;
; check for end of page
;
ckpg:	call	prtcr		;print cr
ckpg1:	test	byte ptr sw,2		;pause option
	jz	fsp2		;br no
	dec	lct		;decr line count
	jnz	fsp2		;br if not end of page
	mov	lct,24		;reset line count
	mov	dx,offset wait	;print
	call	prt		;  pause
	mov	al,8		;wait
	mov	ah,0ch		;  for
	int	21h		;    key
prtcr:	mov	dx,offset cr	;print cr
prt:	mov	ah,9		;print
	int	21h		;  routine
	ret			;return
;
; space for option F
;
fsp:	mov	cx,colp 	;offset
	jcxz	fsp2		;  cols
fsp1:	call	prtb		;    for
	loop	fsp1		;      option
fsp2:	ret			;	 F
;
; move directory file spec
;
mvfs:	push	cx		;save
	push	si		;  regs
	mov	cx,4		;move
	mov	si,offset dfspc ;  file
	repz movsb		;    spec
	pop	si		;restore
	pop	cx		;  regs
	ret			;return
;
; match directory entry against specified filespec
;
cknm:	cmp	byte ptr [di],'?' ;any char
	je	cknm1		;br yes
	cmpsb			;char match
	je	cknm2		;br yes
	dec	word ptr ct	;decr count
	mov	di,bp		;restore reg
	ret			;return
cknm1:	cmpsb			;step pointers
cknm2:	loop	cknm		;check next char
	ret			;return
;
; clear counters
;
clear:	mov	cx,8		;clear
	mov	di,offset ct	;  all
	xor	ax,ax		;    the
	repz	stosw		;      counters
	ret			;return
;
; work area
;
nx	dw	tb		;adr of table
coln	dw	2		;# of cols
lct	dw	24		;line count
sw	db	0		;options
;				   128-erase screen
;				    64-sort by size
;				    32-sort by date
;				    16-sort by file ext
;				     8-4 col. format
;				     4-no sort
;				     2-pause at page end
;				     1-indent
sw1	db	0		;options
;				   128-width 40 screen
;				    64-not used
;				    32-not used
;				    16-not used
;				     8-not used
;				     4-option T
;				     2-option F
;				     1-option A
swn	db	'TFAESDXWNPI'   ;option letters
blnk	db	'    '          ;blanks
b8	db	'        $'
wait	db	'more...$'
max	db	'Max Stor$'
h1	db	'SDL-3.2 $'
h1evl	db	' '
mth	label	word
mtha	db	'00/00/00 '
ti	label	word
tia	db	'00:00 Dr @$'
h1a	db	'  Free Space: $'
h1b	db	' Bytes $'
h1c	db	' Sec.$'
cr	db	13,10,'$'
h1d	db	' Files, $'
h2	db	' Filename.Ext   Bytes    Last Update   $'
h3	db	'Sec.$'
dirm	db	'Date    Dir#  $Dir#'
atr	db	1,'r',2,'h',4,'s',16,'\'
init	db	0ffh,5 dup(0),8 ;dummy extended fcb
	db	' '             ;dummy fcb
	db	11 dup('?')     ;default filespec
dfspc	db	'*.*',0         ;read dir. filespec
wild	equ	$-3		;use ".*" when no extension is given
fspca	dw	path+2		;fspec adr in path
col	dw	1		;col offset
prvt	dw	0		;prev tbl adr
dirn	dw	0		;dir no.
colp	dw	0		;opt F col spacing
path	db	' :\*.*',0      ;drive and root/filespec
; use equates to decrease the size of the COM module
xpath	equ	$		;64-path
da	equ	$+64		;21-DTA, DOS use
daa	equ	da+21		;1-file attributes
das	equ	daa+1		;8-file time, date, and size
dan	equ	das+8		;13-file name
free	equ	dan+13		;4-free space
fcrm	equ	free+4		;2-rem.-files/cols
bpsc	equ	fcrm+2		;2-bytes/sec
scpf	equ	bpsc+2		;2-sectors/fat
ct	equ	scpf+2		;2-file count
dused	equ	ct+2		;4-bytes used by files in dir.
sused	equ	dused+4 	;2-sec used by files in dir.
t4	equ	sused+2 	;6-4th, 3rd, 2nd chain
t1	equ	t4+6		;2-1st chain
svvol	equ	t1+2		;12-label save area
dxfcb	equ	svvol+12	;7-dummy extended fcb
dfcb	equ	dxfcb+7 	;1-dummy fcb
fspc	equ	dfcb+1		;36-default filespec
tb	equ	fspc+36 	;start of table
;   control: 2-not used   normal: 2-chain adr
;offset +2   2-fspec adr	  12-filename.ext
;	 4   2-column offset
;	 6   2-prev. tbl adr
;	 8   2-curr sub-dir adr
;	10   2-table end adr
;	12   2-not used
;	14   1-not used 	  1-end of filename ($)
;	15   1-attribute/switch   1-attribute/switch
;	       8-control entry	    8-control entry
;	16   2-not used 	  2-time
;	18   2-not used 	  2-date
;	20   4-not used 	  4-file size
;	24   2-not used 	  2-dir # (TA option)
subp	endp
sdlp	endp
sdl	ends
	end	bgn
 
[ RETURN TO DIRECTORY ]