%TITLE "Determine Current Directories - CHiPS bv 1997"
;**********************************************************************
;** **
;** Program : DC_DIRS **
;** Purpose : Determine Current Directories **
;** Program assumes that Dir_Map table is initialized **
;** **
;** Author : B.F. Schreurs **
;** Computer High Performance Software (CHiPS) bv **
;** Date : September 4th, 1997 **
;** **
;** Calls : MEMSORT - Sort A (Memory) File **
;** **
;** Parameter : 1. Pass the address of the requested format. **
;** The format specified how the data of the **
;** available directories will be passed back. **
;** Requested format size is 1 byte and may contain: **
;** "1" = Return data in format as specified in **
;** DIRENTRY.STR with size DIR_ENTRY_LENGTH. **
;** "2" = Return data in format **
;** "..
" **
;** "ATARI " **
;** "MYDIR " **
;** "YOURDIR " **
;** " " **
;** " " **
;** " " **
;** etc. with size DIR_ENTRY_LENGTH **
;** Parameter : 2. Pass the address of the data which contains the **
;** path to be searched for the directories to be **
;** retrieved. Path size is PATH_LENGTH. **
;** Parameter : 3. Pass the address of the table where the data **
;** containing the directory info will be stored. **
;** Format "1": Table size: DIR_ENTRY_LENGTH * **
;** number of expected libraries. **
;** Format "2": Table size: DIR_ENTRY_LENGTH * **
;** number of expected libraries. **
;** **
;** Language : Turbo Assembler **
;** **
;** Returncode: 0 - No error encountered **
;** 1 - Drive was not ready **
;** **
;**********************************************************************
IDEAL
JUMPS
;----------------------------------------------------------------------
;-- Functions which can be called --
;----------------------------------------------------------------------
PUBLIC DC_DIRS
;----------------------------------------------------------------------
;-- Equates --
;----------------------------------------------------------------------
include ".\equ\attrib.equ"
include ".\equ\dos.equ"
include ".\equ\equipmnt.equ"
include ".\equ\sysdep.equ"
DIRECTORY_TEXT_LENGTH EQU 12
;**********************************************************************
SEGMENT SSeg Para Stack 'STACK'
;**********************************************************************
db 64 dup (0) ; Stack
ENDS SSeg
;**********************************************************************
SEGMENT DSeg Word Public 'DATA'
;**********************************************************************
;----------------------------------------------------------------------
;-- Structures --
;----------------------------------------------------------------------
include ".\str\direntry.str"
include ".\str\dta.str"
include ".\str\sortkeys.str"
;----------------------------------------------------------------------
;-- Working Storage --
;----------------------------------------------------------------------
GLOBAL Return_Code:Byte:1
Parm_Format_ptr_es DW 1 dup (NULL) ; 1 = "DIRENTRY format .. "
; "DIRENTRY format ATARI "
Parm_Format_ptr_di DW 1 dup (NULL) ; 2 = ".. "
; "ATARI "
Parm_Path_Spec_ptr_es DW 1 dup (NULL)
Parm_Path_Spec_ptr_di DW 1 dup (NULL)
Parm_Dir_Map_ptr_es DW 1 dup (NULL)
Parm_Dir_Map_ptr_di DW 1 dup (NULL)
Parm_SortKeys SortKeys<>
DOS_Find_Files_Or_Dirs DW 1 dup (DOS_FIND_DIRECTORIES)
Requested_Format DB 1 dup (?)
Directory_Above_Text DB ".. "
Directory_Text DB " "
Dir_Map_Entry Dir_Entry <>
Dirs_In_Dir_Table DW 0
Old_Dta_Seg DW ? ; Old Dta Segment Address
Old_Dta_Ofs DW ? ; Old Dta Segment Offset
Own_Dta Dta <>
ENDS DSeg
;**********************************************************************
SEGMENT CSeg Word Public 'CODE'
;**********************************************************************
;----------------------------------------------------------------------
;-- External Variables --
;----------------------------------------------------------------------
EXTRN MEMSORT:proc ; Sort A (Memory) File
;**********************************************************************
PROC DC_DIRS
;**********************************************************************
ASSUME cs:CSeg
ASSUME ds:DSeg
mov ax, DSeg ; Initialize DS to address
mov ds, ax ; of data segment
mov bx, sp
;
; Parameter Directories
;
mov di, [ss:bx+2]
mov es, [ss:bx+4]
mov [Parm_Dir_Map_ptr_es], es
mov [Parm_Dir_Map_ptr_di], di
;
; Parameter Path
;
mov di, [ss:bx+6]
mov es, [ss:bx+8]
mov [Parm_Path_Spec_ptr_es], es
mov [Parm_Path_Spec_ptr_di], di
;
; Parameter Requested Format
;
mov di, [ss:bx+10]
mov es, [ss:bx+12]
mov [Parm_Format_ptr_es], es
mov [Parm_Format_ptr_di], di
mov al, [byte es:di]
mov [Requested_Format], al
; Init return code
mov al, NULL
mov [Return_Code], al
; Save Current Dta
mov ah, DOS_GET_DTA ; Get Disk Transfer Area address
int DOS_SERVICE
mov [Old_Dta_Seg], es ; Save old Dta Segment Address
mov [Old_Dta_Ofs], bx ; Save old Dta Segment Offset
; Specify Own Dta
mov dx, offset Own_Dta ; Address of Own Dta
mov ah, DOS_SET_DTA
int DOS_SERVICE
;
; First entry in our map is always a pointer back to root = ..
;
mov es, [Parm_Dir_Map_ptr_es]
mov di, [Parm_Dir_Map_ptr_di]
mov si, offset Directory_Above_Text
mov cx, DIR_ENTRY_LENGTH
rep movsb
;
; The directory search is split up in 2 parts
; Skip the Files,
; Retrieve ALL Directories
;
mov [Dirs_In_Dir_Table], 1 ; First entry is ..
mov ds, [Parm_Path_Spec_ptr_es] ; Use specified search path
mov dx, [Parm_Path_Spec_ptr_di]
mov cx, [DOS_Find_Files_Or_Dirs] ; Is one or the other
xor ax, ax ; Reset ax
mov ah, DOS_FIND_FIRST_FILE ; Find First File
jmp @@20
; Retrieve dir entries
@@10:
mov cx, [DOS_Find_Files_Or_Dirs] ; Is one or the other
xor ax, ax ; Reset ax
mov ah, DOS_FIND_NEXT_FILE ; Find Next File
; Read VTOC
@@20:
int DOS_SERVICE ; Find First/Next Entry
jc @@50 ; No more Entries?
; Check for "." or ".." entry
mov si, offset Own_Dta.File_Name
; Load address of filename
cmp [byte ds:si], DOT ; Is this a ". " Entry?
je @@10 ; Retrieve next Entry
; Check Entry for being a directory entry
mov si, offset Own_Dta.File_Attribute
; Load address of attribute
xor ax, ax ; Reset ax
mov al, [byte ds:si] ; Load attribute
and al, ATTRIB_FILE_DIRECTORY
cmp al, ATTRIB_FILE_DIRECTORY ; Entry is a directory?
jne @@10 ; No
; Yes, so
;
; Move entry to our dir entry
;
; Init dir entry first
mov si, offset Dir_Map_Entry
push ds si
pop di es
mov cx, DIR_ENTRY_LENGTH
xor ax, ax
rep stosb
; Search the null terminator
mov si, offset Own_Dta.File_Name
push ds si
pop di es
mov cx, DIR_NAME_LENGTH ; Search length
inc cx
xor ax, ax ; Search for null character
repne scasb ; Search uses es:di
mov bx, cx
; File_Name
mov si, offset Dir_Map_Entry.File_Name
push ds si
pop di es
mov si, offset Own_Dta.File_Name
mov cx, DIR_NAME_LENGTH
sub cx, bx
rep movsb
cmp [Requested_Format], "1" ; DIRENTRY format?
je @@30 ; Yes
; No, so
;
; Replace remaining nulls from VTOC read by spaces
;
mov cx, bx
mov al, SPACE
rep stosb
;
;
; Format is ".. "
; "ATARI "
; etc.
;
mov si, offset Directory_Text
mov cx, DIRECTORY_TEXT_LENGTH
rep movsb
jmp @@40
@@30:
; File_Size
mov si, offset Dir_Map_Entry.File_Size
push ds si
pop di es
mov si, offset Own_Dta.File_Size
mov cx, 4
rep movsb
; File_Date
mov si, offset Dir_Map_Entry.File_Date
push ds si
pop di es
mov si, offset Own_Dta.File_Date
mov cx, 2
rep movsb
; File_Time
mov si, offset Dir_Map_Entry.File_Time
push ds si
pop di es
mov si, offset Own_Dta.File_Time
mov cx, 2
rep movsb
; File_Attribute
mov al, offset Own_Dta.File_Attribute
mov [offset Dir_Map_Entry.File_Attribute], al
@@40:
; Calculate location where to store the entry
mov ax, DIR_ENTRY_LENGTH
xor bx, bx
mov cx, [Dirs_In_Dir_Table]
xor dx, dx
mul cx
; Store Entry
mov cx, ax
mov es, [Parm_Dir_Map_ptr_es]
mov di, [Parm_Dir_Map_ptr_di]
add di, cx
mov si, offset Dir_Map_Entry
mov cx, DIR_ENTRY_LENGTH
rep movsb
; Increase Entry count
inc [Dirs_In_Dir_Table]
cmp [Dirs_In_Dir_Table], MAX_DIRS
; Max nr of Entries reached?
jne @@10 ; No
; Yes, so
@@50:
mov es, [Old_Dta_Seg] ; Restore old Dta Address
mov dx, [Old_Dta_Ofs]
mov ah, DOS_SET_DTA
int DOS_SERVICE
cmp [Dirs_In_Dir_Table], 0 ; Files found?
je @@90 ; No
; Yes, so
cmp [Dirs_In_Dir_Table], 1 ; Do we need to sort?
je @@99 ; No
; Yes, so
;
; Set up sort keys
;
mov si, offset Parm_SortKeys
push ds si
pop di es
mov ax, [Parm_Dir_Map_ptr_es]
mov bx, [Parm_Dir_Map_ptr_di]
mov [(SortKeys ptr di).Memory_Address_Hi], ax
mov [(SortKeys ptr di).Memory_Address_Lo], bx
mov ax, [Dirs_In_Dir_Table]
mov [(SortKeys ptr di).Record_Count], ax
mov [(SortKeys ptr di).Record_Size], DIR_ENTRY_LENGTH
mov [(SortKeys ptr di).Key_Count], 1
mov [(SortKeys ptr di).Key_1_Position], 1
mov [(SortKeys ptr di).Key_1_Size], DIR_NAME_LENGTH
mov [(SortKeys ptr di).Key_1_A_D], SORT_ASCENDING
;
; Bubble Sort Directories in alphabetic order
;
push es di
call MEMSORT
pop bx bx
@@90:
mov al, 1
mov [Return_Code], al
@@99:
ret
ENDP DC_DIRS
ENDS CSeg ; End of Code segment
END ; End of Program