; ****************************************************************************
; TRDOS386.ASM (TRDOS 386 Kernel - v2.0.0) - Directory Functions : trdosk4.s
; ----------------------------------------------------------------------------
; Last Update: 29/12/2017
; ----------------------------------------------------------------------------
; 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:
	; 05/10/2016
	; 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	esi, PATH_Array
change_prompt_dir_str: ; 05/10/2016 (call from 'set_working_path')
	mov	edi, Current_Directory
	mov	ah, [Current_Dir_Level]
	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:
	; 15/10/2016
	; 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 (Drive not ready!)
	cmc 	; stc
	retn

loc_get_current_drive_not_ready_retn:
	pop	esi
	;mov	eax, 15
	mov	ax, 15 ; 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 -> successful
	;	   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
	mov	eax, 19 ; Bad directory/path name 
	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:
	; 20/11/2017
	; 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
	push	ebp ; 20/11/2017
	call	find_directory_entry
	pop	ebp ; 20/11/2017
	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, 17 ;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 ASCIIZ 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 01h = Bad Command Argument
	; MS-DOS Error Code 01h : 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:
	; 16/10/2016
	; 02/03/2016, 03/03/2016
	; 26/02/2016, 27/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
	; 16/10/2016 (13h -> 30)
	mov	eax, 30 ; 'Disk write-protected' error
	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 eocc
	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:
	; 15/10/2016
	; 23/03/2016
	; 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:
	; 15/10/2016 (0Dh -> 29)
	mov	al, 29 ; Invalid data !
	mov	byte [DirBuff_ValidData], 0
	jmp	short loc_save_dir_buff_retn 

loc_write_directory_to_disk_err:
	; 15/10/2016 (disk write error code, 1Dh -> 18)
	mov	eax, 18 ; Drive not ready or write error 

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:
	; 29/12/2017
	; 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
	; 29/12/2017
	;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:
	; 16/10/2016
	; 15/10/2016
	; 23/03/2016
	; 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
	; 16/10/2016 (12h -> 12)
	mov	eax, 12 ; 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:
	; 15/10/2016 (0Bh -> 28)
	mov	eax, 28 ; Invalid Format !
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 

loc_lcde_validate_dirBuff:
	mov	byte [DirBuff_ValidData], 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
	jnc	short loc_lcde_validate_dirBuff

	; 15/10/2016 
	; (Disk read error instead of drv not ready err)
	mov	eax, 17 ; Drive not ready or read error !
	jmp	short loc_lcde_retn


remove_file:
	; 15/10/2016
	; 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
	; 15/10/2016 (0Bh -> 28)
	mov	al, 28  ; 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:
	; 15/10/2016
	; 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
	; 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: ; 15/10/2016 (0Dh -> 29)
;	mov	eax, 29 ; 0Dh (TRDOS 8086) ; 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:
	; 13/11/2017
	; 15/10/2016
	; 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:
	; 15/10/2016 (0Dh -> 29)
	mov	eax, 29 ; Invalid data
loc_rename_retn:
	retn 

loc_rename_direntry_check_fcluster:
	mov	dx, [edi+20] ; First Cluster HW
	shl	edx, 16 ; 13/11/2017
	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

move_source_file_to_destination_file:
	; 15/10/2016
	; 11/03/2016
	; 10/03/2016 (TRDOS 386 = TRDOS v2.0)
	; 01/08/2011 (FILE.ASM)
	; 04/08/2010
	;
	;   Phase 1 -> Check destination file, 
	;              'not found' is required
	;   Phase 2 -> Check source file
	;              'found' and proper attributes is required
	;   Phase 3 -> Make destination directory entry,
	;           add new dir cluster or section if it is required
	;   Phase 4 -> Delete source directory entry.
	;       cf = 1 causes to return before the phase 4.
	;    (source file protection against any possible errors)    
	;
	; 08/05/2011 major modification
	;            -> destination file deleting is removed   
	;            for msdos move/rename compatibility.
	;            (Access denied error will return if
	;            the destination file is found...)
	; INPUT ->
	;	 ESI = Source File Pathname (Asciiz)
	;        EDI = Destination File Pathname (Asciiz)
	;        AL = 0 --> Interrupt (System call)
	;        AL > 0 --> Command Interpreter (Question)
	;        AL = 1 --> Question Phase
	;        AL = 2 --> Progress Phase        
	; OUTPUT -> 
	;	 cf = 0 -> OK
	;        EAX = Destination directory first cluster
	;        ESI = Logical DOS drive description table 
	;        EBX = Destination file structure offset
	;        CX = 0 (CX > 0 --> calculate free space error)
	;        cf = 1 -> Error code in EAX (AL) 
	;
	;  (EDX, ECX, EBX, ESI, EDI will be changed)

	cmp	al, 2
	je	msftdf_df2_check_directory
	mov	[move_cmd_phase], al

msftdf_parse_sf_path:
	; ESI = ASCIIZ pathname (Source)
	push	edi 
	mov	edi, SourceFile_Drv
	call	parse_path_name
	pop	esi
	jc	short msftdf_psf_retn

msftdf_parse_df_path:
	; ESI = ASCIIZ pathname	(Destination)
	mov	edi, DestinationFile_Drv
	call	parse_path_name
	jnc	short msftdf_check_sf_drv

	cmp	al, 1 ; File or directory name is not existing
	jna	short msftdf_check_sf_drv

msftdf_stc_retn:
	stc
msftdf_psf_retn:
	retn 

msftdf_check_sf_drv:
	mov	al, [SourceFile_Drv]

msftdf_check_df_drv:
	mov	dl, [DestinationFile_Drv]

msftdf_compare_sf_df_drv:
	sub	ebx, ebx
	mov	bh, [Current_Drv]
	cmp	dl, al
	je	short msftdf_check_sf_df_drv_ok

msftdf_not_same_drv:
        ; DL = source file's drive number
	mov	dh, al ; destination file's drive number
	; 15/10/2016 (11h -> 21)
	mov	eax, 21 ; Not the same drive
	stc
	retn 

msftdf_check_sf_df_drv_ok:
	mov	[msftdf_sf_df_drv], dl

        sub	eax, eax
	mov	ah, dl
	add	eax, Logical_DOSDisks
	mov	[msftdf_drv_offset], eax

	cmp	dl, bh ; byte [Current_Drv]
	je	short msftdf_df_check_directory

msftdf_change_drv:
	call 	change_current_drive
	jc	short msftdf_df_error_retn
	  
msftdf_check_destination_file:
msftdf_df_check_directory:
	mov	esi, DestinationFile_Directory
	cmp	byte [esi], 20h
	jna	short msftdf_df_find_1

msftdf_df_change_directory:
	inc	byte [Restore_CDIR]
	xor	ah, ah ; CD_COMMAND sign -> 0 
	call	change_current_directory
	jc	short msftdf_df_error_retn

;msftdf_df_change_prompt_dir_string:
;	call 	change_prompt_dir_string

msftdf_df_find_1:
        mov     esi, DestinationFile_Name
	cmp	byte [esi], 20h
	jna	short msftdf_df_copy_sf_name

msftdf_df_find_2:
	xor	ax, ax ; DestinationFile_AttributesMask -> any/zero
	call	find_first_file
	jnc	msftdf_permission_denied_retn

msftdf_df_check_error_code:
	;cmp	eax, 2 ; File not found error
	cmp	al, 2
	jne	short msftdf_df_stc_retn
              
msftdf_df_check_fname:
	; 15/10/2016
	mov	esi, DestinationFile_Name ; *
	call	check_filename
	jnc	short msftdf_convert_df_direntry_name
	; invalid file name chars !
	mov	eax, ERR_INV_FILE_NAME  ; 26
	jmp	short msftdf_df_stc_retn

msftdf_convert_df_direntry_name:
	; mov	esi, DestinationFile_Name ; *
	mov	edi, DestinationFile_DirEntry
	call	convert_file_name
  	jmp	short msftdf_restore_current_dir_1

msftdf_df_copy_sf_name:
	mov	edi, esi
	push	edi 
        mov     esi, SourceFile_Name
	mov	ecx, 12
msftdf_df_copy_sf_name_loop:
	lodsb
        stosb
	or	al, al
	jz	short msftdf_df_copy_sf_name_ok	
        loop    msftdf_df_copy_sf_name_loop
msftdf_df_copy_sf_name_ok:	
	pop	esi  
	jmp	short msftdf_df_find_2

msftdf_df_stc_retn:
	stc
msftdf_restore_cdir_failed:
msftdf_df_error_retn:
	retn

msftdf_restore_current_dir_1:
	cmp	byte [Restore_CDIR], 0
	jna	short msftdf_sf_check_directory
	mov	esi, [msftdf_drv_offset] 
	call	restore_current_directory
	jc	short msftdf_restore_cdir_failed

msftdf_sf_check_directory:
	mov	esi, SourceFile_Directory
	cmp	byte [esi], 20h
	jna	short msftdf_sf_find
msftdf_sf_change_directory:
	inc	byte [Restore_CDIR]
	xor	ah, ah ; CD_COMMAND sign -> 0 
	call	change_current_directory
	jc	short msftdf_return

;msftdf_sf_change_prompt_dir_string:
;	call	change_prompt_dir_string

msftdf_sf_find:
        mov     esi, SourceFile_Name  ; Offset 66
	mov	ax, 1800h ; Only files
	call	find_first_file
	jc	short msftdf_return

msftdf_sf_ambgfn_check:
	or	dx, dx ; Ambiguous filename chars used sign (DX>0)
	jz	short msftdf_sf_found

msftdf_ambiguous_file_name_error:
	mov	eax, 2 ; File not found error
	stc
	retn

msftdf_sf_found:
	and	bl, 1Fh ; Attributes, D-V-S-H-R
	jz	short msftdf_save_sf_structure

msftdf_permission_denied_retn:
	mov	eax, 05h ; Access (Permission) denied !
	stc
msftdf_rest_cdir_err_retn:
msftdf_return:
	retn

msftdf_phase_1_return:
	xor	eax, eax
	mov	[move_cmd_phase], al ; 0
	inc	al ; mov al, 1
	mov	ebx, msftdf_df2_check_directory
	;mov	edx, 0FFFFFFFFh 
	retn

msftdf_save_sf_structure:
	mov	esi, FindFile_DirEntry
	mov	edi, SourceFile_DirEntry
	mov	ecx, 8
	rep	movsd

msftdf_df_copy_sf_parameters:
	mov	esi, 11
	mov	edi, esi
	add	esi, SourceFile_DirEntry
	add	edi, DestinationFile_DirEntry
	;mov	ecx, 21
	mov	cl, 21
	rep	movsb

msftdf_restore_current_dir_2:
	cmp	byte [Restore_CDIR], 0
	jna	short msftdf_df2_check_move_cmd_phase
 	mov	esi, [msftdf_drv_offset]
	call	restore_current_directory
	jc	short msftdf_rest_cdir_err_retn

msftdf_df2_check_move_cmd_phase:
	cmp	byte [move_cmd_phase], 1
	je	short msftdf_phase_1_return

msftdf_df2_check_directory:
	mov	esi, DestinationFile_Directory
	cmp	byte [esi], 20h
	jna	short msftdf_make_dfde_locate_ffe_on_directory
msftdf_df2_change_directory:
	inc	byte [Restore_CDIR]
	xor	ah, ah ; CD_COMMAND sign -> 0 
	call	change_current_directory
	jc	short msftdf_return

;msftdf_df2_change_prompt_dir_string:
;	call	change_prompt_dir_string

msftdf_make_dfde_locate_ffe_on_directory:
	; Current directory fcluster <> Directory buffer cluster
	; Current directory will be reloaded by
	; 'locate_current_dir_file' procedure
	;
	;xor	ax, ax
	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	msftdf_make_dfde_set_ff_dir_entry
	
	;cmp	eax, 2
        cmp	al, 2
	jne	short msftdf_error_retn

msftdf_add_new_dir_entry_check_fs:
	mov	esi, [msftdf_drv_offset]
	mov 	eax, [DirBuff_Cluster]
	cmp	byte [esi+LD_FATType], 0
	ja	short msftdf_add_new_subdir_cluster

msftdf_add_new_fs_subdir_section:
	;CL=0, CH=E5h --> deleted entry, CH=0 --> free entry
        ;xor	cx, cx
	xor	ch, ch ; cx = 0 --> add a new subdir section
	call	add_new_fs_section
        jc	short msftdf_dsfde_error_retn
	;mov	[createfile_LastDirCluster], eax

	call	load_FS_sub_directory 
	;mov	ebx, Directory_Buffer 
	jnc	short msftdf_add_new_fs_subdir_section_ok
	retn	 

msftdf_add_new_subdir_cluster:
	call	add_new_cluster
	jc	short msftdf_dsfde_error_retn
	
	;mov	[createfile_LastDirCluster], eax

	call	load_FAT_sub_directory
	jnc	short msftdf_add_new_subdir_cluster_ok
	; EBX = Directory buffer address

msftdf_ansdc_update_parent_dir_lmdt:
msftdf_make_dfde_err_upd_pdir_lmdt:
	push	eax
	call	update_parent_dir_lmdt
	pop	eax

msftdf_error_retn:
	stc
msftdf_dsfde_restore_cdir_failed:
msftdf_dsfde_error_retn:
	retn

msftdf_add_new_fs_subdir_section_ok:
msftdf_add_new_subdir_cluster_ok:
	mov	edi, ebx ; Directory buffer address

msftdf_make_dfde_set_ff_dir_entry:
	mov	edx, [Current_Dir_FCluster]
	mov	[createfile_FFCluster], edx
	; EDI = Directory entry offset
	mov	esi, DestinationFile_DirEntry
	mov	ecx, 8
	rep	movsd

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

msftdf_make_dfde_update_pdir_lmdt:
	call	update_parent_dir_lmdt

msftdf_dsfde_restore_current_dir_1:
	cmp	byte [Restore_CDIR], 0
	jna	short msftdf_dsfde_check_directory
 	mov	esi, [msftdf_drv_offset]
	call	restore_current_directory
	jc	short msftdf_dsfde_restore_cdir_failed

msftdf_dsfde_check_directory:
	mov	esi, SourceFile_Directory
	cmp	byte [esi], 20h
	jna	short msftdf_dsfde_find_file

msftdf_dsfde_change_directory:
	inc	byte [Restore_CDIR]
	sub	ah, ah ; CD_COMMAND sign -> 0 
	call	change_current_directory
	jc	short msftdf_dsfde_error_retn

;msftdf_dsfde_sf_change_prompt_dir_string:
;	call	change_prompt_dir_string

msftdf_dsfde_find_file:
	mov	esi, SourceFile_Name  ; Offset 66
	mov	ax, [esi+14] ; 80 -> SourceFile_AttributesMask
	call	find_first_file
	jc	short msftdf_dsfde_error_retn

msftdf_dsfde_delete_direntry:
	mov	esi, [msftdf_drv_offset]
	
	cmp	byte [esi+LD_FATType], 0
	ja	short msftdf_delete_FAT_direntry
	
	xor	bl, bl
	; BL = 0 -> File
	; EDI -> Directory buffer entry offset/address 
	call	delete_fs_directory_entry
	jnc	short msftdf_dsfde_restore_current_dir_2
	retn

msftdf_delete_FAT_direntry:	
	mov	bl, [FindFile_LongNameEntryLength]
	mov	cx, [FindFile_DirEntryNumber]
	; ESI = Logical DOS drive description table address
	; EDI = Directory buffer entry offset/address 
	call	delete_directory_entry
	jc	short msftdf_retn

msftdf_dsfde_restore_current_dir_2:
	cmp	byte [Restore_CDIR], 0
	jna	short msftdf_new_dir_fcluster_retn
	;mov	esi, [msftdf_drv_offset]
	call	restore_current_directory
	jc	short msftdf_retn

msftdf_new_dir_fcluster_retn:
	xor	ecx, ecx 
	mov	eax, [createfile_FFCluster]
	mov	ebx, DestinationFile_Drv

msftdf_retn:
	retn


copy_source_file_to_destination_file:
	; 17/10/2016
	; 16/10/2016
	; 15/10/2016
	; 30/03/2016, 31/03/2016
	; 24/03/2016, 25/03/2016, 28/03/2016
	; 21/03/2016, 22/03/2016, 23/03/2016
	; 16/03/2016, 17/03/2016, 18/03/2016
	; 15/03/2016 (TRDOS 386 = TRDOS v2.0)
	; 02/09/2011 (FILE.ASM 'copy_source_file_to_destination_file')
	; 01/08/2010 - 18/05/2011
	;
	;   Command Interpreter phase 1 enter ->
	;           AL = 1 -> Caller is command interpreter
	;           AL = 2 -> The second call, re-enter/continue
	;   Phase 1 -> Check source file
	;              'found' is required
	;   Phase 2 -> Check destination file, 
	;              save 'found' or 'not found' status
	;              'permission denied' error will be return
	;              if attributes have not for ordinary file 
	;              without readonly attribute
	;   Command Interpreter phase 1 return ->
	;              DH = Source file attributes
	;              DL = Destination file found status
	;              EAX = 0 
	;   Command Interpreter phase 2 enter ->
	;              AL = 2 -> Continue from the last position
	;              AH = 
	;   Phase 3 -> Load source file or use read/write cluster method
	;   Phase 4 -> Create destination file if it is not found
	;   Phase 5 -> Open destination file
	;   Phase 6 -> Read from source and write to destination
	;   Phase 7 -> Unload source file, if it is loaded at memory
	;       cf = 1 causes to return before the phase 7
	;              but loaded file will be unloaded
	;	       (allocated memory block will be deallocated) 
	;
	; INPUT -> 
	;	 ESI = Source File Pathname (Asciiz)
	;        EDI = Destination File Pathname (Asciiz)
	;        AL = 0 --> Interrupt (System call)
	;        AL > 0 --> Command Interpreter (Question)
	;        AL = 1 --> Question Phase
	;        AL = 2 --> Progress Phase        
	;
	; OUTPUT -> 
	;	cf = 0 -> OK
	;	EAX = Destination file first cluster
	;
	;        CL > 0 if there is file reading error before EOF
	;	        (incomplete copy) 
	;        CH > 0 if file is (full) loaded at memory
	;
	;	cf = 1 -> Error code in AL (EAX) 
	;
	; (EBX, ECX, ESI, EDI register contents will be changed)           


	cmp	al, 2
	je	csftdf2_check_cdrv

; Phase 1

	mov	byte [copy_cmd_phase], al

	push	edi ; *

csftdf_parse_sf_path:
	mov	edi, SourceFile_Drv
	call	parse_path_name
	jc	short csftdf_parse_sf_path_failed

csftdf_parse_df_path:	
	pop	esi ; * (pushed edi) 

csftdf_sf_check_filename_exists:
	cmp	byte [SourceFile_Name], 21h
	jb	short csftdf_sf_file_not_found_error

	mov	edi, DestinationFile_Drv
	call	parse_path_name
	jnc	short csftdf_check_sf_cdrv
	
	cmp	al, 1 ; File or directory name is not existing
	jna	short csftdf_check_sf_cdrv

csftdf_parse_df_path_failed:
	stc 
csftdf_sf_error_retn: 
	retn

csftdf_parse_sf_path_failed:	
	pop	edi ; *
	jmp	short csftdf_sf_error_retn

csftdf_sf_file_not_found_error:
	mov	eax, 2 ; File not found 
	jmp	short csftdf_sf_error_retn

csftdf_check_sf_cdrv:
	mov	bh, [Current_Drv]

	mov	[csftdf_cdrv], bh ; 23/03/2016

	mov	dl, [SourceFile_Drv]
	cmp	dl, bh ; byte [Current_Drv]
	je	short csftdf_sf_check_directory

	call	change_current_drive
	jc	short csftdf_sf_error_retn

csftdf_sf_check_directory:
	mov	esi, SourceFile_Directory
	cmp	byte [esi], 20h
	jna	short csftdf_find_sf

csftdf_sf_change_directory:
	inc	byte [Restore_CDIR]
	xor	ah, ah ; CD_COMMAND sign -> 0 
	call	change_current_directory
	jc	short csftdf_sf_error_retn

;csftdf_sf_change_prompt_dir_string:
;	call	change_prompt_dir_string

csftdf_find_sf:
	mov	esi, SourceFile_Name
	mov	ax, 1800h ; Except volume label and dirs
	call	find_first_file
	jc	short csftdf_sf_error_retn

csftdf_sf_ambgfn_check:
	and	dx, dx ; Ambiguous filename chars used sign (DX>0)
	jz	short csftdf_sf_found

csftdf_ambiguous_file_name_error:
	mov	eax, 2 ; File not found error
	stc
	retn

csftdf_sf_found:
	mov	[csftdf_filesize], eax

	or	eax, eax
	jnz	short csftdf_set_source_file_direntry

csftdf_sf_file_size_zero:
	mov	eax, 20 ; TRDOS zero length (file size) error
	stc
	retn

csftdf_set_source_file_direntry:
	mov	esi, FindFile_DirEntry
	mov	edi, SourceFile_DirEntry
	mov	ecx, 8
	rep	movsd

csftdf_sf_restore_cdrv:
	; 22/03/2016
	mov	dl, [csftdf_cdrv]
	cmp	dl, [Current_Drv]
	je	short csftdf_sf_restore_cdir
	call	change_current_drive 
	jc	short csftdf_df_error_retn ; 30/03/2016

csftdf_sf_restore_cdir:
	cmp	byte [Restore_CDIR], 0
	jna	short csftdf_df_check_filename_exists
	sub	eax, eax
	mov	esi, Logical_DOSDisks
	mov	ah, dl ; byte [csftdf_cdrv]
	add	esi, eax
	call	restore_current_directory
	jc	short csftdf_df_error_retn
  
csftdf_df_check_filename_exists:
	cmp	byte [DestinationFile_Name], 20h
	ja	short csftdf_check_df_cdrv

csftdf_copy_sf_name:
	mov	edi, DestinationFile_Name
	mov	esi, SourceFile_Name
	mov	cl, 12

csftdf_df_copy_sf_name_loop:
	lodsb
	stosb
	or	al, al
	jz	short csftdf_check_df_cdrv             
	dec	cl
	jnz	csftdf_df_copy_sf_name_loop

csftdf_check_df_cdrv:
	mov	dl, [DestinationFile_Drv]
	cmp	dl, [Current_Drv]
	je	short csftdf_df_check_directory

	call	change_current_drive
	jnc	short csftdf_df_check_directory

csftdf_df_error_retn:
	retn

csftdf_df_check_directory:
	mov	esi, DestinationFile_Directory
        cmp     byte [esi], 20h
	jna	short csftdf_find_df

csftdf_df_change_directory:
	inc	byte [Restore_CDIR]
	sub	ah, ah ; CD_COMMAND sign -> 0 
	call	change_current_directory
	jc	short csftdf_df_error_retn

;csftdf_df_change_prompt_dir_string:
;	call	change_prompt_dir_string

csftdf_find_df:
	; 23/03/2016
	sub	ebx, ebx
	mov	bh,  [DestinationFile_Drv]
	add	ebx, Logical_DOSDisks
	mov	[csftdf_df_drv_dt], ebx

	mov	esi, DestinationFile_Name
	xor	ax, ax 
		; DestinationFile_AttributesMask -> any/zero
	call	find_first_file
	jc	short csftdf_df_check_error_code

csftdf_df_ambgfn_check:
	or	dx, dx ; Ambiguous filename chars used sign (DX>0)
	jnz	short csftdf_df_error_inv_fname
	
csftdf_df_found:
	mov	byte [DestinationFileFound], 1
	; 17/10/2016 (cl -> bl)
	and	bl, 1Fh ; Attributes, D-V-S-H-R
	jz	short csftdf_df_save_first_cluster

csftdf_df_permission_denied_retn:	 
	mov	eax, 05h ; Access/Permission denied.
csftdf_df_error_stc_retn:
	stc
	retn

csftdf_df_check_error_code:
	;cmp	eax, 2
	cmp	al, 2
	jne	short csftdf_df_error_stc_retn

	mov	byte [DestinationFileFound], 0

	; 15/10/2016
	mov	esi, FindFile_Name ; *
	call	check_filename
	jnc	short csftdf_df_valid_fname
csftdf_df_error_inv_fname: ; 'invalid file name !'
	mov 	eax, ERR_INV_FILE_NAME  ; 26
	stc	
	retn

csftdf_df_valid_fname:	
	; 21/03/2016
	; (Capitalized file name)
	;mov	esi, FindFile_Name ; * ; 15/10/2016
	mov	edi, DestinationFile_Name
	movsd
	movsd	
	movsd
	;movsb

csftdf_check_disk_free_size_0:
	mov	eax, [SourceFile_DirEntry+DirEntry_FileSize]

csftdf_check_disk_free_size_1:
	;sub	ebx, ebx
	;mov 	esi, Logical_DOSDisks
	;mov	bh,  [DestinationFile_Drv]
	;add	esi, ebx
	
	mov	esi, [csftdf_df_drv_dt] ; 23/03/2016

	movzx	ecx, word [esi+LD_BPB+BytesPerSec] ; 17, LD_BPB + 0Bh
	add	eax, ecx
	dec	eax  ; file size (additional bytes) + 511 (round up)
csftdf_check_disk_free_size_3: ; 16/03/2016
	sub	edx, edx
	div	ecx ; bytes per sector

csftdf_check_disk_free_size:
	cmp	eax, [esi+LD_FreeSectors]
        jb      csftdf_check_disk_free_size_ok
	ja	short csftdf_df_insufficient_disk_space

	cmp	byte [esi+LD_FATType], 0 ; FS needs FDT sector also.
        ja      csftdf_check_disk_free_size_ok 

csftdf_df_insufficient_disk_space:
	mov	eax, 27h ; insufficient disk space
	jmp	short csftdf_df_error_stc_retn

csftdf_df_save_first_cluster:
	; ESI = FindFile_DirEntry (for the old destination file)
	; EAX = Old destination file size
	; 24/03/2016
	; EDI = Directory entry address (within Dir Buffer boundaries)
	sub	edi, Directory_Buffer  ; (<65536)
	shr	di, 5 ; Convert entry offset to entry index/number
	mov	[DestinationFile_DirEntryNumber], di ; (<2048)

csftdf_df_check_sf_df_fcluster:
	mov	dx, [esi+DirEntry_FstClusHI]
	shl	edx, 16
	mov	dx, [esi+DirEntry_FstClusLO]
	mov	[csftdf_df_cluster], edx
csftdf_df_check_sf_df_fcluster_1:
	mov	dx, [SourceFile_DirEntry+DirEntry_FstClusHI]
	shl	edx, 16
	mov	dx, [SourceFile_DirEntry+DirEntry_FstClusLO]
	cmp	edx, [csftdf_df_cluster]
	jne	short csftdf_df_check_sf_df_fcluster_ok
csftdf_df_check_sf_df_drv:
	mov	dl, [SourceFile_Drv]
	cmp	dl, [DestinationFile_Drv]
	jne	short csftdf_df_check_sf_df_fcluster_ok

	; source and destination files are same !
	; (they have same first cluster value on same logical disk)

	xor	eax, eax ; mov eax, 0 -> Bad command or file name !
	stc
	retn 
   
csftdf_df_check_sf_df_fcluster_ok:
csftdf_df_move_findfile_struct:
	; mov	esi, FindFile_DirEntry
	mov	edi, DestinationFile_DirEntry
	mov	ecx, 8
	rep	movsd
	
csftdf_check_disk_free_size_2:
	mov	edx, eax ; Old destination file size

	;mov	eax, [SourceFile_DirEntry+DirEntry_FileSize]
	mov	eax, [csftdf_filesize] ; 23/03/2016

	;;sub	ecx, ecx ; 0
	;mov 	esi, Logical_DOSDisks
	;mov	ch,  [DestinationFile_Drv]
	;add	esi, ecx
	;
	;mov	[csftdf_df_drv_dt], esi

	mov	esi, [csftdf_df_drv_dt] ; 23/03/2016

	mov	cx, [esi+LD_BPB+BytesPerSec] ; 17, LD_BPB + 0Bh
	add	edx, ecx ; + 512
	add	eax, ecx ; + 512
	dec	edx ; old file size + 511 (round up)
	dec	eax ; new file size + 511 (round up)
	neg	ecx ; -512 ; 0FFFFFE00h
	and	edx, ecx ; = old sector count * 512 
	and	eax, ecx ; = new sector count * 512 

	sub	eax, edx ; new file size - old file size (on disk)
	jna	short csftdf_check_disk_free_size_ok

	neg	ecx ; 512 (bytes per sector) ; 200h
	; check free space for additional sectors
	; eax = number of additional sectors * bytes per sector
	; esi = Logical DOS drive number (of destination disk)
        jmp     csftdf_check_disk_free_size_3
 
csftdf_check_disk_free_size_ok:
	; 18/03/2016
csftdf_df_check_copy_cmd_phase:
	mov	al, [copy_cmd_phase]
	cmp	al, 1
	jne	short csftdf2_check_cdrv
	
	xor	eax, eax
	mov	[copy_cmd_phase], al ; 0

	mov	dl, [DestinationFileFound]            
	mov	dh, [SourceFile_DirEntry+11] ; Attributes
 
csftdf_return:	
	retn

; Phase 2

csftdf2_check_cdrv:
	; 18/03/2016
	; Here, destination drive and directory are ready !
	; (checking/restoring is not needed)
	; (Since at the end of the phase 1)

;	mov	dl, [DestinationFile_Drv]
;	cmp	dl, [Current_Drv]
;	je	short csftdf2_df_check_directory
;
;	call	change_current_drive
;	jc	short csftdf2_read_error
;
;csftdf2_df_check_directory:
;	mov	esi, DestinationFile_Directory  
;	cmp	byte [esi], 20h
;	jna	short csftdf2_df_check_found_or_not
;
;csftdf2_df_change_directory:
;	inc	byte [Restore_CDIR]
;	xor	ah, ah ; CD_COMMAND sign -> 0 
;	call	change_current_directory
;	jc	short csftdf2_stc_return
;
;;csftdf2_df_change_prompt_dir_string:
;;	call	change_prompt_dir_string

csftdf2_df_check_found_or_not:
	; 21/03/2016
	cmp	byte [DestinationFileFound], 0 
	ja	short csftdf2_set_sf_percentage

csftdf2_create_file:
	mov	esi, DestinationFile_Name
	mov	eax, [csftdf_filesize]
	xor	cl, cl ; 0

	xor	ebx, ebx ; 0
	dec	ebx ; 0FFFFFFFFh 

	; INPUT ->
	; 	EAX -> File Size
	; 	ESI = ASCIIZ File name
	;	 CL = File attributes
	;	EBX = FFFFFFFFh -> empty file sign for FAT fs
	;	EBX <> FFFFFFFFh -> use file size for FAT fs 
	;
	; OUTPUT ->
	;	EAX = New file's first cluster
	;	ESI = Logical Dos Drv Descr. Table Addr.
	;	EBX = CreateFile_Size address
	;	ECX = Sectors per cluster (<256)
	;	EDX = Directory Entry Index/Number (<65536)
	;		
	;	cf = 1 -> error code in AL (EAX)

	call	create_file
	;pop	esi
        jc      csftdf2_rw_error

csftdf2_create_file_OK:
	mov	[csftdf_df_cluster], eax
	
	; 24/03/2016
	mov	[DestinationFile_DirEntryNumber], dx 

	; 21/03/2016
	mov	esi, Directory_Buffer
	shl	edx, 5 ; 32 * index number
	add	esi, edx
	mov	edi, DestinationFile_DirEntry	
	mov	cl, 8 ; 32 bytes
	rep	movsd

csftdf2_set_sf_percentage:
	; 17/03/2016
	xor	eax, eax	
	mov 	[csftdf_percentage], al ; 0, reset

	mov	[csftdf_sf_rbytes], eax ; 0, reset
	mov	[csftdf_df_wbytes], eax ; 0, reset

	mov	ah, [SourceFile_Drv]	
	mov	esi, Logical_DOSDisks
	add	esi, eax
	
	mov	[csftdf_sf_drv_dt], esi ; 23/03/2016

	mov	dx, [SourceFile_DirEntry+DirEntry_FstClusHI]
	shl	edx, 16
	mov	dx, [SourceFile_DirEntry+DirEntry_FstClusLO]
	mov	[csftdf_sf_cluster], edx

	; 16/03/2016
	; Note: Singlix FS boot sector parameters (for cluster
	;	related calculations) has same offset
	;	values from LD_BPB as in FAT file system.
	;	[esi+LD_BPB+SecPerClust] is 1 for Singlix FS.
	;	
	movzx	ecx, byte [esi+LD_BPB+SecPerClust]
	mov	[SourceFile_SecPerClust], cl

	; 17/03/2016
	cmp	[esi+LD_FATType], ch ; 0
	ja	short csftdf2_set_sf_percent_rsize1

	mov	eax, 65536 ; read/write buffer size for Singlix FS
	jmp	short csftdf2_set_sf_percent_rsize2	
 
csftdf2_set_sf_percent_rsize1:
	mov	ax, [esi+LD_BPB+BytesPerSec]
	mul	ecx
	;sub	edx, edx
csftdf2_set_sf_percent_rsize2:
	mov	[csftdf_r_size], eax

csftdf2_set_df_percentage:
	;sub	eax, eax
	;mov	ah, [DestinationFile_Drv]	
	;mov	edi, Logical_DOSDisks
	;add	edi, eax
	;mov	[csftdf_df_drv_dt], edi ; 17/03/2016

	mov	edi, [csftdf_df_drv_dt] ; 23/03/2016

	; 16/03/2016
	; Note: Singlix FS boot sector parameters (for cluster
	;	related calculations) has same offset
	;	values from LD_BPB as in FAT file system.
	;	[edi+LD_BPB+SecPerClust] is 1 for Singlix FS.
	;	
	;movzx	ecx, byte [edi+LD_BPB+SecPerClust]
	mov	cl, [edi+LD_BPB+SecPerClust]
	mov	[DestinationFile_SecPerClust], cl

	; 17/03/2016
	cmp	[edi+LD_FATType], ch ; 0
	ja	short csftdf2_set_df_percent_wsize1
	
	mov	eax, 65536 ; read/write buffer size for Singlix FS
	jmp	short csftdf2_set_df_percent_wsize2	

csftdf2_set_df_percent_wsize1:
	movzx	eax, word [edi+LD_BPB+BytesPerSec]
	mul	ecx
	;sub	edx, edx
csftdf2_set_df_percent_wsize2:
	mov	[csftdf_w_size], eax

	mov	eax, [csftdf_filesize]

	cmp	eax, 65536 ; 64KB	; small file
	jb	short csftdf2_load_file ; do not display percentage
	
csftdf2_reset_wf_percent_ptr_chk_64k:
	mov	dl, 1 ; 25/03/2016

	cmp	eax, 65536*4 ; 256KB
	jnb	short csftdf2_enable_percentage_display ; big file

	; 64-128KB file size for floppy disks
	cmp	byte [SourceFile_Drv], dl ; 1 ; read from floppy disk ?
	jna	short csftdf2_enable_percentage_display

	cmp	byte [DestinationFile_Drv], dl ; 1 ; write to floppy disk ?
	ja	short csftdf2_load_file

csftdf2_enable_percentage_display:	
	mov	[csftdf_percentage], dl ; 1	
	
csftdf2_load_file:
	; 13/05/2016
	; 19/03/2016
	; 18/03/2016
	; 17/03/2016
	mov	ah, 0Fh
	call	_int10h
	; 13/05/2016
	mov	[csftdf_videopage], bh ; active video page
	mov	ah, 03h
	call	_int10h
	mov	[csftdf_cursorpos], dx

	sub	eax, eax
	mov	[csftdf_rw_err], al ; 0 

; ///
csftdf_sf_amb: ; 15/03/2016
	mov	ecx, [csftdf_filesize]	; 23/03/2016

	; TRDOS 386 (TRDOS v2.0)
	; Allocate contiguous memory block for loading the file
	
	;mov	ecx, [SourceFile_DirEntry+DirEntry_FileSize]
	
	;sub	eax, eax ; First free memory aperture
	
	; eax = 0 (Allocate memory from the beginning)
	; ecx = File (Allocation) size in bytes
	
	call	allocate_memory_block
	jnc	short loc_check_sf_save_loading_parms

	sub	eax, eax
	sub	ecx, ecx
	
loc_check_sf_save_loading_parms:
	mov	[csftdf_sf_mem_addr], eax ; loading address
	mov	[csftdf_sf_mem_bsize], ecx ; block size
; ///   
	; 19/03/2016
	mov	esi, [csftdf_sf_drv_dt] ; logical dos drv desc. tbl.

	; 17/03/2016
	or	eax, eax ; contiguous free memory block address 
        jz      csftdf2_read_sf_cluster

	; 18/03/2016
	mov	ebx, [csftdf_sf_mem_addr] ; memory block address

	cmp	byte [esi+LD_FATType], 0
        jna     csftdf2_load_fs_file

csftdf2_load_fat_file:
	push	ebx ; *

csftdf2_load_fat_file_next:
	mov	esi, msg_reading
	call	print_msg

	cmp	byte [csftdf_percentage], 0
	jna	short csftdf2_load_fat_file_1
	
	call	csftdf2_print_percentage ; 19/03/2016

csftdf2_load_fat_file_1:
	mov	esi, [csftdf_sf_drv_dt]	
	pop	ebx ; *

csftdf2_load_fat_file_2:
	call	csftdf2_read_fat_file_sectors ; 19/03/2016
        jc      csftdf2_rw_error ; eocc! or disk error! 

	or	edx, edx ; edx > 0 -> EOF
	jnz	short csftdf2_load_fat_file_ok

	cmp	byte [csftdf_percentage], 0
	jna	short csftdf2_load_fat_file_2

	push	ebx ; *	

	; Set cursor position
	; AH= 02h, BH= Page Number, DH= Row, DL= Column
	mov	bh, [csftdf_videopage]
	mov	dx, [csftdf_cursorpos]
	mov	ah, 2
	call	_int10h
	jmp	short csftdf2_load_fat_file_next
	
csftdf2_load_fat_file_ok:
	cmp	byte [csftdf_percentage], 0
        jna     csftdf2_save_file ; 25/03/2016
	
	; "Reading... 100%"
	mov	edi, percentagestr
	mov	al, '1'
	stosb
	mov	al, '0'
	stosb
	stosb

	mov	bh, [csftdf_videopage]
	mov	dx, [csftdf_cursorpos]
	mov	ah, 2
	call	_int10h

	mov	esi, msg_reading
	call	print_msg
	
	mov	esi, percentagestr
	call	print_msg

        jmp     csftdf2_save_file ; 25/03/2016

csftdf2_print_percentage:
	; 09/12/2017
	; 19/03/2016
	; 18/03/2016
	mov	al, 20h
	mov	edi, percentagestr
	stosb
	stosb
	mov	eax, [csftdf_sf_rbytes]
	mov	edx, 100
	mul	edx
	mov	ecx, [csftdf_filesize]	
	div	ecx
	mov	cl, 10
	div	cl
	add	ah, '0'
	mov	[edi], ah
	and	al, al
	jz	short csftdf2_print_percent_1
	dec	edi
	;cbw
	sub	ah, ah ; 09/12/2017
	div	cl
	add	ah, '0'
	mov	[edi], ah
	;and	al, al
	;jz	short csftdf2_print_percent_1
	;dec	edi
	;mov	[edi], '1' ; 100%		

csftdf2_print_percent_1:
	mov	esi, percentagestr
	;call	print_msg
	;retn
	jmp	print_msg

csftdf2_read_file_sectors:
	; 19/03/2016
	cmp	byte [esi+LD_FATType], 0
        jna     csftdf2_read_fs_file_sectors

csftdf2_read_fat_file_sectors:
	; 19/03/2016
	; 18/03/2016
	; return:
	;   CF = 0 & EDX > 0 -> END OF FILE
	;   CF = 0 & EDX = 0 -> not EOF
	;   CF = 1 -> read error (error code in AL)	

csftdf2_read_fat_file_secs_0:
	mov	edx, [csftdf_filesize]
	sub	edx, [csftdf_sf_rbytes]
	cmp	edx, [csftdf_r_size]	
	jnb	short csftdf2_read_fat_file_secs_1
	mov	[csftdf_r_size], edx
		
csftdf2_read_fat_file_secs_1:
	mov	eax, [csftdf_r_size]
	sub	edx, edx
	movzx	ecx, word [esi+LD_BPB+BytesPerSec]
	add	eax, ecx
	dec	eax
	div	ecx
	mov	ecx, eax ; sector count
	mov	eax, [csftdf_sf_cluster]

	; EBX = memory block address (current)
	
	call	read_fat_file_sectors
	jc	short csftdf2_read_fat_file_secs_3

	; EBX = next memory address

	mov	eax, [csftdf_sf_rbytes]
	add	eax, [csftdf_r_size]
	mov	edx, [csftdf_filesize]
	cmp	eax, edx
	jnb	short csftdf2_read_fat_file_secs_3 ; edx > 0
	mov	[csftdf_sf_rbytes], eax

	push	ebx ; *
	; get next cluster (csftdf_r_size! bytes)
	mov	eax, [csftdf_sf_cluster]
	call	get_next_cluster
	pop	ebx ; *
	jnc	short csftdf2_read_fat_file_secs_2

	; 15/10/2016
	;Disk read error instad of drv not ready err
	mov	eax, 17 ; Read error !
	retn

csftdf2_read_fat_file_secs_2:
	sub	edx, edx ; 0
	mov	[csftdf_sf_cluster], eax ; next cluster

csftdf2_read_fat_file_secs_3:
	retn

csftdf2_read_sf_cluster:
	; 19/03/2016
	mov	ebx, Cluster_Buffer ; buffer address (64KB)

	cmp	byte [csftdf_percentage], 0
	jna	short csftdf2_read_sf_clust_2

	push	ebx ; *	

csftdf2_read_sf_clust_next:
	call	csftdf2_print_percentage

csftdf2_read_sf_clust_0:
	mov	esi, [csftdf_sf_drv_dt]	
csftdf2_read_sf_clust_1:
	pop	ebx ; *

csftdf2_read_sf_clust_2:
	mov	edx, ebx
	add	edx, [csftdf_r_size]
	cmp	edx, Cluster_Buffer + 65536
	ja	short csftdf2_write_df_cluster

	call	csftdf2_read_file_sectors ; 19/03/2016
        jc      csftdf2_save_fat_file_err2 ; eocc! or disk error! 

	or	edx, edx ; edx > 0 -> EOF
	jnz	short csftdf2_write_df_cluster

	cmp	byte [csftdf_percentage], 0
	jna	short csftdf2_read_sf_clust_2

	push	ebx ; *	

	; Set cursor position
	; AH= 02h, BH= Page Number, DH= Row, DL= Column
	mov	bh, [csftdf_videopage]
	mov	dx, [csftdf_cursorpos]
	mov	ah, 2
	call	_int10h
	jmp	short csftdf2_read_sf_clust_next

csftdf2_write_df_cluster:
	; 19/03/2016
	mov	esi, [csftdf_df_drv_dt]	
	mov	ebx, Cluster_Buffer ; buffer address (64KB)

csftdf2_write_df_clust_next:
	call	csftdf2_write_file_sectors ; 19/03/2016
        jc      csftdf2_save_fat_file_err2 ; eocc! or disk error! 

	or	edx, edx ; edx > 0 -> EOF
	jnz	short csftdf2_rw_f_clust_ok

	cmp	ebx, Cluster_Buffer + 65536
	jb	short csftdf2_write_df_clust_next
	
	jmp	short csftdf2_read_sf_cluster
 
csftdf2_rw_f_clust_ok:
	cmp	byte [csftdf_percentage], 0
        jna     csftdf2_save_fat_file_4 ; 25/03/2016

	; "100%"
	mov	edi, percentagestr
	mov	al, '1'
	stosb
	mov	al, '0'
	stosb
	stosb

	mov	bh, [csftdf_videopage]
	mov	dx, [csftdf_cursorpos]
	mov	ah, 2
	call	_int10h

	mov	esi, percentagestr
	call	print_msg

        jmp     csftdf2_save_fat_file_4

csftdf2_load_fs_file:
	; temporary - 18/03/2016
        jmp     csftdf2_read_error

csftdf2_write_file_sectors:
	; 19/03/2016
	cmp	byte [esi+LD_FATType], 0
        jna     csftdf2_write_fs_file_sectors

csftdf2_write_fat_file_sectors:
	; 19/03/2016
	; 18/03/2016
	; return:
	;   CF = 0 & EDX > 0 -> END OF FILE
	;   CF = 0 & EDX = 0 -> not EOF
	;   CF = 1 -> write error (error code in AL)	

csftdf2_write_fat_file_secs_0:
	mov	edx, [csftdf_filesize]
	sub	edx, [csftdf_df_wbytes]
	cmp	edx, [csftdf_w_size]	
	jnb	short csftdf2_write_fat_file_secs_1
	mov	[csftdf_w_size], edx		

csftdf2_write_fat_file_secs_1:
	mov	eax, [csftdf_w_size]
	sub	edx, edx
	movzx	ecx, word [esi+LD_BPB+BytesPerSec]
	add	eax, ecx
	dec	eax
	div	ecx
	mov	ecx, eax ; sector count
	mov	eax, [csftdf_df_cluster]

	; EBX = memory block address (current)	

	call	write_fat_file_sectors
	jc	short csftdf2_write_fat_file_secs_4

	; EBX = next memory address

	mov	eax, [csftdf_df_wbytes]
	add	eax, [csftdf_w_size]
	mov	edx, [csftdf_filesize]
	cmp	eax, edx
	jnb	short csftdf2_write_fat_file_secs_4
	mov	[csftdf_df_wbytes], eax
	;
	mov	[DestinationFile_DirEntry+DirEntry_FileSize], eax

	push	ebx ; *

	cmp	byte [DestinationFileFound], 1
	jb	short csftdf2_write_fat_file_secs_2

	; get next cluster (csftdf_w_size! bytes)
	mov	eax, [csftdf_df_cluster]
	call	get_next_cluster
	jnc	short csftdf2_write_fat_file_secs_3

	and	eax, eax ; end of cluster chain!?
	jnz	short csftdf2_write_fat_file_secs_5 ; disk error !

csftdf2_write_fat_file_secs_2:
	mov	eax, [csftdf_df_cluster] ; last cluster
	call	add_new_cluster		
	jc	short csftdf2_write_fat_file_secs_5

	; NOTE: Destination file size may be bigger than
	; source file size when the last reading fails after here.
	; (The last -empty- cluster of destination file must be 
	; truncated and LMDT must be current date&time for partial
	; copy result!) 
	mov	edx, [csftdf_w_size] ; bytes per cluster
	add	[DestinationFile_DirEntry+DirEntry_FileSize], edx

csftdf2_write_fat_file_secs_3:
	pop	ebx ; *
	sub	edx, edx ; 0
	mov	[csftdf_df_cluster], eax ; next cluster

csftdf2_write_fat_file_secs_4:
	retn

csftdf2_write_fat_file_secs_5:
	pop	ebx ; *
	; 16/10/2016 (1Dh -> 18)
	mov	eax, 18 ; Write error !
	retn

csftdf2_save_file:
	; 09/12/2017
	; 25/03/2016
	; 19/03/2016
	; 18/03/2016
	mov	esi, [csftdf_df_drv_dt] ; logical dos drv desc. tbl.

	mov	ebx, [csftdf_sf_mem_addr] ; memory block address

	cmp	byte [esi+LD_FATType], 0
        jna     csftdf2_save_fs_file

csftdf2_save_fat_file:
	push	ebx; *

	cmp	byte [csftdf_percentage], 0
	ja	short csftdf2_save_fat_file_0

	; Set cursor position
	; AH= 02h, BH= Page Number, DH= Row, DL= Column
	mov	bh, [csftdf_videopage]
	mov	dx, [csftdf_cursorpos]
	mov	ah, 2
	call	_int10h
	
	mov	esi, msg_writing
	call	print_msg

csftdf2_save_fat_file_next:
	mov	esi, [csftdf_df_drv_dt] ; 25/03/2016

csftdf2_save_fat_file_0:
	pop	ebx ; *

csftdf2_save_fat_file_1:
	call	csftdf2_write_file_sectors ; 19/03/2016	
        jc      csftdf2_rw_error ; eocc! or disk error! 

	or	edx, edx ; edx > 0 -> EOF
        jnz     short csftdf2_save_fat_file_3 ; 25/03/2016

	cmp	byte [csftdf_percentage], 0
	jna	short csftdf2_save_fat_file_1

	mov	al, 20h
	mov	edi, percentagestr
	stosb
	stosb
	mov	eax, [csftdf_df_wbytes]
	mov	edx, 100
	mul	edx
	mov	ecx, [csftdf_filesize]	
	div	ecx
	mov	cl, 10
	div	cl
	add	ah, '0'
	mov	[edi], ah
	and	al, al
	jz	short csftdf2_save_fat_file_2
	dec	edi
	;cbw
	xor	ah, ah ; 09/12/2017
	div	cl
	add	ah, '0'
	mov	[edi], ah
	;and	al, al
	;jz	short csftdf2_save_fat_file_2
	;dec	edi
	;mov	[edi], '1' ; 100%		

csftdf2_save_fat_file_2:
	push	ebx ; *

	call	csftdf2_print_wr_percentage ; 25/03/2016

        jmp     csftdf2_save_fat_file_next

csftdf2_print_wr_percentage:
	; Set cursor position
	; AH= 02h, BH= Page Number, DH= Row, DL= Column
	mov	bh, [csftdf_videopage]
	mov	dx, [csftdf_cursorpos]
	mov	ah, 2
	call	_int10h

	mov	esi, msg_writing
	call	print_msg

	mov	esi, percentagestr
	;call	print_msg
	;retn
	jmp	print_msg

csftdf2_save_fat_file_3:
	cmp	byte [csftdf_percentage], 0
        jna     csftdf2_save_fat_file_4 ; 25/03/2016

	; "100%"
	mov	edi, percentagestr
	mov	al, '1'
	stosb
	mov	al, '0'
	stosb
	stosb

	call	csftdf2_print_wr_percentage

csftdf2_save_fat_file_4:
	cmp	byte [DestinationFileFound], 0
	jna	short csftdf2_save_fat_file_6

	mov	esi, [csftdf_df_drv_dt] ; 31/03/2016	

	mov	eax, [csftdf_df_cluster] ; last cluster
	call	get_next_cluster
	jc	short csftdf2_save_fat_file_6 ; eocc! or disk error!

	mov	eax, [csftdf_df_cluster] ; last cluster
	;xor	ecx, ecx
	;mov	[FAT_ClusterCounter], ecx ; 0 ; reset
	;dec	ecx ; 0FFFFFFFFh
	;shr	ecx, 4 ; 28 bit ; 0FFFFFFFh
	mov	ecx, 0FFFFFFFh
	call	update_cluster
	jc	short csftdf2_save_fat_file_6 ; really last cluster!?

	mov	[csftdf_df_cluster], eax ; next cluster
	
	; byte [FAT_BuffValidData] = 2 
	call	save_fat_buffer
	jnc	short csftdf2_save_fat_file_5
	
	mov	edx, [csftdf_filesize]
	mov	[DestinationFile_DirEntry+DirEntry_FileSize], edx
	jmp	short csftdf2_save_fat_file_err3

csftdf2_save_fat_file_5:
	mov	eax, [csftdf_df_cluster]

	; EAX = First cluster to be truncated/unlinked
	; ESI = Logical dos drive description table address
	call	truncate_cluster_chain

csftdf2_save_fat_file_6:
	; 28/03/2016
	mov	esi, SourceFile_DirEntry+DirEntry_Attr ; +11 to + 18
	mov	edi, DestinationFile_DirEntry+DirEntry_Attr ; +11 to + 18
	movsb ; +11
	movsd ; +12 .. +15
	movsw ; +16 .. +17
		; + 18
	add	esi, 4
	add	edi, 4
	movsd	; DirEntry_WrtTime ; +22 .. +25

	mov	edx, [csftdf_filesize]
	mov	[DestinationFile_DirEntry+DirEntry_FileSize], edx

	call	convert_current_date_time
	; DX = Date in dos dir entry format
	; AX = Time in dos dir entry format
	jmp	short csftdf2_save_fat_file_7

csftdf2_save_fat_file_err1:
	pop	ebx ; *	
csftdf2_save_fat_file_err2:
	mov	eax, [csftdf_df_wbytes]
	mov	edx, [DestinationFile_DirEntry+DirEntry_FileSize]
	cmp	edx, eax
	jna	short csftdf2_save_fat_file_err3
	mov	eax, [csftdf_df_cluster] ; last (empty) cluster
	; ESI = Logical dos drive description table address
	call	truncate_cluster_chain
	jc	short csftdf2_save_fat_file_err3
	mov	eax, [csftdf_df_wbytes]	
	mov	[DestinationFile_DirEntry+DirEntry_FileSize], eax
csftdf2_save_fat_file_err3:
	call	convert_current_date_time
	; DX = Date in dos dir entry format
	; AX = Time in dos dir entry format
	mov	byte [DestinationFile_DirEntry+DirEntry_CrtTimeTenth], 0
	mov	[DestinationFile_DirEntry+DirEntry_CrtTime], ax
	mov	[DestinationFile_DirEntry+DirEntry_CrtDate], dx		
	mov	[DestinationFile_DirEntry+DirEntry_WrtTime], ax
	mov	[DestinationFile_DirEntry+DirEntry_WrtDate], dx
	stc
csftdf2_save_fat_file_7:
	pushf
	mov	[DestinationFile_DirEntry+DirEntry_LastAccDate], dx
	mov	esi, DestinationFile_DirEntry
	mov	edi, Directory_Buffer
	movzx	ecx, word [DestinationFile_DirEntryNumber] ; (<2048)
	shl	cx, 5 ; 32 * directory entry number
	add	edi, ecx
	;mov	ecx, 8
	mov	cx, 8
	rep	movsd
	popf
	jnc	short csftdf2_write_file_OK
	 		
csftdf2_write_error:
	; 18/03/2016
	mov	al, 1Dh ; write error
	jmp	short csftdf2_rw_error

	; 16/03/2016
csftdf2_read_error:
	mov	al, 17 ; ; Drive not ready or read error!
csftdf2_rw_error:
	mov	[csftdf_rw_err], al 

csftdf2_write_file_OK:
	; 18/03/2016
	mov	byte [DirBuff_ValidData], 2
	call	save_directory_buffer

 	; Update last modification date&time of destination
	; file's (parent) directory
	call	update_parent_dir_lmdt
	;
	mov	eax, [csftdf_sf_mem_addr] ; start address

	and	eax, eax
	jnz	short csftdf2_dealloc_mblock

	mov	ch, al ; 0 (Cluster r/w, not full loading)
csftdf2_dealloc_retn:
	mov	cl, [csftdf_rw_err]
	mov	eax, [csftdf_df_cluster]
	retn

csftdf2_dealloc_mblock:
	mov	ecx, [csftdf_sf_mem_bsize] ; block size	
	call	deallocate_memory_block
        mov     ch, 0FFh ; (File was full loaded at memory)
	jmp	short csftdf2_dealloc_retn

csftdf2_save_fs_file:
	; 16/10/2016 (1Dh -> 18)
	; temporary - (21/03/2016)
	mov	eax, 18 ; write error
	stc
	retn

create_file:
	; 16/10/2016
	; 24/03/2016, 31/03/2016
	; 20/03/2016, 21/03/2016, 23/03/2016
	; 19/03/2016 (TRDOS 396 = TRDOS v2.0)
	; 03/09/2011 (FILE.ASM, 'proc_create_file')
	; 09/08/2010
	;
	; INPUT ->
	; 	EAX = File Size
	; 	ESI = ASCIIZ File Name
	; 	CL = File Attributes 
	;	EBX = FFFFFFFFh -> create empty file 
	;			 (only for FAT fs) 
	; OUTPUT ->
	;     CF = 0 ->
	;	EAX = New file's first cluster
	; 	ESI = Logical Dos Drv Descr. Table Addr.
	; 	EBX = offset CreateFile_Size
	; 	ECX = Sectors per cluster (<256) 
	; 	EDX = Directory entry index/number (<65536)
	;     CF = 1 -> error code in AL

;	test	cl, 18h (directory or volume name)
;	jnz	short loc_createfile_access_denied
	and	cl, 07h ; S, H, R
        mov     [createfile_attrib], cl 

	mov	ecx, ebx
	mov	ebx, esi ; ASCIIZ File Name address
	sub	edx, edx
        mov     dh, [Current_Drv]
        mov     esi, Logical_DOSDisks
	add	esi, edx

	mov	[createfile_UpdatePDir], dl ; 0 ; 31/03/2016 

	; LD_DiskType = 0 for write protection (read only) 
	cmp	byte [esi+LD_DiskType], 1 ; 0 = Invalid
	jnb	short loc_createfile_check_file_sytem
	; 16/10/2016 (TRDOS Error code: 30, disk write protected) 
	mov	eax, 30 ; 13h, MSDOS err : Disk write-protected 
	mov	dx, 0
	; err retn: EDX = 0, EBX = File name offset
	; ESI -> Dos drive description table address	
	retn

;loc_createfile_access_denied:
;	mov	eax, 05h ; access denied (invalid attributes input)
;	stc
;	retn

loc_createfile_check_file_sytem:
	cmp	byte [esi+LD_FATType], 1
	jnb	short loc_createfile_chk_empty_FAT_file_sign1

	mov	[createfile_size], eax
	; ESI = Logical Dos Drive Description Table address
	; EBX = ASCIIZ File Name address
	jmp	create_fs_file

loc_createfile_chk_empty_FAT_file_sign1:
	; ECX = FFFFFFFFh -> create empty file if drive has FAT fs
	inc	ecx
	jnz	short loc_createfile_chk_empty_FAT_file_sign2
	mov	[createfile_size], ecx ; 0 ; empty file

loc_createfile_chk_empty_FAT_file_sign2:
	; 23/03/2016
	mov	cx, [esi+LD_BPB+BytesPerSec]
	mov	[createfile_BytesPerSec], cx
	
	; EBX = ASCIIZ File Name address
	movzx	edx, byte [esi+LD_BPB+SecPerClust]
	mov	[createfile_SecPerClust], dl
	mov	ecx, [esi+LD_FreeSectors]
	cmp	ecx, edx ; byte [createfile_SecPerClust]
	jnb	short loc_create_fat_file
	  
loc_createfile_insufficient_disk_space:
	mov	eax, 27h
loc_createfile_gffc_retn:
	retn

loc_create_fat_file:
	mov	[createfile_Name_Offset], ebx
	mov	[createfile_FreeSectors], ecx

loc_createfile_gffc_1:
	call	get_first_free_cluster
	jc	short loc_createfile_gffc_retn

	mov	[createfile_FFCluster], eax

loc_createfile_locate_ffe_on_directory:
	; Current directory fcluster <> Directory buffer cluster
	; Current directory will be reloaded by
	; 'locate_current_dir_file' procedure
	;
	; ESI = Logical Dos Drv Desc. Table Adress
	push	esi ; *
	xor	eax, eax

	mov	dword [FAT_ClusterCounter], eax ; 0
	; 21/03/2016
	mov	byte [createfile_wfc], al ; 0 

 	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	loc_createfile_set_ff_dir_entry
	pop	esi ; *
	 ; ESI = Logical DOS Drv. Description Table Address 
	cmp	eax, 2
	je	short loc_createfile_add_new_cluster
loc_createfile_locate_file_stc_retn:
	stc
	retn

loc_createfile_add_new_cluster:
	cmp	byte [Current_FATType], 2
	;cmp	byte [esi+LD_FATType], 2
	ja	short loc_createfile_add_new_cluster_check_fsc
	cmp	byte [Current_Dir_Level], 1
	;cmp	byte [esi+LD_CDirLevel], 1
	jnb	short loc_createfile_add_new_cluster_check_fsc
	
	;mov	eax, 12
	mov	al, 12 ; No more files 

loc_createfile_anc_retn:
	retn

loc_createfile_add_new_cluster_check_fsc:
	mov	ecx, [createfile_FreeSectors]
	movzx	eax, byte [createfile_SecPerClust]
	shl	ax, 1 ; AX = 2 * AX
	cmp	ecx, eax
        jb	short loc_createfile_insufficient_disk_space

loc_createfile_add_new_subdir_cluster:
	mov	edx, [DirBuff_Cluster]
	mov	[createfile_LastDirCluster], edx	

	mov	eax, [createfile_FFCluster]
	call	load_FAT_sub_directory 
	jc	short loc_createfile_anc_retn

pass_createfile_add_new_subdir_cluster:
	;movzx	eax, word [esi+LD_BPB+BytesPerSec]
	movzx	eax, word [createfile_BytesPerSec] ; 23/03/2016
	mul	ecx ; ecx = directory buffer sector count
	mov	ecx, eax
	shr	ecx, 2 ; dword count
	sub	eax, eax ; 0
	rep	stosd 
	;
	mov	byte [DirBuff_ValidData], 2 
	call	save_directory_buffer
	jc	short loc_createfile_anc_retn

loc_createfile_save_added_subdir_cluster:
	mov	eax, [createfile_LastDirCluster]
	mov	ecx, [createfile_FFCluster]
	call	update_cluster
	jnc	short loc_createfile_save_fat_buffer_0
	or	eax, eax ; EAX = 0 -> cluster value is 0 or eocc
	jnz	short loc_createfile_save_fat_buffer_stc_retn

loc_createfile_save_fat_buffer_0:
	mov	eax, [createfile_FFCluster]
	mov	[createfile_LastDirCluster], eax
	mov	ecx, 0FFFFFFFh ; 28 bit
	call	update_cluster
	jnc	short loc_createfile_save_fat_buffer_1
	or	eax, eax ; Was it free cluster
	jz	short loc_createfile_save_fat_buffer_1

loc_createfile_save_fat_buffer_stc_retn:
	stc
loc_createfile_save_fat_buffer_retn:
loc_createfile_gffc_2_stc_retn:
	retn

loc_createfile_save_fat_buffer_1:
	; byte [FAT_BuffValidData] = 2 
	call	save_fat_buffer
	jc	short loc_createfile_save_fat_buffer_retn

	cmp	byte [FAT_ClusterCounter], 1
	jb	short loc_createfile_save_fat_buffer_2

	; ESI = Logical DOS Drive Description Table address 
	mov	eax, [FAT_ClusterCounter]

	mov	byte [FAT_ClusterCounter], 0 ; 21/03/2016

	mov	bx, 0FF01h ; add free clusters 
	call	calculate_fat_freespace

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

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

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

loc_createfile_save_fat_buffer_2:
	;call	update_parent_dir_lmdt

loc_createfile_gffc_2:
	call	get_first_free_cluster
	jc	short loc_createfile_gffc_2_stc_retn

	mov	[createfile_FFCluster], eax

	mov	eax, [createfile_LastDirCluster]
	
	call	load_FAT_sub_directory 
	jc	short loc_createfile_gffc_2_stc_retn

	mov	edi, Directory_Buffer

	sub	bx, bx ; directory entry index/number = 0

	push	esi ; * ; 23/03/2016

loc_createfile_set_ff_dir_entry:
	mov	[createfile_DirIndex], bx

        ; EDI = Directory entry address
	mov	esi, [createfile_Name_Offset]
	mov	eax, [createfile_FFCluster]
	mov	[createfile_Cluster], eax ; 24/03/2016
	mov	ch, 0FFh
        mov	cl, [createfile_attrib] ; file attributes
	; CH > 0 -> File size is in [EBX]
	mov	ebx, createfile_size
  
	call	make_directory_entry
	
	pop	esi ; * ; ESI = Logical Dos Drv Desc. Table address

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

	mov	byte [createfile_UpdatePDir], 1 ; 31/03/2016 

loc_createfile_get_set_write_file_cluster:
	mov	eax, [createfile_size]
	or	eax, eax
	jnz	short loc_createfile_get_set_wfc_cont
	inc	eax
	; 23/03/2016
	movzx	ebx, byte [createfile_SecPerClust]
	;movzx	ecx, word [esi+LD_BPB+BytesPerSec] ; 512
        movzx   ecx, word [createfile_BytesPerSec] ; 512
	jmp	loc_createfile_set_cluster_count 

loc_createfile_set_ff_dir_entry_retn:
	retn

loc_createfile_write_fcluster_to_disk:
	add	eax, [esi+LD_DATABegin] ; convert to physical address
	mov	ebx, Cluster_Buffer
	; ESI = Logical DOS Drv. Desc. Tbl. address
	; EAX = Disk address
	; EBX = Sector Buffer
	; ECX = sectors per cluster
	call	disk_write
	jc	short loc_createfile_dsk_wr_err

loc_createfile_update_fat_cluster:
	; 21/03/2016	
	cmp	byte [createfile_wfc], 0 
	ja	short loc_createfile_update_fat_cluster_n1

	inc	byte [createfile_wfc] ; 1
	jmp	short loc_createfile_update_fat_cluster_n2

loc_createfile_dsk_wr_err:
	; 16/10/2016 (1Dh -> 18)
	; 23/03/2016
	mov	eax, 18 ; Drive not ready or write error !
	jmp	loc_createfile_stc_retn

loc_createfile_update_fat_cluster_n1:
	mov	eax, [createfile_PCluster]
	mov	ecx, [createfile_Cluster]
	call	update_cluster
	jnc	short loc_createfile_update_fat_cluster_n2
	or	eax, eax ; EAX = 0 -> cluster value is 0 or eocc
	jnz	loc_createfile_stc_retn

loc_createfile_update_fat_cluster_n2:
        mov	eax, [createfile_Cluster]
	mov	ecx, 0FFFFFFFh
	call	update_cluster
	jnc	short loc_createfile_save_fat_buffer_3
	or	eax, eax ; EAX = 0 -> cluster value is 0 or eocc
	jz	short loc_createfile_save_fat_buffer_3

loc_createfile_upd_fat_fcluster_stc_retn:
	jmp	loc_createfile_stc_retn

loc_createfile_get_set_wfc_cont:
	;movzx	ecx, word [esi+LD_BPB+BytesPerSec] ; 512	
	movzx	ecx, word [createfile_BytesPerSec] ; 512
	add	eax, ecx
	dec	eax  ; add eax, 511
	sub	edx, edx
	div	ecx
	movzx	ebx, byte [createfile_SecPerClust]
	add	eax, ebx
	dec	eax  ; add eax, SecPerClust - 1
	xor	dx, dx
	div	ebx

loc_createfile_set_cluster_count:
	mov 	[createfile_CCount], eax
	
	mov	edi, Cluster_Buffer
	mov	eax, ecx ; Bytes per Sector
	mul	ebx ; Sectors per Cluster 
	; EAX = Bytes per Cluster
	mov	ecx, eax
	shr	ecx, 2 ; dword count
	xor	eax, eax
	rep	stosd ; clear cluster buffer

	mov	eax, [createfile_Cluster] ; 24/03/2016

	mov	ecx, ebx

loc_createfile_get_set_wf_fclust_cont:
	sub	eax, 2
	mul	ecx
	; EAX = Logical DOS disk address (offset)
        jmp     loc_createfile_write_fcluster_to_disk

loc_createfile_save_fat_buffer_3:
	; byte [FAT_BuffValidData] = 2
	call	save_fat_buffer
	jc	loc_createfile_stc_retn

	; 21/03/2016
	cmp	byte [FAT_ClusterCounter], 1
	jb	short loc_createfile_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_createfile_save_fat_buffer_4

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

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

loc_createfile_save_fat_buffer_4:
	dec	dword [createfile_CCount]
	;jz	short loc_createfile_upd_dir_modif_date_time
	jz	short loc_createfile_stc_retn_cc ; 31/03/2016

loc_createfile_get_set_write_next_cluster:
	call	get_first_free_cluster
	jc	short loc_createfile_stc_retn

loc_createfile_get_set_write_next_cluster_1:
	cmp	eax, 0FFFFFFFFh
	jb	short loc_createfile_get_set_write_next_cluster_2

loc_createfile_wnc_insufficient_disk_space:	
	mov	eax, 27h ; Insufficient disk space

loc_createfile_stc_retn:
	cmp	byte [createfile_wfc], 1
	jnb	short loc_createfile_err_retn
	retn

loc_createfile_wnc_inv_format_retn:
	;mov	eax, 28
	mov	al, 28 ; Invalid format
	jmp	short loc_createfile_stc_retn
	         
loc_createfile_get_set_write_next_cluster_2:
	cmp	eax, 2
	jb	short loc_createfile_wnc_inv_format_retn

loc_createfile_get_set_write_next_cluster_3:
	mov	ecx, [createfile_Cluster]
	mov	[createfile_Cluster], eax
	mov	[createfile_PCluster], ecx
	movzx	ecx, byte [createfile_SecPerClust]
	jmp	short loc_createfile_get_set_wf_fclust_cont

loc_createfile_err_retn:
	stc

;loc_createfile_upd_dir_modif_date_time:
loc_createfile_stc_retn_cc: ; 31/03/2016
	pushf	; cpu is here for an error return or completion 
	push	eax ; error code if cf = 1

	;call	update_parent_dir_lmdt

;loc_createfile_stc_retn_cc:
	mov	eax, [FAT_ClusterCounter]
	or	eax, eax
	jz	short loc_createfile_stc_retn_pop_eax
	mov	bh, [Current_Drv]
	mov	bl, 01h ; BL = 1 -> add clusters
	; NOTE: EAX value will be added to Free Cluster Count
	; (If EAX value is negative, Free Cluster Count will be decreased)
  	call	calculate_fat_freespace
        ; ESI = Logical DOS Drive Description Table Address 
        ;jc	short loc_createfile_stc_retn_pop_eax_cf
	and	ecx, ecx ; cx = 0 -> valid free sector count
	jz	short loc_createfile_stc_retn_pop_eax

loc_createfile_stc_retn_recalc_FAT_freespace:
	mov	bx, 0FF00h ; bh = 0FFh -> 
	; ESI = Logical DOS Drv DT Addr
	; BL = 0 -> Recalculate 
	call	calculate_fat_freespace

loc_createfile_stc_retn_pop_eax:
	pop	eax
	popf
	jc	short loc_createfile_retn

loc_createfile_retn_fcluster:
	mov	eax, [createfile_FFCluster]
	mov	ebx, createfile_size
	;movzx	ecx, byte [esi+LD_BPB+SecPerClust]
	movzx	ecx, byte [createfile_SecPerClust] ; 23/03/2016
	movzx	edx, word [createfile_DirIndex]

loc_createfile_retn:
	retn

create_fs_file:
	; temporary (21/03/2016)
	retn

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

rename_fs_file_or_directory:
	retn

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

add_new_fs_section:
	; temporary (11/03/2016)
	retn

delete_fs_directory_entry:
	; temporary (11/03/2016)
	retn

csftdf2_read_fs_file_sectors:
	; temporary (19/03/2016)
	retn

csftdf2_write_fs_file_sectors:
	; temporary (19/03/2016)
	retn
