; File DIR_SUBS.S contains the SIO2PC subroutines used for
; the get directory functions:
;
;       CONTAINS THE SUBROUTINES:

; DODIR;  ATAR_DIR;  SETDTA;  GETDTA;  RESETDTA
; GET_DIR;  GET_DRIVE;  FIND1ST;  FINDNEXT;  EXTRACT
; NOT_ENUF; PUT_DIRSEC; SPARTA_DIR; LINE_FEED; GETPATH
; FILELIST; REGLITE; HILITE; LIST2SCRN; LIST2RAM;

;       Directory Subroutines




; DODIR - A routine to search the directory (current or specified)
; and list filenames on the screen. Note, this function doesn't use
; GET_TORK for input, so it can't be run from REMOTE.

DODIR:
        CALL CLR_SCRN
        CURSET 0005
        MOV FIELD_COUNT,0; 3.06
; first ask if user wants PC dir, or to extract Atari dir from image

        PRINTL DIR_FIRST
        CALL GET_TORK
        CMP AL,'1'
        JE >L1
        CMP AL, '2'
        JNE DODIR
        JMP ATAR_DIR; Finish up in subroutine for Atari directory

; at this point, the user wants a PC directory

L1:
        PRINTL DIR_INSTR
        CURSET 0605h
        CALL SETDTA
        MOV AH,0Ah; DOS buffered input function
        PUSH CS
        POP DS
        MOV DX, OFFSET DPTHHDR
        INT 021h
        CMP B[DIRPATH],0Dh; just ENTER pressed?
        JNE >L1
        JMP SHORT FINDIR

; Buffered input function 0Ah ends with a CR (0Dh), then 0. The
; directory search functions won't stand for the CR, so the code
; below changes it to a 0. (ASCIIZ string).

L1:     MOV BH,0
        MOV BL,[DPTHHDR+1]; get # of bytes
        MOV B[DIRPATH+BX],0
        CURSET 0800h
        CALL FIND1ST; Get first directory match
        JC ABN
L1:     CALL UPDATE
        CALL FINDNEXT
        JNC L1
        JMP TTSALF

ABN:    CMP AX,03; Invalid path error
        JNE TTSALF; "That's all folks"
        PRINTL BADPATH
        TICKS 45
        JMP DODIR

TTSALF: PRINTL END_O_DIR
DIRDUN: MOV AH,0Bh; Check STDIN status (is a keypress ready?)
        INT 021h
        CMP AH,0
        JE DIRDUN; 0 means no char waiting

L1:     MOV AH,08h; Now, get the char. and throw it away
        INT 021h
        CMP AL,0; Extended code?
        JE L1; If so, get the rest of it
FINDIR:
;       CALL RESETDTA ; comment out via 4.11d
        RET; We're outta here!

; GET_DIR gets original directory and stores in OLDPATH for permanent.
; GET_CDIR gets current directory and stores in NEWPATH for current use. 

GET_DIR:
        MOV AH,047h; DOS function: get current directory
	MOV DL, 0 ; current default drive 3.16.  NOTE default
; drive gotten from function 19h DOESN'T match that expected by
; function 047h !!

;	 MOV DL,B[CUR_DRIVE]; for current drive  (gotten w/ function 19h)
        PUSH CS
        POP DS
        MOV SI,OFFSET OLDPATH; PATH will be stored in OLDPATH as ASCIIZ
        INT 021h; note: carry set if error...
        RET


GET_CDIR:
        MOV AH,047h; DOS function: get current directory
	MOV DL, 0 ; current default drive 3.16.  NOTE default
; drive gotten from function 19h DOESN'T match that expected by
; function 047h !!

        PUSH CS
        POP DS
        MOV SI,OFFSET NEWPATH; PATH will be stored in NEWPATH as ASCIIZ
        INT 021h; note: carry set if error...
        RET


GET_DRIVE:
        MOV AH,19h; DOS get drive function
        INT 021h
        MOV [CUR_DRIVE],AL; A = 0, B = 1, Z = 25
        RET

;       Find first directory match:

FIND1ST:
        PUSH CX,DX
        FILL ' ', DIRFNAME, 12
        MOV AH,4Eh; DOS find first match
        MOV CX,10h; Attribute to find normal files & directories
        PUSH CS
        POP DS
        MOV DX,OFFSET DIRPATH
        INT 021h

; Note: carry set on error. AX = 2 means no match found; 3 means
; invalid path

L1:     POP DX,CX
        RET

;       Find next directory match:

FINDNEXT:
        PUSH AX
        FILL ' ', DIRFNAME, 12
        MOV AH,4Fh; DOS find next match function
        INT 021h; File info goes to, carry set if no match
        POP AX
        RET

;       Set DTA to my DIRDTA data area:

SETDTA:
        MOV AH,1Ah; DOS set DTA function
        PUSH CS
        POP DS
        MOV DX,OFFSET DIRDTA
        INT 021h
        RET

;       Get and save original DTA:

GETDTA:
        PUSH AX,BX,ES
        MOV AH,2Fh
        INT 021h
        MOV [SEG_ODTA],ES
        MOV [OFF_ODTA],BX
        POP ES,BX,AX
        RET

;       Restore DTA to as-found:

RESETDTA:
        PUSH AX,DS,DX
        MOV AH,1Ah
        MOV DS,SEG_ODTA
        MOV DX,OFF_ODTA
        INT 021h
        POP DX,DS,AX
        RET

; This routine puts the found file name into a line field and prints
; it when it is full:

UPDATE:
        CLD
        MOV CX,12; # of bytes to move
        MOV DI,OFFSET DLPLUS5
        MOV SI,OFFSET DIRFNAME
        PUSH CS
        PUSH CS
        POP DS
        POP ES
        REP MOVSB; Move filename from DTA to DIRLINE field

        CMP B[ATTDIR],010h; Directory?
        JNE >L1
        MOV CX,5; Length of {dir} string
        MOV SI,OFFSET DIRSTR
        MOV DI,OFFSET DIRSPOT
        REP MOVSB

L1:     MOV AH,040h; put bytes to file
        MOV BX,1; Handle for screen

        MOV DX,OFFSET DIRLINE
        MOV CX,20; # of bytes to write
        INT 021h
        FILL ' ', DIRLINE, 20
        RET

; Routine to extract the Atari directory from a disk image:

ATAR_DIR:


   CALL SETDTA

; First, get the user to give the search spec:
        CALL CLR_SCRN
        CURSET 0000
        PRINTL ENT_IMG

        MOV AH,0Ah; DOS buffered input function
        PUSH CS
        POP DS
        MOV DX, OFFSET DPTHHDR
        INT 021h
        CMP B[DIRPATH],0Dh; just ENTER pressed?
        JNE >L1
        JMP FINDIR1

; See if user put ,P at end of pathname, if so output
; also goes to printer

L1: MOV W[HANDLP],0; Assume no output to printer
        MOV BH,0
        MOV BL,[DPTHHDR+1]; # of bytes

        MOV AL,[DIRPATH+BX-1]
        AND AL, 11011111xB; Force uppercase
        CMP AL,'P'
        JNE >L1
        MOV AL,[DIRPATH+BX-2]; Comma before P?
        CMP AL,','
        JNE >L1
        MOV W[HANDLP],4; Handle for printer
        MOV B[DIRPATH+BX-2],0; Fix pathname for DOS


; Buffered input function 0Ah ends with a CR (0Dh), then 0. The
; directory search functions won't stand for the CR, so the code
; below changes it to a 0. (ASCIIZ string).

L1: MOV BH,0
        MOV BL,[DPTHHDR+1]; get # of bytes
        MOV B[DIRPATH+BX],0
        CURSET 0400h
        MOV B[DIR1],0; flag that this is first match
        CALL FIND1ST; Get first directory match
        JC ABZ


L1: CALL EXTRACT; Now, extract the Atari directory from the file
        JNC ACB; No carry means no error
        PRINTL ERRDIR
        JMP TTSXLF

ACB:    INC DIR1; flag this will not be first match
        CALL FINDNEXT
        JNC L1
        JMP TTSXLF

ABZ: CMP AX,03; Invalid path error
        JNE TTSXLF; "That's all folks"
        PRINTL BADPATH
        TICKS 45
        JMP DODIR

TTSXLF: PRINTL END_O_DIR
        CALL WAIT4KEY
FINDIR1:
;        CALL RESETDTA ; 4.11d commented out
        RET; We're outta here!

; A routine to extract Atari directory information from a disk image

EXTRACT:

        MOV N_SUBDIR, -6; Moves in incrs. of 6; stays at 6 below next
                                        ; free location.

; If this is not the first match, ask the user to press a key
; to continue to next:

        CMP B[DIR1],0; 0 means first match
        JE >L1
        PRINTL CRLF
        PRINTL KEYWAIT
        PRINTL CRLF
        CALL WAIT4KEY
        CMP AL, 27      ; 3.12  - user can bail out here
        JNE > L1
        JMP BADRET
;        MOV FIELD_COUNT,0
; Put the found filename into the pathname spec
; First, find last backslash, if there was one:

L1: MOV BH,0
        MOV BL,[DPTHHDR+1]; number of bytes in pathname from user
L2:     DEC BX
        CMP B[DIRPATH+BX],'\'
        JE >L1
        CMP BX,0
        JNE L2
        JMP SHORT ACE; never found \, so start from BX=0
L1: INC BX; found \ so inc past it

; Now, move found filename into pathname

ACE: MOV SI,0
L0: MOV AL, [DIRFNAME+SI]
        MOV [DIRPATH+BX],AL
        CMP AL,0; 0 marks end of ASCIIZ string
        JE >L1
        INC SI
        INC BX
        JMP L0

; Tell the user what atari image dir is being listed:

L1:
        MOV AL, [DIRPATH+BX-1]; last char of filename - rev 3.04
        MOV DISK_TYPE, AL; 'S' will mean SPARTADOS format
        MOV CX,BX; Get # of bytes to print
        PUSH CX
        PUSH CX; 2nd copy of output to printer
        PRINTL DIR_OF
        POP CX
        MOV AH,040h; PRINT
        MOV BX,1; Screen handle
        MOV DX, DIRPATH; ADDRESS OF - DIRPATH IS A LABEL
        INT 021h
        CALL LINE_FEED
        CALL LINE_FEED

        POP CX; retrieve length for hard copy output

        CMP W[HANDLP],0
        JE >L1; No printer

        PUSH CX; Again save length of filename

        MOV AH,040h; put bytes to file
        MOV BX,4; Handle for printer
        MOV DX,DIR_OF; OFFSET
        MOV CX,18; Length of string
        GO2DOS BADRET

        POP CX; Now get back length of filename field:

        MOV AH,040h; put bytes to file
        MOV BX,4; Handle for printer
        MOV DX, OFFSET DIRPATH
        GO2DOS BADRET

        CALL CRLF2P; Linefeed to printer
        CALL CRLF2P; and another


L1: MOV W[HANDL],0; Initialize to show if opened

; Now, open the file:

        MOV AH,03Dh; Open file
        MOV AL,0; Read access
        MOV DX, OFFSET DIRPATH
        INT 021h
        JNC >L1; no error
        PRINTL EOPF
        MOV AH,0; AX contains error code
        ADD AL,'0'; Convert to ASCII digit
        CALL PRINT1
        TICKS 54
        JMP BADRET

L1:     MOV BP, BLOCK_SIZE; 3.04 "5th" disk
	MOV CL, 2
	SHL BP, CL      ; BLOCK_SIZE * 4
	MOV HANDL,AX; save file handle
        MOV [HANDLE+BP], AX


L1: MOV [HANDL],AX; save file handle

; First, read the header to see what kind of file this is:

        MOV AH,03Fh; Read from file
        MOV BX, HANDL
        MOV CX,16; Number of bytes to read
        MOV DX, OFFSET D_HEADR; where to park  'em
        INT 021h
        JNC >L1; Jmp if no error
        JMP BADRET

L1:     MOV B[SEC_PTR+BP],1; pointer for disk 5 is now 1: r3.04
        MOV AX, CATARI; Atari disk identifier
        CMP WORD PTR [D_HEADR], AX
        JE >L1
        PRINTL NATDSK
        TICKS 54
        JMP BADRET

L1:
	CMP DISK_TYPE, 'S' ; SPARTA? rev 3.04
        JNE >L1
	CALL SPARTA_DIR
        JNC >L2
	JMP BADRET
L2:     JMP L8 ; Good return

L1: MOV CX,0; MSB of offset; Assume single density
        MOV DX,46096; LSB of offset; this points to sector 361
        MOV AL,0; Access from start of file
        CMP B[D_HEADR+4], 080h; single density?
        JE >L1; If it was single density, bypass next...

        MOV CX, 1; for 64K part;    MSB
        MOV DX, 26256;     LSB

; Now, position the pointer to sector 361:

L1:
        MOV DI, N_SUBDIR; Point DI to next stack loc
        ADD DI,6
        CMP DI,96; 96 means stack is full
        JE >L1
        MOV [FILOSH+DI],CX; save for subdir expansion
        MOV [FILOSL+DI],DX
L1:     PUSH DI
        MOV AH,042h; Position file pointer
        MOV BX, HANDL
        INT 021h
        POP DI
        JNC >L1
        PRINTL ERRRF
        TICKS 54
        JMP BADRET

L1:     MOV CX,64; counter for # of 16 byte fields

ACA:
        CMP DI,96; Subdir stack full?
        JE >L1
        MOV [FIELD+DI],CX; for possible subdir expansion
L1:     PUSH CX
        READ_FILE HANDL, 16, DIRBUF, >L1

        POP CX; part of error return
        PRINTL ERRRF
        TICKS 54
        JMP BADRET

L1: MOV B[SDFLAG],0; Assume not a subdir
        MOV AL, B[DIRBUF]
        AND AL, 11000000xB
        CMP AL, 01000000xB; In use: b6 set, not deleted: b7 clear
        JE >L1; Jump if valid filename
        MOV AL,B[DIRBUF]; check for MYDOS subdir signature (010H)
        CMP AL, 010h
        JNE ACF
        MOV B[SDFLAG],0FFh; Flag entry is a subdir
        CMP N_SUBDIR,96; Is subdir stack already full?
        JE ACF; if so, this one won't get expanded...

; Here, we KNOW this is a MYDOS subdir. We have already put the
; pointer info on the subdir stack, but it's not officially on
; the stack until the stack pointer has been moved. So:

        ADD N_SUBDIR, 6

ACF: POP CX
        LOOP ACA
        JMP GOODRET; end of dir data

; now, put dirline to screen:

L1:     CALL PUT_DIRLINE; 3.04
        POP CX ; 3.12 - moved location of POP CX so BADRET
        JC BADRET ; will also get it
        JMP >L0
L4:     JMP ACA ; fix out of range jmp for LOOP instr

L0:     LOOP L4

GOODRET:

; First, are there any subdir entries on the stack to be
; expanded?

        CMP N_SUBDIR, -6
        JE >L8; -6 means the stack is empty
        CALL EXSUB

L8: CALL CLOSDIRF
        CLC; Carry clear means good return
        RET

BADRET:
        CALL CLOSDIRF
        STC
        RET


; REV 3.01 ADDED:

LINE_FEED:
	PRINTL CRLF
        RET



; sub to put the dir name, separator, and ext. to screen and/or
; printer. This was in line before 3.04

PUT_DIRLINE:

	MOV AH,040h; put bytes to file
	MOV BX,1; Handle for screen
	MOV DX,OFFSET ATNAM
	MOV CX,8; # of bytes to write
	INT 021h

        CMP W[HANDLP],0
        JE >D1; No printer

	MOV AH,040h; put bytes to file
	MOV BX,4; Handle for printer
	MOV DX,OFFSET ATNAM
	MOV CX,8; # of bytes to write
	GO2DOS AEF

; Now put the dot, if there's an extension

D1:
        CMP B[SDFLAG],0
        JE >C1   ; 3.04: previously was JNE ...
        MOV B[DOT],'*'; Use * to indicate subdir...
	JMP SHORT ACG
C1: MOV B[DOT],'.'; Assume extension

        CMP B[ATEXT],' '
	JNE ACG
        CMP B[ATEXT+1],' '
	JNE ACG
        CMP B[ATEXT+2],' '
	JNE ACG
        MOV B[DOT], ' '; No extension

ACG: MOV AH,040h
	MOV BX,1
	MOV DX, OFFSET DOT
	MOV CX,1
	INT 021h

        CMP W[HANDLP],0
        JE >B1; No printer

	MOV AH,040h; put bytes to file
	MOV BX,4; Handle for printer
	MOV DX,OFFSET DOT
	MOV CX,1; # of bytes to write
	GO2DOS AEF

; Now put the extension

B1: MOV AH,040h
	MOV BX,1
	MOV DX, OFFSET ATEXT
	MOV CX,7; 3 plus 4 for padding to 16 byte field
	INT 021h
	INC FIELD_COUNT
	CMP FIELD_COUNT, 90; 18 lines; 3.17 - WAS 20 LINES
        JB >L1
	CALL LINE_FEED
	PRINTL KEYWAIT
        CALL LINE_FEED ; 4.11 added
	CALL WAIT4KEY
        CMP AL, 27 ; ESCAPE? REV 3.12 CHANGE
        JE AEF

        MOV FIELD_COUNT, 0

L1:     CMP W[HANDLP],0
        JE >A1; No printer

	MOV AH,040h; put bytes to file
	MOV BX,4; Handle for printer
	MOV DX,OFFSET ATEXT
	MOV CX,7; # of bytes to write
	GO2DOS AEF

A1:     CLC
	RET

AEF:    STC     ; flag bad return
        RET


; A routine to set the file pointers for extraction of a MYDOS
; subdirectory and print the subdir name to the output devices:


EXSUB:   RET; EXSUB NOT PROGRAMMED YET


; close dir file, if it was opened:

CLOSDIRF:
        CMP W[HANDL],0
        JNE >L1
        RET
L1: MOV AH,3Eh
        MOV BX,HANDL
        INT 021h
        RET


; A routine to extract the directory of a SPARTA dos disk image


SPARTA_DIR:

; First, fill in some info from the header into the disk #5 info
; area:

        MOV AX, WORD PTR[D_HEADR+4]; Sector size
	MOV SEC_SIZE[BP], AX
        MOV AX, WORD PTR [D_HEADR+2]; low word of disk size in paras
	MOV LO_SIZE[BP], AX
        MOV AX, WORD PTR [D_HEADR+6]; hi word of size in paras
	MOV HI_SIZE[BP], AX

        MOV FIELD_COUNT, 0
        MOV N_SUBDIR, 0 ; init stack pointer for subdirs

	MOV DIR_NEXT, 0 ; offset where next sector will go

	MOV AX, RAM; # of paragraphs free, make a copy
	MOV DIR_RAM, AX; for this function to calculate on

V1:     MOV SECTOR, 1   ; Now, read in the first boot sector
	CALL PUT_DIRSEC
	MOV DX, ES:[09] ; sector # of MAIN dir sector MAP

; Below is where subdir recursion will re-enter:

JUMP_IN:
	MOV SECTOR, DX
	CALL PUT_DIRSEC; read in the sector map

; Now, starting at the 3rd word of the sector map, read in the
; identified sectors until 0 is found.

	MOV DX, DIR_NEXT       ; First save adr. of where dir string
	MOV SPDIR, DX          ; will start

	MOV DI, 4       ; 3rd word of sector map
L1:     MOV DX, ES:[128 + DI]; 128 skips boot sector
	CMP DX, 0
        JE >N1
	MOV SECTOR, DX
	INC DI
	INC DI
	PUSH DI
	CALL PUT_DIRSEC
	POP DI
        JNC L1;
	RET


N1:     MOV SI, SPDIR   ; get offset of dir string
	MOV AX, ES:[SI+3]; Low word of file (dir) length
	XOR DH,DH       ; This is a 1 1/2 word length
	MOV DL, ES:[SI+5]; high half word
	MOV CX, 23
	DIV CX          ; get # of entries total into AX
			; SPARTA entries are 23 bytes long

	MOV CX, AX      ; CX <- number of entries
	MOV BX, 0       ; BX will count offset to current entry

AEH:    MOV B[SDFLAG], 0; Not a directory (?)
	TEST BYTE PTR ES:[SI+BX], 8 ; entry in use? 3.17 was SI+BX+7
        JNE >L1      ; bit 3 clear means deleted
	ADD BX, 23
	JMP AEQ
L1:	TEST BYTE PTR ES:[SI+BX], 020h; directory? 3.17: was +7
        JE >P1
        MOV B[SDFLAG], 0FFh

; Save Sector Map reference of subdirectories:

        MOV MAIN_FLAG, BX; hold on to this fact...
	CMP BX, 0 ; Don't save ref for MAIN or Current dir
        JE >P1
        CMP N_SUBDIR, 32 * 2 ; Stack full?
        JA >P1
	MOV AX, ES:[SI+BX+1]; Sector # of Dir Map
	PUSH SI
	MOV SI, N_SUBDIR
	MOV [FILOSL+SI], AX; Put it on stack
        ADD N_SUBDIR, 2; Inc stack pointer; it grows UP
	POP SI


P1:     PUSH CX
	MOV DI, 0
	MOV CX, 4; 4 words in 8 char filename
W1:     MOV AX, ES:[SI+BX+6]
	MOV WORD PTR [ATNAM+DI], AX
	INC DI
	INC DI
	INC BX
	INC BX
        LOOP W1

; Add name to name stack, if subdir, if there's room:

        CMP B[SDFLAG], 0
        JE >Q1
        CMP MAIN_FLAG, 0
        JE >Q1; don't save main or current, either
        CMP W[N_STACK_PTR], 32*8; 1 past top already?
        JE >Q1
	MOV CX, 4
	PUSH ES
	PUSH DS
	POP ES
	PUSH DI
	PUSH SI
	MOV DI, OFFSET NAME_STACK
        ADD DI, W[N_STACK_PTR]; 3.06
	MOV SI, OFFSET ATNAM
	CLD
	REP MOVSW
	POP SI
	POP DI
	POP ES

        ADD W[N_STACK_PTR], 8

Q1:     POP CX

; now, move the extension:

	MOV AX, ES:[SI+BX+6]
	MOV WORD PTR [ATEXT], AX
	MOV AL, ES:[SI+BX+8]
	MOV [ATEXT+2], AL

; now, point to next entry

	ADD BX, 15      ; (already added 8 above)
	PUSH BX
	PUSH CX
	CALL PUT_DIRLINE; Print filename to screen/printer
	POP CX
	POP BX
	JNC AEQ  ; Error return from PUT_DIRLINE
	RET
R1:     JMP AEH
AEQ:    LOOP R1

; Now, is subdirectory stack empty?

        CMP N_SUBDIR, 0
        JNE >S1
	CLC
	RET

S1:     PUSH BX
	MOV DIR_NEXT, 128; Start just past boot sector again...
	MOV AX, RAM
	MOV DIR_RAM, AX
	SUB DIR_RAM, 8
        SUB N_SUBDIR, 2; Point to last entry
	CALL LINE_FEED
	CALL LINE_FEED
	PRINTL SAY_SUB

        SUB W[N_STACK_PTR], 8
	MOV DX, OFFSET NAME_STACK
        ADD DX, W[N_STACK_PTR]; 3.06 CORRECTION?
	PUSH BP
	PUSH ES
	WRITE_SCREEN 8
	CALL LINE_FEED
	CALL LINE_FEED
        ADD FIELD_COUNT, 15
	POP ES
	POP BP

        CMP W[HANDLP],0
	JE AEP; No printer
	PUSH BP
	PUSH ES
	CALL CRLF2P
	CALL CRLF2P
	MOV AH, 040h; put bytes to file
	MOV BX, 4; Handle for printer
	MOV DX, OFFSET SAY_SUB
	MOV CX, OFFSET FILOSL- OFFSET SAY_SUB ; # of bytes to write
	GO2DOS AEO

	MOV AH, 040h; put bytes to file
	MOV BX, 4; Handle for printer
	MOV DX, OFFSET NAME_STACK
        ADD DX, W[N_STACK_PTR]; 3.06
	MOV CX, 8 ; # of bytes to write
	GO2DOS AEO

	CALL CRLF2P
	POP ES
	POP BP

AEP:    POP BX
	MOV SI, N_SUBDIR
	MOV DX, [FILOSL+SI]; Get sector map reference

	JMP JUMP_IN

AEO:    POP BX
	STC     ; Error return
        RET

; PUT_DIRSEC reads a sector from the physical disk into SECBUF,
; then transfers it to free ram area

PUT_DIRSEC:
	MOV AX, SECTOR; Set CFAUXes for CX_SIZE routine
	MOV CFAUX1, AL
	MOV CFAUX2, AH

	CALL RD_FSEC    ; Data will go to SECBUF
	JNC >L1
	JMP AEL ; error exit

L1:	CALL CX_SIZE	; Assume SECTOR and BP are still right
	MOV AX, CX      ; I need CL to do my shift
	MOV BX, CX
	MOV CL, 4
	SHR AX, CL      ; AX <- paras; BX <- bytes
	SUB DIR_RAM, AX
        JA >U1
	JMP NOT_ENUF

U1:     MOV CX, BX

; move dir sector from SECBUF into next free ram spot:
; CX contains the number of bytes

	CLD
	MOV ES, NEXTS
	MOV DI, DIR_NEXT
	MOV SI, OFFSET SECBUF
	REP MOVSB
	ADD DIR_NEXT, BX ; Point to next free address
	CLC
	RET

NOT_ENUF:
	PRINTL DIR_RAM
	TICKS 45
AEL:    STC
        RET

; ***************************** FILE LIST *****************************
;
COMMENT\

This function will present a list of file names in scrolling column format.
The selected name will be hi-lited.  Directories will show with backslash
The user will be able to select a file or change directories by pressing
ENTER on the desired selection.  Carry clear means file or directory
name has been placed in RFSPEC.  Carry set and AX = 0 means user decided
to cancel the file request.

ENDOFCOMMENT\

FILELIST:

; Clear the screen and put the path on the top line:

        CALL CLR_SCRN
        CURSET 0
        WRITE_TSTR NEWDRIVE, 0 ;; write ASCIIZ string
        CALL DIR_BOX
        PRINT_LM 27, 5, DROPSAY

; now, get file list and put in RAM

        MOV TOP_NOW, 0 ; # of field @ top of list range 0 -> TOTALD
        MOV SELECTED, 0 ; field in list selected -> 0 - 21 fields
        CALL LIST2RAM
        JNC > C1
        CMP AX, 03 ; if carry set and AX=3, need new path. 4.12
        JNE > D1
        JMP ATP2
D1:     JMP BADO

C1:     CALL BUBBLE ;  sort the list
        CALL LIST2SCRN
        CALL HILITE ; make first entry be hilited
ZL3:
L3:     CALL GET_UP ; look for up arrow, down arrow, ESC, or CR
L5:     CMP AX, 04800h ; arrow UP?
        JNE > L1
        CMP SELECTED, 0
        JE > L2

; here, arrow up and not at top already

        CALL REGLITE ; first, deselect current entry
        DEC SELECTED ; not at top of list, so move up one
        CALL HILITE ; and select next one up
        JMP SHORT L3

; here, arrow up but we are at top of list, so scroll if possible

L2:     CMP TOP_NOW, 0 ; are we at beginning of list?
        JE L3 ; can't scroll if already at top and at start of list
        DEC TOP_NOW ; so now, scroll away
        CALL LIST2SCRN ; we won't need to change hilited field (at top)
        JMP SHORT L3

L1:     CMP AX, 05000h ; arrow DOWN?
        JNE > L6
        CMP SELECTED, 21 ; already at bottom of list box?
        JNE > L7

; here, we are at bottom of list box, so scroll if possible

        MOV AX, TOP_NOW ; top field in list box
        ADD AX, 21 ; see which field is on bottom
        CMP AX, TOTALD
        JAE L3 ; if last field already fits, can't scroll

; here, more fields left, so scroll down

        INC TOP_NOW
        CALL LIST2SCRN ; again, hilited field stays on bottom
        JMP SHORT L3

; here, not at bottom of box, so move down if not on last field

L7:     XOR AX, AX
        MOV AL, SELECTED
        ADD AX, TOP_NOW ; what field in ram are we on?
        CMP AX, TOTALD
        JAE L3 ; can't scroll if at last field
        CALL REGLITE ; restore hilited field
        INC SELECTED ; go ahead and scroll down
        CALL HILITE ; hilite new selected field
        JMP SHORT L3
L6:     CMP AL, 27     ; ESCAPE?
        JNE > Q1
BADO:   XOR AX, AX
        STC
        JNC > Q1
        JMP LP4 ; bail out

Q1:     CMP AL, 13     ; ENTER?
        JNE > L4
        JMP CL4
L4:     CMP AL, 020h ; spacebar?? (4.13 added this option)
        JNE > L5
        JMP ATP2


; Now, check for PGUP and PGDN keys

L5:     CMP AX, 04900 ; Page UP??
        JNE > R1
BUGN1:  CALL REGLITE
        CMP TOP_NOW, 0 ; already at top??
        JNE > R6

; Here, top of list is at top of ram, so just move selected field up to
; top if necessary

        CMP SELECTED, 0
        JE > R3          ; jmp if already at top and top field selected
        MOV SELECTED, 0  ; window at top, but top field not selected
        JNE > R5 ; forced branch

; here, top of list is not at top of ram, so move up whole or part page
; as approprtiate

R6:     CMP TOP_NOW, 22 ; room to move up a whole page?
        JB > R4
        SUB TOP_NOW, 22 ; move up a page
        JMP NEAR > R7
R4:     MOV TOP_NOW, 0 ; if can't do whole page, go to top of list
R7:     CALL LIST2SCRN
;R5:     CALL REGLITE ; unhilite current field
R5:     MOV SELECTED, 0
R3:     CALL HILITE
        JMP ZL3

R1:     CMP AX, 05100 ; Page DN?
        JNE > R2
        CALL REGLITE
        MOV SELECTED, 0
        MOV AX, 22 ; was 43
        ADD AX, TOP_NOW
        CMP TOTALD, AX
        JB > P3 ; if can't do full page down ; was > P1
        ADD TOP_NOW, 22
P3:     CALL LIST2SCRN
        CALL HILITE
        JMP ZL3

; Here, can't do a full page down

;P1:     SUB AX, 22
;        CMP TOTALD, AX
;        JBE > P2
;        MOV TOP_NOW, TOTALD
;        SUB TOP_NOW, 21
;        JMP NEAR P3

;P2:     MOV SELECTED, 21 ; if can't page down, just hilite bottom field
;        JMP NEAR P3

;P2:     JMP ZL3

; Below, assume char is the first char of a filename or dir, so jump
; to next entry with that 1st char

R2:     CMP AL, 0 ; 4.14 - but first, if extended char, it's invalid ...
        JNE > R3
        JMP ZL3
R3:     PUSH AX
        CALL REGLITE ; unhilite current field
         MOV AL, SELECTED
;        CMP AX, TOP_NOW
;        JNE > B1
;       MOV AL, 1 ; start with field 3 if at top already
        INC AL ; start search with SELECTED + 1
        XOR AH, AH
        ADD AX, TOP_NOW ; what field in ram are we on?
        MOV BL, 13 ; length of field
        MUL BL ; multiply AX * BL, results to DX:AX
        MOV DI, AX

; Now, if we started at last field, need to rollover to 1st ...

        CMP NXT_DRAM, DI ; if equal, one beyond list
        JNE > E1
        MOV DI, 0 ; reset to top of list
E1:     MOV START_PT, DI ; record starting point

; Now ES:DI points to current field + 1, so start hunting for a match

        POP AX ; get back char to find ...
        MOV ES, NEXTS
B6:     CMP ES:[DI], AL
        JE > B2 ; B2 means found it!
        ADD DI, 13
        CMP START_PT, DI ; full circle, no match?
        JE > B7 ; re-hilite and go back for next char from user

        CMP NXT_DRAM, DI ; if equal, one beyond list
        JNE B6
        MOV DI, -0D ; reset to top of list 4.13 -> -0D + 0D = 0000
        JMP B6 ; forced branch (was JE)

; Here, item was found so, ...


B2:     MOV AX, TOP_NOW ; calculate ram top and bottom of list box
        MOV BX, 13 ; field length
        MUL BX ; result in DX:AX, assume 16 bit, so in AX ...
        MOV WIN_S, AX ; start of window, ram address
        ADD AX, 13 * 21 ; end of window
        MOV WIN_F, AX
        CMP DI, WIN_S
        JB > C1 ; out of window, above
        CMP DI, WIN_F
        JA > C1 ; out of window, above
        SUB DI, WIN_S ; calculate # of new selected field
        MOV AX, DI ; prepare to divide
        MOV BL, 13
        DIV BL ; divide AX by 13 - results in new field in window
        MOV SELECTED, AL
B7:     CALL HILITE
        JMP ZL3

; Below, found field known to be outside of window, so shift TOP_NOW
; to make found field be bottom of list.  DI still holds found field
; address ...

C1:     MOV DX, 0 ; going to do big divide - may be more than 256 fields
        MOV AX, DI
        MOV BX, 13
        DIV BX ; divide DX:AX by BX, result in AX
        SUB AX, 21
        MOV TOP_NOW, AX
        MOV SELECTED, 21 ; found field at bottom
        CALL LIST2SCRN
        JMP B7

; below, Enter has been depressed, so get filename

CL4:    CALL TAKE_IT ; get field name to RFSPEC
        JNC > Z2 ; carry means it's a directory
        MOV B [DI-1], 0 ; change trailing \ to 0 for ASCIIZ string
CH1:    CALL CHDIR ; change directory to that in RFSPEC string
        JNC > C3
        CALL CLR_SCRN
        PRINTL ERRDIR
        CALL WAIT4KEY
        JMP FILELIST ; start over with list box

; carry set means error, AX = 03h means path not found

C3:     CALL GETPATH ; get current dir to NEWPATH, add search spec too
        JMP FILELIST ; if successful, start over

Z2:     CMP AX, 0 ; field 0 means CANCEL
        JNE > P3
        STC
        JNC > P3 ; return with carry set
T4:     JMP LP4
P3:     CMP AX, 1 ; field 1 means manual entry of search spec
        JE > P2 ; AX not 0 or 1 means normal return status
        JMP LP1

; **************** MANUAL ENTRY OF SEARCH SPEC / DIR ***********************
; Now, ask user for search spec or ENTER to cancel

ATP2:
P2:     CALL CLR_SCRN
        CURSET 0605h
        PRINTL WHATSPEC
;        CALL SETDTA
        MOV AH,0Ah; DOS buffered input function
        PUSH CS   ; read string into DIRPATH
        POP DS
        MOV DX, OFFSET DPTHHDR
        INT 021h
        CMP B[DIRPATH],0Dh; just ENTER pressed?
        JNE >L1
D4:     XOR AX, AX ; signal cancel function requested
        STC
        JC T4 ; long jump to P4

; now search string user put at DIRPATH, see if there is a drive spec

L1:     CMP B [DIRPATH+1], ':' ; colon second means drive letter included
        JNE > D1
        MOV AL, B [DIRPATH] ; get drive letter
        CALL TO_UPPER
        MOV DL, AL
        MOV B [DIRPATH], AL ; make drive letter be uppercase

        CMP B [NEWDRIVE], DL ; is drive same as current?
        JE > D1 ; skip if no drive change required
        SUB DL, 'A' ; make DL have drive # as A = 0
        MOV AH, 0Eh ; change drive function
        GO2DOS BADO ;; Jumps to next line unless crit error ignored
                    ; then goes to BADO for error exit

; now, verify drive change was successful

        CALL GET_DRIVE; Store drive # @ CUR_DRIVE
        MOV AL,B[CUR_DRIVE]
        ADD AL,'A'; Change drive # to drive letter, 0 = A.
        CMP AL, B [ DIRPATH] ; should be same if success
        JE > D3
        PRINTL BAD_DRIVE
        CALL WAIT4KEY
        JMP D4 ; error exit

D3:     MOV [NEWDRIVE], AL

; here, either no drive spec, or drive change has been processed. So now
; parse the rest of the string

ATD1:

D1:
        XOR AX, AX
        MOV AL, B [DPTHHDR+1]; get length of string
        DEC AX ; convert to 0 based
        PUSH DS
        POP ES

; first, all chars from end back to \ or : or beginning are search spec ...
; count length of filespec if any, then move to FILENAME ...

        MOV CX, 0
        MOV SI, DIRPATH
        ADD SI, AX ; point to last char
        CMP B [SI], '\' ; if \, no spec to get
        JE > F3
        CMP B [SI], ':' ; if :, no spec or path ...
        JNE > E2 ; go back get current path and reenter
        JMP C3
E2:     MOV AL, B [SI]
        CMP AL, ':'
        JE > E1
        CMP AL, '\'
        JE > E1
        CMP SI, DIRPATH ; beyond end of string?
        JB > E1
        INC CX
        DEC SI
        JMP SHORT E2

; at this point we've counted the filename, if there was one.  Now SI is at
; the start of the filename - 1 and CX has the total number of bytes, so
; move it to FILENAME


E1:     CMP CX, 0
        JE > E3 ; nothing to move
        MOV DI, FILENAME
        PUSH SI
        INC SI
        REP MOVSB ; move the string to FILENAME
        POP SI
        MOV B [DI], 0; now add 0 to end

; Here drive change has been processed and filename extracted.  Now get
; directory if there is one.  Here, SI points to \ at end of path ...
; replace it with a 0 for a marker
; If the \ at the end of the path comes right after the drive spec, then
; it's not just a directory marker, it means root directory - so don't
; replace with a 0 in that case!  Same if \ was first char of string!

; I'm going to copy to RFSPEC from left to right

E3:     CMP B [SI], '\' ; if no \, then there is no path
        JE > F3
        CALL CONCPATH
        JMP FILELIST
F3:     CMP B [SI-1], ':' ; is the \ a root directory indicator?
        JE > F2 ; if not, replace it with 0, otherwise
        CMP SI, DIRPATH ; else was \ the first char?
        JNE > F1
F2:     INC SI
F1:      MOV B [SI], 0
        MOV DI, DIRPATH
        MOV SI, RFSPEC
        CMP B [DI+1], ':' ; If there was a drive spec, skip it
        JNE > L1
        INC DI
        INC DI ; point to 1 beyond :
L1:     MOV AL, B [DI]
        MOV B [SI], AL
        INC DI
        INC SI
        CMP AL, 0
        JNE L1

; here, path name has been moved to RFSPEC, so change dir to path listed

        JMP CH1 ; re-enter FILELIST at change dir point


; Now, after manual entry of new search spec, re-do the file list box

        JMP FILELIST
LP1:
P1:     CLC ; good return

; lastly, fix screen if needed while preserving state of carry and AX
LP4:
P4:     PUSH AX
        LAHF ; store flags
        CMP TAG_RD3, 0FFh ; FF means don't restore normal SIO2PC screen
        JE > P5
        PUSH AX
        CALL FIX_SCRN
        POP AX
P5:     SAHF ; restore flags (for carry status)
        POP AX
        RET


; CHDIR changes the current directory to the one in the string in RFSPEC

CHDIR:
        MOV DX, RFSPEC
        MOV AH, 03Bh ; set directory function
        INT 021h
        RET ; carry set means bad; AX = 3 means path not found

; TAKE_IT will get the file or dir name selected from the list and move
; it to RFSPEC to get to the DS segment ...
; Because the first two fields (0 and 1) mean CANCEL and TYPE IT, the
; field number is returned in AX
; all 13 bytes are moved and if NOT a directory, 0 is appended
; Returns with carry set if the field is a directory name ...
; Also has DI pointing to \ + 1 if a directory

TAKE_IT:
        CALL BLANK_RFS ; fill RFSPEC with blanks
        XOR AX, AX
        MOV AL, SELECTED
        ADD AX, TOP_NOW ; what field in ram are we on?
        PUSH AX ; hold that thought - fields 0 and 1 have special meaning
        MOV BX, 13 ; length of field [4.18 -- WAS BL]
        MUL BX ; multiply AX * BX, results to DX:AX  [4.18, WAS MUL BL]
        MOV ES, NEXTS
        MOV SI, AX ; start of name in ES ram
        MOV DI, RFSPEC ; place to put it
        MOV CX, 13 ; # of bytes to move
U1:     MOV AL, ES:[SI]
        MOV [DI], AL
        INC DI
        INC SI
        LOOP U1

; now, see if it's a directory

        FIND_BYTE RFSPEC, '\', 55 ;; Zero flag clear means not found
        STC
        JZ > Z1 ; zero condit means \ found, means directory ...
        FIND_BYTE RFSPEC, ' ', 55 ;; find 1st blank
        MOV B [DI-1], 0 ; replace with 0 for ASCIIZ
        CLC
Z1:     POP AX
        RET


; LIST2RAM searches the path/filespec starting at NEWDRIVE and puts list
; plus two options to ram starting at NEXTS:0000
; returns with NXT_DRAM pointing to 1 field beyond last

LIST2RAM:
        MOV TOTALD, 1 ; for CANCEL and TYPE IT (TOTALD 0 = 1)
        SMOVE NEWDRIVE, DIRPATH, 65 ;; FIND1ST needs it in DIRPATH
        MOV ES, NEXTS ; point to start of next free segment
        MOV CX, 26 ; start with CANCEL and TYPE SPEC choices
        MOV DI, 0  ; start at offset 0 of NEXTS
        MOV SI, CAN_DIR
	CLD
        REP MOVSB  ; move two 13 byte strings
        MOV NXT_DRAM, DI ; assume DI points to byte following

; next, get actual file list from DOS; file goes to DIRFNAME in my DTA

        CALL FIND1ST ; C = error, AX = 2, no match, 3 = badpath
        JNC > L1
        CMP AX, 2 ; return if no match
        JE > L2
        CMP AX, 012h ; also means no match
        JE > L2

        CALL CLR_SCRN ; only error besides no match is bad path, so
        CURSET 0202h
        PRINTL PATH_NG
        TICKS 36
        MOV AX, 3 ; indicate bad path error.  4.12
        STC
        JC > L2 ; return error status

; HERE, GO TO ROUTINE WHICH ASKS FOR MANUAL PATH ENTRY

; below copies the file entry to ram, doesn't copy the 0, fills out
; unused spaces with space char (13 space field)

L1:     INC TOTALD ; TOTALD is the total entries -1 in the list
        MOV ES, NEXTS
        MOV SI, DIRFNAME
        MOV DI, NXT_DRAM
        MOV CX, 13 ; max number to move, NAME, ., EXT, AND \ = 13
L4:     MOV AL, B[SI] ; get entry char
        CMP AL, 0     ; 0 marks end of string
        JNE > L5
        MOV AL, ' ' ; put space instead of 0 ... (assume not directory)
        CMP B[ATTDIR],010h; Directory?
        JNE > L5
        MOV AL, '\' ; mark entry as directory
L5:     ES:MOV B[DI], AL
        INC SI
        INC DI
        CMP AL, ' ' ; if space, we're in pad out phase ...
        JE > L6
        LOOP L4 ; forced branch
        JMP SHORT > L7
L3:     MOV AL, ' ' ; pad out with blanks
L6:     LOOP L5
L7:     MOV NXT_DRAM, DI
        CALL FINDNEXT
        JNC L1 ; if not end of DIR, move entry to ram
        CLC     ; else report good status
L2:     RET     ; after return, NXT_DRAM is also last entry + 1.


; BUBBLE will do a bubble sort on the dir list, not counting the first two
; entries.  List expected to start at NEXTS:0000 and entry length is 13
; bytes long.

BUBBLE:
        CMP TOTALD, 3
        JB > L1 ; must be at least 2 dir entries for a sort
        MOV ES, NEXTS
L5:     MOV CX, TOTALD ; get total - 1
        SUB CX, 2 ; less two for 1st two entries
        MOV DID_BS, 0 ; flag no swaps required
        MOV DI, 26 ; first entry
        MOV SI, 39 ; 2nd entry
L4:     MOV AL, ES:[DI]
        CMP AL, ES:[SI]
        JBE > L2 ; no need to swap if 1st is >= 2nd

; here we swap the two entries

        PUSH CX, SI, DI
        MOV CX, 13
L3:     MOV BL, ES:[SI]
        MOV AL, ES:[DI]
        MOV ES:[DI], BL
        MOV ES:[SI], AL
        INC DI
        INC SI
        LOOP L3
        MOV DID_BS, 0FFh ; flag swap did occur
        POP DI, SI, CX

L2:     ADD DI, 13 ; go to next entry
        ADD SI, 13
        LOOP L4 ; check next pair

; Now, if any swaps occurred we must go thru again

        CMP DID_BS, 0FFh
        JE L5 ; run thru list again

L1:     PUSH DS
        POP ES
        RET



; LIST2SCRN takes the list gotten by LIST2RAM and puts it to the screen
; in the list box.

LIST2SCRN:
        CALL CLRDLIST ; 4.12
;        MOV SI, FIRST_ONE ; offset of 1st dir entry to list
        MOV AX, TOP_NOW ; offset (in fields) from start of list
        MOV BX, 13 ; length of a field
        MUL BX ; computes AX * BX, result in DX:AX, but I figure 16 bits max
        MOV SI, AX ; calculate actual offset of starting field
        MOV DI, (DB_ROW + 1)*160 + (DB_COL + 2) * 2
        MOV ES, SCR_SEG
        MOV DS, NEXTS
        MOV CX, 22 ; # of fields available in box
N2:     PUSH CX
        MOV CX, 13 ; # of characters per field
N1:     MOV AL, [SI]
        MOV ES:[DI], AL
        INC SI
        INC DI
        INC DI;; Skip attribute byte on screen
        LOOP N1
        ADD DI, 160 - 26 ; down one row and back one field
        POP CX
        CMP SI, CS:[NXT_DRAM]
        JE > L1 ; pointing to last entry + 1 if equal
        LOOP N2
L1:     PUSH CS
        POP DS
;        CALL WAIT4KEY
        RET


; Clear the directory list to all spaces; 4.12 added

CLRDLIST:
        MOV DI, (DB_ROW + 1)*160 + (DB_COL + 2) * 2
        MOV ES, SCR_SEG
        MOV CX, 22 ; # of fields available in box
        MOV AL, ' '
N2:     PUSH CX
        MOV CX, 13 ; # of characters per field
N1:     MOV ES:[DI], AL
        INC DI
        INC DI;; Skip attribute byte on screen
        LOOP N1
        ADD DI, 160 - 26 ; down one row and back one field
        POP CX
        LOOP N2
L1:     PUSH CS
        POP ES
        RET

; HILITE hilites the selected entry in the list box.

HILITE:
        PUSH ES
        MOV ES, SCR_SEG
        MOV DI, (DB_ROW + 1)*160 + (DB_COL + 2) * 2; points to field 0
        MOV AL, SELECTED
        MOV BL, 160 ; add 160 bytes per row
        MUL BL      ; product goes in AX
        ADD DI, AX
        INC DI ; point to attribute which is char + 1
        MOV AL, INV_ATTR ; get inverse video attribute
        MOV CX, 13 ; length of field to hilite
L1:     MOV B ES:[DI], AL
        INC DI
        INC DI ; skip char
        LOOP L1
        POP ES
        RET

; REGLITE restores normal attribute to SELECTED field ...

REGLITE:
        PUSH ES
        MOV ES, SCR_SEG
        MOV DI, (DB_ROW + 1)*160 + (DB_COL + 2) * 2; points to field 0
        MOV AL, SELECTED
        MOV BL, 160 ; add 160 bytes per row
        MUL BL      ; product goes in AX
        ADD DI, AX
        INC DI ; point to attribute which is char + 1
        MOV AL, ATTR1 ; get normal video attribute
        MOV CX, 13 ; length of field to hilite
L1:     MOV B ES:[DI], AL
        INC DI
        INC DI
        LOOP L1
        POP ES
        RET


; CONCPATH adds the search spec @ FILENAME to the end of the NEWPATH string

CONCPATH:

; first search NEWPATH upward until 0 is found ...

        FIND_BYTE NEWPATH, 0, 64 ;; Now DI points to 0 plus 1

; now go from there back to the last \ mark ...
; note that we might go all the way back to the \ on the end of
; NEWDRIVE, but that should be OK if it happens (in root directory)

        DEC DI          ; point to the 0 string terminator
        STD             ; this time search backwards
        MOV CX, 64      ; max length to be searched
        MOV AL, '\'     ; AL is the byte we are looking for
        REPNE SCASB     ; now, DI wil be at last \ - 1
        CLD             ; fix direction flag
        INC DI          ; point to \ + 1
        INC DI

; now, copy the filespec string from FILENAME to this place

        MOV BX, FILENAME
L2:     MOV AL, [BX]    ; get filename byte
        MOV [DI], AL    ; put on end of path, even if 0
        CMP AL, 0       ; but 0 marks end of string so
        JE > L1         ; quit after moving it
        INC BX          ; else, get next one
        INC DI
        JMP SHORT L2
L1:     RET

; GETPATH gets the current path including drive letter to string starting
; at NEWDRIVE.  It also appends a \ and default *.* search spec.

GETPATH:
        CALL GET_DRIVE; Store drive # @ CUR_DRIVE
        MOV AL,B[CUR_DRIVE]
        ADD AL,'A'; Change drive # to drive letter, 0 = A.
        MOV [NEWDRIVE], AL
        CALL GET_CDIR; Store path at NEWPATH

        FIND_BYTE NEWPATH, 0, 64 ;; find end of string and add \ unless
        CMP B [DI-2], '\' ; theres already a \ at end of existing string
        JE > L1
        MOV B [DI-1], '\' ; as preface to adding search spec
        MOV B [DI], 0 ; mark new end
L1:     CALL CONCPATH ; add default *.* to search spec
        RET

; return to original default drive ...

RES_DRIVE:
        MOV DL, B[OLDRIVE]
        SUB DL, 'A' ; make DL have drive # as A = 0
        MOV AH, 0Eh ; change drive function
        INT 021h
        RET

; return to original path ...

RES_PATH:
        MOV DX, OLDPATH - 1 ; point to \ root symbol for start of string
        MOV AH, 03Bh ; set directory function
        INT 021h
        RET ; carry set means bad; AX = 3 means path not found
