; ****************************************************************************
; TRDOS386.ASM (TRDOS 386 Kernel - v2.0.0) - Directory Functions : trdosk4.s
; ----------------------------------------------------------------------------
; Last Update: 06/03/2016
; ----------------------------------------------------------------------------
; Beginning: 24/01/2016
; ----------------------------------------------------------------------------
; Assembler: NASM version 2.11 (trdos386.s)
; ----------------------------------------------------------------------------
; Derived from TRDOS Operating System v1.0 (8086) source code by Erdogan Tan
; DIR.ASM (09/10/2011)
; ****************************************************************************

; DIR.ASM  [ TRDOS KERNEL - COMMAND EXECUTER SECTION - DIRECTORY FUNCTIONS ]
; (c) 2004-2010  Erdogan TAN  [ 17/01/2004 ]  Last Update: 09/10/2011
; FILE.ASM [ FILE FUNCTIONS ] Last Update: 09/10/2011

change_prompt_dir_string:
	; 24/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 27/03/2011
	; 09/10/2009
	; INPUT/OUTPUT => none
	; this procedure changes current directory string/text  
	; 2005

	mov	edi, Current_Directory
	mov	ah, [Current_Dir_Level]
	mov	esi, PATH_Array
	call	set_current_directory_string
	mov	[Current_Dir_StrLen], cl

	retn

set_current_directory_string:
	; 24/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 27/03/2011
	; 09/10/2009
	; INPUT:
	;    ESI = Path Array Address 
	;    EDI = Current Directory String Buffer
	;    AH = Current Directory Level
	; OUTPUT => EAX, EBX, ESI will be changed
	;    EDI will be same with input
	;    ECX = Current Directory String Length 

	push    edi
	cmp     ah, 0
	jna	short pass_write_path
	add	esi, 16
	mov	ebx, esi
loc_write_path:
	mov	ecx, 8
path_write_dirname1:
	lodsb
	cmp	al, 20h
	jna	short pass_write_dirname1
	stosb
	cmp	edi, End_Of_Current_Dir_Str
	jnb	short pass_write_path
	loop	path_write_dirname1
	cmp	byte [esi], 20h
	jna	short pass_write_dirname2
	jmp     short loc_put_dot_cont_ext
pass_write_dirname1:
	mov	esi, ebx
	add	esi, 8
	cmp	byte [esi], 20h
	jna	short pass_write_dirname2
loc_put_dot_cont_ext:
	mov	byte [edi], "."
	;mov	ecx, 3
	mov	cl, 3
loc_check_dir_name_ext:
	lodsb
	inc	edi
	cmp	al, 20h
	jna	short pass_write_dirname2
	mov	[edi], al
	cmp	edi, End_Of_Current_Dir_Str
	jnb	short pass_write_path
	loop    loc_check_dir_name_ext
	inc	edi
pass_write_dirname2:
	dec	ah
	jz      short pass_write_path
	add	ebx, 16
	mov	esi, ebx
	mov	byte [edi],"/"
	inc	edi
	jmp	short loc_write_path
pass_write_path:
	mov	byte [edi], 0
	inc	edi
	mov	ecx, edi
	pop	edi
	sub	ecx, edi
	; ECX = Current Directory String Length
	retn

get_current_directory:
	; 14/02/2016
	; 24/01/2016 (TRDOS 386 = TRDOS v2.0)
	; 27/03/2011
	;
	; INPUT-> ESI = Current Directory Buffer
	;         DL = TRDOS Logical Dos Drive Number + 1
	;              (0= Default/Current Drive)
	;           
	;   Note: Required dir buffer length may be <= 92 bytes
	;         for TRDOS (7*12 name chars + 7 slash + 0)
	; OUTPUT ->  ESI = Current Directory Buffer
	;            EAX, EBX, ECX, EDX, EDI will be changed
	;            CX/CL = Current Directory String Length
	;	     DL = Drive Number (0 based)
	;            (If input is 0, output is current drv number) 
	;            DH = same with input 
	;   cf = 0 -> AL = 0
	;   cf = 1 -> error code in AL 
              
loc_get_current_drive_0:
	cmp	dl, 0
	ja	short loc_get_current_drive_1
	mov	dl, [Current_Drv]
	jmp	short loc_get_current_drive_2
loc_get_current_drive_1:
	dec 	dl
	cmp	dl, [Last_DOS_DiskNo]
	jna	short loc_get_current_drive_2
	mov	eax, 0Fh ; Invalid drive
	cmc 	; stc
	retn

loc_get_current_drive_not_ready_retn:
	pop	esi
	;mov	eax, 15h
	mov	ax, 15h ; Drive not ready
	retn  
 
loc_get_current_drive_2:
	xor	eax, eax
	mov	ah, dl
	push	esi
	mov	esi, Logical_DOSDisks
	add	esi, eax
	mov	al, [esi+LD_Name] 
	cmp	al, 'A'
	jb	short loc_get_current_drive_not_ready_retn

	mov	ah, [esi+LD_CDirLevel]
	or	ah, ah
	jnz	short loc_get_current_drive_3

	;xor	ah, ah ; mov ah, 0
	mov	[esi], ah
	xor	ecx, ecx
	jmp	short loc_get_current_drive_4

loc_get_current_drive_3:
        mov     edi, PATH_Array
	push	edi
	add	esi, LD_CurrentDirectory
	mov	ecx, 32
	rep	movsd
	pop	esi ; Path Array Address
	pop	edi ; pushed esi (current dir buffer offset) 
	;
	call	set_current_directory_string
	mov	esi, edi

loc_get_current_drive_4:
	xor	al, al
	retn

change_current_directory:
	; 19/02/2016
	; 11/02/2016
	; 10/02/2016
	; 08/02/2016
	; 06/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 18/09/2011 (DIR.ASM, 09/10/2011)	
	; 04/10/2009
	; 2005
	; INPUT -> 
	;	ESI = Directory string
	;	ah = CD command (CDh = save current dir string)
	; OUTPUT -> 
	; 	EDI = DOS Drive Description Table
	; 	cf = 1 -> error
	;	   EAX = Error code
	;	cf = 0 -> succesful
	;	   ESI = PATH_Array
	;	   EAX = Current Directory First Cluster
	;
	; (EAX, EBX, ECX, EDX, ESI, EDI will be changed)
	
	mov	[CD_COMMAND], ah
	cmp	byte [esi], '/'
	jne	short loc_ccd_cdir_level
	inc	esi
	xor	al, al
	jmp	short loc_ccd_parse_path_name
loc_ccd_cdir_level:
	mov	al, [Current_Dir_Level]
loc_ccd_parse_path_name:
	mov	ah, al
	mov	edi, PATH_Array

; Reset directory levels > cdir level
	; is this required !?
	;
	; Relations:
	; MAINPROG.ASM (pass_ccdrv_reset_cdir_FAT_fcluster)
	; proc_parse_dir_name,
	; proc_change_current_directory (this procedure)
	; proc_change_prompt_dir_string 
 
	movzx	ecx, al
	inc	cl
	shl	cl, 4
	add	edi, ecx
	mov	cl, 7
	sub	cl, al
	shl	cl, 2
	mov	ebx, eax
	xor	eax, eax ; 0
	rep	stosd
	mov	eax, ebx

	mov	edi, PATH_Array

	cmp	byte [esi], 20h
	cmc
	jnc	short pass_ccd_parse_dir_name

		; ESI = Path name
		; AL = CCD_Level
        call    parse_dir_name
		; AL = CCD_Level 
		; AH = Last_Dir_Level
		; (EDI = PATH_Array)

pass_ccd_parse_dir_name:
	pushf

	;mov	[CCD_Level], al
        ;mov	[Last_Dir_Level], ah
	mov	[CCD_Level], ax

	xor	ebx, ebx
	mov	bh, [Current_Drv]
	mov	esi, Logical_DOSDisks
	add	esi, ebx

	popf 
	jc	short loc_ccd_bad_path_name_retn

	mov	[CCD_DriveDT], esi

	cmp	al, 7
	jb	short loc_ccd_load_child_dir

loc_ccd_bad_path_name_retn:
	xchg	esi, edi
	; DOS Error Code 
	mov	eax, 18h ; Bad request structure length 
	stc
loc_ccd_retn_p:
	retn

loc_ccd_load_child_dir:
	; AL = CCD_Level
	or	al, al
	jz	short loc_ccd_load_root_dir

	mov	cx, ax
	shl	al, 4
	movzx	esi, al
     	add	esi, edi  ; offset PATH_Array

	mov	eax, [esi+12]
	cmp	cl, ch
        je      loc_ccd_load_sub_directory
	mov	[Current_Dir_FCluster], eax

loc_ccd_load_child_dir_next:
	add	esi, 16 ; DOS DirEntry Format FileName Address

 	; Directory attribute : 10h
	mov	al, 00010000b ; 10h (Attrib AND mask)
	;mov	ah, 11001000b ; C8h
	; Volume name attribute: 8h
	mov	ah, 00001000b ; 08h (Attrib NAND, AND --> zero mask)

	xor	cx, cx  
	call	locate_current_dir_file
	jnc	short loc_ccd_set_dir_cluster_ptr

	 ; 19/02/2016
	;mov	edi, [CCD_DriveDT]
	mov	ah, [CCD_Level]
	cmp	byte [CD_COMMAND], 0CDh ;'CD' command or another
	jne	short loc_ccd_load_child_dir_err
	; It is better to save recent successful part 
	; of the (requested) path as current directory.
	; (Otherwise the path would be reset to back
	; on the next 'CD' command.)
	mov	cl, ah
	push	eax
	call	loc_ccd_save_current_dir
	pop	eax
loc_ccd_load_child_dir_err:            
	cmp	al, 3	; AL = 2 => File not found error
	jb	short loc_ccd_path_not_found_retn
	stc
	retn

loc_ccd_path_not_found_retn:
	mov	al, 3	; Path not found
	retn

loc_ccd_load_FAT_root_dir:
	cmp	byte [Current_FATType], 2
	ja	short loc_ccd_load_FAT32_root_dir

	;mov	esi, [CCD_DriveDT]
	;push	esi
	call	load_FAT_root_directory
	;pop	edi ; Dos Drv Description Table

	mov	edi, esi
	mov	esi, PATH_Array
	jc	short loc_ccd_retn_p

	xor	eax, eax
        jmp	short loc_ccd_set_cdfc

loc_ccd_load_root_dir:
	cmp	byte [Current_FATType], 1
	jnb	short loc_ccd_load_FAT_root_dir

loc_ccd_load_FS_root_dir:
	call	load_FS_root_directory
	jmp	short pass_ccd_load_FAT_sub_directory

loc_ccd_load_FS_sub_directory_next:
	call	load_FS_sub_directory
	jmp	short pass_ccd_set_dir_cluster_ptr  

loc_ccd_set_dir_cluster_ptr:
	; EDI = Directory Entry
	mov	ax, [edi+20] ; First Cluster High Word
	shl	eax, 16
	mov	ax, [edi+26] ; First Cluster Low Word

	mov	esi, [CCD_DriveDT]
	cmp	byte [Current_FATType], 1
	jb	short loc_ccd_load_FS_sub_directory_next
	;push	esi
	call	load_FAT_sub_directory
	;pop	edi ; Dos Drv Description Table

pass_ccd_set_dir_cluster_ptr:
	;mov	edi, esi
	mov	esi, PATH_Array
	jc	short loc_ccd_retn_c

	mov	eax, [DirBuff_Cluster]

	inc	byte [CCD_Level]
	movzx	ebx, byte [CCD_Level]
	shl	bl, 4 ; * 16 (<= 128)   
	add	esi, ebx ; 19/02/2016
	mov	[esi+12], eax
	jmp	short loc_ccd_set_cdfc

loc_ccd_load_FAT32_root_dir:
	mov	esi, PATH_Array
	mov	eax, [esi+12]
	mov	esi, [CCD_DriveDT]
 
loc_ccd_load_FAT_sub_directory:
	;push	esi
	call	load_FAT_sub_directory
	;pop	edi ; Dos Drv Description Table

pass_ccd_load_FAT_sub_directory:
	;mov	edi, esi
	mov	esi, PATH_Array
	jc	short loc_ccd_retn_c

	mov	eax, [DirBuff_Cluster]

loc_ccd_set_cdfc:
	mov	cl, [CCD_Level]
	mov	[Current_Dir_Level], cl
	mov	[Current_Dir_FCluster], eax

	mov	ch, [Last_Dir_Level]
	cmp	cl, ch 
	jb	loc_ccd_load_child_dir_next
	
	cmp	byte [CD_COMMAND], 0CDh ;'CD' command or another
	je	short loc_ccd_save_current_dir

        ; jne -> don't save, restore (the previous cdir) later !
        ; (saving the cdir would prevent previous cdir restoration!)

	clc

loc_ccd_retn_c:
	mov	edi, [CCD_DriveDT]
	retn

loc_ccd_load_sub_directory:
	mov	esi, [CCD_DriveDT]
	cmp	byte [Current_FATType], 1
	jnb	short loc_ccd_load_FAT_sub_directory 
	call	load_FS_sub_directory
	jmp	short pass_ccd_load_FAT_sub_directory 

loc_ccd_save_current_dir:
	mov	esi, PATH_Array ; 19/02/2016
	mov	edi, [CCD_DriveDT]
	push	edi
        add     edi, LD_CDirLevel
	mov	[edi], cl
	inc	edi ; LD_CurrentDirectory 
	push	esi
	;mov	ecx, 32  ; always < 65536 (in this procedure)
	mov	cx, 32
	rep	movsd
	; Current directory has been saved to 
	; the DOS drive description table, cdir area !
	pop	esi  ; PATH_Array
	pop	edi  ; Dos Drv Description Table

	retn

parse_dir_name:
	; 11/02/2016
	; 10/02/2016
	; 07/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 18/09/2011
	; 17/10/2009
	; INPUT ->
	;	ESI = ASCIIZ Directory String Address
	;	AL = Current Directory Level
	;	EDI = Destination Adress
	;	     (8 levels, each one 12+4 byte)
	; OUTPUT ->
	;	EDI = Dir Entry Formatted Array
	;	     with zero cluster pointer at the last level
	;	AH = Last Dir Level
	;	AL = Current Dir Level
	;
	; (esi, ebx, ecx will be changed) 

	;mov	[PATH_Array_Ptr], edi
	mov	ah, al
	mov	[PATH_CDLevel], ax
repeat_ppdn_check_slash:
	lodsb
	cmp	al, '/'
	je	short repeat_ppdn_check_slash
	cmp	al, 21h
	jb	short loc_ppdn_retn
	push	edi
loc_ppdn_get_dir_name:
	mov	ecx, 12
	mov	edi, Dir_File_Name
repeat_ppdn_get_dir_name:
	stosb
	lodsb
	cmp	al, '/'
	je	short loc_check_level_dot_conv_dir_name
	cmp	al, 20h
	jna	short loc_ppdn_end_of_path_scan
	loop	repeat_ppdn_get_dir_name
	pop	edi
	stc
loc_ppdn_retn:
	retn

loc_ppdn_end_of_path_scan:
	dec	esi
loc_check_level_dot_conv_dir_name:
	xor	eax, eax
	stosb
	mov	ebx, esi
	mov	esi, Dir_File_Name
	lodsb
repeat_ppdn_name_check_dot:
	cmp	al, '.'
	jne	short loc_ppdn_convert_sub_dir_name
repeat_ppdn_name_dot_dot:
	lodsb
	cmp	al, '.'
	je	short loc_ppdn_dot_dot
	cmp	al, 21h
	jb	short pass_ppdn_convert_sub_dir_name
loc_ppdn_convert_sub_dir_name:
	mov	ah, [PATH_Level]
	cmp	ah, 7
	jnb	short pass_ppdn_convert_sub_dir_name
	inc	ah  
	mov	[PATH_Level], ah
	mov	esi, Dir_File_Name
	;mov	edi, [PATH_Array_Ptr]
	mov	al, 16
	mul	ah
	mov	edi, [esp]
	;push	edi 
	add	edi, eax
	call	convert_file_name
	;pop	edi
pass_ppdn_convert_sub_dir_name:
	mov	esi, ebx
repeat_ppdn_check_last_slash:
	lodsb
	cmp	al, '/'
	je	short repeat_ppdn_check_last_slash
	cmp	al, 21h
	jnb	short loc_ppdn_get_dir_name
end_of_parse_dir_name:
	pop	edi
	cmc  
	;mov	al, [PATH_CDLevel]
	;mov	ah, [PATH_Level]
	mov	ax, [PATH_CDLevel]
	retn

loc_ppdn_dot_dot:
	lodsb
	cmp	al, 21h
	jnb	short end_of_parse_dir_name 
loc_ppdn_dot_dot_prev_level:
	mov	ax, [PATH_CDLevel]
	sub	ah, 1
	adc	ah, 0
	cmp	al, ah
	jna	short pass_ppdn_set_al_to_ah
	mov	al, ah
pass_ppdn_set_al_to_ah:
	mov	[PATH_CDLevel], ax
	jmp	short pass_ppdn_convert_sub_dir_name

locate_current_dir_file:
	; 14/02/2016
	; 13/02/2016
	; 10/02/2016
	; 06/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 14/08/2010
	; 19/09/2009
        ; 2005
	; INPUT ->
	;	ESI = DOS DirEntry Format FileName Address
	;	AL = Attributes Mask 
	;	(<AL AND EntryAttrib> must be equal to AL)
	;	AH = Negative Attributes Mask (If AH>0)
	;	(<AH AND EntryAttrib> must be ZERO)
	;	CH > 0 Find First Free Dir Entry or Deleted Entry
	;	CL = 0 -> Return the First Free Dir Entry
	;	CL = E5h -> Return the 1st deleted entry
	;	CL = FFh -> Return the 1st deleted or free entry
	;	CL > 0 and CL <> E5h and CL <> FFh -> Return the first 
	;	     proper entry (which fits with Atributes Masks)
	;	CX = 0 Find Valid File/Directory/VolumeName
	;	? = Any One Char
	;	* = Every Chars
	; OUTPUT ->
	;	EDI = Directory Entry Address (in Directory Buffer)
	;	ESI = DOS DirEntry Format FileName Address
	;	CF = 0 -> No Error, Proper Entry,
	;	DL = Attributes
	;	DH = Previous Entry Attr (LongName Check)
	;	AL > 0 -> Ambiguous filename wildcard "?" used
	;	AH > 0 -> Ambiguous filename wildcard "*" used
	;	AX = 0 -> Filename full fits with directory entry
	;	CH = The 1st Name Char of Current Dir Entry
	;	CF = 1 -> Proper entry not found, Error Code in EAX/AL
	;	CL = 0 and CH = 0 -> Free Entry (End Of Dir)
	;	CL = 0 and CH = E5h -> Deleted Entry fits with filters
	;	CL > 0 -> Entry not found, CH invalid
	;	CF = 0 -> 
	;	EBX = Current Directory Entry Index/Number (BX)

	;mov	word [DirBuff_EntryCounter], 0 ; Zero Based

	mov	[CDLF_FNAddress], esi
	mov	[CDLF_AttributesMask], ax
	mov	[CDLF_DEType], cx

	xor	ebx, ebx
	mov	[PreviousAttr], bl ; 0  ; 13/02/2016

	mov	bh, [Current_Drv]
	cmp	byte [DirBuff_ValidData], bl ; 0
	jna	short loc_lcdf_reload_current_dir2
        mov     bl, [DirBuff_DRV]
	sub	bl, 'A'
	cmp	bh, bl
	jne	short loc_lcdf_reload_current_dir1
	mov	edx, [DirBuff_Cluster]
	cmp	edx, [Current_Dir_FCluster]
	je	short loc_cdir_locatefile_search

loc_lcdf_reload_current_dir1:
	xor	bl, bl
loc_lcdf_reload_current_dir2:
	mov	esi, ebx
        add     esi, Logical_DOSDisks
	call	reload_current_directory 
	jnc	short loc_locatefile_search_again 
	retn  

loc_cdir_locatefile_search:
	xor	ebx, ebx
	call	find_directory_entry
	jnc	short loc_cdir_locate_file_retn

loc_locatefile_check_stc_reason:
	or	ch, ch
	jz	short loc_cdir_locate_file_stc_retn

loc_locatefile_check_next_entryblock:
	mov	bh, [Current_Drv]
	sub	bl, bl
	movzx	esi, bx
        add     esi, Logical_DOSDisks

	cmp	byte [Current_Dir_Level], 0
	jna	short loc_locatefile_check_FAT_type
            
	cmp	byte [Current_FATType], 1
	jnb	short loc_locatefile_load_subdir_cluster
	retn  

loc_locatefile_check_FAT_type:
	cmp	byte [Current_FATType], 3
	jb	short loc_cdir_locate_file_retn

loc_locatefile_load_subdir_cluster:
	mov	eax, [DirBuff_Cluster]
	call	get_next_cluster
	jnc	short loc_locatefile_next_cluster
	or	eax, eax
	jnz	short loc_locatefile_drive_not_ready_read_err
	stc
loc_locatefile_file_notfound:
	mov	eax, 2 ; File/Directory/VolName not found
	retn

loc_locatefile_drive_not_ready_read_err:
	;mov	eax, 15h ;Drive not ready or read error
loc_cdir_locate_file_stc_retn:
	cmc ;stc
loc_cdir_locate_file_retn:
	retn

loc_locatefile_next_cluster:
	call	load_FAT_sub_directory
	;jc	short loc_locatefile_drive_not_ready_read_err
	jc	short loc_cdir_locate_file_retn 

loc_locatefile_search_again:
	mov	esi, [CDLF_FNAddress] 
	mov	ax, [CDLF_AttributesMask]
	mov	cx, [CDLF_DEType] 
	jmp	short loc_cdir_locatefile_search

reload_current_directory:
	; 06/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 13/06/2010
	; 22/09/2009
        ;
	; INPUT ->
	;	ESI = Dos drive description table address
	
	;mov	al, [esi+LD_FATType]
	mov	al, [Current_FATType]
	cmp	al, 2
	ja	short loc_reload_FAT_sub_directory
	mov	ah, [Current_Dir_Level]
	or	al, al
	jz	short loc_reload_FS_directory
	or	ah, ah
	jnz	short loc_reload_FAT_sub_directory
loc_reload_FAT_12_16_root_directory:
	call	load_FAT_root_directory
	retn
loc_reload_FS_directory:
	and	ah, ah
	jnz	short loc_reload_FS_sub_directory 
loc_reload_FS_root_directory: 
	call	load_FS_root_directory
	retn
loc_reload_FS_sub_directory:
	mov	eax, [Current_Dir_FCluster]
	call	load_FS_sub_directory
	retn 
loc_reload_FAT_sub_directory:
	mov	eax, [Current_Dir_FCluster]
	call	load_FAT_sub_directory
	retn

find_directory_entry:
	; 14/02/2016
	; 13/02/2016
	; 10/02/2016
	; 06/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 14/08/2010 (DIR.ASM, "proc_find_direntry")
	; 19/09/2009
	; 2005
	; INPUT ->
	;	ESI = Sub Dir or File Name Address
	;	AL = Attributes Mask 
	;	(<AL AND EntryAttrib> must be equal to AL)
	;	AH = Negative Attributes Mask (If AH>0)
	;	(<AH AND EntryAttrib> must be ZERO)
	;	CH > 0 Find First Free Dir Entry or Deleted Entry
	;	CL = 0 -> Return the First Free Dir Entry
	;	CL = E5h -> Return the 1st deleted entry
	;	CL = FFh -> Return the 1st deleted or free entry
	;	CL > 0 and CL <> E5h and CL <> FFh -> Return the first 
	;            proper entry (which fits with Atributes Masks)
	;	CX = 0 -> Find Valid File/Directory/VolumeName
	;	? = Any One Char
	;	* = Every Chars
	;	EBX = Current Dir Entry (BX)
	;
	; OUTPUT -> 
	;	EDI = Directory Entry Address (in DirectoryBuffer)
	;	ESI = Sub Dir or File Name Address
	;	CF = 0 -> No Error, Proper Entry,
	;	DL = Attributes
	;	DH = Previous Entry Attr (LongName Check)
	;	AL > 0 -> Ambiguous filename wildcard "?" used
	;	AH > 0 -> Ambiguous filename wildcard "*" used
	;	AX = 0 -> Filename full fits with directory entry
	;	EBX = CurrentDirEntry (BX)
	;	CH = The 1st Name Char of Current Dir Entry
	;	CF = 1 -> Proper entry not found, Error Code in AX/AL
	;	CL = 0 and CH = 0 -> Free Entry (End Of Dir)
	;	CL = 0 and CH = E5h -> Deleted Entry fits with filters
	;	CL > 0 -> Entry not found, CH invalid
	;
	; (EAX, EBX, ECX, EDX, EDI, EBP will be changed)	 

	cmp	bx, [DirBuff_LastEntry]
        ja      loc_ffde_stc_retn_255

	;mov    [DirBuff_CurrentEntry], bx  

  	mov	edi, Directory_Buffer
	mov	[FDE_AttrMask], ax

	sub	eax, eax
            
	;;mov	[PreviousAttr], al ; 0 ;; 13/02/2016
	mov	[AmbiguousFileName], ax ; 0

	mov	ax, bx
	shl	ax, 5 ; ; * 32 ; Directory entry size
	add     edi, eax

	or	ch, ch
        jnz     loc_find_free_deleted_entry_0

	or      cl, cl
        jnz     loc_ffde_stc_retn_255
 
check_find_dir_entry:
	mov	ax, [FDE_AttrMask]
	mov	ch, [edi]
	cmp     ch, 0 ; Is it never used entry?
	jna	loc_find_direntry_stc_retn 
	push	esi
	mov	dl, [edi+0Bh] ; File attributes
	cmp	ch, 0E5h ; Is it a deleted file?
	je	short loc_find_dir_next_entry_prevdeleted

	cmp     dl, 0Fh ; longname sub component check
	jne     short loc_check_attributes_mask
	call	save_longname_sub_component

loc_check_attributes_mask:
	mov	dh, al
	and	dh, dl    
	cmp	al, dh
        jne     loc_find_dir_next_entry
	and	ah, dl
        jnz     loc_find_dir_next_entry
	cmp	dl, 0Fh
	jne	short pass_direntry_attr_check

	cmp	al, 0Fh ; AL = 0Fh -> find long name
        jne     loc_find_dir_next_entry

	pop	esi
	xor	ax, ax
	mov	dh, [PreviousAttr]
	mov	[DirBuff_CurrentEntry], bx
	retn

pass_direntry_attr_check:
	mov	ebp, edi ; 14/02/2016
	mov	ecx, 8
loc_lodsb_find_dir:
	lodsb
	cmp	al, '*'
	jne	short pass_fde_ambiguous1_check
        inc     byte [AmbiguousFileName+1]
	jmp	short loc_check_direntry_extension

pass_fde_ambiguous1_check:
	cmp	al, '?'
	jne	short pass_fde_ambiguous2_check
	inc	byte [AmbiguousFileName]
	cmp	byte [edi], 20h
	jna	short loc_find_dir_next_entry_ebp
	jmp	short loc_scasb_find_dir_inc_di

pass_fde_ambiguous2_check:
	cmp	al, 20h
	jne	short loc_scasb_find_dir
	cmp	byte [edi], 20h
	jne	short loc_find_dir_next_entry_ebp
	jmp	short loc_check_direntry_extension

loc_find_dir_next_entry_prevdeleted:
	or	dl, 80h  ; Bit 7 -> deleted entry sign
	jmp	short loc_find_dir_next_entry

loc_scasb_find_dir:
	cmp	al, [edi]
	jne	short loc_find_dir_next_entry_ebp
loc_scasb_find_dir_inc_di:
	inc	edi
	loop	loc_lodsb_find_dir

loc_check_direntry_extension:
	mov	esi, 8
	mov	edi, esi ; 8
	add	esi, [esp] ; Sub Dir or File Name Address
	add	edi, ebp
	mov	cl, 3
loc_lodsb_find_dir_ext:
	lodsb
	cmp	al, '*'
	jne	short pass_fde_ambiguous3_check
	inc	byte [AmbiguousFileName+1]
	jmp	short loc_find_dir_proper_direntry

pass_fde_ambiguous3_check:
	cmp	al, '?'
	jne	short pass_fde_ambiguous4_check
	inc	byte [AmbiguousFileName]
	cmp	byte [edi], 20h
	jna	short loc_find_dir_next_entry_ebp
	jmp	short loc_scasb_find_dir_ext_inc_di

pass_fde_ambiguous4_check:
	cmp	al, 20h
	jne	short loc_scasb_find_dir_ext
	cmp	byte [edi], 20h
	je	short loc_find_dir_proper_direntry

loc_find_dir_next_entry_ebp:
	mov	edi, ebp ; 14/02/2016
	jmp	short loc_find_dir_next_entry

loc_find_dir_proper_direntry:
	xor	cl, cl
loc_find_dir_proper_direntry_1:
	pop	esi
        mov     edi, ebp
	mov	ch, [edi]
	mov     dl, [edi+0Bh] ; Dir entry attributes
	mov	ax, [AmbiguousFileName]
loc_find_dir_proper_direntry_2:
	mov     dh, [PreviousAttr]
	mov	[DirBuff_CurrentEntry], bx
	retn

loc_find_dir_next_entry:
	mov	byte [PreviousAttr], dl ; LongName check
loc_find_dir_next_entry_1:
	pop	esi
	add	edi, 32
	;inc	word [DirBuff_EntryCounter]
	inc	bx
	cmp	bx, [DirBuff_LastEntry]
	ja	short loc_ffde_stc_retn_255
        jmp     check_find_dir_entry 

loc_scasb_find_dir_ext:
	cmp	al, [edi]
	jne	short loc_find_dir_next_entry_ebp
loc_scasb_find_dir_ext_inc_di:
	inc	edi
	loop    loc_lodsb_find_dir_ext
	jmp	short loc_find_dir_proper_direntry_1

loc_ffde_stc_retn_255:
	;mov	cx, 0FFFFh
	xor	ecx, ecx
	dec	ecx ; 0FFFFFFFFh
	;xor	eax, eax
loc_find_direntry_stc_retn:
loc_check_ffde_retn_1:
	;mov	ax, 2
	mov	eax, 2 ; File Not Found
	mov	dh, [PreviousAttr]
	mov	[DirBuff_CurrentEntry], bx
	stc
	retn

loc_find_free_deleted_entry_0:
	mov	ax, [FDE_AttrMask]
	mov	ch, [edi]
	mov	dl, [edi+0Bh] ; File attributes
	or	cl, cl 
	jz	short loc_check_ffde_0_repeat
	;cmp	cl, 0E5h
	;je	short pass_loc_check_ffde_0_err
	cmp	cl, 0FFh
	je	short loc_find_free_deleted_entry_1
	jmp	short pass_loc_check_ffde_0_err

loc_check_ffde_0_repeat:
	or	ch, ch
	jnz	short loc_check_ffde_0_next

loc_check_ffde_retn_2:
	sub	ax, ax
	mov	dh, [PreviousAttr]
	mov	[DirBuff_CurrentEntry], bx
	retn
 
loc_check_ffde_0_next:
	inc	bx
	add	edi, 32
	;inc	word [DirBuff_EntryCounter]
	 
        cmp	bx, [DirBuff_LastEntry]
	ja	short loc_ffde_stc_retn_255
	mov	[PreviousAttr], dl
	mov	ch, [edi]
	mov	dl, [edi+0Bh] ; file attributes
	jmp	short loc_check_ffde_0_repeat

loc_find_free_deleted_entry_1:
	sub	dl, dl      
loc_find_free_deleted_entry_2:
	and	ch, ch  
	jz	short loc_check_ffde_retn_2
	cmp	ch, 0E5h
	je	short loc_check_ffde_retn_2
	inc	bx
	add	edi, 32
	cmp	bx, [DirBuff_LastEntry]
	ja	short loc_ffde_stc_retn_255
	mov	ch, [edi]
	jmp	short loc_find_free_deleted_entry_2

pass_loc_check_ffde_0_err:
	cmp	ch, cl
	je	short loc_check_ffde_attrib 

	inc	bx
	add	edi, 32
	cmp	bx, [DirBuff_LastEntry]
        ja      loc_ffde_stc_retn_255
	mov	[PreviousAttr], dl
	mov	ch, [edi]
	mov	dl, [edi+0Bh]
	jmp	short pass_loc_check_ffde_0_err

loc_check_ffde_attrib:
	mov	dh, al
	and	dh, dl    
	cmp	al, dh
	jne	short loc_check_ffde_0_next
	and	ah, dl
	jnz	short loc_check_ffde_0_next
	xor	cl, cl 
        jmp     loc_check_ffde_retn_2

convert_file_name:
	; 06/03/2016
	; 11/02/2016
	; 07/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 06/10/2009
	; 2005
	;
	; INPUT  ->
	;	ESI = Dot File Name Location
	;	EDI = Dir Entry Format File Name Location
	; OUTPUT ->
	;	EDI = Dir Entry Format File Name Location
	;	ESI = Dot File Name Location (capitalized)
	;
	; (ECX, AL will be changed) 
     
	push	esi  
	push	edi

	mov	ecx, 11
	mov	al, 20h
	rep	stosb

	mov	edi, [esp]

	mov	cl, 12 ; file name length (max.)
	; 06/03/2016
	; Directory entry name limit (11 bytes) check for
	; 'rename_directory_entry' procedure.
	; (EDI points to Directory Entry)
	; (If the file name would not contain a dot
	; and file name length would be 12, this would cause to
	; overwrite the attributes byte of the directory entry.)
	;
	mov	ch, 11 ; directory entry's name length
loc_check_first_dot:
	mov	al, [esi]
	cmp	al, 2Eh
	jne	short pass_check_first_dot
	mov	[edi], al
	inc	edi
	inc	esi
	dec	cl
	jnz	short loc_check_first_dot
	;;(ecx <= 12)
	;;loop	loc_check_first_dot 
	jmp	short stop_convert_file

loc_get_fchar:
	mov	al, [esi]
pass_check_first_dot:
	cmp	al, 61h ; 'a'
	jb	short pass_name_capitalize
	cmp	al, 7Ah ; 'z'
	ja	short pass_name_capitalize
	and	al, 0DFh
	mov	[esi], al
pass_name_capitalize:
	cmp	al, 21h
	jb	short stop_convert_file
	cmp	al, 2Eh ; '.'
	jne	short pass_dot_space
add_dot_space: 
	cmp	cl, 4
	jna	short inc_and_loop
	inc	edi
	dec	ch ; 06/03/2016
	dec	cl
	jmp	short add_dot_space
	
	;mov	al, 4
	;cmp	cl, al
	;jna	short inc_and_loop
	;sub	cl, al
	;add	edi, ecx
	;mov	cl, al
	;jmp	short inc_and_loop	

pass_dot_space:
	mov	[edi], al
loc_after_double_dot:
	; 06/03/2016
	dec	ch ; count down for 11 bytes dir entry limit
	jz	short stop_convert_file_x
	inc	edi
inc_and_loop:
	dec	cl ; count down for 12 bytes filename limit 
	jz	short stop_convert_file	
	inc	esi
	;;(ecx <= 12)
	;;loop	loc_get_fchar
	jmp	short loc_get_fchar

stop_convert_file:
	; 06/03/2016
	xor	ch, ch
	; ECX < 256 ; 'find_first_file' -> xor cl, cl
stop_convert_file_x:
	pop	edi
	pop	esi
	retn
 
save_longname_sub_component:
	; 13/02/2016
	; 06/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 28/02/2010
	; 17/10/2009
	; INPUT ->
	;	EDI = Directory Entry    
	;     	// This procedure is called
	;	// from 'find_directory_entry' procedure.
	;	// If the last entry returns with
	;	// a non-zero LongnameFound value and
	;	// if LFN_CheckSum value is equal to
	;	// the next shortname checksum,
	;	// long name is valid.
	;	// If a longname is longer than 65 bytes,
	;	// it is invalid for trdos. (>45h)
 
	push	edi
	push	esi
	;push	ebx
	;push	ecx
	;push	edx
	push	eax
           
	sub	ecx, ecx
	;sub	eax, eax
	mov	cl, 26

	movzx	eax, byte [edi] ; LDIR_Order
	cmp	al, 41h  ; 40h (last long entry sign) + 1
	jb	short pass_pslnsc_last_long_entry

	mov	ah, al
	sub	ah, 40h
	mov	[LFN_EntryLength], ah
	
	cmp	al, 45h  ; 40h (last long entry sign) + 5
 		; Max 130 byte length is usable in TRDOS
; 26*5 = 130
	ja	short loc_pslnsc_retn

	and	al, 07h ; 0Fh
	mov	[LongNameFound], al

	dec	al
	;mov	cl, 26
	mul	cl

	mov	esi, eax
	add	esi, ecx
		; to make is an ASCIZZ string
		; with ax+26 bytes length
	add	esi, LongFileName
	mov	word [esi], 0   
	jmp	short loc_pslsc_move_ldir_name2 

pass_pslnsc_last_long_entry:
	cmp	al, 04h
	ja	short loc_pslnsc_retn
	dec	byte [LongNameFound]
	cmp	al, [LongNameFound]
	jne	short loc_pslnsc_retn

loc_pslsc_move_ldir_name1:
	dec	al
	;mov	cl, 26
	mul	cl

loc_pslsc_move_ldir_name2:
	mov	cl, [edi+0Dh] ; long name checksum
	mov	[LFN_CheckSum], cl 
	mov	esi, edi ; LDIR_Order
	mov	edi, LongFileName
	add	edi, eax
	inc	esi
	mov	cl, 5 ; chars 1 to 5
	rep	movsw
	add	esi, 3
	movsd	; char 6 & 7 
	movsd	; char 8 & 9
	movsd	; char 10 & 11
	inc	esi
	inc	esi 
	movsd   ; char 12 & 13 

loc_pslnsc_retn:
 	pop	eax
	;pop	edx
	;pop	ecx
	;pop	ebx
	pop	esi  
	pop	edi
 
    	retn

parse_path_name:
	; 10/02/2016
	; 08/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 10/009/2011 ('proc_parse_pathname')
	; 27/11/2009
	; 05/12/2004
	;
	; INPUT ->
	;	ESI = Beginning of ASCIIZ pathname string
	;       EDI = Destination Address
	;	      (which is TR-DOS FindFile data buffer)
	; OUTPUT ->
	;	CF = 1 -> Error
	;	     EAX = Error Code (AL)
	;
	; (Modified registers: eax, ecx, esi, edi) 
	
	; Clear the pathname bytes in TR-DOS Findfile data buffer 
	push	edi
	mov	ecx, 20  ; 80 bytes
	xor	eax, eax
	rep	stosd 
	pop	edi

	mov	ax, [esi]
	cmp	ah, ':'
	je	short loc_ppn_change_drive
	mov	al, [Current_Drv]
	jmp	short pass_ppn_change_drive

pass_ppn_cdir:
	mov	esi, [First_Path_Pos]
	lodsb
loc_ppn_get_filename:
	add	edi, 65 ; FindFile_Name location
	; TRDOS Filename length must not be more than 12 bytes
	;mov	ecx, 12
	mov	cl, 12
loc_ppn_get_fnchar_next:
	stosb
	lodsb
	cmp	al, 21h
	jb	short loc_ppn_clc_return 
        loop    loc_ppn_get_fnchar_next
loc_ppn_return:
	retn

loc_ppn_change_drive:
	and	al, 0DFh
	sub	al, 'A'; A:
	jc	short loc_ppn_invalid_drive
	cmp	[Last_DOS_DiskNo], al
	jb	short loc_ppn_invalid_drive

	inc	esi
	inc	esi
	mov	ah, [esi]
	cmp	ah, 21h
	jnb	short pass_ppn_change_drive

loc_ppn_cmd_failed:
	; File or directory name is not existing
	mov	[edi], al ; Drv 
	mov	ax, 1 ; eax = 1
	; TR-DOS Error Code 1h = Bad Command Argument
	; MS-DOS Error Code 1h : Invalid Function Number
	;stc
	; (MainProg ErrMsg: "Bad command or file name!")
	retn

pass_ppn_change_drive:
	mov	[First_Path_Pos], esi
	mov	dword [Last_Slash_Pos], 0
	stosb
	mov	al, [esi]
loc_scan_ppn_dslash:
	cmp	al, '/'
  	jne	short loc_scan_next_slash_pos
	mov	[Last_Slash_Pos], esi
loc_scan_next_slash_pos:
	inc	esi
	mov	al, [esi]
	cmp	al, 20h
	ja	short loc_scan_ppn_dslash
	cmp	dword [Last_Slash_Pos], 0
	jna	short pass_ppn_cdir
	
	mov	ecx, [Last_Slash_Pos]
	mov	esi, [First_Path_Pos]
	sub	ecx, esi
	inc	ecx
	;cmp	ecx, 64
	cmp	cl, 64
	ja	short loc_ppn_invalid_drive_stc

	mov	eax, edi ; Dest Dir String Location (65 byte)
	rep	movsb
	;mov	[edi], cl ; 0, End of Dir String
	mov	esi, [Last_Slash_Pos]
	inc	esi
	mov	edi, eax
	lodsb
	cmp	al, 21h
	jnb	short loc_ppn_get_filename
loc_ppn_clc_return:
	;clc
	xor	eax, eax
	retn

loc_ppn_invalid_drive_stc:
	cmc	 ; stc
loc_ppn_invalid_drive:
	; cf = 1
	; The Drive Letter/Char < "A" or > "Z"
	mov	ax, 0Fh
	; MS-DOS Error Code 0Fh = Disk Drive Invalid 
	; (MainProg ErrMsg: "Drive not ready or read error!")
	retn

find_longname:
	; 13/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 24/01/2010 (DIR.ASM, 'proc_find_longname')
	; 17/10/2009
	
	; INPUT -> 
	;	ESI = DOS short file name address
	; 	for example: "filename.ext"
	;
	; OUTPUT ->
	; 	ESI = ASCIIZ longname address (cf = 0)
	;	cf = 1 -> error number returns in EAX (AL)
	;	AL = 0 & CF=1 -> longname not found
	;	     the file/directory has no longname
	; 	cf = 0 -> AL = FAT Type 
 
	; 17/10/2009
	; ASCIIZ string will be returned
	; as LongFileName
	; clearing/reset is not needed
	;mov	ecx, 33
	;mov	edi, LongFileName
	;sub	ax, ax ; 0
	;rep	stosw

	;mov	byte [LongNameFound], 0

	; ESI = ASCIIZ file/directory name address
	;   AL = Attributes AND mask 
	;	(Result of AND must be equal to AL)
	;   AH = Negative attributes mask 
	;	(Result of AND must be ZERO)
	mov	ax, 0800h 
		; it must not be volume name or longname
	call	find_first_file
	jc	short loc_fln_retn
 
loc_fln_check_FAT_Type:
	cmp	byte [Current_FATType], 1
	jnb	short loc_fln_check_longname_yes_sign

	call	get_fs_longname
	retn

loc_fln_check_longname_yes_sign:
	or	bh, bh
	jnz	short loc_fln_check_longnamefound_number
loc_fln_longname_not_found_retn:
	xor	eax, eax 
	; cf = 1 & al = 0 -> longname not found
	stc
loc_fln_retn:
	retn

loc_fln_check_longnamefound_number:
	; 'LongNameFound' is set by
        ; by 'save_longname_sub_component'
	; which is called from
	; 'find_directory_entry' 
	; which is called from 
	; 'find_first_file'
	; It must 1 if the longname is valid
        cmp     byte [LongNameFound], 1
	jne	short loc_fln_longname_not_found_retn
             
loc_fln_calculate_checksum: 
	call	calculate_checksum
	; AL = shortname checksum

loc_fln_longname_validation:
	; 'LFN_CheckSum' has been set already
	; by 'save_longname_sub_component'
	; which is called from
	; 'find_directory_entry' 
	; which is called from 
	; 'find_first_file'
	cmp	[LFN_CheckSum], al
	jne	short loc_fln_longname_not_found_retn

	mov	esi, LongFileName
	mov	al, [Current_FATType]
	retn

calculate_checksum:
	; 13/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 17/10/2009 (DIR.ASM, 'proc_calculate_checksum')
        ;    
	; INPUT ->
	;	ESI = 11 byte DOS File Name location
	;	(in DOS Directory Entry Format)
	; OUTPUT ->
	;	 AL = 8 bit checksum (CRC) value
	;
	; (Modified registers: EAX, ECX, ESI)

	; Erdogan Tan [ 17-10-2009 ]
	;  'ror al, 1' instruction

	; Erdogan Tan [ 20-06-2004 ]
	; This 8086 assembly code is an original code
	; which is adapted from C code in
	; Microsoft FAT32 File System Specification
	; Version 1.03, December 6, 2000
	; Page 28

	xor	al, al
	mov	ecx, 11
loc_next_sum:
	;xor	ah, ah
	;test	al, 1
	;jz	short pass_ah_80h
	;mov	ah, 80h
;pass_ah_80h:
	;shr	al, 1
	ror	al, 1 ; 17/10/2009  
	add	al, [esi]
	inc	esi
	;add	al, ah
	loop	loc_next_sum
	retn

get_fs_longname:
	; temporary (13/02/2016)
	xor eax, eax
	stc
	retn

make_sub_directory:
	; 03/03/2016
	; 02/03/2016
	; 27/02/2026
	; 26/02/2016
	; 21/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011 (DIR.ASM, 'proc_make_directory')
	; 10/07/2010
	; INPUT ->
	; 	ESI = ASCIIZ Directory Name
	;	CL = Directory Attributes
	; OUTPUT ->
	;	EAX = New sub dir's first cluster
	;	ESI = Logical Dos Drv Descr. Table Addr.
	;	CF = 1 -> error code in AL (EAX)

	;test	cl, 10h  ; directory
	;jz	short loc_make_directory_access_denied
	;test	cl, 08h ; volume name
	;jnz	short loc_make_directory_access_denied

	and	cl, 07h
	mov	byte [mkdir_attrib], cl

	push	esi
	xor	ebx, ebx
	mov	bh, [Current_Drv]
	mov	esi, Logical_DOSDisks
	add	esi, ebx
	pop	ebx

	; 10/07/2010 -> 1st writable disk check for trdos
	; LD_DiskType = 0 for write protection (read only) 
	cmp	byte [esi+LD_DiskType], 1 ; 0 = Invalid
	jnb	short loc_mkdir_check_file_sytem
	mov	eax, 13h ; MSDOS err => Disk write-protected 
	mov	edx, 0
	; err retn: EDX = 0, EBX = Dir name offset
	;ESI = Logical DOS drive description table address
	retn

;loc_make_directory_access_denied:
	;mov	ax, 05h ; access denied (invalid attributes input)
	;stc
	;retn

loc_mkdir_check_file_sytem:
	cmp	byte [esi+LD_FATType], 1
	jnb	short loc_mkdir_check_free_sectors

loc_make_fs_directory:
	mov	eax, [Current_Dir_FCluster]
	; EAX = Parent directory DDT Address
	; ESI = Logical DOS Drive DT Address
	; EBX = Directory name offset (as ASCIIZ name)
	call	make_fs_directory
	retn

loc_mkdir_check_free_sectors:
        movzx   eax, byte [esi+LD_BPB+SecPerClust]
	mov	ecx, [esi+LD_FreeSectors]
	cmp	ecx, eax
	jb	short loc_mkdir_insufficient_disk_space

loc_make_fat_directory:
	mov	[mkdir_DirName_Offset], ebx
	mov	[mkdir_FreeSectors], ecx

	;mov	al, [esi+LD_BPB+SecPerClust]
	mov	byte [mkdir_SecPerClust], al

loc_mkdir_gffc_1:
	call	get_first_free_cluster
	jc	short loc_mkdir_gffc_retn

;loc_mkdir_gffc_1_cont: 
	;cmp	eax, 2
	;jb	short loc_mkdir_gffc_insufficient_disk_space

;loc_mkdir_gffc_1_save_fcluster:  
	mov	[mkdir_FFCluster], eax

loc_mkdir_locate_ffe:
	; Current directory fcluster <> Directory buffer cluster
	; Current directory will be reloaded by
	; 'locate_current_dir_file' procedure
	;
	; ESI = Logical DOS Drive Description Table Address 
	;push	esi ; 27/02/2016
	xor	eax, eax
        mov	ecx, eax
	dec	cx ; FFFFh  
	; CX = FFFFh -> find first deleted or free entry
	; ESI would be ASCIIZ filename address if the call
	; would not be for first free or deleted dir entry
	call	locate_current_dir_file
	jnc	short loc_mkdir_set_ff_dir_entry_1
	;pop	esi 
	; ESI = Logical DOS Drive Description Table Address 
	cmp	eax, 2  ; cmp al, 2 ; File/Dir not found !
	jne	short loc_mkdir_stc_return

loc_mkdir_add_new_cluster:
	cmp	byte [Current_FATType], al ; 2
	;cmp	byte ptr [esi+LD_FATType], 2
	ja	short loc_mkdir_add_new_cluster_check_fsc
	cmp	byte [Current_Dir_Level], 1
	;cmp	byte [esi+LD_CDirLevel], 1
	jnb	short loc_mkdir_add_new_cluster_check_fsc

	mov	al, 12 ; No more files 
loc_mkdir_gffc_retn:
	retn

loc_mkdir_add_new_cluster_check_fsc:
	mov	ecx, [mkdir_FreeSectors]
	;movzx	eax, byte [mkdir_SecPerClust]
	mov	al, [mkdir_SecPerClust]
	shl	ax, 1 ; AX = 2 * AX
	cmp	ecx, eax
	jnb	short loc_mkdir_add_new_subdir_cluster

loc_mkdir_insufficient_disk_space:
	;mov	edx, ecx
;loc_mkdir_gffc_insufficient_disk_space:
	mov	ax, 27h ; MSDOS err => insufficient disk space
	; err retn: EDX = Free sectors, EBX = Dir name offset
        ; ESI -> Dos drive description table address
	;; ecx = edx
	;
	retn

loc_mkdir_stc_return:
	stc
	retn 

loc_mkdir_gffc_2:
	call	get_first_free_cluster
	jc	short loc_mkdir_gffc_retn

;loc_mkdir_gffc_1_cont: 
	;cmp	eax, 2
	;jb	short loc_mkdir_gffc_insufficient_disk_space

;loc_mkdir_gffc_2_save_fcluster:  
	mov	[mkdir_FFCluster], eax

	mov	eax, [mkdir_LastDirCluster]

	call	load_FAT_sub_directory 
	jc	short loc_mkdir_gffc_retn

	xor	edi, edi
loc_mkdir_set_ff_dir_entry_1:
	; 27/02/2016
	push	esi ; Logical DOS Drv Desc. Tbl. address
	; EDI = Directory Entry Address
	mov	esi, [mkdir_DirName_Offset]
	mov	eax, [mkdir_FFCluster]

	mov	cx, 10h	; CL = Directory attribute
			; CH = 0 -> File size is 0
	or	cl, [mkdir_attrib] ; S, H, R  
	call	make_directory_entry

	pop	esi

	mov	byte [DirBuff_ValidData], 2
	call	save_directory_buffer
        jnc     loc_mkdir_set_ff_dir_entry_2

loc_mkdir_return:
	retn

loc_mkdir_add_new_subdir_cluster:
	mov	edx, [DirBuff_Cluster]
	mov	[mkdir_LastDirCluster], edx       

	mov	eax, [mkdir_FFCluster]
	call	load_FAT_sub_directory 
	jc	short loc_mkdir_return
	; eax = 0
	; ecx =  directory buffer sector count (<= 128)

pass_mkdir_add_new_subdir_cluster:
	sub	edi, edi ; 0
	;mov	al, 128 ; double word
	;mul	ecx ; ecx =  directory buffer sector count
	;mov	ecx, eax
	;shl	cx, 7 ; 128 * sector count	
	mov	ax, [esi+LD_BPB+BytesPerSec] ; 512
	shr	ax, 2 ; 'byte count / 4' for 'stosd'
	mul	cx ; max = 128*(512/4) -> 16384 (stosd)
	mov	cx, ax
	sub	ax, ax ; 0
	rep	stosd ; clear directory buffer

	mov	byte [DirBuff_ValidData], 2
	call	save_directory_buffer 
	jc	short loc_mkdir_return

loc_mkdir_save_added_cluster:
	mov	eax, [mkdir_LastDirCluster]
	mov	ecx, [mkdir_FFCluster]
	; 01/03/2016
	xor	edx, edx
	mov	[FAT_ClusterCounter], edx ; 0 ; reset
	call	update_cluster
	jnc	short loc_mkdir_save_fat_buffer_0
	or	eax, eax ; EAX = 0 -> cluster value is 0 or eoc
	jnz	short loc_mkdir_save_fat_buffer_stc_retn

loc_mkdir_save_fat_buffer_0:
	mov	eax, [mkdir_FFCluster]
	mov	[mkdir_LastDirCluster], eax

	xor	ecx, ecx
	dec	ecx ; FFFFFFFFh
	; ESI = Logical DOS Drive Description Table address 
	call	update_cluster
	jnc	short loc_mkdir_save_fat_buffer_1
	or	eax, eax
	jz	short loc_mkdir_save_fat_buffer_1

loc_mkdir_save_fat_buffer_stc_retn:
	; 01/03/2016
	cmp	byte [FAT_ClusterCounter], 1
	jb	short loc_mkdir_save_fat_buffer_retn

	mov	bx, 0FF00h ; recalculate free space (BL = 0)
			   ; (BH = FFh -> Use ESI as Drv Param. Tbl.)
	push	eax
	call	calculate_fat_freespace
	pop	eax
	stc
loc_mkdir_save_fat_buffer_retn:
	retn

loc_mkdir_save_fat_buffer_1:
	; byte [FAT_BuffValidData] = 2 
	call	save_fat_buffer
	jc	short loc_mkdir_save_fat_buffer_stc_retn

	; 01/03/2016
	cmp	byte [FAT_ClusterCounter], 1
	jb	short loc_mkdir_save_fat_buffer_2

	; ESI = Logical DOS Drive Description Table address 
	mov	eax, [FAT_ClusterCounter]
	mov	bx, 0FF01h ; add free clusters 
	call	calculate_fat_freespace

	;inc	eax ; 0FFFFFFFFh -> 0 ; recalculation is needed!
	;jnz	short loc_mkdir_save_fat_buffer_2

	; ecx > 0 -> Recalculation is needed
	or	ecx, ecx 
	jz	short loc_mkdir_save_fat_buffer_2

	mov	bx, 0FF00h ; ; recalculate free space
	call	calculate_fat_freespace

loc_mkdir_save_fat_buffer_2:
	mov	byte [mkdir_add_new_cluster], 1
	jmp	loc_mkdir_upd_parent_dir_lmdt

loc_mkdir_update_sub_dir_cluster:
	mov	eax, [mkdir_FFCluster]
	sub	ecx, ecx ; 0
	; 01/03/2016
	mov	[FAT_ClusterCounter], ecx ; 0 ; Reset
	dec	ecx ; 0FFFFFFFFh

	; ESI = Logical DOS Drive Descisption Table address  
	call	update_cluster
	jnc	short loc_mkdir_save_fat_buffer_3
	or	eax, eax ; EAX = 0 -> cluster value is 0 or eocc
	jz	short loc_mkdir_save_fat_buffer_3
	; 01/03/2016
	jmp	short loc_mkdir_save_fat_buffer_stc_retn

loc_mkdir_set_ff_dir_entry_2:
	; ESI = Logical DOS Drive Description Table address  
	mov	eax, [mkdir_FFCluster]
	; Load disk sectors as a directory cluster
	call	load_FAT_sub_directory 
	jc	short retn_make_fat_directory
	
	; eax = 0
	; ecx =  directory buffer sector count (<= 128)

	mov	edi, Directory_Buffer + 64 ; 26/02/2016

	; 02/03/2016
	mov	ax, [esi+LD_BPB+BytesPerSec] ; 512
	shr	ax, 2 ; 'byte count / 4' for 'stosd'
	mul 	ecx
	mov	ecx, eax
	sub	ax, ax
	rep	stosd

	;;mov	al, 128 ; double word
	;;mul	ecx ; ecx =  directory buffer sector count
	;;mov	ecx, eax
	;shl	cx, 7 ; 128 * sector count	
	;;sub	eax, eax
	;;sub	al, al ; 0
	;rep	stosd ; clear directory buffer

	mov	edi, Directory_Buffer ; 26/02/2016
	
	push	esi

	mov	esi, mkdir_Name
	mov	word [esi], 2Eh ; db '.', '0'

	mov	eax, [mkdir_FFCluster]
	mov	cx, 10h ; CL = Directory attribute
			; CH = 0 -> File size is 0
	call	make_directory_entry

	mov	edi, Directory_Buffer + 32 ; 26/02/2016

	; 03/03/2016
	; Following modification has been done according to 
	; 'Microsoft Extensible Firmware Initiative
	; FAT32 File System Specification' document,
	; 'FAT: General Overview of On-Disk Format—Page 25'.
	; "Finally, you set DIR_FstClusLO and DIR_FstClusHI
	; for the dotdot entry (the second entry) to the
	; first cluster number of the directory in which you 
	; just created the directory (value is 0 if this directory
	; is the root directory even for FAT32 volumes)."
	; (Correctness of this modification has been verified
	;  by using Windows 98 'scandisk.exe'.)

	sub	eax, eax
	cmp	byte [Current_Dir_Level], al ; 0
	jna	short loc_mkdir_set_ff_dir_entry_3
	mov	eax, [Current_Dir_FCluster] ; parent dir
loc_mkdir_set_ff_dir_entry_3:
	mov	word [esi+1], 2Eh ; db '.', '0'

	;mov	cx, 10h
	call	make_directory_entry

	pop	esi

	mov	byte [DirBuff_ValidData], 2
	call	save_directory_buffer
        jnc     loc_mkdir_update_sub_dir_cluster
 
retn_make_fat_directory:
	retn

loc_mkdir_save_fat_buffer_3:
	; 01/03/2016
	; byte [FAT_BuffValidData] = 2 
	call	save_fat_buffer
        jc      loc_mkdir_save_fat_buffer_stc_retn

	cmp	byte [FAT_ClusterCounter], 1
	jb	short loc_mkdir_save_fat_buffer_4

	; ESI = Logical DOS Drive Description Table address 
	mov	eax, [FAT_ClusterCounter]
	mov	bx, 0FF01h ; add free clusters 
	call	calculate_fat_freespace

	;inc	eax ; 0FFFFFFFFh -> 0 ; recalculation is needed!
        ;jnz    short loc_mkdir_save_fat_buffer_4

	; ecx > 0 -> Recalculation is needed
	or	ecx, ecx 
        jz      short loc_mkdir_save_fat_buffer_4

	mov	bx, 0FF00h ; ; recalculate free space
	call	calculate_fat_freespace

loc_mkdir_save_fat_buffer_4:	
	mov	byte [mkdir_add_new_cluster], 0

loc_mkdir_upd_parent_dir_lmdt:
	call	update_parent_dir_lmdt

	; 01/03/2016
	cmp	byte [mkdir_add_new_cluster], 0
        ja      loc_mkdir_gffc_2

loc_mkdir_retn_new_dir_cluster:
	mov	eax, [mkdir_FFCluster]
	xor	edx, edx
loc_mkdir_retn:
	retn

make_directory_entry:
	; 02/03/2016
	; 21/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 09/08/2010 (DIR.ASM, 'proc_make_directory_entry')
	; 17/07/2010
	; INPUT ->
	; 	EDI = Directory Entry Address
	;	ESI = Dot File Name Location
	;	EAX = First Cluster
	;	File Size = 0 (Must be set later)
	;	CL = Attributes
	;	CH = 0 (File size = 0) 
	;	(If CH>0, File size is in dword [EBX]) (*)
	; OUTPUT -> 
	;	EDI = Directory Entry Address
	;	ESI = Dot File Name Location (Capitalized)
	;	If CH input = 0, File Size = 0
	;	Otherwise file size is as dword [EBX] (*)
	;	DX = Date, AX = Time in DOS Dir Entry format
	;	EBX = same
	;	ECX = same

	push	ecx

	mov	[edi+11], cl ; Attributes
	mov	[edi+26], ax ; FClusterLw, 26
	shr	eax, 16
	mov	[edi+20], ax ; FClusterHw, 20
	xor	ax, ax 
	mov	[edi+12], ax ; NTReserved, 12
			     ; CrtTimeTenth, 13
	or	ch, ch
	jz	short loc_make_direntry_set_filesize

	mov	eax, [ebx]
        
loc_make_direntry_set_filesize:
	mov	[edi+28], eax ; FileSize, 28
	
	call	convert_file_name
	;EDI = Dir Entry Format File Name Location
	;ESI = Dot File Name Location (capitalized)

	call	convert_current_date_time
	; OUTPUT -> DX = Date in dos dir entry format
        ; 	    AX = Time in dos dir entry format
	mov	[edi+14], ax ; CrtTime, 14
	mov	[edi+16], dx ; CrtDate, 16
	mov	[edi+18], dx ; LastAccDate, 18
	mov	[edi+22], ax ; WrtTime, 14
	mov	[edi+24], dx ; WrtDate, 16
	pop	ecx

	retn

convert_current_date_time:
	; 21/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 13/06/2010 (DIR.ASM, 'proc_convert_current_date_time')
	; converts date&time to dos dir entry format
	; INPUT -> none
	; OUTPUT -> DX = Date in dos dir entry format
	;           AX = Time in dos dir entry format
 
	mov	ah, 04h ; Return Current Date
	call	int1Ah 

	mov	al, ch ; <- century BCD
	and	al, 0Fh
	mov	ah, ch
	shr	ah, 4
	aad
	mov	ch, al ; -> century 

	mov	al, cl ; <- year BCD
	and	al, 0Fh
	mov	ah, cl
	shr	ah, 4
	aad
	mov	cl, al ; -> year

	mov	al, ch
	mov	ah, 100
	mul	ah
	xor	ch, ch
	add	ax, cx
	sub	ax, 1980 ; ms-dos epoch
	mov	cx, ax

	mov	al, dh ; <- month in bcd
	and	al, 0Fh
	mov	ah, dh
	shr	ah, 4
	aad
	mov	dh, al ; -> month

	mov	al, dl ; <- day BCD
	and	al, 0Fh
	mov	ah, dl
	shr	ah, 4
	aad
	mov	dl, al ; -> day

	mov	al, cl ; count of years from 1980
	shl	ax, 4
	or	al, dh ; month of year, 1 to 12
	shl	ax, 5
	or	al, dl ; day of year, 1 to 31
	
	push	ax ; push date

	mov	ah, 02h ; Return Current Time
	call	int1Ah

	mov	al, ch ; <- hours BCD
	and	al, 0Fh
	mov	ah, ch
	shr	ah, 4
	aad
	mov	ch, al ; -> hours

	mov	al, cl ; <- minutes BCD
	and	al, 0Fh
	mov	ah, cl
	shr	ah, 4
	aad
	mov	cl, al ; -> minutes

	mov	al, dh ; <- seconds BCD
	and	al, 0Fh
	mov	ah, dh
	shr	ah, 4
	aad
	mov	dh, al ; -> seconds

	mov	al, ch ; hours
	shl	ax, 6
	or	al, cl ; minutes
	shl	ax, 5
	shr	dh, 1 ; 2 seconds
	; There is a bug in TRDOS v1 here !
	; it was 'or al, dl' ! 
	or	al, dh ; seconds

	pop	dx ; pop date
	
	retn

save_directory_buffer:
	; 26/02/2016
	; 22/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011
	; 14/03/2010
	; INPUT ->
	; 	 none
	; OUTPUT ->
	;  cf = 0 -> write OK...
	;  cf = 1 -> error code in AL (EAX)
	;  cf = 1 & AL = 0Dh => CH & CL = FS & FAT type
	;  EBX = Directory Buffer Address
	;
	;  (EAX, ECX, EDX will be modified)
 
	mov	ebx, Directory_Buffer
	cmp	byte [DirBuff_ValidData], 2
	je	short loc_save_dir_buffer
	xor	eax, eax
	retn            

loc_save_dir_buffer:
	push	esi
	xor	ebx, ebx 
        mov     bh, [DirBuff_DRV]
	sub	bh, 'A'
        mov     esi, Logical_DOSDisks
	add	esi, ebx
        mov     cx, [esi+LD_FATType]
	; CH = FS Type (A1h for FS)
	; CL = FAT Type (0 for FS)
	or	cl, cl
	jz	short loc_save_dir_buff_stc_retn

loc_save_dir_buffer_check_cluster_no:    
	mov	eax, [DirBuff_Cluster]
	sub	bh, bh ; ebx = 0
	or	eax, eax
	jnz	short loc_save_sub_dir_buffer
	mov	ah, [DirBuff_FATType]
	inc	bl ;  bl = 1
	cmp	ah, bl
	jb	short loc_save_dir_buff_inv_data_retn
	inc	bl ; bl = 2
	cmp	bl, ah
	jb	short loc_save_dir_buff_inv_data_retn

loc_save_root_dir_buffer:
	mov	bx, [esi+LD_BPB+RootDirEnts]
	add	bx, 15
	shr	bx, 4 ; 16 dir entries per sector
	or	bx, bx
	jz	short loc_save_dir_buff_stc_retn
	;mov	ecx, ebx 
	mov	eax, [esi+LD_ROOTBegin] ; 26/02/2016
	jmp	short loc_write_directory_to_disk

loc_save_dir_buff_stc_retn:
	stc
loc_save_dir_buff_inv_data_retn:
	mov	al, 0Dh ; Invalid data !
	mov	byte [DirBuff_ValidData], 0 
loc_write_directory_to_disk_err:
loc_save_dir_buff_retn:
	mov	ebx, Directory_Buffer
	pop	esi
	retn 

loc_save_sub_dir_buffer:
	; ebx  = 0
	sub	eax, 2
	mov	bl, [esi+LD_BPB+SecPerClust]
	mul	ebx
        add     eax, [esi+LD_DATABegin]
 	;mov	ecx, ebx

loc_write_directory_to_disk:
 	mov	ecx, ebx
	mov	ebx, Directory_Buffer
	call	disk_write
	jc	short loc_write_directory_to_disk_err

loc_save_dir_buff_validate_retn:
	mov	byte [DirBuff_ValidData], 1
	xor	eax, eax
	; 26/02/2016
	jmp	short loc_save_dir_buff_retn

update_parent_dir_lmdt:
	; 22/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011
	; 16/10/2010 
	; 
	; INPUT -> 
	;	none
 	; OUTPUT ->
	;	(last modification date & time of the parent dir
	;	will be changed/updated)
	;
	; (EAX, EBX, ECX, EDX, EDI will be changed)

	sub	eax, eax
	mov	ah, [Current_Dir_Level]
	mov	al, [Current_FATType]
	cmp	al, 1
	jb	short loc_UPDLMDT_proc_retn
    
loc_update_parent_dir_lm_date_time:
	or	ah, ah
	jz	short loc_UPDLMDT_proc_retn

	push	esi ; *
	mov	[UPDLMDT_CDirLevel], ah
	mov	edx, [Current_Dir_FCluster]
	mov	[UPDLMDT_CDirFCluster], edx

	dec	ah
	mov	ecx, 12
        mov     esi, PATH_Array

	mov	[Current_Dir_Level], ah
	or	ah, ah
	jnz	short loc_update_parent_dir_lmdt_load_sub_dir_1
	cmp	byte [Current_FATType], 2
	ja	short loc_update_parent_dir_lmdt_load_sub_dir_2
	sub	al, al ; eax = 0
	jmp	short loc_update_parent_dir_lmdt_load_sub_dir_3

loc_UPDLMDT_proc_retn:
	retn
         
loc_update_parent_dir_lmdt_load_sub_dir_1:
	mov	al, 16
	mul	ah 
	add	esi, eax

loc_update_parent_dir_lmdt_load_sub_dir_2:  
	mov	eax, [esi+12] ; Parent Dir First Cluster

loc_update_parent_dir_lmdt_load_sub_dir_3:
	mov	[Current_Dir_FCluster], eax

	add	esi, 16
	mov	di, Dir_File_Name  
	rep	movsb
	
	mov	esi, Logical_DOSDisks
	sub	ebx, ebx
	mov	bh, [Current_Drv]
	add	esi, ebx
	call	reload_current_directory
	jc	short loc_update_parent_dir_lmdt_restore_cdirlevel

loc_update_parent_dir_lmdt_locate_dir: 
	mov	esi, Dir_File_Name        
	xor	cx, cx
	mov	ax, 0810h ; Only directories
        call    locate_current_dir_file
	; EDI = DirBuff Directory Entry Address
	jc short loc_update_parent_dir_lmdt_restore_cdirlevel

	call	convert_current_date_time
	mov	[edi+18], dx ; Last Access Date
	mov	[edi+24], dx ; Last Write Date
	mov	[edi+22], ax ; Last Write Time

	mov	byte [DirBuff_ValidData], 2
	call	save_directory_buffer
	jc	short loc_update_parent_dir_lmdt_restore_cdirlevel
	;xor	al, al 
loc_update_parent_dir_lmdt_restore_cdirlevel:
 	;current directory level restoration
	mov	ah, [UPDLMDT_CDirLevel]
	mov	[Current_Dir_Level], ah
        mov     edx, [UPDLMDT_CDirFCluster]
	mov	[Current_Dir_FCluster], edx

	pop	esi ; *
	retn

delete_longname:
	; 27/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011 (DIR.ASM, 'proc_delete_longname')
	; 14/03/2010
	; INPUT ->
	; 	EAX = Directory Entry (Index) Number (< 65536)
	; OUTPUT ->
	;	cf = 0 -> OK  (EAX = 0)
	; 	cf = 1 -> error code in EAX (AL)
	;
	; (Modified registers: EAX, EDX, ECX, EBX, EDI) 

	mov	[DLN_EntryNumber], ax
        mov     byte [DLN_40h], 40h

	call	locate_current_dir_entry
	jnc	short loc_dln_check_attributes
	retn

loc_dln_longname_not_found:
	mov	eax, 2
	stc
	retn

loc_dln_check_attributes:
	mov	al, 0Fh  ; long name
	mov	ah, [edi+0Bh] ; dir entry attributes
	cmp	ah, al
	jne	short loc_dln_longname_not_found
	mov	ah, [edi]
	sub	ah, [DLN_40h]
	jna	short loc_dln_longname_not_found         
	cmp	ah, 14h ; 84-64=20 -> 20*13=260 bytes
	ja	short loc_dln_longname_not_found
             
	mov	byte [edi], 0E5h  ; deleted sign
	mov	byte [DirBuff_ValidData], 2 ; changed/write sign
	mov	byte [DLN_40h], 0 ; 40h -> 0
	  
loc_dln_delete_next_ln_entry:
	cmp	ah, 1
	jna	short loc_dln_longname_retn
loc_dln_delete_next_ln_entry_0:
	inc	word [DLN_EntryNumber]
	movzx	eax, word [DLN_EntryNumber] 
	call	locate_current_dir_entry
	jnc	short loc_dln_check_attributes

loc_dln_longname_stc_retn:
	retn 
	   
loc_dln_longname_retn:
	;cmp	byte [DirBuff_ValidData], 2
	;jne	short loc_dln_longname_retn_xor_eax
	call	save_directory_buffer
	jc	short loc_dln_longname_stc_retn

loc_dln_longname_retn_xor_eax:
	xor	eax, eax
	retn

locate_current_dir_entry:
	; 27/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011 (DIR.ASM, 'proc_locate_current_dir_entry')
	; 07/03/2010
	; INPUT ->
	;	EAX = Directory Entry (Index) Number (< 65536) 
	; OUTPUT ->
	;	EDI = Directory Entry Address
	; 	EAX = Cluster Number of Directory Buffer
	;	EBX = Directory Buffer Entry Offset
	;	ECX = DirBuff Valid Data identifier (CL)
	;   	If CF = 0 and CL = 2 then
	;	   directory buffer modified and
	;	   must be written to disk.
	; 	If CF = 0  and CL = 1 then
	;	   dir buffer has been written to disk, already.
	;	CF = 1 -> Error code in EAX (AL)
	;
	; (Modified registers: EAX, EDX, ECX, EBX, EDI) 

loc_locate_current_dir_entry:
	push	esi
	mov	ecx, eax
	mov	edx, 32
	mul	edx 
	mov	[LCDE_ByteOffset], eax
	xor	ebx, ebx
	mov	bh, [Current_Drv]
        mov     al, [DirBuff_DRV]
	sub	al, 'A'
        mov     esi, Logical_DOSDisks
	add	esi, ebx
	cmp	bh, al
        jne     loc_lcde_reload_current_directory
loc_lcde_cdl_check:
	cmp	byte [Current_Dir_Level], 0
	ja	short loc_lcde_calc_dirbuff_cluster_offset
	; 27/02/2016
	; TRDOS v1 has bug here for FAT32 fs !
	; (Root Directory Entries for FAT32 = 0)
	cmp	byte [esi+LD_FATType], 3  ; FAT32
	jnb	short loc_lcde_calc_dirbuff_cluster_offset

loc_lcde_cdl_check_FAT12_16:
	mov	ax, [esi+LD_BPB+RootDirEnts]
	dec	ax
	;xor	dx, dx  
	cmp	ax, cx ; cx = Directory Entry (Index) Number
	jb	short loc_lcde_stc_12h_retn
	mov	[LCDE_EntryIndex], cx
	xor	eax, eax
        jmp     loc_lcde_check_dir_buffer_cluster

loc_lcde_stc_12h_retn:
	pop	esi
	mov	ebx, ecx
	mov	ecx, edx
	mov	eax, 12h ; No more files
	retn 

loc_lcde_calc_dirbuff_cluster_offset:
	mov	bl, [esi+LD_BPB+SecPerClust]
	xor	bh, bh
	mov	ax, [esi+LD_BPB+BytesPerSec]
	mul	bx
 	or	dx, dx ; If bytes per cluster > 32KB it is invalid
	jnz	short loc_lcde_invalid_format
	;mov	ecx, eax
	mov	cx, ax ; BYTES PER CLUSTER
	mov	eax, [LCDE_ByteOffset]
	;sub	edx, edx
	div	ecx
	cmp	eax, 65535
	ja	short loc_lcde_invalid_format

	; cluster sequence number of directory (< 65536)
	mov	[LCDE_ClusterSN], ax 

	mov	ax, dx ; byte offset in cluster (directory buffer)
	mov	bx, 32 ; ; 1 dir entry = 32 bytes
        sub     dx, dx  ; 0
	div	bx 
	mov	[LCDE_EntryIndex], ax ; dir entry index/sequence number
				      ; (in directory buffer/cluster)	  
loc_lcde_get_current_sub_dir_fcluster:
	mov	eax, [Current_Dir_FCluster]

loc_lcde_get_next_cluster:
	cmp	word [LCDE_ClusterSN], 0
	jna	short loc_lcde_check_dir_buffer_cluster
	mov	[LCDE_Cluster], eax
	call	get_next_cluster
	jc	short loc_lcde_check_gnc_error
  	dec	word [LCDE_ClusterSN]
	jmp	short loc_lcde_get_next_cluster

loc_lcde_reload_current_directory:
	push	ecx
	call	reload_current_directory
	pop	ecx
        jnc     loc_lcde_cdl_check
	pop	esi
	retn

loc_lcde_invalid_format:
	mov	eax, 0Bh ; MSDOS Error code: Invalid Format
	;mov	eax, 0Dh ; MSDOS Error code: Invalid Data
loc_lcde_drive_not_ready_read_err:
	stc
	pop	esi 
	retn  

loc_lcde_check_gnc_error:
	or	eax, eax
	jnz	short loc_lcde_drive_not_ready_read_err
	dec	word [LCDE_ClusterSN]
	jnz	short loc_lcde_invalid_format 
	mov	eax, [LCDE_Cluster]

loc_lcde_check_dir_buffer_cluster:
	cmp	eax, [DirBuff_Cluster]
	jne	short loc_lcde_load_dir_cluster
	cmp	byte [DirBuff_ValidData], 0
	ja	short lcde_check_dir_buffer_cluster_next
	cmp	byte [Current_Dir_Level], 0    
	ja	short loc_lcde_load_dir_cluster_0
	; 27/02/2016
	; TRDOS v1 has bug here for FAT32 fs !
	cmp	byte [esi+LD_FATType], 3  ; FAT32
	jnb	short loc_lcde_load_dir_cluster_0
	;
	movzx	ecx, word [esi+LD_BPB+RootDirEnts]
	add	cx, 15 ; round up (16 entries per sector)
	shr	cx, 4 ; 1 sector contains 16 dir entries	

        mov     eax, [esi+LD_ROOTBegin]
	jmp	short loc_lcde_load_dir_cluster_1 

lcde_check_dir_buffer_cluster_next:
	movzx	ebx, word [LCDE_EntryIndex]
	cmp	bx, [DirBuff_LastEntry]
	ja	short loc_lcde_invalid_format 
	mov	eax, 32
	mul	ebx
	;or	edx, edx
	;jnz	short loc_lcde_invalid_format

	mov	edi, Directory_Buffer  
	add	edi, eax ; add entry offset to buffer address

loc_lcde_dir_buffer_last_check:
	mov	eax, [DirBuff_Cluster]
	movzx	ecx, byte [DirBuff_ValidData]

loc_lcde_retn:
	pop	esi
	retn

loc_lcde_load_dir_cluster:
	;cmp	byte [DirBuff_ValidData], 2
	;jne	short loc_lcde_load_dir_cluster_n2
	push	eax
	call	save_directory_buffer
	pop	eax
	jc	short loc_lcde_retn

loc_lcde_load_dir_cluster_n2:
	mov	byte [DirBuff_ValidData], 0
	mov	[DirBuff_Cluster], eax

loc_lcde_load_dir_cluster_0:
	sub	eax, 2
	movzx	ecx, byte [esi+LD_BPB+SecPerClust]
	mul	ecx
        add     eax, [esi+LD_DATABegin]

loc_lcde_load_dir_cluster_1:
	mov	ebx, Directory_Buffer
	; ecx = sector count
	call	disk_read
	jc	short loc_lcde_retn

loc_lcde_validate_dirBuff:
	mov	byte [DirBuff_ValidData], 1
	jmp	short lcde_check_dir_buffer_cluster_next

remove_file:
	; 28/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 10/04/2011 (FILE.ASM, 'proc_delete_file')
	; 09/08/2010
	; INPUT ->
	;	EDI = Directory Buffer Entry Address
	;	 CX = Directory Buffer Entry Counter/Index
	;	 BL = Longname Entry Length
	;	 BH = Logical DOS Drive Number 

	sub	eax, eax
	mov	ah, bh
	mov	esi, Logical_DOSDisks
	add	esi, eax

	cmp	byte [esi+LD_FATType], 1
	jnb	short loc_del_fat_file 
              
	cmp	byte [esi+LD_FSType], 0A1h
	je	short loc_del_fs_file

loc_del_file_invalid_format:
	xor	ah, ah
	mov	al, 0Bh ; Invalid Format
	stc 
	retn

loc_del_fs_file:
	call	delete_fs_file
	retn

loc_del_fat_file:
	call	delete_directory_entry
	jc	short loc_del_file_err_retn 

loc_delfile_unlink_cluster_chain:
	call	truncate_cluster_chain
	;jc	short loc_del_file_err_retn

loc_delfile_return:
loc_del_file_err_retn:
	retn

delete_directory_entry:
	; 28/02/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011 (DIR.ASM, 'proc_delete_directory_entry')
	; 10/04/2011 
	; INPUT ->
	; 	ESI = Logical Dos Drive Descripton Table Address 
	;	EDI = Directory Buffer Entry Address
	;	 CX = Directory Buffer Entry Counter/Index
	;	 BL = Longname Entry Length
	;	 BH = Logical DOS Drive Number 
	; OUTPUT ->
	; 	ESI = Logical dos drive descripton table address 
	;	EAX = First cluster to be truncated/unlinked
	;       CF = 1 -> Error code in EAX (AL)
	;       CF = 0 & BH <> 0 -> LMDT write error  (BH = 1)
	;       CF = 0 & BL <> 0 -> Long name delete error (BL = FFh) 
	;
	;  (EDI, EBX, ECX register contents will be changed)

	mov	[DelFile_LNEL], bl
	mov	[DelFile_EntryCounter], cx

	mov	ax, [edi+20] ; First Cluster High Word
	shl	eax, 16
	mov	ax, [edi+26] ; First Cluster Low Word

	mov	[DelFile_FCluster], eax

loc_del_short_name:
	mov	byte [edi], 0E5h  ; Deleted sign

	mov	byte [DirBuff_ValidData], 2
	call	save_directory_buffer
	jc	short loc_delete_direntry_err_return
 
loc_del_long_name:
	movzx	edx, byte [DelFile_LNEL]
	or	dl, dl
	jz	short loc_del_dir_entry_update_parent_dir_lm_date

	mov	byte [DelFile_LNEL], dh ; 0              
  
	movzx	eax,  word [DelFile_EntryCounter]
	sub	eax, edx
	;jnc	short loc_del_long_name_continue
	jc	short loc_del_dir_entry_update_parent_dir_lm_date   

;loc_del_direntry_inv_data_return:
;	mov	eax, 0Dh ; Invalid data
;	retn

loc_del_long_name_continue: 
	; AX = Directory Entry Number of the long name last entry
	call	delete_longname
	;jc	short loc_delete_direntry_err_return

loc_del_dir_entry_update_parent_dir_lm_date:
	sbb	byte [DelFile_LNEL], 0 ; 0FFh if cf = 1

	call	update_parent_dir_lmdt
	mov	bh, 0
	adc	bh, 0

	mov	bl, byte [DelFile_LNEL]
 
loc_delete_direntry_return:
	mov	eax, [DelFile_FCluster]
loc_delete_direntry_err_return:
	retn

rename_directory_entry:
	; 06/03/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011 (DIR.ASM, 'proc_rename_directory_entry')
	; 19/11/2010
	; INPUT -> (Current Directory)
	;	CX = Directory Entry Number
	;      EAX = First Cluster number of file or directory
	;      EBX = Longname Length (dir entry count) (< 256)
	;      ESI = New file (or directory) name (no path).
	;           (ASCIIZ string)  
	; OUTPUT -> 
	;      CF = 0 -> successfull
	;      CF = 1 -> error code in EAX (AL)
	;
	; (EAX, EBX, ECX, EDX, ESI, EDI will be changed)

	cmp	byte [Current_FATType], 0
	ja	short loc_rename_directory_entry

	call	rename_fs_file_or_directory
	retn 
	
loc_rename_directory_entry:
	mov	[DelFile_LNEL], bl
	mov	[DelFile_EntryCounter], cx
	mov	[DelFile_FCluster], eax

	movzx	eax, cx
	call	locate_current_dir_entry
	jnc	short loc_rename_direntry_check_fcluster

loc_rename_direntry_pop_retn:
	retn

loc_rename_direntry_pop_invd_retn:
	stc
loc_rename_direntry_invd_retn:
	mov	eax, 0Dh ; Invalid data
loc_rename_retn:
	retn 

loc_rename_direntry_check_fcluster:
	mov	dx, [edi+20] ; First Cluster HW
	shl	dx, 16
	mov	dx, [edi+26] ; First Cluster LW
	cmp	edx, [DelFile_FCluster]
	jne	short loc_rename_direntry_pop_invd_retn
	; ESI = New file (or directory) name. (ASCIIZ string)
	; 06/03/2016
	; TRDOS v2 - NOTE: 'convert_file_name' procedure
	; has been modified for eliminating following situation.
	; 
	; TRDOS v1 - NOTE: If file/dir name is more than 11 bytes
	; without a dot, attributes (edi+11) byte will be overwritten !
	; (Dot file name input must be proper for 11 byte dir entry
	;  type file name output.) 
	call	convert_file_name

        mov     byte [DirBuff_ValidData], 2
	call	save_directory_buffer
	jc	short loc_rename_retn

loc_rename_direntry_del_ln:
	movzx	edx, byte [DelFile_LNEL]
	or	dl, dl
	jz	short loc_rename_direntry_update_parent_dir_lm_date

	movzx	eax, word [DelFile_EntryCounter]
	sub	eax, edx
	jc	short loc_rename_direntry_invd_retn

loc_rename_direntry_del_ln_continue: 
	; EAX = Directory Entry Number of the long name last entry
	call	delete_longname

loc_rename_direntry_update_parent_dir_lm_date:
	call	update_parent_dir_lmdt
	xor	eax, eax 
	retn

make_fs_directory:
	; temporary (21/02/2016)
	retn

delete_fs_file:
	; temporary (28/02/2016)
	retn

rename_fs_file_or_directory:
	retn
