;*****************************************************************************
; TRDOS.ASM  [ Draft for Kernel TRDOS.COM ]
; (c) 2004-2005  Erdogan TAN  [ 17/01/2004 ]  Last Update: 09/02/2005
; ! Under Development !
; Currently, usable prompt line commands: 'CD','DIR','VER','EXIT','PROMPT'
; 'VOLUME','LONGNAME','DATE','TIME','CLS','SHOW','RUN','SET', DEL','RENAME'
; 'RMDIR', 'MKDIR' (MSDOS INT21h full compatibility revisions continue)
;
; Current Stage: COPY command  (after FULL PATH NAME revisions)
;
; ****************************************************************************
; masm.bat -> masm trdos -> link /t trdos -> TRDOS.COM [ MASM v6.11 ]
; This is source code of TRDOS.COM file which succesfully runs in MS-DOS 7.1 
;*****************************************************************************
; Required Files: DRV_INIT.ASM, CMD_INTR.ASM, INT_21H.ASM (29/01/2005)
; (above files must be in same directory with TRDOS.ASM)
;
; you can run TRDOS.COM on Windows 98 command prompt (MSDOS mode)
; or by using windows 98 emergency boot disk as operation system 
; (It can run on windows 98 GUI but it can not set TRDOS drives
; while protected mode windows is running.)
; Start Windows 98, press F8 during startup, select "command prompt only";
; change directory to trdos.com directory, for example: "D:\TRDOS\TRDOS.COM"
; write "TRDOS", you will see "[TRDOS] C:/>" prompt, you can stop TRDOS.COM
; by using "EXIT" command. (Warning! Be Carefull!
; do not use "del", "mkdir", "rmdir", "rename" commands with filenames!)


; Masterboot / Partition Table at Beginning+1BEh
ptBootable       equ 0
ptBeginHead      equ 1
ptBeginSector    equ 2
ptBeginCylinder  equ 3
ptFileSystemName equ 4
ptEndHead        equ 5
ptEndSector      equ 6
ptEndCylinder    equ 7
ptStartSector    equ 8
ptSectors        equ 12

; Boot Sector Parameters at 7C00h
DataArea1     equ -4
DataArea2     equ -2
BootStart     equ 0h
OemName       equ 03h
BytesPerSec   equ 0Bh
SecPerClust   equ 0Dh
ResSectors    equ 0Eh
FATs          equ 10h
RootDirEnts   equ 11h
Sectors       equ 13h
Media         equ 15h
FATsecs       equ 16h
SecPerTrack   equ 18h
Heads         equ 1Ah 
Hidden1       equ 1Ch
Hidden2       equ 1Eh
HugeSec1      equ 20h
HugeSec2      equ 22h
DriveNumber   equ 24h
Reserved1     equ 25h
bootsignature equ 26h                 
VolumeID      equ 27h
VolumeLabel   equ 2Bh
FileSysType   equ 36h          
Reserved2     equ 3Eh                           ; Starting cluster of P2000

; FAT32 BPB Structure
FAT32_FAT_Size equ 36
FAT32_RootFClust equ 44
FAT32_FSInfoSec equ 48
FAT32_DrvNum equ 64
FAT32_BootSig equ 66
FAT32_VolID equ 67
FAT32_VolLab equ 71
FAT32_FilSysType equ 82

; BIOS Disk Parameters
DPDiskNumber  equ 0h
DPDType       equ 1h
DPReturn      equ 2h
DPHeads       equ 3h
DPCylinders   equ 4h
DPSecPerTrack equ 6h
DPDisks       equ 7h
DPTableOff    equ 8h
DPTableSeg    equ 0Ah
DPNumOfSecs   equ 0Ch

; BIOS INT 13h Extensions (LBA extensions)
; Just After DP Data (DPDiskNumber+)
DAP_PacketSize equ 10h  ; If extensions present, this byte will be >=10h
DAP_Reserved1 equ 11h   ; Reserved Byte 
DAP_NumOfBlocks equ 12h ; Value of this byte must be 0 to 127
DAP_Reserved2 equ 13h   ; Reserved Byte
DAP_Destination equ 14h ; Address of Transfer Buffer as SEGMENT:OFFSET
DAP_LBA_Address equ 18h ; LBA=(C1*H0+H1)*S0+S1-1
                        ; C1= Selected Cylinder Number
                        ; H0= Number Of Heads (Maximum Head Number + 1)
                        ; H1= Selected Head Number
                        ; S0= Maximum Sector Number
                        ; S1= Selected Sector Number
                        ; QUAD WORD
; DAP_Flat_Destination equ 20h ; 64 bit address, if value in 4h is FFFF:FFFFh
                             ; QUAD WORD (Also, value in 0h must be 18h) 
                             ; TR-DOS will not use 64 bit Flat Address

; INT 13h Function 48h "Get Enhanced Disk Drive Parameters"
; Just After DP Data (DPDiskNumber+)
GetDParams_48h equ 20h ; Word. Data Length, must be 26 (1Ah) for short data.
GDP_48h_InfoFlag equ 22h ; Word
; Bit 1 = 1 -> The geometry returned in bytes 4-15 is valid.
GDP_48h_NumOfPCyls equ 24h ; Double Word. Number physical cylinders.
GDP_48h_NumOfPHeads equ 28h ; Double Word. Number of physical heads.
GDP_48h_NumOfPSpT equ 2Ch ; Double word. Num of physical sectors per track.
GDP_48h_LBA_Sectors equ 30h ; 8 bytes. Number of physical/LBA sectors.
GDP_48h_BytesPerSec equ 38h ; Word. Number of bytes in a sector.

; TR-DOS Standalone Program Extensions to the DiskParams Block
; Just After DP Data (DPDiskNumber+)
TRDP_CurrentSector equ 3Ah  ; DX:AX (LBA)
TRDP_SectorCount equ 3Eh    ; CX (or Counter)

; DOS Logical Disks
LD_Name equ 0
LD_DiskType equ 1
LD_PhyDrvNo equ 2
LD_FATType equ 3
LD_FSType equ 4
LD_LBAYes equ 5
LD_BPB equ 6
LD_FATBegin equ 96
LD_ROOTBegin equ 100
LD_DATABegin equ 104
LD_StartSector equ 108
LD_TotalSectors equ 112
LD_FreeSectors equ 116
LD_Clusters equ 120
LD_PartitionEntry equ 124
LD_DParamEntry equ 125
LD_MediaChanged equ 126
LD_CDirLevel equ 127
LD_CurrentDirectory equ 128

; Valid FAT Types
FS_FAT12 equ 1
FS_FAT16_CHS equ 2
FS_FAT32_CHS equ 3
FS_FAT16_LBA equ 4
FS_FAT32_LBA equ 5

; Cursor Location
CCCpointer equ  0450h   ; BIOS data, current cursor column
; FAT Clusters EOC sign
FAT12EOC equ 0FFFh
FAT16EOC equ 0FFFFh
;FAT32EOC equ 0FFFFFFFh ; It is not direct usable for 8086 code
; BAD Cluster
FAT12BADC equ 0FF7h
FAT16BADC equ 0FFF7h
;FAT32BADC equ 0FFFFFF7h ; It is not direct usable for 8086 code
; MS-DOS FAT16 FS (Maximum Possible) Last Cluster Number= 0FFF6h 


Present segment Para 'code'

		assume CS:Present, DS:Present, ES:Present, SS:Present


;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±
;±
;±              PROCEDURE proc_start
;±
;±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±

proc_start      proc    far

                org 100h
start:                                         
                cmp ax, 417
                jne short pass_trdos_boot_sector
                mov byte ptr [Boot_Disk], dl
pass_trdos_boot_sector:
                mov ah, 0 ; Set Video Mode
                mov al, 3 ; 80*25 text mode, color with CGA card
                int 10h

                mov ah, 5 ; Set Video Page
                mov al, 0 ; TRDOS MainProg Running on Page 0
                int 10h

                mov si, offset Starting_Msg
                call proc_printmsg

                call proc_drv_init  ; DRV_INIT.ASM

launch_current_dos_drive:
                push ds
                xor ax, ax
                mov ds, ax
                push word ptr DS:[084h]
                pop word ptr CS:[INT21h_Offset]
                push word ptr DS:[086h]
                pop word ptr CS:[INT21h_Segment]
                mov word ptr DS:[084h], offset trdos_int21h_routine
                push cs
                pop word ptr DS:[086h]
                pop ds
trdos_mainprog:
                call proc_clear_screen
                mov al, byte ptr [Boot_Disk]
                cmp al, 0FFh
                jne short trdos_mainprog_current_drive_a 
                mov al, byte ptr [Last_Dos_DiskNo]
                cmp al, 2
                ja short trdos_mainprog_current_drive_c
                mov al, 0 ; A:
                jmp short trdos_mainprog_current_drive_a
trdos_mainprog_current_drive_c:
                mov al, 2 ; C:
trdos_mainprog_current_drive_a:
                call proc_change_current_drive
                call proc_dos_prompt
end_of_program:
                xor ax, ax
                mov ds, ax
                push word ptr CS:[INT21h_Offset]
                pop word ptr DS:[084h]
                push word ptr CS:[INT21h_Segment]
                pop word ptr DS:[086h]

                int 20h

Boot_Disk:      db 0FFh
                    
proc_start      endp

proc_printmsg   proc near

                mov AH, 0Fh ; Get Video Display Mode
                int 10h
                ;AH= Number of columns
                ;AL= Video mode
                ;BH= Current video page
                mov BL, byte ptr [Program_CharColorAtr]
loc_print:
		lodsb                           ; Load byte at DS:SI to AL
		and     AL,AL            
		je      short loc_return        ; If AL = 00h then return
		mov     AH,0Eh                  
		int     10h                     ; BIOS Service func ( ah ) = 0Eh
						; Write char as TTY
						;AL-char BH-page BL-color
		jmp     short loc_print           
loc_return:
		retn

proc_printmsg   endp

program_videomode: dw 0
program_charcoloratr: db 0
program_videopage: db 0

proc_clear_screen proc near

                mov ah, 0Fh 
                int 10h
                mov ah, 0
                int 10h

                retn

proc_clear_screen endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; Rx_DOS  32 bit Divide                                      ;
; (Special version by Erdogan Tan)                           ;
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -;
;                                                            ;
; input -> DX_AX = 32 bit dividend                           ;
; input -> CX = 16 bit divisor                               ;
; output -> DX_AX = 32 bit quotient                          ;
; output -> BX = 16 bit remainder                            ;
;                                                            ;
;  This procedure divides the requested 32 bit number        ;
;  and gives the result in DX, AX and BX (remainder)         ;
;                                                            ;
; Original Procedure by Michael Podanoffsky / Real Time DOS  ;
; (c) Erdogan TAN  1999                     [ RXDOSBIO.ASM ] ;
;............................................................;

Rx_Dos_Div32    proc near

		mov  bx, dx
		xchg ax, bx
		xor  dx, dx
		div  cx         ; at first, divide DX
		xchg ax, bx     ; remainder is in DX
				; now, BX has quotient
				; save remainder
		div  cx         ; so, DX_AX divided and
				; AX has quotient
				; DX has remainder
		xchg dx, bx     ; finally, BX has remainder

		retn

Rx_Dos_Div32    endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; From binary (byte) to hexadecimal (character) converter    ;
;                                                            ;
; input -> AL = byte (binary number) to be converted         ;
; output -> AH = First character of hexadecimal number       ;
; output -> AL = Second character of hexadecimal number      ;
;                                                            ;
; (c) Erdogan TAN  1998 - 1999                               ;
;............................................................;

; 1998

proc_hex        proc    near

		db 0D4h,10h                     ; Undocumented inst. AAM
						; AH = AL / 10h
						; AL = AL MOD 10h
		or AX,'00'                      ; Make it ZERO (ASCII) based

                xchg AH,AL 

; 1999
		cmp AL,'9'
		jna pass_cc_al
		add AL,7
pass_cc_al:
		cmp AH,'9'
		jna pass_cc_ah
		add AH,7
pass_cc_ah:

; 1998
		retn

proc_hex        endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; 32 bit Multiply                                            ;
;- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - -;
;                                                            ;
; input -> DX_AX = 32 bit multiplier                         ;
; input -> BX = 16 bit number to be multiplied by DX_AX      ;
; output -> BX_DX_AX = 48 bit (16+32 bit) result number      ;
;                                                            ;
; (c) Erdogan TAN  1999                                      ;
;............................................................;

proc_mul32    proc near

	      push cx

	      mov cx, bx
	      mov bx, dx

	      mul cx

              xchg ax, bx

	      push dx

              mul cx 

              pop cx 

              add ax, cx 
	      adc dx, 0

	      xchg bx, ax
	      xchg dx, bx

	      pop cx

	      retn

proc_mul32    endp

INCLUDE DRV_INIT.ASM  ; TRDOS Drive Initialization Procedures

proc_CHS_read proc near
                push si
                ; INPUT -> DX:AX = Logical Block Address
                ; CX = Number of sectors to read
                ; DS:SI = Logical Dos Disk Table Offset (DRV)
                ; ES:BX = Destination Buffer
                ; OUTPUT -> clc or stc
                mov byte ptr [CHS_RetryCount], 4
loc_read_disk_chs:
                push    CX                      ; # of FAT/FILE/DIR sectors
                push    AX                      ; Linear sector #
                push    DX                      ; DX_AX = Linear address (sectors)
                mov     CX,Word Ptr [SI][LD_BPB][SecPerTrack]
                push    BX

                call    RX_DOS_DIV32            ; Special 32 bit divide !!!
                                                ; To fix large disk problem.
                                                ; (c) Erdogan Tan 1999
                                                ; (October 20th, 1999)

                mov     CX, BX                  ; Sector (zero based)
                inc     CX                      ; To make it 1 based
                push    CX
                mov     CX,Word Ptr [SI][LD_BPB][Heads]
                call    RX_DOS_DIV32            ; Convert track to head & cyl
                mov     DH, BL                  ; BX = Head (max. FFh)
                pop     CX
                                                ; AX=Cyl, DH=Head, CX=Sector
                pop     BX                      ; ES:BX = Buffer

                mov     DL,Byte Ptr [SI][LD_PhyDrvNo]
                mov     CH,AL                   
                ror     AH,1                    ; Rotate right
                ror     AH,1                   
                or      CL,AH                   
                mov     AX,0201h
                int     13h                     ; BIOS Service func ( ah ) = 2
                                                ; Read disk sectors
                                                ;AL-sec num CH-track CL-sec
                                                ; DH-head DL-drive ES:BX-buffer
                                                ;CF-flag AH-stat AL-sec read
                                                ; If CF = 1 then (If AH > 0)
                pop     DX
                pop     AX
                pop     CX 
                jnc     short pass_read_disk_chs_error
                                                ; error code in AH
                sub     byte ptr [CHS_RetryCount], 1
                jnb     short loc_read_disk_chs
                pop si
                retn
pass_read_disk_chs_error:
                loop    loc_read_next_sector
                pop si
                retn
loc_read_next_sector:
                add     AX,1
                adc     DX,0    
                add     BX, 512
                jmp     short loc_read_disk_chs

proc_CHS_read   endp

proc_LBA_read   proc near
                push si
                ; INPUT -> DAP_Buffer
                ; OUTPUT -> clc or stc
loc_read_disk_lba:
                mov si, offset DAP_Buffer
                ; DS:SI= DAP Location
                mov ah, 42h  ; Extended Disk Read - LBA Read
               ;mov dl, byte ptr [DAP_BuffDisk]
                int 13h
                jnc short pass_read_disk_lba_error
                dec byte ptr [DAP_RetryCount]
                cmp byte ptr [DAP_RetryCount],1
                jnb short loc_read_disk_lba
pass_read_disk_lba_error:
                pop si
                retn
proc_LBA_read   endp

proc_load_disk_sectors proc near
                ; INPUT -> DS:SI = DOS Drive Description Table 
                ; INPUT -> DX:AX = LBA address
                ; INPUT -> CX = Sector Count (CH=0)
                ; INPUT -> ES:BX = Buffer
                cmp byte ptr [SI][LD_LBAYes], 0
                ja short loc_loadsecs_lba_sectors
loc_loadsecs_chs_sectors:
                call proc_chs_read
                jc  short retn_loadsecs_stc
                retn
retn_loadsecs_stc:
                mov ax, 1
                stc
                retn
loc_loadsecs_lba_sectors:
              ; mov byte ptr [DAP_BuffLBAyes], 1
                mov word ptr [DAP_BuffLBA_Address], ax
                mov word ptr [DAP_BuffLBA_Address]+2, dx
                mov byte ptr [DAP_BuffPacketSize], 10h
                mov word ptr [DAP_BuffDestination], bx
                push es
                pop word ptr [DAP_BuffDestination]+2
                mov byte ptr [DAP_BuffNumOfBlocks], cl
                mov byte ptr [DAP_RetryCount], 4
                mov dl, byte ptr [SI][LD_PhyDrvNo]
                mov byte ptr [DAP_BuffDisk], dl

                call proc_lba_read
                jc  short retn_loadsecs_stc
                retn

proc_load_disk_sectors endp

proc_get_next_cluster   proc near
                ; INPUT -> AX = Cluster Number, low 16 bit
                ; INPUT -> DX = Cluster Number, high 16 bit
                ; INPUT -> DS:SI = Logical Dos Drive Parameters Table
                ; OUTPUT -> clc -> No Error, DX:AX valid
                ; OUTPUT -> stc & AX=0 -> End Of Cluster Chain
                ; OUTPUT -> stc & AX>0 -> Error
                ; OUTPUT -> CX, BX will be destroyed
                ; AX: Next Cluster Number, low 16 bit
                ; DX: Next Cluster Number, high 16 bit
                ; stc -> Error
                mov word ptr [FAT_CurrentCluster], ax
                mov word ptr [FAT_CurrentCluster]+2, dx
check_next_cluster_fat_type:
                cmp byte ptr [SI][LD_FATType], 2
                jb short get_FAT12_next_cluster
                ja get_FAT32_next_cluster
get_FAT16_next_cluster:
                mov bx, 300h ;768
                div bx
                ; AX = Count of 3 FAT sectors
                ; DX = Sector Offset
                shl dx, 1 ; Multiply by 2
                push dx
                mov bx, 3
                mul bx  
                pop bx ; Sector Offset
                ; AX = FAT Sector
                ; DX = 0
                mov cl, byte ptr [SI][LD_Name]
                cmp byte ptr [FAT_BuffValidData], 0
                jna load_FAT_sectors0
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne load_FAT_sectors0
                cmp ax, word ptr [FAT_BuffSector]
                jne load_FAT_sectors2
                mov ax, word ptr [FAT_Buffer][BX]
                xor dx, dx
                cmp al, 0F6h
                jna short loc_pass_gnc_FAT16_eoc_check
                cmp ah, 0Fh
                jb short loc_pass_gnc_FAT16_eoc_check
                xor ax, ax
                stc
                retn
loc_pass_gnc_FAT16_eoc_check:
                clc
                retn

get_FAT12_next_cluster:
                mov bx, 400h ;1024
                div bx
                ; AX = Count of 3 FAT sectors
                ; DX = Buffer Entry Offset
                push ax
                mov ax, 3
                mul dx    ; Multiply by 3
                shr ax, 1 ; Divide by 2
                mov dx, ax
                pop ax
                push dx
                mov bx, 3
                mul bx  
                pop bx ; Buffer Byte Offset
                ; AX = FAT Beginning Sector
                ; DX = 0
                mov cl, byte ptr [SI][LD_Name]
                cmp byte ptr [FAT_BuffValidData], 0
                jna load_FAT_sectors0
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne short load_FAT_sectors0
                cmp ax, word ptr [FAT_BuffSector]
                jne short load_FAT_sectors2

                mov cx, word ptr [FAT_CurrentCluster]
                shr cx, 1
                mov ax, word ptr [FAT_Buffer][BX]
                jnc short get_FAT12_nc_even
                shr ax, 1
                shr ax, 1
                shr ax, 1
                shr ax, 1

loc_gnc_fat12_eoc_check:
                cmp al, 0F6h
                jna short loc_pass_gnc_FAT12_eoc_check
                cmp ah, 0Fh
                jb short loc_pass_gnc_FAT12_eoc_check
                xor ax, ax
                stc
                retn
loc_pass_gnc_FAT12_eoc_check:
                clc
                retn

get_FAT12_nc_even:
                and ah,0Fh
                jmp short loc_gnc_fat12_eoc_check

get_FAT32_next_cluster:
                mov cx, 180h ;384
                call Rx_Dos_Div32
                ; DX:AX = Count of 3 FAT sectors
                ; BX = Sector Offset
                shl bx, 1
                shl bx, 1 ; Multiply by 4
                push bx
                mov bx, 3
                call proc_mul32
                pop bx ; Sector Offset
                ; DX:AX = FAT Sector

                mov cl, byte ptr [SI][LD_Name]
                cmp byte ptr [FAT_BuffValidData], 0
                jna short load_FAT_sectors0
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne short load_FAT_sectors0
                cmp dx, word ptr [FAT_BuffSector]+2
                jne short load_FAT_sectors1
                cmp ax, word ptr [FAT_BuffSector]
                jne short load_FAT_sectors2

                mov ax, word ptr [FAT_Buffer][BX]
                mov dx, word ptr [FAT_Buffer][BX]+2
                and dh, 0Fh ; 28 bit Cluster

                cmp al, 0F6h
                jna short loc_pass_gnc_FAT32_eoc_check
                cmp ah, 0FFh
                jb short loc_pass_gnc_FAT32_eoc_check
                cmp dx, 0FFFh
                jb short loc_pass_gnc_FAT32_eoc_check
                xor ax, ax
                xor dx, dx
                stc
                retn
loc_pass_gnc_FAT32_eoc_check:
                clc
                retn

load_FAT_sectors0:
                mov byte ptr [FAT_BuffDrvName], cl
load_FAT_sectors1:
                mov word ptr [FAT_BuffSector]+2, dx
load_FAT_sectors2:
                mov word ptr [FAT_BuffSector], ax
                add ax, word ptr [SI][LD_FATbegin]
                adc dx, word ptr [SI][LD_FATbegin]+2
                mov bx, offset FAT_Buffer
                cmp byte ptr [SI][LD_FATType], 2
                ja short pass_FAT_load_scount_0
                mov cx, word ptr [SI][LD_BPB][FATsecs]
                sub cx, word ptr [FAT_BuffSector]
                cmp cx, 3
                jna short pass_FAT_load_scount_2
                jmp short pass_FAT_load_scount_1
pass_FAT_load_scount_0:
                push ax
                push dx
                mov ax, word ptr [SI][LD_BPB][FAT32_FAT_size]
                mov dx, word ptr [SI][LD_BPB][FAT32_FAT_size]+2
                sub ax, word ptr [FAT_BuffSector]
                sbb dx, word ptr [FAT_BuffSector]+2
                cmp dx, 0
                ja short pass_FAT32_load_scount
                cmp ax, 3
                ja short pass_FAT32_load_scount
                mov cx, ax
                pop dx
                pop ax
                jmp short pass_FAT_load_scount_2
pass_FAT32_load_scount:
                pop dx
                pop ax
pass_FAT_load_scount_1:
                mov cx, 3
pass_FAT_load_scount_2:
               ;push ds
               ;pop es
                call proc_load_disk_sectors
                jnc short pass_FAT_sectors_load_error
                mov byte ptr [FAT_BuffValidData], 0
                mov ax, 1 ; Read Error
                mov dx, 0
                retn
pass_FAT_sectors_load_error:
                mov byte ptr [FAT_BuffValidData], 1
                mov ax, word ptr [FAT_CurrentCluster]
                mov dx, word ptr [FAT_CurrentCluster]+2
                jmp check_next_cluster_fat_type
proc_get_next_cluster endp

proc_load_root_directory proc near
               ; BL = Sector Offset
               ; BH = DRV
               mov byte ptr [DirBuff_ValidData],0
               mov byte ptr [DirBuff_SectorOffset], bl
               mov byte ptr [DirBuff_LastEntry], 15
               cmp byte ptr [Current_FS], 1
               jne short pass_set_FAT12_lastsector
               mov byte ptr [DirBuff_LastSector], 13
               cmp bl, 13
               jna short pass_set_FAT16_lastsector
ld_drv_root_eorde:
               xor ax, ax
               stc
               retn
pass_set_FAT12_lastsector:
               mov byte ptr [DirBuff_LastSector], 31
               cmp bl, 31
               ja short ld_drv_root_eorde
pass_set_FAT16_lastsector:
               xor bl,bl
               mov si, offset Logical_DOSDisks
               add si, bx
               mov byte ptr [DirBuff_Drv], bh
               mov word ptr [DirBuff_DirCluster], 0
               mov word ptr [DirBuff_DirCluster]+2, 0
               mov word ptr [DirBuff_NextCluster], 0
               mov word ptr [DirBuff_NextCluster]+2, 0
               mov byte ptr [DirBuff_CurrentEntry],0
               mov ax, word ptr [SI][LD_ROOTbegin]
               mov dx, word ptr [SI][LD_ROOTbegin]+2
               xor bh, bh
               mov bl, byte ptr [DirBuff_SectorOffset]
               add ax, bx
               adc dx, 0
               mov word ptr [DirBuff_DirSector], ax
               mov word ptr [DirBuff_DirSector]+2, dx
               ; push ds
               ; pop es
               mov bx, offset Directory_Buffer
               mov cx, 1
               call proc_load_disk_sectors
               jnc short validate_RDirBuff_and_return
               mov ax, 1 ; read error
               retn
validate_RDirBuff_and_return:
               mov byte ptr [DirBuff_ValidData], 1
             ; xor ax, ax
               retn
proc_load_root_directory endp

proc_load_directory proc near
               ; DX:AX = Cluster Number
               ; BL = Sector Offset in cluster
               ; BH = DRV
                 mov byte ptr [DirBuff_ValidData],0

                 mov byte ptr [DirBuff_SectorOffset], bl
               ; mov byte ptr [DirBuff_LastEntry], 0 ;[RESET]
                 xor bl,bl
                 mov si, offset Logical_DOSDisks
                 add si, bx
                 cmp byte ptr [Current_FS],2
                 ja short pass_ld_reset_dx
                 xor dx,dx
pass_ld_reset_dx:
                 mov byte ptr [DirBuff_Drv], bh
                 mov word ptr [DirBuff_DirCluster], ax
                 mov word ptr [DirBuff_DirCluster]+2, dx
                 mov word ptr [DirBuff_NextCluster], 0
                 mov word ptr [DirBuff_NextCluster]+2, 0
                 mov bl, byte ptr [SI][LD_BPB][SecPerClust]
                 dec bl
                 mov byte ptr [DirBuff_LastSector], bl
                 cmp bl, byte ptr [DirBuff_SectorOffset]
                 jnb short pass_ld_drv_secoff_failed
                 retn
pass_ld_drv_secoff_failed:
                 mov byte ptr [DirBuff_CurrentEntry],0
                 mov byte ptr [DirBuff_LastEntry], 15
                 sub ax, 2
                 sbb dx, 0
                 xor bh, bh
                 mov bl, byte ptr [DirBuff_LastSector]
                 inc bl
                 call proc_mul32
                 add ax, word ptr [SI][LD_DATAbegin]
                 adc dx, word ptr [SI][LD_DATAbegin]+2
               ; xor bh, bh
                 mov bl, byte ptr [DirBuff_SectorOffset]
                 add ax, bx
                 adc dx, 0
loc_read_directory_sector:
                 mov word ptr [DirBuff_DirSector], ax
                 mov word ptr [DirBuff_DirSector]+2, dx
               ; push ds
               ; pop es
                 mov bx, offset Directory_Buffer
                 mov cx, 1
                 call proc_load_disk_sectors
                 jnc short validate_DirBuff_and_return
                 retn
validate_DirBuff_and_return:
                 mov byte ptr [DirBuff_ValidData], 1
                 retn
proc_load_directory endp

proc_dos_prompt proc near
                push ds
                pop  es 
loc_TRDOS_prompt: 
                mov byte ptr [Current_DirReset], 0
                mov DI, offset TextBuffer
                mov byte ptr [DI], "["
                inc di
                mov si, offset TRDOSPromptLabel
get_next_prompt_label_char:
                mov al, byte ptr [SI]
                cmp al, 20h
                jb  short pass_prompt_label
                mov byte ptr [DI], al
                inc si
                inc di
                jmp short get_next_prompt_label_char
pass_prompt_label:
                mov byte ptr [DI], "]"
                inc di
                mov byte ptr [DI], 20h
                inc di
                mov al, byte ptr [Current_DosDisk]
                add al, 'A'
                mov byte ptr [DI], al
                inc DI
                mov byte ptr [DI], ':'
                inc DI
                mov byte ptr [DI], 0
                mov si, offset TextBuffer
                call proc_printmsg
                mov SI, offset Dir_Str_Root
                call proc_printmsg

                mov al, '>'
                mov ah, 0Eh
                mov bx, 07h
                int 10h

                mov al, 20h
                mov ah, 0Eh
                mov bx, 07h
                int 10h

                mov     ah,03h
                mov     bx,07h                  
		int     10h
		mov     Byte Ptr [CursorColumn],dl
loc_rw_char_again:
                call    proc_rw_char
                mov     Byte Ptr [CommandBuffer]+79,0
loc_move_command:
                mov     CX, 8
                xor     SI, SI
                mov     byte ptr [CmdArgStart],1
		mov     DI, offset CommandBuffer
next_command_char:
		mov     al, byte ptr [SI][CommandBuffer]
		inc     si
		cmp     al, 20h
		ja      short pass_space_control
		jb      short pass_move_command
                cmp     cx, 8
		jb      short pass_move_command
                cmp     si,79
		jb      short next_command_char
		jmp     short pass_move_command
pass_space_control:
		cmp     al,61h
		jb      short pass_capitalize
		cmp     al,7Ah
		ja      short pass_capitalize
		and     al,0DFh
pass_capitalize:
		stosb   
                inc     byte ptr [CmdArgStart]
                loop    short next_command_char
pass_move_command:
                mov     byte ptr [DI],0
                call    command_interpreter
                cmp     byte ptr [Current_DirReset], 0
                jna     short pass_cdir_reset
                mov     byte ptr [Current_DirReset], 0
                mov     al, byte ptr [Current_DosDisk]
                call    proc_change_current_drive
                jc      loc_cd_drive_not_ready
                call    proc_load_current_path
                cmp     byte ptr [Current_DirLevel], 0
                jna     short pass_cdir_reset
                call    proc_change_current_directory
                xor     bl, bl
                mov     bh, byte ptr [Current_DosDisk]
                mov     di, offset Logical_DOSdisks
                add     di, bx
                mov     al, byte ptr [Current_DirLevel]
                mov     byte ptr [DI][LD_CDirLevel],al
                mov     si, offset Current_Path
                add     di, LD_CurrentDirectory
                mov     cx, 64
                rep     movsw
                call    proc_change_prompt_dir_string
pass_cdir_reset:
                mov     cx,79
                mov     di,offset CommandBuffer
                xor     al,al
                rep     stosb
                cmp     byte ptr [Program_Exit], 0
                ja      short loc_terminate_trdos
                mov     al,0Dh
                mov     ah, 0Eh
                int     10h
		mov     al,0Ah
		int     10h
                jmp     loc_TRDOS_prompt ; loop
loc_terminate_trdos:
                cmp     byte ptr [Boot_Disk], 0FFh
                je      short return_to_msdos
                int     19h
return_to_msdos:
                retn

proc_dos_prompt  endp

proc_rw_char    proc    near
                push    es
                xor     cx,cx
                mov     es,cx
readnextchar:
                xor     ah,ah
		int     16h
		and     al,al
		jz      short loc_arrow    
		cmp     al,0E0h          
		jz      short loc_arrow
		cmp     al,08h             
		jnz     short char_return
loc_back:
		cmp     dl,Byte ptr [CursorColumn]
		ja      short prev_column
		jmp     short readnextchar
prev_column:
		dec     dl
set_cursor_pos:
		mov     ah,02h
		int     10h
              ; xor     bh,bh
                mov     bl,dl
                sub     bl,byte ptr [CursorColumn] 
                mov     cx,1
                mov     ah,09h
		mov     al,20h
                mov     Byte Ptr [CommandBuffer][BX],al
                mov     bl,7
loc_write_it:
		int     10h
                mov     dl,Byte Ptr ES:[CCCpointer]
                jmp     short readnextchar
loc_arrow:    
		cmp     AH,4Bh
		jz      short loc_back
		cmp     AH,53h
		jz      short loc_back
		cmp     AH,4Dh
		jnz     short readnextchar
		cmp     dl,79
		jnb     short readnextchar
		inc     dl
		jmp     short set_cursor_pos
char_return:
                mov     bl,dl
              ; xor     bh,bh 
                sub     bl,byte ptr [CursorColumn] 
                mov     ah,0Eh
                cmp     al,20h
		jb      short loc_escape
                mov     Byte Ptr [CommandBuffer][BX],al
                mov     bl,7
                cmp     dl,79
		jb      short loc_write_it
		jmp     short readnextchar
loc_escape:
		cmp     al,1Bh
                jnz     short pass_escape
                pop     es
                retn
pass_escape:
		cmp     al,0Dh
		jnz     short readnextchar
                int     10h
		mov     al,0Ah
		int     10h
                pop     es
                retn
proc_rw_char    endp

proc_print_directory proc near

                mov word ptr [Dir_Count],0
                mov word ptr [File_Count],0
                mov word ptr [Total_FSize], 0
                mov word ptr [Total_FSize]+2, 0

              ; push    ds
              ; pop     es

                mov     byte ptr [PrintDir_RowCounter], 16
                mov     ax, word ptr [AttributesMask]
                call    proc_find_first_file
                pushf
                push si
                push ax
                push dx
                push cx

                call    proc_change_prompt_dir_string

                mov     al, byte ptr [DirBuff_Drv]
                add     al, 'A'
                mov     byte ptr [Dir_Drive_Name], al

                mov     si, offset Current_Path
                mov     di, offset Vol_Name
                mov     cx, 11
                rep     movsb

                mov al, byte ptr [Current_VolSerial1]
                call proc_hex
                mov word ptr [Vol_Serial1]+2, ax
                mov al, byte ptr [Current_VolSerial1]+1
                call proc_hex
                mov word ptr [Vol_Serial1], ax
                mov al, byte ptr [Current_VolSerial2]
                call proc_hex
                mov word ptr [Vol_Serial2]+2, ax
                mov al, byte ptr [Current_VolSerial2]+1
                call proc_hex
                mov word ptr [Vol_Serial2], ax

                call    proc_clear_screen

                mov     si, offset Dir_Drive_Str
                call    proc_printmsg

                mov     si, offset Vol_Serial_Header
                call    proc_printmsg

                mov     ah, 0Eh
                mov     bx, 07h
                mov     al,0Dh
                int     10h
                mov     al,0Ah
                int     10h
                mov     al,0Dh
                int     10h
                mov     al,0Ah
                int     10h

                pop     cx
                pop     dx
                pop     ax
                pop     si
                popf
                jc      loc_dir_ok

loc_dfname_use_this:
                push    cx  ; CL = Attr = byte ptr [SI]+11
                test    cl, 10h  ; Is it a directory?
                jz      short loc_not_dir

                inc     word ptr [Dir_Count]
                push    si
                mov     cx, 10
                mov     si, offset Type_Dir      ; '<DIR>      '
                mov     di, offset Dir_Or_FileSize
                rep     movsb                    ; move 10 bytes
                pop     si

                jmp     short loc_dir_attribute
loc_not_dir:
                inc     word ptr [File_Count]

                add     word ptr [Total_FSize], ax
                adc     word ptr [Total_FSize]+2, dx

                mov     di,9
loc_dir_rdivide:
                mov     cx,10                   ; 16 bit divisor
                call    Rx_Dos_Div32            ; 32 bit divide
                add     bl, '0'                 ; to make visible
                mov     Byte Ptr [Dir_Or_FileSize][DI],bl
                dec     di
                cmp     ax,0
                ja      short loc_dir_rdivide
                cmp     dx,0
                ja      short loc_dir_rdivide
loc_dir_fill_space:
                mov     Byte Ptr [Dir_Or_FileSize][DI],20h
                cmp     di,0
                jna     short loc_dir_attribute
                dec     di
                jmp     short loc_dir_fill_space
loc_dir_attribute:
                pop     cx
                mov     word ptr [File_Attribute], 2020h
                mov     word ptr [File_Attribute]+2, 2020h
                cmp     cl, 20h  ; Is it an archive file?
                jb      short loc_dir_pass_arch
                mov     Byte Ptr [File_Attribute]+3,'A'
loc_dir_pass_arch:
                and     cl,7
                jz      short loc_dir_file_name
                mov     ch,cl
                and     cl,3
                cmp     ch,cl
                jna     short loc_dir_pass_s
                mov     byte ptr [File_Attribute], 'S'
loc_dir_pass_s:
                and     cl,2
                jz      short loc_dir_pass_h
                mov     byte ptr [File_Attribute]+1, 'H'
loc_dir_pass_h:
                and     ch,1
                jz      short loc_dir_file_name
                mov     byte ptr [File_Attribute]+2, 'R'
loc_dir_file_name:
                mov     bx, word ptr [SI]+18h ; Date
                mov     dx, word ptr [SI]+16h ; Time
                push    si
                mov     cx, 8
                mov     di, offset File_Name
                rep     movsb                    ; move 8 bytes
                mov     Byte Ptr [DI],20h
                inc     di
                mov     cx, 3
                rep     movsb                    ; move 3 bytes
                pop     si
Dir_Date_start:
		mov     ax, bx                   ; Date
		and     ax, 00011111b            ; Day Mask
		aam                              ; Q([AL]/10)->AH
						 ; R([AL]/10)->AL
						 ; [AL]+[AH]= Day as BCD
		or      ax, '00'                 ; Convert to ASCII
		xchg    al,ah
                mov     word ptr [File_Day],ax

		mov     ax, bx
		mov     cl, 5
		shr     ax, cl                   ; shift right 5 times
		and     ax, 00001111b            ; Month Mask
		aam
		or      ax, '00'
		xchg    ah,al
                mov     word ptr [File_Month],ax

		mov     ax, bx
		mov     cl, 9
		shr     ax, cl
		and     ax, 01111111b            ; Result = Year - 1980
		add     ax, 1980

		mov     cl, 10
		div     cl                        ; Q -> AL, R -> AH 
		or      ah, '0'
                mov     byte ptr [File_Year]+3,ah

		aam
		xchg    ah, al
		or      ah, '0'                  ; Convert to ASCII
                mov     byte ptr [File_Year]+2,ah

		aam
                xchg    al, ah
		or      ax, '00'
                mov     word ptr [File_Year],ax

Dir_Time_start:
		mov     ax, dx                   ; Time
		mov     cl, 5
		shr     ax, cl                   ; shift right 5 times
		and     ax, 0000111111b          ; Minute Mask
		aam
		or      ax, '00'
		xchg    ah,al
                mov     word ptr [File_Minute],ax

		mov     al, dh                   
		shr     al, 1
		shr     al, 1
		shr     al, 1                    ; ax = hours
		aam
		or      ax, '00'
		xchg    ah, al
                mov     word ptr [File_Hour],ax
loc_show_line:
                push    si
                mov     si, offset File_Name
                mov     cx, 46
		mov     ah, 0Eh
		mov     bx, 07h
loop_loc_dir_entry:
                lodsb                           
                int     10h                     
                loop    loop_loc_dir_entry     
                pop     si

                mov     al,0Dh
                int     10h
                mov     al,0Ah
                int     10h
                sub     byte ptr [PrintDir_RowCounter], 1
                jna     Pause_dir_scroll
loc_next_entry:
                call    proc_find_next_file
                jnc     loc_dfname_use_this
loc_dir_ok:
                mov     ax, word ptr [Dir_Count]
                mov     di, offset Decimal_Dir_Count
                cmp     ax, 10
                jb      short pass_ddc
                inc     di
                cmp     ax, 100
                jb      short pass_ddc
                inc     di
                cmp     ax, 1000
                jb      short pass_ddc
                inc     di
                cmp     ax, 10000
                jb      short pass_ddc
                inc     di
pass_ddc:
                mov     byte ptr [DI]+1, 0
loc_ddc_rediv:
                xor     dx, dx
                mov     cx, 10
                div     cx
                add     dl, "0"
                mov     byte ptr [DI], dl
                dec     DI
                cmp     ax, 0
                ja      short loc_ddc_rediv

                mov     ax, word ptr [File_Count]
                mov     di, offset Decimal_File_Count
                cmp     ax, 10
                jb      short pass_dfc
                inc     di
                cmp     ax, 100
                jb      short pass_dfc
                inc     di
                cmp     ax, 1000
                jb      short pass_dfc
                inc     di
                cmp     ax, 10000
                jb      short pass_dfc
                inc     di
pass_dfc:
                mov     byte ptr [DI]+1, 0
loc_dfc_rediv:
                xor     dx, dx
                mov     cx, 10
                div     cx
                add     dl, "0"
                mov     byte ptr [DI], dl
                dec     DI
                cmp     ax, 0
                ja      short loc_dfc_rediv

                mov     di, offset TFS_Dec_End
                mov     byte ptr [DI], 0
                mov     ax, word ptr [Total_FSize]
                mov     dx, word ptr [Total_FSize]+2
                mov     cx, 10
rediv_tfs_hex:
                call    Rx_Dos_Div32
                add     bl, "0"
                dec     DI
                mov     byte ptr [DI], bl
                cmp     ax, 0
                ja      short rediv_tfs_hex
                cmp     dx, 0
                ja      short rediv_tfs_hex
                mov     word ptr [TFS_Dec_Begin], DI
                mov     si, offset Decimal_File_Count_Header
                call    proc_printmsg
                mov     si, offset str_files
                call    proc_printmsg
                mov     si, offset str_dirs
                call    proc_printmsg
                mov     si, word ptr [TFS_Dec_Begin]
                call    proc_printmsg
                mov     si, offset str_bytes
                call    proc_printmsg

                retn

Pause_dir_scroll:
                xor    ah, ah                                           
                int    16h
                cmp    al,1Bh
                je     loc_dir_ok
                mov    byte ptr [PrintDir_RowCounter], 16 ; Reset counter
                jmp    loc_next_entry

File_Count:     dw 0
Dir_Count:      dw 0
Decimal_File_Count_Header:  db 0Dh, 0Ah
Decimal_File_Count: db 6 dup(0)
str_files:      db " file(s) & "
Decimal_Dir_Count: db 6 dup(0)
str_dirs:       db " directory(s) ", 0Dh, 0Ah, 0
Total_FSize:    dd 0
TFS_Dec_Begin:  dw 0
                db 10 dup(0)
TFS_Dec_End:    db 0
str_bytes:      db " byte(s) in file(s)", 0Dh, 0Ah, 0

proc_print_directory endp

proc_change_current_drive proc near
               ; INPUT al= logical dos drive number
               cmp al, 1
               ja short loc_change_current_drv0
loc_init_drv_fd:
               mov dl, al
               call floppy_drv_init
               jnc short loc_change_current_drv2
loc_return_change_drive:
               mov ax, 15h ; Drive not ready
               retn
loc_change_current_drv0:
               cmp byte ptr [Last_Dos_DiskNo], al
               jc short loc_return_change_drive  
loc_change_current_drv1:
               mov si, offset Logical_DOSdisks
               mov ah, al
               xor al, al
               add si, ax
loc_change_current_drv2:
               mov al, byte ptr [SI][LD_Name]
               cmp al, 'A'
               jc short loc_return_change_drive
               mov byte ptr [DirBuff_Drv], ah
               mov byte ptr [Current_DirLevel], 0
               mov byte ptr [Last_DirLevel], 0
               mov byte ptr [Dir_Str], 0
               mov ah, byte ptr [SI][LD_FATType]
               mov byte ptr [Current_FS], ah
               mov word ptr [Current_FS_RDFC], 0
               mov word ptr [Current_FS_RDFC]+2, 0
               mov word ptr [Current_DirFCluster], 0
               mov word ptr [Current_DirFCluster]+2, 0
               mov word ptr [DirBuff_DirCluster], 0
               mov word ptr [DirBuff_DirCluster]+2, 0
               add si, LD_BPB
               cmp ah, 2
               ja short loc_get_FAT32_bs_volume_name
               push word ptr [SI][VolumeID]
               pop word ptr [Current_VolSerial1]
               push word ptr [SI][VolumeID]+2
               pop word ptr [Current_VolSerial2]
               add si, VolumeLabel
               jmp short loc_init_ccd_volume
loc_get_FAT32_bs_volume_name:
               push word ptr [SI][FAT32_RootFClust]
               pop word ptr [Current_FS_RDFC]
               push word ptr [SI][FAT32_RootFClust]+2
               pop word ptr [Current_FS_RDFC]+2
               push word ptr [Current_FS_RDFC]
               pop word ptr [Current_DirFCluster]
               push word ptr [Current_FS_RDFC]+2
               pop word ptr [Current_DirFCluster]+2
               push word ptr [SI][FAT32_VolID]
               pop word ptr [Current_VolSerial1]
               push word ptr [SI][FAT32_VolID]+2
               pop word ptr [Current_VolSerial2]
               add si, FAT32_VolLab
loc_init_ccd_volume:
               mov cx, 11
               mov di, offset Current_Path
               rep movsb
               xor al, al
               stosb
loc_get_root_vol_name:
               call proc_get_volume_name
               jc short pass_overwrite_bs_vol_name
               mov cx, 11
               mov di, offset Current_Path
              ;push ds
              ;pop es
               rep movsb
pass_overwrite_bs_vol_name:
               mov al, byte ptr [DirBuff_Drv]
               mov byte ptr [Current_DosDisk], al
               xor bl, bl
               mov bh, al
               mov si, offset Current_Path
               mov di, offset Logical_DosDisks
               add di, bx
               add di, LD_CurrentDirectory
               mov cx, 11
               rep movsb
               retn

proc_change_current_drive endp

proc_get_volume_name proc near

               ; OUTPUT -> CF = 0 -> DS:SI = Volume Name Address
               ; CF = 1 -> Root volume name not found

                xor     bl, bl
                mov     bh, byte ptr [DirBuff_Drv]
                mov     byte ptr [DirBuff_CurrentEntry], 0
                cmp     byte ptr [Current_FS], 2
                ja      short get_FAT32_root_cluster
loc_get_fat_volume_next_sector:
                call    proc_load_root_directory
                jnc     short loc_get_volume_name
                retn
get_FAT32_root_cluster:
                mov     ax, word ptr [Current_FS_RDFC]
                mov     dx, word ptr [Current_FS_RDFC]+2
                call    proc_load_directory
                jnc     short loc_get_volume_name
                retn
loc_get_volume_name:
                mov     si, offset Directory_Buffer
check_root_volume_name:
                cmp     byte ptr [SI]+0Bh, 28h
                je      short loc_get_volume_name_retn
                inc     byte ptr [DirBuff_CurrentEntry]
                cmp     byte ptr [DirBuff_CurrentEntry], 15
                ja      short pass_check_root_volume_name
                add     si, 32
                cmp     byte ptr [SI], 0
                ja      short check_root_volume_name
pass_check_root_volume_name:
                mov     byte ptr [DirBuff_CurrentEntry], 0
                mov     bl, byte ptr [DirBuff_SectorOffset]
                inc     bl
                cmp     byte ptr [DirBuff_LastSector], bl
                jc      short loc_get_volume_name_retn

                mov     bh, byte ptr [DirBuff_drv]
                cmp     byte ptr [Current_FS], 2
                jna     short loc_get_fat_volume_next_sector

                mov     ax, word ptr [DirBuff_DirCluster]
                mov     dx, word ptr [DirBuff_DirCluster]+2
                call    proc_load_directory
                jnc     short loc_get_volume_name

loc_get_volume_name_retn:
                retn

proc_get_volume_name endp

proc_locate_current_dir_file proc near

                ; INPUT ->
                ;  DS:SI = DOS DirEntry Format FileName
                ;  DX = Attributes Mask
                ;  AH > 0 -> Return First Free Dir Entry
                ;  AL = 0 -> Return End Of Dir Entries
                ;  AL = E5h -> Return the 1st Deleted/Empty Entry
                ; OUTPUT ->
                ;  ES:DI = Directory Entry Address (DirBuff+CL)
                ;  DS:SI = 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
                ;  CL= CurrentDirEntry (0-15=Valid, >15 Invalid)
                ;  CH = The 1st Name Char of Current Dir Entry
                ;  CF=1 -> Proper entry not found, Error Code in AX/AL
                ;  CL<=15 and CH=0 -> Free Entry (End Of Dir)
                ;  CL<=15 and CH=E5h -> Deleted Entry fits with filters
                ;  CL > 15 -> Entry not found, CH invalid
                ;  CF
                ;  BX = Count of Dir Entries have been checked - 1

                mov word ptr [DirBuff_EntryCounter], 0 ; Zero Based

              ; push ds
              ; pop es

                mov word ptr [CDLF_FNAddress], si
                mov word ptr [CDLF_FFDEsign], ax
                mov word ptr [AttributesMask], dx
loc_cdir_locatefile_search:
                mov ch, ah
                mov ah, al
                xor cl, cl
                call proc_find_direntry
                jc short loc_locatefile_check_next_entryblock
loc_cdir_locate_file_retn:
                mov bx, word ptr [DirBuff_EntryCounter]
                retn

loc_locatefile_check_next_entryblock:
                mov bh, byte ptr [DirBuff_Drv]
                cmp byte ptr [Current_DirLevel], 0
                ja short loc_locatefile_load_subdir_sector
                cmp byte ptr [Current_FS], 2
                ja short loc_locatefile_load_subdir_sector
                mov bl, byte ptr [DirBuff_SectorOffset]
                inc bl
                cmp byte ptr [DirBuff_LastSector], bl
                jc short loc_locatefile_file_notfound
                call proc_load_root_directory
                jc short loc_locatefile_drive_not_ready_read_err
                jmp short loc_locatefile_search_again
loc_locatefile_load_subdir_sector:
                mov ax, word ptr [DirBuff_DirCluster]
                mov dx, word ptr [DirBuff_DirCluster]+2
                mov bl, byte ptr [DirBuff_SectorOffset]
                inc bl
                cmp bl, byte ptr [DirBuff_LastSector]
                jna short loc_locatefile_next_sec2
                xor bl, bl
                mov si, offset Logical_DosDisks
                add si, bx
                push bx
                call proc_get_next_cluster
                pop bx
                jnc short loc_locatefile_next_sec2
                cmp ax, 0
                ja short loc_locatefile_drive_not_ready_read_err

loc_locatefile_file_notfound:
                mov ax, 2 ; File/Directory/VolName not found
                stc
                jmp short loc_cdir_locate_file_retn
loc_locatefile_drive_not_ready_read_err:
                mov ax, 15h ;Drive not ready or read error
                jmp short loc_cdir_locate_file_retn
loc_locatefile_next_sec1:
                mov ax, word ptr [Current_DirFCluster]
                mov dx, word ptr [Current_DirFCluster]+2
loc_locatefile_next_sec2:
                call proc_load_directory
                jc short loc_locatefile_drive_not_ready_read_err
loc_locatefile_search_again:
                mov ax, word ptr [CDLF_FFDEsign]
                mov si, word ptr [CDLF_FNAddress] 
                mov dx, word ptr [AttributesMask]
                jmp short loc_cdir_locatefile_search

CDLF_FNAddress: dw 0
CDLF_FFDEsign:  dw 0

proc_locate_current_dir_file endp

proc_parse_dir_name proc near
                ; DS:SI = Directory String
                cmp byte ptr [SI], "/"
                jne short pass_reset_parse_sd_levels
                xor ah, ah
                mov byte ptr [Last_DirLevel],0
                mov byte ptr [Current_DirLevel],0
                jmp short repeat_parse_sd_name0
pass_reset_parse_sd_levels:
                mov ah, byte ptr [Current_DirLevel]
                mov byte ptr [Last_DirLevel],ah
                jmp short repeat_parse_sd_name2
repeat_parse_sd_name0:
                inc si
repeat_parse_sd_name1:
                cmp byte ptr [SI], "/"
                je short repeat_parse_sd_name0
repeat_parse_sd_name2:
                cmp byte ptr [SI], 20h
                ja short pass_reset_dir_level
                jb short end_of_parse_dir_name
                jmp short repeat_parse_sd_name0
pass_reset_dir_level:
                inc ah 
                cmp ah, 7
                ja short end_of_parse_dir_name
                mov byte ptr [Last_DirLevel],ah
                mov cx, 12
                mov di, offset Dir_File_Name
loc_get_subdir_name:
                lodsb
                mov byte ptr [DI], al
                cmp al, 20h
                jna short end_of_subdir_name
                cmp al, "/"
                je short end_of_subdir_name
                inc di
                loop loc_get_subdir_name
end_of_subdir_name:
                mov byte ptr [DI], 0
                push ax
                push si
                mov si, offset Dir_File_Name
                mov al, byte ptr [Last_DirLevel]
                mov ah, 16
                mul ah
                mov di, offset Current_Path
                add di, ax
                cmp ax, 0
                jna short pass_current_dirlevel_fc_reset
                mov word ptr [DI]+12, 0
                mov word ptr [DI]+14, 0
pass_current_dirlevel_fc_reset:
                call proc_convert_file_name
                pop si
                pop ax
                cmp al, 0Dh
                jna short end_of_parse_dir_name
                mov ah, byte ptr [Last_DirLevel]
                jmp short repeat_parse_sd_name1
end_of_parse_dir_name:
                retn
proc_parse_dir_name endp

proc_convert_file_name proc near
     ; INPUT -> DS:SI = Dot File Name Location
     ; INPUT -> ES:DI = Dir Entry Format File Name Location
     push di
     mov cx, 11
     mov al, 20h
     rep stosb
     pop di
     mov cx, 12
     mov al, 2Eh
     cmp byte ptr [SI], 2Eh
     je short pass_dot_space
loc_get_fchar:
     mov al, byte ptr [SI]
     cmp al, 61h
     jb  short pass_name_capitalize
     cmp al, 7Ah
     ja  short pass_name_capitalize
     and al, 0DFh
     mov byte ptr [SI], al
pass_name_capitalize:
     cmp al, 21h
     jb  short stop_convert_file
     cmp al, 2Eh
     jne short pass_dot_space
add_space:
     cmp cx, 4
     jna short inc_and_loop
     inc di
     dec cx
     jmp short add_space
pass_dot_space:
     mov byte ptr ES:[DI], al
     inc di
inc_and_loop:
     inc si
     loop loc_get_fchar
stop_convert_file:
     retn
proc_convert_file_name endp

Last_DirLevel: db 0
Dir_File_Name: db 13 dup(0)

proc_change_current_directory proc near
               xor bl, bl
               mov bh, byte ptr [DirBuff_Drv]
               mov di, offset Logical_DOSDisks
               add di, bx
               mov ah, byte ptr [DI][LD_FATType]
               mov byte ptr [Current_FS], ah
               cmp ah, 2
               jna short pass_fat32_fs_rdfc
               push word ptr [DI][LD_BPB][FAT32_RootFClust]
               pop word ptr [Current_FS_RDFC]
               push word ptr [DI][LD_BPB][FAT32_RootFClust]+2
               pop word ptr [Current_FS_RDFC]+2
               jmp short pass_fat_fs_rdfc
check_fat32_root_dir0:
               mov ax, word ptr [Current_FS_RDFC]
               mov dx, word ptr [Current_FS_RDFC]+2
               call proc_load_directory
               jc short retn_find_sub_dir0
               push word ptr [Current_FS_RDFC]
               pop word ptr [Current_DirFCluster]
               push word ptr [Current_FS_RDFC]+2
               pop word ptr [Current_DirFCluster]+2
               jmp short pass_fat16_root_dir_loading
pass_fat32_fs_rdfc:
               mov word ptr [Current_FS_RDFC], 0
               mov word ptr [Current_FS_RDFC]+2, 0
pass_fat_fs_rdfc:
               mov al, byte ptr [Current_DirLevel]
               cmp al, 0
               ja short pass_cd_root_dir_fixup
check_fat32_root_dir1:
               cmp byte ptr [Current_FS], 2
               ja short check_fat32_root_dir0
check_fat16_root_dir:
               call proc_load_root_directory
               jc short retn_find_sub_dir0
               mov word ptr [Current_DirFCluster], 0
               mov word ptr [Current_DirFCluster]+2, 0
pass_fat16_root_dir_loading:
               mov si, offset Current_Path
               add si, 16
               cmp byte ptr [Last_DirLevel], 0
               ja short loc_cd_find_directory
               mov byte ptr [Dir_Str],0
               retn
pass_cd_root_dir_fixup:
               cmp byte ptr [Last_DirLevel], 0
               ja short pass_return_to_root_dir
               mov byte ptr [Current_DirLevel], 0
               jmp short check_fat32_root_dir1
retn_find_sub_dir0:
               mov ax, 3  ; Path not found
retn_find_sub_dir1:
               retn
pass_return_to_root_dir:
               cmp al, byte ptr [Last_DirLevel]
               jb short locate_next_level_dir
               je short reload_current_dir
               mov al, byte ptr [Last_Dirlevel]
               mov byte ptr [Current_DirLevel], al
reload_current_dir:
               mov ah, 16
               mul ah
               mov si, offset Current_Path
               add si, ax
               mov ax, word ptr [SI]+12
               mov dx, word ptr [SI]+14
               jmp update_cdir_fclust_exit
locate_next_level_dir:
               mov ah, 16
               mul ah
               mov si, offset Current_Path
               add si, ax
               cmp byte ptr [SI]+16, 20h
               jna stc_retn_find_sub_dir
             ; mov ax, word ptr [SI]+12
             ; mov dx, word ptr [SI]+14
               add si, 16
loc_cd_find_dir_next_sec0:
               mov ax, word ptr [Current_DirFCluster]
               mov dx, word ptr [Current_DirFCluster]+2
loc_cd_find_dir_next_sec1:
               xor bl, bl
loc_cd_find_dir_next_sec2:
               push si
               mov bh, byte ptr [DirBuff_Drv]
               call proc_load_directory
               pop si
               jc short retn_find_sub_dir0
loc_cd_find_directory:
               xor cx, cx
               mov dx, 0810h
               call proc_find_direntry
               jnc short loc_directory_found

               mov bh, byte ptr [DirBuff_Drv]
               mov bl, byte ptr [DirBuff_SectorOffset]
               inc bl               
               cmp byte ptr [Current_DirLevel], 0
               ja short pass_loc_cd_load_next_root_sec
               cmp byte ptr [Current_FS], 2
               ja short pass_loc_cd_load_next_root_sec
               cmp byte ptr [DirBuff_LastSector], bl
               jb short retn_find_sub_dir0
               jmp check_fat16_root_dir
pass_loc_cd_load_next_root_sec:
               mov ax, word ptr [DirBuff_DirCluster]
               mov dx, word ptr [DirBuff_DirCluster]+2
               cmp bl, byte ptr [DirBuff_LastSector]
               jna short loc_cd_find_dir_next_sec2
pass_loc_cd_load_next_root_sec2:
               push si
               call proc_get_next_cluster
               pop si
               jnc short loc_cd_find_dir_next_sec1
stc_retn_find_sub_dir:
               mov ax, 3 ; Path not found
               retn
loc_directory_found:
               mov ax, word ptr [DI]+1Ah  ;First Cluster LW
               mov dx, word ptr [DI]+14h  ;First Cluster HW
               push ax
               push dx
               mov al, byte ptr [Current_DirLevel]
               inc al
               mov byte ptr [Current_DirLevel], al
               mov ah, 16
               mul ah
               mov si, offset Current_Path
               add si, ax
               pop dx
               pop ax
               mov word ptr [SI]+12, ax
               mov word ptr [SI]+14, dx
update_cdir_fclust_exit:
               mov word ptr [Current_DirFCluster], ax
               mov word ptr [Current_DirFCluster]+2,dx
               xor bl,bl
               mov bh, byte ptr [DirBuff_Drv]
               call proc_load_directory
               jc short retn_find_sub_dir
               mov al, byte ptr [Current_DirLevel]
               cmp al, byte ptr [Last_DirLevel]
               jb locate_next_level_dir
retn_find_sub_dir:
               retn
proc_change_current_directory endp

proc_find_direntry proc near
                
                ; INPUT -> DS:SI = Sub Dir or File Name Address
                ; DL = Attributes Mask 
                ;      ("DL AND EntryAttrib" must be equal to DL)
                ; DH = Negative Attributes Mask (If DH>0)
                ;      ("DH AND EntryAttrib" must be ZERO)
                ; CL = Current Entry
                ; CH > 0 Find First Free Dir Entry or Deleted Entry
                ;    AL = 0 -> Return the First Free Dir Entry
                ;    AL = E5h -> Return the 1st deleted entry
                ;    AL > 0 and AL<> E5h -> Return the first entry 
                ;         which result of "AL and AH" is not ZERO 
                ;    AH = Mask (0-> Return Free Dir Entry only)
                ; CH = 0 Find Valid File/Directory/VolumeName
                ;    ? = Any One Char
                ;    * = Every Chars
                ; BX = Not will be used
                ;
                ; RETURN -> 
                ; ES:DI = Directory Entry Address (DirectoryBuffer+CL)
                ; DS:SI = 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
                ; CL= CurrentDirEntry (0-15=Valid, >15 Invalid)
                ; CH = The 1st Name Char of Current Dir Entry
                ; CF=1 -> Proper entry not found, Error Code in AX/AL
                ; CL<=15 and CH=0 -> Free Entry (End Of Dir)
                ; CL<=15 and CH=E5h -> Deleted Entry fits with filters
                ; CL > 15 -> Entry not found, CH invalid
                ; CF
                ; BX = Not be changed
                 
                ; push  cs
                ; pop   ds
                ; push  ds
                ; pop   es                
                mov     di, offset Directory_Buffer
                mov     word ptr [FDE_AttrMask], dx
                mov     byte ptr [DirBuff_CurrentEntry], cl
                
                cmp     ch, 0 
                ja      loc_find_free_deleted_entry_0

                mov     word ptr [AmbiguousFileName], 0

                cmp     cl, 0
                jna     short check_find_dir_entry
                mov     al, 32
                mul     cl
                add     di, ax
check_find_dir_entry:
                push    si
                mov     ch, byte ptr [DI]
                cmp     ch, 0 ; Is it never used entry?
                jna     short pop_si_loc_find_direntry_stc_retn
                mov     ah, byte ptr [DI]+0Bh
                cmp     ch, 0E5h ; Is it a deleted file?
                je      short loc_find_dir_next_entry_prevdeleted
loc_check_attributes_mask:
                mov     al, dl
                and     dl, ah
                cmp     dl, al
                jne     loc_find_dir_next_entry
                cmp     dh, 0
                ja      short loc_negative_attr_check
                cmp     dl, 0Fh
                jne     short pass_direntry_attr_check
                pop     si
                xor     ax, ax
                mov     dh, byte ptr [PreviousAttr]
                mov     cl, byte ptr [DirBuff_CurrentEntry]
                retn
pop_si_loc_find_direntry_stc_retn:
                pop     si
                jmp     loc_find_direntry_stc_retn 
loc_negative_attr_check:                
                and     dh, ah
                jnz     loc_find_dir_next_entry
pass_direntry_attr_check:
                mov     dx, di
                mov     cx, 8
loc_lodsb_find_dir:
                lodsb
                cmp     al, '*'
                jne     short pass_fde_ambiguous1_check
                inc     byte ptr [AmbiguousFileName]+1
                jmp     short loc_check_direntry_extension
pass_fde_ambiguous1_check:
                cmp     al, '?'
                jne     short pass_fde_ambiguous2_check
                inc     byte ptr [AmbiguousFileName]
                cmp     byte ptr [DI], 20h
                jna     short loc_find_dir_next_entry_dx
                jmp     short loc_scasb_find_dir_inc_di
pass_fde_ambiguous2_check:
                cmp     al, 20h
                jne     short loc_scasb_find_dir
                cmp     byte ptr [DI], 20h
                jne     short loc_find_dir_next_entry_dx
                jmp     short loc_check_direntry_extension
loc_scasb_find_dir:
                cmp     al, byte ptr [DI]
                jne     short loc_find_dir_next_entry_dx
loc_scasb_find_dir_inc_di:
                inc     di
                loop    loc_lodsb_find_dir
loc_check_direntry_extension:
                pop     si
                push    si
                add     si, 8
                mov     di, dx
                add     di, 8
                mov     cl, 3
loc_lodsb_find_dir_ext:
                lodsb
                cmp     al, '*'
                jne     short pass_fde_ambiguous3_check
                inc     byte ptr [AmbiguousFileName]+1
                jmp     short loc_find_dir_proper_direntry
loc_find_dir_next_entry_prevdeleted:
                or      ah, 80h  ; Bit 7 -> deleted entry sign
                jmp     short loc_find_dir_next_entry
pass_fde_ambiguous3_check:
                cmp     al, '?'
                jne     short pass_fde_ambiguous4_check
                inc     byte ptr [AmbiguousFileName]
                cmp     byte ptr [DI], 20h
                jna     short loc_find_dir_next_entry_dx
                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 ptr [DI], 20h
                jne     short loc_find_dir_next_entry_dx
                jmp     short loc_find_dir_proper_direntry
loc_find_dir_next_entry_dx:
                mov     di, dx
loc_find_dir_next_entry:
                mov     byte ptr [PreviousAttr], ah ; LongName check
                pop     si
                add     di, 32
                inc     word ptr [DirBuff_EntryCounter]
                mov     dx, word ptr [FDE_AttrMask]
                inc     byte ptr [DirBuff_CurrentEntry]
                cmp     byte ptr [DirBuff_CurrentEntry], 15
                jna     check_find_dir_entry
                mov     ch, 0FFh
loc_find_direntry_stc_retn:
                mov     dl, ch
                mov     ax, 2  ; File Not Found
                mov     dh, byte ptr [PreviousAttr]
                mov     cl, byte ptr [DirBuff_CurrentEntry]
                stc
                retn
loc_scasb_find_dir_ext:
                cmp     al, byte ptr [DI]
                jne     short loc_find_dir_next_entry_dx
loc_scasb_find_dir_ext_inc_di:
                inc     di
                loop    loc_lodsb_find_dir_ext
loc_find_dir_proper_direntry:
                pop     si
                mov     di, dx
                mov     ch, byte ptr [DI]
                mov     dl, byte ptr [DI]+0Bh
                mov     dh, byte ptr [PreviousAttr]
                mov     cl, byte ptr [DirBuff_CurrentEntry]
                mov     ax, word ptr [AmbiguousFileName]
                retn

loc_find_free_deleted_entry_0:
                cmp    cl, 0
                jna    short loc_find_free_deleted_entry_1
              ; cmp    cl, 15
              ; ja     short loc_ffde_stc_retn_255
                xor    dh, dh
                mov    dl, cl
                shl    dl, 1
                shl    dl, 1
                shl    dl, 1
                shl    dl, 1
                shl    dl, 1
                add    di, dx
loc_find_free_deleted_entry_1:
                mov    ch, byte ptr [DI]
                cmp    ch, 0
                ja     short pass_loc_check_ffde_0_err
                cmp    al, 0
                jna    short loc_check_ffde_retn_0
loc_check_ffde_stc_retn:
                mov    ax, 2 ; File Not Found
                stc
                jmp    short loc_check_ffde_retn_1  
pass_loc_check_ffde_0_err: 
                cmp    ch, al
                je     short loc_check_ffde 
                mov    dh, byte ptr [DI]+0Bh
                mov    byte ptr [PreviousAttr], dh
                inc    cl
                add    di, 32
                cmp    cl, 15
                jna    short loc_find_free_deleted_entry_1
loc_ffde_stc_retn_255:
                mov    ch, 0FFh
                mov    dl, ch
                jmp    short loc_check_ffde_stc_retn
loc_check_ffde:
                and    ah, ch
                jz     short loc_check_ffde_stc_retn
loc_check_ffde_retn_0:
                xor    ax, ax
                mov    dl, byte ptr [DI]+0Bh
loc_check_ffde_retn_1:
                mov    dh, byte ptr [PreviousAttr]
                mov    byte ptr [DirBuff_CurrentEntry], cl
                retn  
                 
PreviousAttr: db 0
FDE_AttrMask: dw 0
AmbiguousFileName: dw 0

proc_find_direntry endp


proc_load_current_path proc near
                ; INPUT, OUTPUT => none
                xor bl, bl
                mov bh, byte ptr [DirBuff_Drv]
                mov si, offset Logical_DOSdisks
                add si, bx
              ; mov al, byte ptr [SI][LD_FATType]
              ; mov byte ptr [Current_FS], al
                mov al, byte ptr [SI][LD_CDirLevel]
                mov byte ptr [Current_DirLevel],al
                mov byte ptr [Last_DirLevel],al
                add si, LD_CurrentDirectory
                mov di, offset Current_Path
                mov cx, 64
                rep movsw
proc_load_current_path endp

proc_parse_pathname proc near
                ; 5-12-2004
                ; Input DS:SI -> Beginning of ASCIIZ pathname string
                ; Input ES:DI -> Destination Address
                ;                is TR-DOS Findfile data buffer
                ; Output, CF = 1 : Error, Error Code in AX (AL)
                ; 
                push di
                mov cx, 40
                xor ax, ax
                rep stosw ; Reset the pathname structure in TR-DOS Findfile data buffer 
                pop di

                mov ax, word ptr [SI]
                cmp ah, ':'
                je short loc_ppn_change_drive
                mov al, byte ptr CS:[Current_DosDisk]
                jmp short pass_ppn_change_drive

pass_ppn_cdir:
                mov si, word ptr CS:[First_Path_Pos]
                mov al, byte ptr [SI]
                inc di
loc_ppn_get_filename:
                add di, 64 ; FindFile_FileName location
                mov cx, 12  ; TRDOS Filename length must not be more than 12 bytes
loc_ppn_get_fnchar_next:
                mov byte ptr ES:[DI], al
                inc di
                inc si
                mov al, byte ptr [SI]
                cmp al, 20h
                jna short loc_ppn_get_fname_finish
                loop short loc_ppn_get_fnchar_next
loc_ppn_get_fname_finish:                
                xor al, al
                mov byte ptr ES:[DI], al
loc_ppn_return:
                retn

loc_ppn_change_drive:
                inc si
                inc si
                mov ah, byte ptr [SI]
                cmp ah, 20h
                jna short loc_ppn_cmd_failed
                and al, 0DFh
                sub al, 'A'; A:
                jc short loc_ppn_invalid_drive
                cmp byte ptr CS:[Last_Dos_DiskNo], al
                jb short loc_ppn_invalid_drive
pass_ppn_change_drive:
                mov word ptr CS:[First_Path_Pos], si
                mov word ptr CS:[Last_Slash_Pos], 0
                mov byte ptr ES:[DI], al  ; FindFile_Drv
                inc di
                mov al, byte ptr [SI]
loc_scan_ppn_dslash:
                cmp al, '/'
                jne short loc_scan_next_slash_pos
                mov word ptr CS:[Last_Slash_Pos], si
loc_scan_next_slash_pos:
                inc si
                mov al, byte ptr [SI]
                cmp al, 20h
                ja  short loc_scan_ppn_dslash
                cmp word ptr CS:[Last_Slash_Pos], 0
                jna short pass_ppn_cdir

                mov cx, word ptr CS:[Last_Slash_Pos]
                push cx
                mov si, word ptr CS:[First_Path_Pos]
                sub cx, si
                inc cx
                cmp cx, 64
                ja short loc_ppn_invalid_drive   
                mov byte ptr ES:[DI], cl ; Dest Dir Str Length
                inc di
                push di ; Dest Dir String Location (64 byte)
                rep movsb
                mov byte ptr ES:[DI], 0 ; End of Dir String
                pop di
                pop si ; pushed CX
                inc si
                mov al, byte ptr [SI]
                cmp al, 20h
                ja short loc_ppn_get_filename
                clc
                retn

loc_ppn_cmd_failed:
                mov ax, 1
                ; TR-DOS Error Code 1h = Bad Command Argument
                ; MS-DOS Error Code 1h : Invalid Function Number
                stc
                ; (MainProg ErrMsg: "Bad command or file name!")
                retn
loc_ppn_invalid_drive:
                ; The Drive Letter/Char < "A" or > "Z"
                mov ax, 0Fh
                ; MS-DOS Error Code 0Fh = Disk Drive Invalid 
                ; stc
                ; (MainProg ErrMsg: "Drive not ready or read error!")
                retn
loc_ppn_drive_not_ready:
                ; Drive is not ready or read error (from disk io process)
                ; or Drive Number > Last_Dos_DiskNo
                mov ax, 15h
                ; MS-DOS Error Code 15h = Drive Not Ready
                ; stc
                ; (MainProg ErrMsg: "Drive not ready or read error!")
                retn

First_Path_Pos: dw 0
Last_Slash_Pos: dw 0

proc_parse_pathname endp

proc_change_prompt_dir_string proc near

                mov     di, offset Dir_Str
                cmp     byte ptr [Current_DirLevel],0
                jna     short pass_write_path
                mov     al, byte ptr [Current_DirLevel]
                mov     byte ptr [DirLevel_Count], al
                mov     si, offset Current_Path
                mov     di, offset Dir_Str
                add     si, 16
                mov     bx, si
loc_write_path:
                mov     cx, 8
path_write_dirname1:
                lodsb
                cmp     al, 20h
                jna     short pass_write_dirname1
                mov     byte ptr [DI], al
                inc     di
                cmp     di, offset End_Of_Dir_Str
                jnb     short pass_write_path
                loop    path_write_dirname1
                cmp     byte ptr [SI], 20h
                jna     short pass_write_dirname2
                jmp     short loc_put_dot_cont_ext
pass_write_dirname1:
                mov     si, bx
                add     si, 8
                cmp     byte ptr [SI], 20h
                jna     short pass_write_dirname2
loc_put_dot_cont_ext:
                mov     byte ptr [DI],"."
                mov     cx, 3
loc_check_dir_name_ext:
                lodsb
                inc     di
                cmp     al, 20h
                jna     short pass_write_dirname2
                mov     byte ptr [DI], al
                cmp     di, offset End_Of_Dir_Str
                jnb     short pass_write_path
                loop    loc_check_dir_name_ext
                inc     di
pass_write_dirname2:
                dec     byte ptr [DirLevel_Count]
                cmp     byte ptr [DirLevel_Count], 0
                jna     short pass_write_path
                add     bx, 16
                mov     si, bx
                mov     byte ptr [DI],"/"
                inc     di
                jmp     short loc_write_path
pass_write_path:
                mov     byte ptr [DI],0
                retn
DirLevel_Count: db 0

proc_change_prompt_dir_string endp

proc_volume_total_free_space proc near
                ; INPUT AL = DOS Drive Number
                mov word ptr [FreeClusterCount], 0
                mov word ptr [FreeClusterCount]+2, 0
                xor bl, bl
                mov bh, al
                mov si, offset Logical_DOSDisks
                add si, bx
                add al, 'A'
                cmp al, byte ptr [SI]  
                je short pass_vol_drv_name_check
                stc
                retn
pass_vol_drv_name_check:
                push si
                push bx
                mov byte ptr [Vol_Drv_Name], al
                cmp byte ptr [SI][LD_FATType],2
                ja short loc_vol_get_FAT32_vol_name
                cmp byte ptr [SI][LD_BPB][BootSignature], 29h
                jne short loc_start_calc_vol_space
                add si, LD_BPB+VolumeLabel
                mov di, offset Vol_Vol_Name
                mov cx, 11
                rep movsb
                mov si, offset Volume_in_drive
                call proc_printmsg
                jmp short loc_start_calc_vol_space
loc_vol_get_FAT32_vol_name:
              ; cmp byte ptr [SI][LD_BPB][FAT32_Bootsig], 29h
              ; jne short loc_start_calc_vol_space
                add si, LD_BPB+FAT32_VolLab
                mov di, offset Vol_Vol_Name
                mov cx, 11
                rep movsb
                mov si, offset Volume_in_drive
                call proc_printmsg
loc_start_calc_vol_space:
                pop bx
                pop si
                mov ax, word ptr [SI][LD_TotalSectors]
                mov dx, word ptr [SI][LD_TotalSectors]+2
                push bx
                mov bx, word ptr [SI][LD_BPB][BytesPerSec]
                cmp byte ptr [SI][LD_FATType],2
                ja short pass_vol_size_bytes_calc
                push word ptr [SI][LD_Clusters]
                pop word ptr [LastCluster]
                inc word ptr [LastCluster]
              ; cmp dx, 127
              ; ja short pass_vol_size_bytes_calc
                call proc_mul32
                jmp short pass_volsize_overflow
pass_vol_size_bytes_calc:
                cmp bx, 1024
                jnb short loc_vol_ax_div_bx
                push ax
                push dx
                xor dx, dx
                mov ax, 1024
                div bx
                mov cx, ax
                pop dx
                pop ax
                call Rx_Dos_Div32
                jmp short pass_volsize_overflow
loc_vol_ax_div_bx:
                push ax
                push dx
                xor dx, dx
                mov ax, 1024
                xchg ax, bx
                div bx
                mov bx, ax
                pop dx
                pop ax
                call Proc_Mul32
pass_volsize_overflow:
                pop bx
                mov di, offset Vol_Tot_Sec_Str_End
              ; mov byte ptr [DI], 0
                mov cx, 10
loc_vol_div32_1_again:
                call Rx_Dos_Div32
                add bl, '0'
                dec di
                mov byte ptr [DI], bl
                cmp ax, 0
                ja short loc_vol_div32_1_again
                cmp dx, 0
                ja short loc_vol_div32_1_again

                mov word ptr [Vol_Tot_Sec_Str_Start], DI

                cmp byte ptr [SI][LD_FATType], 2
                jna loc_get_FAT_freespace

                mov ax, word ptr [SI][LD_StartSector]
                mov dx, word ptr [SI][LD_StartSector]+2
                add ax, word ptr [SI][LD_BPB][FAT32_FSInfoSec]
                adc dx, 0
               ;push ds
               ;pop es
                mov bx, offset DOSBootSectorBuff
                mov cx, 1
                call proc_load_disk_sectors
                jnc short loc_check_fsinfo_signs
retn_get_vol_fs_info_sec:
                retn
retn_get_vol_fs_info_stc:
                stc
                retn

loc_check_FSINFO_signs:
                cmp word ptr [DOSBootSectorBuff], 5252h
                jne short retn_get_vol_fs_info_stc
                cmp word ptr [DOSBootSectorBuff]+2, 4161h
                jne short retn_get_vol_fs_info_stc
                mov bx, offset DOSBootSectorBuff
                add bx, 484
                cmp word ptr [BX], 7272h
                jne short retn_get_vol_fs_info_stc
                cmp word ptr [BX]+2, 6141h
                jne short retn_get_vol_fs_info_stc
                add bx, 4
                push word ptr [BX]
                pop word ptr [FreeClusterCount]
                push word ptr [BX]+2
                pop word ptr [FreeClusterCount]+2

                xor ah, ah
                mov al, byte ptr [SI][LD_BPB][SecPerClust]
                mov dx, [SI][LD_BPB][BytesPerSec]
                mul dx
              ; cmp dx, 0
              ; ja short retn_get_vol_fs_info_stc
                mov bx, 1024
                cmp ax, bx
                jb short pass_fsinfo_freesize_div_1024
                div bx
                mov bx, ax
                mov ax, word ptr [FreeClusterCount]
                mov dx, word ptr [FreeClusterCount]+2
                call Proc_Mul32
                jmp short loc_vol_decimal_fat32_freesize
pass_fsinfo_freesize_div_1024:
                xchg ax, bx
                div bx
                mov cx, ax
                mov ax, word ptr [FreeClusterCount]
                mov dx, word ptr [FreeClusterCount]+2
                call Rx_Dos_Div32
loc_vol_decimal_fat32_freesize:
                mov di, offset Vol_Free_Clust_Str_End
              ; mov byte ptr [DI], 0
                mov cx, 10
loc_vol_div32_3_again:
                call Rx_Dos_Div32
                add bl, '0'
                dec di
                mov byte ptr [DI], bl
                cmp ax, 0
                ja short loc_vol_div32_3_again
                cmp dx, 0
                ja short loc_vol_div32_3_again

                mov word ptr [Vol_Free_Clust_Str_Start], DI

                mov si, offset Vol_Total_Sector_Header
                call proc_printmsg
                mov si, word ptr [Vol_Tot_Sec_Str_Start]
                call proc_printmsg
                mov si, offset VolSize_KiloBytes
                call proc_printmsg
                mov si, offset Vol_Free_Clusters_Header
                call proc_printmsg
                mov si, word ptr [Vol_Free_Clust_Str_Start]
                call proc_printmsg
                mov si, offset VolSize_KiloBytes
                call proc_printmsg

pass_write_fat32_free_clusters_calc:
                retn

loc_get_fat_freespace:
                mov ax, 2
                mov dx, 0
loc_get_fcc_next_cluster:
                push ax
                push dx
                call proc_get_next_cluster
                jnc short loc_calc_free_fat_clusters
                cmp ax, 0
                jna short pass_inc_free_cluster_count
                pop dx
                pop ax
                retn

loc_calc_free_fat_clusters:
                cmp ax, 0
                ja short pass_inc_free_cluster_count
                inc word ptr [FreeClusterCount]
pass_inc_free_cluster_count:
                pop dx
                pop ax
                inc ax
                cmp ax, word ptr [LastCluster]
                jna short loc_get_fcc_next_cluster
                xor ah, ah
                mov al, byte ptr [SI][LD_BPB][SecPerClust]
                mov dx, word ptr [SI][LD_BPB][BytesPerSec]
                mul dx
              ; cmp dx, 0
              ; ja retn_get_lba_fs_info_stc
                mov dx, word ptr [FreeClusterCount]
                mul dx

                mov di, offset Vol_Free_Clust_Str_End
              ; mov byte ptr [DI], 0
                mov cx, 10
loc_vol_div32_2_again:
                call Rx_Dos_Div32
                add bl, '0'
                dec di
                mov byte ptr [DI], bl
                cmp ax, 0
                ja short loc_vol_div32_2_again
                cmp dx, 0
                ja short loc_vol_div32_2_again

                mov word ptr [Vol_Free_Clust_Str_Start], DI

                mov si, offset Vol_Total_Sector_Header
                call proc_printmsg
                mov si, word ptr [Vol_Tot_Sec_Str_Start]
                call proc_printmsg
                mov si, offset VolSize_Bytes
                call proc_printmsg

                mov si, offset Vol_Free_Clusters_Header
                call proc_printmsg
                mov si, word ptr [Vol_Free_Clust_Str_Start]
                call proc_printmsg
                mov si, offset VolSize_Bytes
                call proc_printmsg

                retn

LastCluster: dd 0
FreeClusterCount: dd 0
Vol_Free_Clust_Str_Start: dw 0
Vol_Free_Clust_Str: db 10 dup(0)
Vol_Free_Clust_Str_End: db 0
Vol_Free_Clusters_Header:
                db "Free Space : ", 0
Vol_Tot_Sec_Str_Start: dw 0
Vol_Tot_Sec_Str: db 10 dup(0)
Vol_Tot_Sec_Str_End: db 0
Vol_Total_Sector_Header:
                db 0Dh, 0Ah, "Volume Size : ", 0
VolSize_Unit:   dw 0
VolSize_KiloBytes: db " kilobytes", 0Dh, 0Ah, 0
VolSize_Bytes:  db " bytes", 0Dh, 0Ah, 0
Volume_in_drive:
                db 0Dh, 0Ah, "Volume in drive "
Vol_Drv_Name:   db 30h
                db ":"
                db " is "
Vol_Vol_Name:   db 11 dup (30h)
                db 0Dh, 0Ah, 0

proc_volume_total_free_space endp

proc_calculate_freespace proc near
               ; INPUT: DX:AX = Cluster count to be added or subtracted
               ; BH= TR-DOS Logical Drive Number
               ; BL: 0= Calculate, 1= Add, 2= Subtract, 3= Get (Not Set/Calc)
               ; OUTPUT: DX:AX = Free Space in sectors
               ; SI= Logical Dos Drive Table Offset
               ; BH= Logical Dos drive Number
               ; BL= Performed operation (same with input value of BL)
               mov word ptr [CFS_OPType], BX
               xor bl,bl
               mov si, offset Logical_DOSdisks
               add si, bx
               cmp byte ptr [CFS_OPType], 3
               jae loc_get_free_sectors

               cmp byte ptr [SI][LD_FATType], 2
               jna short pass_cl_FAT32_fsinfo_sec 
               push ax
               push dx
               mov ax, word ptr [SI][LD_StartSector]
               mov dx, word ptr [SI][LD_StartSector]+2
               add ax, word ptr [SI][LD_BPB][FAT32_FSInfoSec]
               adc dx, 0
               mov word ptr [CFS_FAT32FSINFOSEC], ax
               mov word ptr [CFS_FAT32FSINFOSEC]+2, dx
               pop dx
               pop ax
pass_cl_FAT32_fsinfo_sec:
               cmp byte ptr [CFS_OPType], 0
               jna short loc_reset_fcc
               mov word ptr [CFS_CC], AX
               mov word ptr [CFS_CC]+2, DX
               jmp loc_set_free_sectors
loc_reset_fcc:
               mov word ptr [FreeClusterCount], 0
               mov word ptr [FreeClusterCount]+2, 0
               push word ptr [SI][LD_Clusters]
               pop word ptr [LastCluster]
               push word ptr [SI][LD_Clusters]+2
               pop word ptr [LastCluster]+2
               add word ptr [LastCluster],1
               adc word ptr [LastCluster]+2,0
               cmp byte ptr [SI][LD_FATType],2
               jna short loc_count_free_fat_clusters_0  

               mov word ptr [CFS_FAT32FC],0FFFFh
               mov word ptr [CFS_FAT32FC]+2,0FFFFh
               mov ax, 2
               mov dx, 0
loc_count_fc_next_cluster_0:
               push ax
               push dx
               call proc_get_next_cluster
               jnc short loc_check_fat32_ff_cluster
               cmp ax, 0
               ja short loc_put_fcc_unknown_sign
               cmp dx, 0
               jna short pass_inc_cfs_fcc_0
loc_put_fcc_unknown_sign:
               pop dx
               pop ax
               ; "Free count is Unknown" sign
               mov word ptr [FreeClusterCount], 0FFFFh
               mov word ptr [FreeClusterCount]+2, 0FFFFh
               jmp loc_update_FAT32_fs_info_fcc
loc_check_fat32_ff_cluster:
               cmp ax, 0
               ja short pass_inc_cfs_fcc_0
               cmp dx, 0
               ja short pass_inc_cfs_fcc_0
               pop dx
               pop ax
               mov word ptr [CFS_FAT32FC], ax
               mov word ptr [CFS_FAT32FC]+2, dx
               mov word ptr [FreeClusterCount], 1
               jmp short pass_inc_cfs_fcc_1
pass_inc_cfs_fcc_0:
               pop dx
               pop ax
pass_inc_cfs_fcc_0c:
               add ax,1
               adc dx,0
               cmp dx, word ptr [LastCluster]+2
               jb short loc_count_fc_next_cluster_0
               ja loc_update_FAT32_fs_info_fcc
               cmp ax, word ptr [LastCluster]
               jna short loc_count_fc_next_cluster_0
               jmp loc_update_FAT32_fs_info_fcc

loc_count_free_fat_clusters_0:
               mov ax, 2
               mov dx, 0
loc_count_fc_next_cluster:
               push ax
               push dx
               call proc_get_next_cluster
               jnc short loc_count_free_clusters_1
               cmp ax, 0
               ja short loc_count_fcc_stc
               cmp dx, 0
               jna short pass_inc_cfs_fcc
loc_count_fcc_stc:
               pop dx
               pop ax
               ; "Free count is Unknown" sign
               mov word ptr [FreeClusterCount], 0FFFFh
               mov word ptr [FreeClusterCount]+2, 0FFFFh
               jmp loc_update_FAT32_fs_info_fcc
loc_count_free_clusters_1:
               cmp ax, 0
               ja short pass_inc_cfs_fcc
               cmp dx, 0
               ja short pass_inc_cfs_fcc
               add word ptr [FreeClusterCount],1
               adc word ptr [FreeClusterCount]+2,0
pass_inc_cfs_fcc:
               pop dx
               pop ax
pass_inc_cfs_fcc_1:
               add ax,1
               adc dx,0
               cmp dx, word ptr [LastCluster]+2
               jb short loc_count_fc_next_cluster
               ja short loc_set_free_sectors
               cmp ax, word ptr [LastCluster]
               jna short loc_count_fc_next_cluster
loc_set_free_sectors:
               cmp byte ptr [SI][LD_FATType], 2
               ja short loc_update_FAT32_fs_info_fcc
               cmp byte ptr [CFS_OPtype], 0
               jna short pass_FAT_add_sub_fcc
               mov ax, word ptr [CFS_CC]
               cmp byte ptr [CFS_OPtype], 1
               ja short pass_FAT_add_fcc
               add word ptr [FreeClusterCount], ax
               jmp short pass_FAT_add_sub_fcc
pass_FAT_add_fcc:
               sub word ptr [FreeClusterCount], ax
pass_FAT_add_sub_fcc:
               xor ah, ah
               mov al, byte ptr [SI][LD_BPB][SecPerClust]
               mov dx, word ptr [FreeClusterCount]
               mul dx
               mov word ptr [SI][LD_FreeSectors], ax
               mov word ptr [SI][LD_FreeSectors]+2, dx
               mov bx, word ptr [CFS_OPType]
               retn

loc_update_FAT32_fs_info_fcc:
               mov ax, word ptr [CFS_FAT32FSINFOSEC]
               mov dx, word ptr [CFS_FAT32FSINFOSEC]+2
              ;push ds
              ;pop es
               mov bx, offset DOSBootSectorBuff
               mov cx, 1
               call proc_load_disk_sectors
               jnc short loc_check_fcc_FSINFO_signs
loc_put_fcc_invalid_sign:
               mov word ptr [FreeClusterCount], 0FFFFh
               mov word ptr [FreeClusterCount]+2, 0FFFFh
               jmp loc_set_FAT32_free_sectors
loc_check_fcc_FSINFO_signs:
               cmp word ptr [DOSBootSectorBuff], 5252h
               jne short loc_put_fcc_invalid_sign
               cmp word ptr [DOSBootSectorBuff]+2, 4161h
               jne short loc_put_fcc_invalid_sign
               mov bx, offset DOSBootSectorBuff
               add bx, 484
               cmp word ptr [BX], 7272h
               jne short loc_put_fcc_invalid_sign
               cmp word ptr [BX]+2, 6141h
               jne short loc_put_fcc_invalid_sign
               add bx, 4
               cmp byte ptr [CFS_OPtype], 0
               jna short pass_FAT32_add_sub_fcc_0
               mov ax, word ptr [BX]
               mov dx, word ptr [BX]+2
               cmp byte ptr [CFS_OPtype], 1
               ja short pass_FAT32_add_fcc
               add ax, word ptr [CFS_CC]
               adc dx, word ptr [CFS_CC]+2
               mov word ptr [FreeClusterCount], ax
               mov word ptr [FreeClusterCount]+2, dx
               ; Folllowing "FFFFFFFFh" replacement is a sign
               ; for the first free cluster reset, later
               ; This is only for bl=1 status (after deleting a file)
               mov word ptr [BX]+4, 0FFFFh ; Next free Cluster Low Word
               mov word ptr [BX]+6, 0FFFFh ; Next free Cluster High Word
               jmp short pass_FAT32_add_sub_fcc
pass_FAT32_add_fcc:
               sub ax, word ptr [CFS_CC]
               sbb dx, word ptr [CFS_CC]+2
               mov word ptr [FreeClusterCount], ax
               mov word ptr [FreeClusterCount]+2, dx
               jmp short pass_FAT32_add_sub_fcc
pass_FAT32_add_sub_fcc_0:
               push word ptr [CFS_FAT32FC]
               pop word ptr [BX]+4
               push word ptr [CFS_FAT32FC]+2
               pop word ptr [BX]+6
pass_FAT32_add_sub_fcc:
               push word ptr [FreeClusterCount]
               pop word ptr [BX]
               push word ptr [FreeClusterCount]+2
               pop word ptr [BX]+2
               mov ax, word ptr [CFS_FAT32FSINFOSEC]
               mov dx, word ptr [CFS_FAT32FSINFOSEC]+2
              ;push ds
              ;pop es
               mov bx, offset DOSBootSectorBuff
               mov cx, 1
               call proc_save_disk_sectors
               jnc short loc_set_FAT32_free_sectors
               ; If Free Cluster Count = FFFFFFFFh, it is INVALID/UNKNOWN
               ; That is an error sign which will be checked/corrected later
               mov word ptr [FreeClusterCount], 0FFFFh
               mov word ptr [FreeClusterCount]+2, 0FFFFh
loc_set_FAT32_free_sectors:
               xor bh, bh
               mov bl, byte ptr [SI][LD_BPB][SecPerClust]
               mov ax, word ptr [FreeClusterCount]
               mov dx, word ptr [FreeClusterCount]+2
               call proc_mul32
               mov word ptr [SI][LD_FreeSectors], ax
               mov word ptr [SI][LD_FreeSectors]+2, dx
               mov bx, word ptr [CFS_OPType]
               retn

loc_get_free_sectors:
               mov ax, word ptr [SI][LD_FreeSectors]
               mov dx, word ptr [SI][LD_FreeSectors]+2
               retn

CFS_OPType:    db 0
CFS_Drv:       db 0
CFS_CC:        dd 0
CFS_FAT32FSINFOSEC: dd 0
CFS_FAT32FC:   dd 0

proc_calculate_freespace endp

proc_find_longname proc near

                ; INPUT DS:SI = DOS short file name input
                ; for example: "filename.ext"

                mov cx, 33
                mov di, Offset LongFileName
                mov ax, 0
                rep stosw

                mov byte ptr [LongNameFound],0

              ; mov byte ptr [PreviousAttr], 0 ; Reset LongName Flag
              ; above instruction is for: "find file
              ; and check if it has long name" (? PreviousAttr= 0Fh)
              ; It is not needed during long name search but
              ; it is useful for short name search for delete/rename

                mov di, offset Dir_File_Name
                call proc_convert_file_name
                mov si, offset Dir_File_Name
                call proc_calculate_checksum
                mov byte ptr [LFN_Checksum], al

                xor bl, bl
                mov bh, byte ptr [DirBuff_Drv]
                mov di, offset Logical_DOSDisks
                add di, bx
                cmp byte ptr [Current_FS], 2
                jna short pass_ln_fat32_fs
check_ln_sub_dir:
                mov ax, word ptr [Current_DirFCluster]
                mov dx, word ptr [Current_DirFCluster]+2
loc_load_ln_next_sector:
                call proc_load_directory
                jc short retn_find_longname_stc
                jmp short loc_find_longname_next
pass_ln_fat32_fs:
                mov al, byte ptr [Current_DirLevel]
                cmp al, 0
                ja short check_ln_sub_dir
loc_load_ln_fat_next_root_sector:
                call proc_load_root_directory
                jc short retn_find_longname_check_eorde
                jmp short loc_find_longname_next
retn_find_longname_check_eorde:
                cmp ax, 0
                jna retn_find_longname_notfound 
retn_find_longname_stc:
                mov si, offset Msg_Not_Ready_Read_Err
                call proc_printmsg
                stc
                retn
loc_find_longname_next:
                mov     cx, 0
check_ln_dirbuff_next_entry:
                cmp     byte ptr [LongNameFound], 0
                jna     short pass_check_ln_short_name
                mov     si, offset Directory_Buffer
                mov     al, 32
                mul     cl
                add     si, ax
                mov     di, offset Dir_File_Name
                push    cx
                mov     cx, 11
loc_ln_sn_comp:
                cmpsb
                jne     short pass_loop_ln_sn_comp
                loop    loc_ln_sn_comp
pass_loop_ln_sn_comp:
                cmp     cl, 0
                jna     short loc_longname_found
                mov     byte ptr [LongNameFound], 0
                pop     cx
                jmp     short pass_check_ln_short_name
loc_longname_found:
                pop cx
                mov si, offset Msg_LongName
                call proc_printmsg
                mov si, offset nextline
                call proc_printmsg

                retn

pass_check_ln_short_name:
              ; xor ch, ch 
              ; mov si, offset LFN_NameFlt
                mov dl, 0Fh ; LFN Attr
                xor dh, dh
                call proc_find_direntry
                jc short pass_longname_found_1
                cmp dl, 0Fh
                jne short pass_longname_found_0
                ; Output DI = DirEntry Location

                mov ah, byte ptr [DI]+0Dh ; Checksum
                cmp ah, byte ptr [LFN_Checksum]
                jne short pass_longname_found_0

                mov ah, ch ; Byte ptr [DI]
                cmp ah, 41h
                jb short pass_longname_lastpart
                cmp ah, 45h
                ja short pass_longname_found_0
                sub ah, 40h
pass_longname_lastpart:
                dec ah
                mov al, 13
                mul ah
                mov cx, 5
                mov si, di
                inc si
                push di
                mov di, offset LongFileName
                add di, ax
get_lfn_first_5_chars:
                lodsw
                stosb
                loop get_lfn_first_5_chars
                pop si
                push si
                add si, 14
                mov cx, 6
get_lfn_middle_6_chars:
                lodsw
                stosb
                loop get_lfn_middle_6_chars
                pop si
                add si, 28
                lodsw
                stosb
                lodsw
                stosb

                cmp byte ptr [LongFileName], 0
                jna short pass_longname_found_2
                mov byte ptr [LongNameFound], 1

pass_longname_found_2:
                mov cl, byte ptr [DirBuff_CurrentEntry]
pass_longname_found_0:
                xor ch, ch
                inc cl
                cmp cl, 16
                jb check_ln_dirbuff_next_entry
pass_longname_found_1:
                mov bh, byte ptr [DirBuff_Drv]
                mov bl, byte ptr [DirBuff_SectorOffset]
                inc bl                                
                cmp byte ptr [Current_DirLevel], 0
                ja short pass_loc_ln_load_next_root_sec1
                cmp byte ptr [Current_FS], 2
                ja short pass_loc_ln_load_next_root_sec1                
                cmp bl, byte ptr [DirBuff_LastSector]
                jna loc_load_ln_fat_next_root_sector
retn_find_longname_notfound:
                mov si, offset Msg_LongNameNotFound
                call proc_printmsg
                retn
pass_loc_ln_load_next_root_sec1:
                mov ax, word ptr [DirBuff_DirCluster]
                mov dx, word ptr [DirBuff_DirCluster]+2
                cmp bl, byte ptr [DirBuff_LastSector]
                jna loc_load_ln_next_sector
pass_loc_ln_load_next_root_sec2:
                push si
                xor bl, bl
                mov si, Offset Logical_DOSdisks
                add si, bx
                call proc_get_next_cluster
                pop si
                jc short retn_find_longname_notfound
                xor bl, bl
                mov bh, byte ptr [DirBuff_Drv]
                jmp loc_load_ln_next_sector

LFN_Checksum:   db 0
Msg_LongName:  
LongFileName:   db 66 dup(0)
LongNameFound:  db 0
Msg_LongNameNotFound: db "Long name not found!"
NextLine:       db 0Dh, 0Ah, 0

proc_find_longname endp

proc_calculate_checksum proc near

               ; INPUT DS:SI = 11 byte Dos File Name location
               ; (in DOS Directory Entry Format)

               ; © Erdogan Tan [ 20-6-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 cx, 11
loc_next_sum:
               xor ah, ah
               test al, 1
               jz short pass_ah_80h
               mov ah, 80h
pass_ah_80h:
               shr al, 1
               add al, byte ptr [si]
               inc si
               add al, ah
               loop loc_next_sum

               ; al= 8 bit checksum (CRC) value

               retn

proc_calculate_checksum endp

proc_show_date  proc    near

                mov ah, 04h
                int 1Ah

                mov al, dl
                call proc_hex
                mov word ptr [Day], ax

                mov al, dh
                call proc_hex
                mov word ptr [Month], ax

                mov al, ch
                call proc_hex
                mov word ptr [Century], ax

                mov al, cl
                call proc_hex
                mov word ptr [Year], ax
                
                mov si, offset Msg_Show_Date
                call proc_printmsg

                retn
Msg_Show_Date:
                db   'Current date is '
Day:            db   '0'
		db   '0'
                db   '/'
Month:          db   '0'
		db   '0'
                db   '/'
Century:        db   '0'
                db   '0'
Year:           db   '0'
		db   '0'
                db   0Dh, 0Ah, 0

proc_show_date  endp

proc_set_date   proc near

                mov si, offset Msg_Enter_Date
                call proc_printmsg
loc_enter_day_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 13
                je loc_set_date_retn
                cmp al, 27
                je loc_set_date_retn
                mov byte ptr [Day], al
                cmp al, '0'
                jb loc_set_date_stc_0
                cmp al, '3'
                ja loc_set_date_stc_0
                mov ah, 0Eh
                int 10h
loc_enter_day_2:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je loc_set_date_retn
                mov byte ptr [Day]+1, al
                cmp al, '0'
                jb loc_set_date_stc_1
                cmp al, '9'
                ja loc_set_date_stc_1
                cmp byte ptr [Day], '3'
                jb  short pass_set_day_31
                cmp al, '1'
                ja  loc_set_date_stc_1
pass_set_day_31:
                mov ah, 0Eh
                int 10h
loc_enter_separator_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_date_retn
                cmp al, '-'
                je  short pass_set_date_separator_1
                cmp al, '/'
                jne loc_set_date_stc_2
pass_set_date_separator_1:
                mov ah, 0Eh
                int 10h
loc_enter_month_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_date_retn
                mov byte ptr [Month], al
                cmp al, '0'
                jb  loc_set_date_stc_3
                cmp al, '1'
                ja  loc_set_date_stc_3
                mov ah, 0Eh
                int 10h
loc_enter_month_2:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je loc_set_date_retn
                mov byte ptr [Month]+1, al
                cmp al, '0'
                jb  loc_set_date_stc_4
                cmp al, '9'
                ja  loc_set_date_stc_4
                cmp byte ptr [Month], '1'
                jb  short pass_set_month_12
                cmp al, '2'
                ja  loc_set_date_stc_4
pass_set_month_12:
                mov ah, 0Eh
                int 10h
loc_enter_separator_2:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_date_retn
                cmp al, '-'
                je  short pass_set_date_separator_2
                cmp al, '/'
                jne loc_set_date_stc_5
pass_set_date_separator_2:
                mov ah, 0Eh
                int 10h
loc_enter_year_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_date_retn
                mov byte ptr [Year], al
                cmp al, '0'
                jb  loc_set_date_stc_6
                cmp al, '9'
                ja  loc_set_date_stc_6
                mov ah, 0Eh
                int 10h
loc_enter_year_2:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_date_retn
                mov byte ptr [Year]+1, al
                cmp al, '0'
                jb  loc_set_date_stc_7
                cmp al, '9'
                ja  loc_set_date_stc_7
                mov ah, 0Eh
                int 10h

loc_set_date_get_lchar_again:
                xor ah, ah
                int 16h

                cmp al, 13
                je short loc_set_date_progress
                cmp al, 27
                je short loc_set_date_retn

                cmp ax, 0E08h
                je short loc_set_date_bs_8
                cmp ax, 4BE0h
                je short loc_set_date_bs_8
                cmp ax, 4B00h
                je short loc_set_date_bs_8
                cmp ax, 53E0h
                je short loc_set_date_bs_8

                jmp short loc_set_date_get_lchar_again
                
loc_set_date_bs_8:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_year_2

loc_set_date_progress:
                ; Get Current Date
                mov ah, 04h
                int 1Ah

                mov ah, byte ptr [Year]
                sub ah, '0'
                mov al, 16
                mul ah
                mov cl, al
                mov al, byte ptr [Year]+1
                sub al, '0'
                add cl, al

                mov ah, byte ptr [Month]
                sub ah, '0'
                mov al, 16
                mul ah
                mov dh, al
                mov al, byte ptr [Month]+1
                sub al, '0'
                add dh, al

                mov ah, byte ptr [Day]
                sub ah, '0'
                mov al, 16
                mul ah
                mov dl, al
                mov al, byte ptr [Day]+1
                sub al, '0'
                add dl, al

                mov ah, 05h
                int 1Ah

loc_set_date_retn:
                mov si, offset nextline
                call proc_printmsg
                retn

loc_set_date_stc_0:
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_day_1
loc_set_date_stc_1:
                cmp ax, 0E08h
                je short loc_set_date_bs_1
                cmp ax, 4BE0h
                je short loc_set_date_bs_1
                cmp ax, 4B00h
                je short loc_set_date_bs_1
                cmp ax, 53E0h
                je short loc_set_date_bs_1
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_day_2
loc_set_date_bs_1:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_day_1
loc_set_date_stc_2:
                cmp ax, 0E08h
                je short loc_set_date_bs_2
                cmp ax, 4BE0h
                je short loc_set_date_bs_2
                cmp ax, 4B00h
                je short loc_set_date_bs_2
                cmp ax, 53E0h
                je short loc_set_date_bs_2
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_separator_1
loc_set_date_bs_2:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_day_2
loc_set_date_stc_3:
                cmp ax, 0E08h
                je short loc_set_date_bs_3
                cmp ax, 4BE0h
                je short loc_set_date_bs_3
                cmp ax, 4B00h
                je short loc_set_date_bs_3
                cmp ax, 53E0h
                je short loc_set_date_bs_3
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_month_1
loc_set_date_bs_3:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_separator_1
loc_set_date_stc_4:
                cmp ax, 0E08h
                je short loc_set_date_bs_4
                cmp ax, 4BE0h
                je short loc_set_date_bs_4
                cmp ax, 4B00h
                je short loc_set_date_bs_4
                cmp ax, 53E0h
                je short loc_set_date_bs_4
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_month_2
loc_set_date_bs_4:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_month_1
loc_set_date_stc_5:
                cmp ax, 0E08h
                je short loc_set_date_bs_5
                cmp ax, 4BE0h
                je short loc_set_date_bs_5
                cmp ax, 4B00h
                je short loc_set_date_bs_5
                cmp ax, 53E0h
                je short loc_set_date_bs_5
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_separator_2
loc_set_date_bs_5:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_month_2
loc_set_date_stc_6:
                cmp ax, 0E08h
                je short loc_set_date_bs_6
                cmp ax, 4BE0h
                je short loc_set_date_bs_6
                cmp ax, 4B00h
                je short loc_set_date_bs_6
                cmp ax, 53E0h
                je short loc_set_date_bs_6
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_year_1
loc_set_date_bs_6:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_separator_2
loc_set_date_stc_7:
                cmp ax, 0E08h
                je short loc_set_date_bs_7
                cmp ax, 4BE0h
                je short loc_set_date_bs_7
                cmp ax, 4B00h
                je short loc_set_date_bs_7
                cmp ax, 53E0h
                je short loc_set_date_bs_7
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_year_2
loc_set_date_bs_7:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_year_1
Msg_Enter_Date:
                db 'Enter new date (dd-mm-yy): '
                db 0

proc_set_date   endp

proc_show_time  proc    near

                mov ah, 02h
                int 1Ah

                mov al, ch
                call proc_hex
                mov word ptr [Hour], ax

                mov al, cl
                call proc_hex
                mov word ptr [Minute], ax

                mov al, dh
                call proc_hex
                mov word ptr [Second], ax

                mov si, offset Msg_Show_Time
                call proc_printmsg

                retn
Msg_Show_Time:
                db   'Current time is '
Hour:           db   '0'
		db   '0'
                db   ':'
Minute:         db   '0'
		db   '0'
                db   ':'
Second:         db   '0'
                db   '0'
                db   0Dh, 0Ah, 0

proc_show_time  endp

proc_set_time   proc near
                mov si, offset Msg_Enter_Time
                call proc_printmsg

loc_enter_hour_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 13
                je loc_set_time_retn
                cmp al, 27
                je loc_set_time_retn
                mov byte ptr [Hour], al
                cmp al, '0'
                jb loc_set_time_stc_0
                cmp al, '2'
                ja loc_set_time_stc_0
                mov ah, 0Eh
                int 10h
loc_enter_hour_2:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je loc_set_time_retn
                mov byte ptr [Hour]+1, al
                cmp al, '0'
                jb loc_set_time_stc_1
                cmp al, '9'
                ja loc_set_time_stc_1
                cmp byte ptr [Hour], '2'
                jb  short pass_set_time_24
                cmp al, '4'
                ja  loc_set_time_stc_1
pass_set_time_24:
                mov ah, 0Eh
                int 10h
loc_enter_time_separator_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_time_retn
                cmp al, ':'
                jne loc_set_time_stc_2
                mov ah, 0Eh
                int 10h
loc_enter_minute_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_time_retn
                mov byte ptr [Minute], al
                cmp al, '0'
                jb  loc_set_time_stc_3
                cmp al, '5'
                ja  loc_set_time_stc_3
                mov ah, 0Eh
                int 10h
loc_enter_minute_2:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_time_retn
                mov byte ptr [Minute]+1, al
                cmp al, '0'
                jb  loc_set_time_stc_4
                cmp al, '9'
                ja  loc_set_time_stc_4
                mov ah, 0Eh
                int 10h
loc_enter_time_separator_2:
                mov word ptr [Second], 3030h
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 13
                je  loc_set_time_progress
                cmp al, 27
                je  loc_set_time_retn
                cmp al, ':'
                jne loc_set_time_stc_5
                mov ah, 0Eh
                int 10h
loc_enter_second_1:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 13
                je  loc_set_time_progress
                cmp al, 27
                je  loc_set_time_retn
                mov byte ptr [Second], al
                cmp al, '0'
                jb  loc_set_time_stc_6
                cmp al, '5'
                ja  loc_set_time_stc_6
                mov ah, 0Eh
                int 10h
loc_enter_second_2:
                xor ah, ah
                int 16h
                ; al = ASCII Code of the Character
                cmp al, 27
                je  loc_set_time_retn
                mov byte ptr [Second]+1, al
                cmp al, '0'
                jb  loc_set_time_stc_7
                cmp al, '9'
                ja  loc_set_time_stc_7
                mov ah, 0Eh
                int 10h

loc_set_time_get_lchar_again:
                xor ah, ah
                int 16h

                cmp al, 13
                je short loc_set_time_progress
                cmp al, 27
                je short loc_set_time_retn

                cmp ax, 0E08h
                je short loc_set_time_bs_8
                cmp ax, 4BE0h
                je short loc_set_time_bs_8
                cmp ax, 4B00h
                je short loc_set_time_bs_8
                cmp ax, 53E0h
                je short loc_set_time_bs_8

                jmp short loc_set_time_get_lchar_again
                
loc_set_time_bs_8:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_second_2

loc_set_time_progress:
                ; Get Current Time
                mov ah, 02h
                int 1Ah

                mov ah, byte ptr [Hour]
                sub ah, '0'
                mov al, 16
                mul ah
                mov ch, al
                mov al, byte ptr [Hour]+1
                sub al, '0'
                add ch, al

                mov ah, byte ptr [Minute]
                sub ah, '0'
                mov al, 16
                mul ah
                mov cl, al
                mov al, byte ptr [Minute]+1
                sub al, '0'
                add cl, al

                mov ah, byte ptr [Second]
                sub ah, '0'
                mov al, 16
                mul ah
                mov dh, al
                mov al, byte ptr [Second]+1
                sub al, '0'
                add dh, al

                mov ah, 03h
                int 1Ah

loc_set_time_retn:
                mov si, offset nextline
                call proc_printmsg
                retn

loc_set_time_stc_0:
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_hour_1
loc_set_time_stc_1:
                cmp ax, 0E08h
                je short loc_set_time_bs_1
                cmp ax, 4BE0h
                je short loc_set_time_bs_1
                cmp ax, 4B00h
                je short loc_set_time_bs_1
                cmp ax, 53E0h
                je short loc_set_time_bs_1
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_hour_2
loc_set_time_bs_1:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_hour_1
loc_set_time_stc_2:
                cmp ax, 0E08h
                je short loc_set_time_bs_2
                cmp ax, 4BE0h
                je short loc_set_time_bs_2
                cmp ax, 4B00h
                je short loc_set_time_bs_2
                cmp ax, 53E0h
                je short loc_set_time_bs_2
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_time_separator_1
loc_set_time_bs_2:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_hour_2
loc_set_time_stc_3:
                cmp ax, 0E08h
                je short loc_set_time_bs_3
                cmp ax, 4BE0h
                je short loc_set_time_bs_3
                cmp ax, 4B00h
                je short loc_set_time_bs_3
                cmp ax, 53E0h
                je short loc_set_time_bs_3
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_minute_1
loc_set_time_bs_3:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_time_separator_1
loc_set_time_stc_4:
                cmp ax, 0E08h
                je short loc_set_time_bs_4
                cmp ax, 4BE0h
                je short loc_set_time_bs_4
                cmp ax, 4B00h
                je short loc_set_time_bs_4
                cmp ax, 53E0h
                je short loc_set_time_bs_4
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_minute_2
loc_set_time_bs_4:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_minute_1
loc_set_time_stc_5:
                cmp ax, 0E08h
                je short loc_set_time_bs_5
                cmp ax, 4BE0h
                je short loc_set_time_bs_5
                cmp ax, 4B00h
                je short loc_set_time_bs_5
                cmp ax, 53E0h
                je short loc_set_time_bs_5
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_time_separator_2
loc_set_time_bs_5:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_minute_2
loc_set_time_stc_6:
                cmp ax, 0E08h
                je short loc_set_time_bs_6
                cmp ax, 4BE0h
                je short loc_set_time_bs_6
                cmp ax, 4B00h
                je short loc_set_time_bs_6
                cmp ax, 53E0h
                je short loc_set_time_bs_6
                mov al, 07h
                mov ah, 0Eh
                int 10h
                mov word ptr [Second], 3030h
                jmp loc_enter_second_1
loc_set_time_bs_6:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_time_separator_2
loc_set_time_stc_7:
                cmp ax, 0E08h
                je short loc_set_time_bs_7
                cmp ax, 4BE0h
                je short loc_set_time_bs_7
                cmp ax, 4B00h
                je short loc_set_time_bs_7
                cmp ax, 53E0h
                je short loc_set_time_bs_7
                mov al, 07h
                mov ah, 0Eh
                int 10h
                jmp loc_enter_second_2
loc_set_time_bs_7:
                mov al, 08h
                mov ah, 0Eh
                int 10h
                mov al, 20h
                mov ah, 09h
                int 10h
                jmp loc_enter_second_1
Msg_Enter_Time:
                db 'Enter new time: '
                db 0

proc_set_time   endp

proc_load_file  proc near
              ; ES:DI = File Buffer
              ; DX:AX = First Cluster Number
              ; BL = 0
              ; BH = DRV
                mov  si, offset Logical_DOSDisks
                add  si, bx
                cmp byte ptr [SI][LD_Name], 'A'
                jnb short pass_lf_drv_failed
                retn
pass_lf_drv_failed:
                cmp byte ptr [SI][LD_FATType],2
                ja short pass_lf_reset_dx
                xor dx,dx
pass_lf_reset_dx:
                mov byte ptr [SourceFile_Drv], bh
                mov word ptr [SourceFile_BufferOff], di
                push es
                pop word ptr  [SourceFile_BufferSeg]
loc_load_file_next_cluster:
                mov word ptr [SourceFile_Cluster], ax
                mov word ptr [SourceFile_Cluster]+2, dx
                mov bl, byte ptr [SI][LD_BPB][SecPerClust]
                sub ax, 2
                sbb dx, 0
                xor bh, bh
                mov cx, bx
                call proc_mul32
                add ax, word ptr [SI][LD_DATAbegin]
                adc dx, word ptr [SI][LD_DATAbegin]+2
                mov bx, word ptr [SourceFile_BufferOff]
                ; cx = Sectors per Cluster
                cmp cx, 20
                jna short pass_temporary_csizefix
               ; cx = 20 sectors ! Temporary !
                mov cx, 20
pass_temporary_csizefix:
                shl cx, 1 ; CX = 2 * CX
                cmp cl, byte ptr [Program_Size]+1
                jc short loc_load_file_retn
                shr cx, 1 ; CX = CX / 2 -> CX <= 20
pass_temporary_csize_fix:
                call proc_load_disk_sectors
                jc short loc_load_file_retn
loc_cont_load_file:
                mov ax, word ptr [SourceFile_Cluster]
                mov dx, word ptr [SourceFile_Cluster]+2
                call proc_get_next_cluster
                jnc short loc_cont_load_file_2
                cmp ax, 0
                jna short loc_load_file_retn
                stc
loc_load_file_retn:
                retn
loc_cont_load_file_2:
                push ax
                push dx
                xor bh, bh
                mov bl, byte ptr [SI][LD_BPB][SecPerClust]
                mov ax, 512
                mul bx
                add word ptr [SourceFile_BufferOff], ax
                pop dx
                pop ax
                jnc loc_load_file_next_cluster
                mov bx, word ptr [SourceFile_BufferSeg]
                add bx, 1000h
                mov es, bx
                mov word ptr [SourceFile_BufferSeg], bx
                jmp loc_load_file_next_cluster

proc_load_file  endp

proc_update_cluster   proc near
                ; INPUT -> AX = Cluster Number, low 16 bit
                ; INPUT -> DX = Cluster Number, high 16 bit
                ; INPUT -> BX = New Cluster Value, low 16 bit
                ; INPUT -> CX = New Cluster Value, high 16 bit
                ; INPUT -> DS:SI = Logical Dos Drive Parameters Table
                ; OUTPUT -> clc -> No Error, DX:AX valid
                ; OUTPUT -> stc & AX=0 -> End Of Cluster Chain
                ; OUTPUT -> stc & AX>0 -> Error
                ; AX: Next Cluster, low 16 bit
                ; DX: Next Cluster, high 16 bit
                ; BX: New Cluster Value, low 16 bit
                ; CX: New Cluster Value, high 16 bit
                ; stc -> Error
                mov word ptr [FAT_CurrentCluster], ax
                mov word ptr [FAT_CurrentCluster]+2, dx
                mov word ptr [ClusterValue], bx
                mov word ptr [ClusterValue]+2, cx
check_update_cluster_fat_type:
                cmp byte ptr [SI][LD_FATType], 2
                ja update_FAT32_cluster
                jb update_FAT12_cluster
update_FAT16_cluster:
                cmp ax, 2
                jb short return_uc_FAT_stc
                push word ptr [SI][LD_Clusters]
                pop word ptr [LastCluster]
                inc word ptr [LastCluster]
                cmp ax, word ptr [LastCluster]
                jna short pass_uc_fat16_errc
return_uc_FAT_stc:
                xor ax, ax
                xor dx, dx
                stc
                retn
pass_uc_fat16_errc:
                mov bx, 300h ;768
                div bx
                ; AX = Count of 3 FAT sectors
                ; DX = Sector Offset
                shl dx, 1 ; Multiply by 2
                push dx
                mov bx, 3
                mul bx  
                pop bx ; Sector Offset
                ; AX = FAT Sector
                ; DX = 0
                mov cl, byte ptr [SI][LD_Name]
                cmp byte ptr [FAT_BuffValidData], 0
                jna load_uc_FAT_sectors0
                cmp byte ptr [FAT_BuffValidData], 2
                jne short pass_save_fat16_buffer
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne short loc_save_FAT_buffer
                cmp ax, word ptr [FAT_BuffSector]
                jne short loc_save_FAT_Buffer
                jmp short loc_update_fat16_cell
pass_save_fat16_buffer:
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne load_uc_FAT_sectors0
                cmp ax, word ptr [FAT_BuffSector]
                jne load_uc_FAT_sectors2
loc_update_fat16_cell:
                mov ax, word ptr [FAT_Buffer][BX]
                xor dx, dx
                mov word ptr [FAT_CurrentCluster], ax
                mov word ptr [FAT_CurrentCluster]+2, dx
                mov cx, word ptr [ClusterValue]
                mov word ptr [FAT_Buffer][BX],cx
                inc word ptr [FAT_ClusterCounter]
                mov byte ptr [FAT_BuffValidData], 2
                cmp ax, 2
                jb short return_uc_FAT_stc
                cmp ax, word ptr [LastCluster]
                ja short return_uc_FAT_stc
loc_fat_buffer_updated:
                mov cx, word ptr [ClusterValue]+2
loc_fat_buffer_updated_1:
                mov bx, word ptr [ClusterValue]
                clc
                retn
loc_save_fat_buffer:
                call proc_save_fat_buffer
                jc short loc_FAT_sectors_write_error
                mov byte ptr [FAT_BuffValidData], 1
                mov ax, word ptr [FAT_CurrentCluster]
                mov dx, word ptr [FAT_CurrentCluster]+2
                mov bx, word ptr [ClusterValue]
                mov cx, word ptr [ClusterValue]+2
                jmp check_update_cluster_fat_type
                retn

loc_FAT_sectors_write_error:
                mov byte ptr [FAT_BuffValidData], 0
                mov ax, 2 ; Write Error
                mov dx, 0
                mov bx, word ptr [ClusterValue]
                mov cx, word ptr [ClusterValue]+2
                retn

update_FAT12_cluster:
                cmp ax, 2
                jb return_uc_FAT_stc
                push word ptr [SI][LD_Clusters]
                pop word ptr [LastCluster]
                inc word ptr [LastCluster]
                cmp ax, word ptr [LastCluster]
                ja return_uc_FAT_stc

                mov bx, 400h ;1024
                div bx
                ; AX = Count of 3 FAT sectors
                ; DX = Buffer Entry Offset
                push ax
                mov ax, 3
                mul dx    ; Multiply by 3
                shr ax, 1 ; Divide by 2
                mov dx, ax
                pop ax
                push dx
                mov bx, 3
                mul bx  
                pop bx ; Buffer Byte Offset
                ; AX = FAT Beginning Sector
                ; DX = 0
                mov cl, byte ptr [SI][LD_Name]
                cmp byte ptr [FAT_BuffValidData], 0
                jna load_uc_FAT_sectors0
                cmp byte ptr [FAT_BuffValidData], 2
                jne short pass_save_fat12_buffer
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne short loc_save_FAT_buffer
                cmp ax, word ptr [FAT_BuffSector]
                jne loc_save_FAT_Buffer
                jmp short loc_update_fat12_cell
pass_save_fat12_buffer:
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne load_uc_FAT_sectors0
                cmp ax, word ptr [FAT_BuffSector]
                jne load_uc_FAT_sectors2
loc_update_fat12_cell:
                mov cx, word ptr [FAT_CurrentCluster]
                shr cx, 1
                mov ax, word ptr [FAT_Buffer][BX]
                jnc short uc_FAT12_nc_even

                push ax
                and ax, 0Fh
                mov cx, word ptr [ClusterValue]
                shl cx, 1
                shl cx, 1
                shl cx, 1
                shl cx, 1
                or cx, ax
                pop ax
                mov word ptr [FAT_Buffer][BX],cx
                shr ax, 1
                shr ax, 1
                shr ax, 1
                shr ax, 1
update_FAT12_buffer:
                inc word ptr [FAT_ClusterCounter]
                mov word ptr [FAT_CurrentCluster], ax
                xor dx,dx
                mov word ptr [FAT_CurrentCluster]+2, dx
                mov byte ptr [FAT_BuffValidData], 2
                cmp ax,2
                jb return_uc_FAT_stc
                cmp ax, word ptr [LastCluster]
                ja return_uc_FAT_stc
                jmp loc_fat_buffer_updated
uc_FAT12_nc_even:
                push ax
                and ax, 0F000h
                mov cx, word ptr [ClusterValue]
                and ch, 0Fh
                or cx, ax
                pop ax
                mov word ptr [FAT_Buffer][BX],cx
                and ah, 0Fh
                jmp short update_fat12_buffer

update_FAT32_cluster:
                cmp dx, 0
                ja short pass_uc_FAT32_c_zero_check_1
                cmp ax,2
                jb return_uc_FAT_stc
pass_uc_FAT32_c_zero_check_1:
                push word ptr [SI][LD_Clusters]
                pop word ptr [LastCluster]
                push word ptr [SI][LD_Clusters]+2
                pop word ptr [LastCluster]+2
                add word ptr [LastCluster],1
                adc word ptr [LastCluster]+2,0
                cmp dx, word ptr [LastCluster]+2
                jb short pass_uc_fat32_errc
                ja return_uc_FAT_stc
                cmp ax, word ptr [LastCluster]
                ja return_uc_FAT_stc
pass_uc_fat32_errc:
                mov cx, 180h ;384
                call Rx_Dos_Div32
                ; DX:AX = Count of 3 FAT sectors
                ; BX = Sector Offset
                shl bx, 1
                shl bx, 1 ; Multiply by 4
                push bx
                mov bx, 3
                call proc_mul32
                pop bx ; Sector Offset
                ; DX:AX = FAT Sector
                mov cl, byte ptr [SI][LD_Name]
                cmp byte ptr [FAT_BuffValidData], 0
                jna load_uc_FAT_sectors0
                cmp byte ptr [FAT_BuffValidData], 2
                jne short pass_save_fat32_buffer
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne loc_save_FAT_buffer
                cmp dx, word ptr [FAT_BuffSector]+2
                jne loc_save_FAT_Buffer
                cmp ax, word ptr [FAT_BuffSector]
                jne loc_save_FAT_Buffer
                jmp short loc_update_fat32_cell
pass_save_fat32_buffer:
                cmp cl, byte ptr [FAT_BuffDrvName]
                jne load_uc_FAT_sectors0
                cmp dx, word ptr [FAT_BuffSector]+2
                jne short load_uc_FAT_sectors1
                cmp ax, word ptr [FAT_BuffSector]
                jne short load_uc_FAT_sectors2
loc_update_fat32_cell:
                mov ax, word ptr [FAT_Buffer][BX]
                mov dx, word ptr [FAT_Buffer][BX]+2
                and dh, 0Fh ; 28 bit Cluster
                mov word ptr [FAT_CurrentCluster], ax
                mov word ptr [FAT_CurrentCluster]+2, dx
                mov cx, word ptr [ClusterValue]
                mov word ptr [FAT_Buffer][BX],cx
                mov cx, word ptr [ClusterValue]+2
                mov word ptr [FAT_Buffer][BX]+2,cx
                add word ptr [FAT_ClusterCounter],1
                adc word ptr [FAT_ClusterCounter]+2,0
                mov byte ptr [FAT_BuffValidData], 2
                cmp dx,0
                ja short pass_uc_FAT32_c_zero_check_2
                cmp ax,2
                jb return_uc_FAT_stc
pass_uc_FAT32_c_zero_check_2:
                cmp dx, word ptr [LastCluster]+2
                jb loc_fat_buffer_updated_1
                ja return_uc_FAT_stc
                cmp ax, word ptr [LastCluster]
                ja return_uc_FAT_stc
                jmp loc_fat_buffer_updated_1
load_uc_FAT_sectors0:
                mov byte ptr [FAT_BuffDrvName], cl
load_uc_FAT_sectors1:
                mov word ptr [FAT_BuffSector]+2, dx
load_uc_FAT_sectors2:
                mov word ptr [FAT_BuffSector], ax
                add ax, word ptr [SI][LD_FATbegin]
                adc dx, word ptr [SI][LD_FATbegin]+2
               ;push ds
               ;pop es
                mov bx, offset FAT_Buffer
                mov cx, 3
                call proc_load_disk_sectors
                jc short uc_FAT_sectors_load_error
                mov byte ptr [FAT_BuffValidData], 1
                mov ax, word ptr [FAT_CurrentCluster]
                mov dx, word ptr [FAT_CurrentCluster]+2
                mov bx, word ptr [ClusterValue]
                mov cx, word ptr [ClusterValue]+2
                jmp check_update_cluster_fat_type
uc_FAT_sectors_load_error:
                mov byte ptr [FAT_BuffValidData], 0
                mov ax, 1 ; Read Error
                mov dx, 0
                mov bx, word ptr [ClusterValue]
                mov cx, word ptr [ClusterValue]+2
                retn

ClusterValue:   dd 0

proc_update_cluster endp

proc_save_fat_buffer proc near
                ; INPUT: DS:SI= Logical DOS Drive Parameters Table
                mov ax, word ptr [FAT_BuffSector]
                cmp byte ptr [SI][LD_FATType], 2
                ja short loc_save_fat32_buff
                xor dx, dx
                mov cx, word ptr [SI][LD_BPB][FATSecs] 
                sub cx, ax
                cmp cx, 3
                jna short loc_save_fat_buff_cont
                jmp short pass_save_fat_buff_remain_sectors_3
loc_save_fat32_buff:
                mov dx, word ptr [FAT_BuffSector]+2
                mov bx, Word Ptr [SI][LD_BPB][FAT32_FAT_Size]+2
                mov cx, Word Ptr [SI][LD_BPB][FAT32_FAT_Size]
                sub cx, ax
                sbb bx, dx
                cmp bx, 0
                ja short pass_save_fat_buff_remain_sectors_3
                cmp cx, 3
                jna short loc_save_fat_buff_cont
pass_save_fat_buff_remain_sectors_3:
                mov cx, 3
loc_save_fat_buff_cont:
                add ax, word ptr [SI][LD_FATbegin]
                adc dx, word ptr [SI][LD_FATbegin]+2
               ;push ds
               ;pop es
                mov bx, offset FAT_Buffer
                push cx
                call proc_save_disk_sectors
return_from_uc_fat_secs_write:
                pop cx
                jc short loc_save_FAT_buff_write_err
                cmp byte ptr [SI][LD_FATType], 2
                jna short pass_calc_2nd_fat32_addr
                mov ax, Word Ptr [SI][LD_BPB][FAT32_FAT_Size]
                mov dx, Word Ptr [SI][LD_BPB][FAT32_FAT_Size]+2
                jmp short pass_calc_2nd_fat_addr
pass_calc_2nd_fat32_addr:
                mov ax, word ptr [SI][LD_BPB][FATSecs]
                xor dx, dx
pass_calc_2nd_fat_addr:
                add ax, word ptr [SI][LD_FATbegin]
                adc dx, word ptr [SI][LD_FATbegin]+2
                add ax, word ptr [FAT_BuffSector]
                adc dx, word ptr [FAT_BuffSector]+2
               ;push ds
               ;pop es
                mov bx, offset FAT_Buffer
                call proc_save_disk_sectors
                jc short loc_save_FAT_buff_write_err
                mov byte ptr [FAT_BuffValidData], 1 ; Valid (but do not save)
loc_save_FAT_buff_write_err:
                retn
proc_save_fat_buffer endp

proc_CHS_write  proc near
                push si
                ; INPUT -> DX:AX = Logical Block Address
                ; CX = Number of sectors to read
                ; DS:SI = Logical Dos Disk Table Offset (DRV)
                ; ES:BX = Source Buffer
                ; OUTPUT -> clc or stc
                mov byte ptr [CHS_RetryCount], 4
loc_write_disk_chs:
                push    CX                      ; # of FAT/FILE/DIR sectors
                push    AX                      ; Linear sector #
                push    DX                      ; DX_AX = Linear address (sectors)
                mov     CX,Word Ptr [SI][LD_BPB][SecPerTrack]
                push    BX

                call    RX_DOS_DIV32            ; Special 32 bit divide !!!
                                                ; To fix large disk problem.
                                                ; (c) Erdogan Tan 1999
                                                ; (October 20th, 1999)

                mov     CX, BX                  ; Sector (zero based)
                inc     CX                      ; To make it 1 based
                push    CX
                mov     CX,Word Ptr [SI][LD_BPB][Heads]
                call    RX_DOS_DIV32            ; Convert track to head & cyl
                mov     DH, BL                  ; BX = Head (max. FFh)
                pop     CX
                                                ; AX=Cyl, DH=Head, CX=Sector
                pop     BX                      ; ES:BX = Buffer

                mov     DL,Byte Ptr [SI][LD_PhyDrvNo]
                mov     CH,AL                   
                ror     AH,1                    ; Rotate right
                ror     AH,1                   
                or      CL,AH                   
                mov     AX,0301h
                int     13h                     ; BIOS Service func ( ah ) = 3
                                                ; Write disk sectors
                                                ;AL-sec num CH-track CL-sec
                                                ; DH-head DL-drive ES:BX-buffer
                                                ;CF-flag AH-stat AL-sec read
                                                ; If CF = 1 then (If AH > 0)
                pop     DX
                pop     AX
                pop     CX 
                jnc     short pass_write_disk_chs_error
                                                ; error code in AH
                sub     byte ptr [CHS_RetryCount], 1
                jnb     short loc_write_disk_chs
                pop si
                retn
pass_write_disk_chs_error:
                loop    loc_write_next_sector
                pop si
                retn
loc_write_next_sector:
                add     AX,1
                adc     DX,0    
                add     BX, 512
                jmp     short loc_write_disk_chs

proc_CHS_write  endp

proc_LBA_write  proc near
                push si
                ; INPUT -> DAP_Buffer
                ; OUTPUT -> clc or stc
loc_write_disk_lba:
                mov si, offset DAP_Buffer
                ; DS:SI= DAP Location
                mov ax, 4300h  ; Extended Disk Write - LBA write (verify off)            ;mov dl, byte ptr [DAP_BuffDisk]
                int 13h
                jnc short pass_write_disk_lba_error
                dec byte ptr [DAP_RetryCount]
                cmp byte ptr [DAP_RetryCount],1
                jnb short loc_write_disk_lba
pass_write_disk_lba_error:
                pop si
                retn
proc_LBA_write  endp

proc_save_disk_sectors proc near

                ; INPUT -> DS:SI = DOS Drive Description Table 
                ; INPUT -> DX:AX = LBA address
                ; INPUT -> CX = Sector Count (CH=0)
                ; INPUT -> ES:BX = Buffer

                cmp byte ptr [SI][LD_LBAYes], 0
                ja short loc_save_lba_sectors

                call proc_CHS_write
                jc  retn_savesecs_stc
                retn
retn_savesecs_stc:
                mov ax, 2
                stc
                retn
loc_save_lba_sectors:
               ;xor ch, ch
               ;mov byte ptr [DAP_BuffLBAyes], 1
                mov word ptr [DAP_BuffLBA_Address], ax
                mov word ptr [DAP_BuffLBA_Address]+2, dx
                mov byte ptr [DAP_BuffPacketSize], 10h
                mov word ptr [DAP_BuffDestination], bx
                push es
                pop word ptr [DAP_BuffDestination]+2
                mov byte ptr [DAP_BuffNumOfBlocks], cl
                mov byte ptr [DAP_RetryCount], 4
                mov dl, byte ptr [SI][LD_PhyDrvNo]
                mov byte ptr [DAP_BuffDisk], dl
                call proc_LBA_write
                jc short retn_savesecs_stc
                retn

proc_save_disk_sectors endp

proc_load_cluster proc near
              ; INPUT :
              ; ES:DI = Cluster (Data) Buffer or Sector Buffer
              ; DX:AX = Cluster Number
              ; BL = 0
              ; BH = DRV
              ; CL = Number of sectors will be loaded
              ; CH = Beginning sector offset of the cluster
              ;
              ; OUTPUT :
              ; CF -> Error in AX (AX=0 & CL=0 -> sector num invalid)
              ;       AX=15h -> Drive not ready or read error
              ; If CF = 0
              ; ES:DI = Cluster or Sector Buffer
              ; DX:AX = Cluster Number
              ; BL = 0
              ; BH = DRV
              ; CL = Number of sectors have been loaded
              ; CH = Beginning sector offset has been loaded

                mov  si, offset Logical_DOSDisks
                add  si, bx
                cmp byte ptr [SI][LD_Name], 'A'
                jnb short pass_lcl_drv_failed
                retn
pass_lcl_drv_failed:
                mov byte ptr [SourceFile_Drv], bh
                mov word ptr [SourceFile_Cluster], ax
                mov word ptr [SourceFile_Cluster]+2, dx
                mov bl, byte ptr [SI][LD_BPB][SecPerClust]
                cmp bl, ch
                jnc short pass_lcl_bc_check
loc_lcl_inv_cx_retn:
                xor cl, cl
                xor ax, ax
                stc
                retn
pass_lcl_bc_check:
                push cx
                add cl, ch
                jnc short pass_lcl_s_cary_check
                pop cx
                jmp short loc_lcl_inv_cx_retn
pass_lcl_s_cary_check:
                cmp bl, cl
                pop cx
                jnc short pass_lcl_ls_over_check
                mov cl, bl
                sub cl, ch
pass_lcl_ls_over_check:
                mov word ptr [LCL_SECTOR_OFF], cx
                mov word ptr [SourceFile_BufferOff], di
                push es
                pop word ptr  [SourceFile_BufferSeg]
loc_lcl_calc_sector:
                sub ax, 2
                sbb dx, 0
                xor bh, bh
                call proc_mul32
                add ax, word ptr [SI][LD_DATAbegin]
                adc dx, word ptr [SI][LD_DATAbegin]+2
                push cx
                xchg ch, cl
                xor ch, ch
                add ax, cx
                adc dx, 0
                pop cx
                xor ch, ch
                ; CL = sector count
              ; mov bx, word ptr [SourceFile_BufferOff]
                mov bx, di
                call proc_load_disk_sectors
                jnc short loc_cont_load_cluster
                mov ax, 15h
                retn
loc_cont_load_cluster:
                mov ax, word ptr [SourceFile_Cluster]
                mov dx, word ptr [SourceFile_Cluster]+2
                xor bl, bl
                mov bh, byte ptr [SourceFile_Drv]
                mov di, word ptr [SourceFile_BufferOff]
                push word ptr  [SourceFile_BufferSeg]
                pop es
                mov cx, word ptr [LCL_SECTOR_OFF]
                retn

LCL_SECTOR_OFF: dw 0
                 
proc_load_cluster endp


proc_delete_longname proc near

                ; INPUT
                ; Dir_File_Name = Directory Entry Format File Name Location
                ; for example: "FILENAMEEXT"

                mov cx, 13
                mov di, Offset LN_Count
                mov ax, 0
                rep stosw

                mov byte ptr [LN_Valid], 0FFh
                mov byte ptr [LN_Last], 0

                mov si, offset Dir_File_Name
                call proc_calculate_checksum
                mov byte ptr [LFN_Checksum], al

                xor bl, bl
                mov bh, byte ptr [DirBuff_Drv]
                cmp byte ptr [Current_FS], 2
                jna short pass_dln_fat32_fs
check_dln_sub_dir:
                mov ax, word ptr [Current_DirFCluster]
                mov dx, word ptr [Current_DirFCluster]+2
loc_load_dln_next_sector:
                call proc_load_directory
                jc short retn_delete_longname_stc
                jmp short loc_delete_longname_next
pass_dln_fat32_fs:
                mov al, byte ptr [Current_DirLevel]
                cmp al, 0
                ja short check_dln_sub_dir
loc_load_dln_fat_next_root_sector:
                call proc_load_root_directory
                jc short retn_delete_longname_check_eorde
                jmp short loc_delete_longname_next
retn_delete_longname_check_eorde:
                cmp ax, 0
                jna retn_delete_longname_notfound 
retn_delete_longname_stc:
                mov ax, 1
                stc
                retn
loc_delete_longname_next:
                mov cl, 0
check_dln_dirbuff_next_entry:
                cmp byte ptr [LN_Valid], 0
                jna short loc_dln_check_sfn
              ; xor ch, ch 
              ; mov si, offset LFN_NameFlt
                mov dl, 0Fh ; LFN Attr
                xor dh, dh
                call proc_find_direntry
                jc pass_del_longname_found_1
                cmp dl, 0Fh
                jne pass_del_longname_found_0
                ; Output DI = DirEntry Location

                mov ah, byte ptr [DI]+0Dh ; Checksum
                cmp ah, byte ptr [LFN_Checksum]
                jne pass_del_longname_found_0

                mov ah, ch ; Byte ptr [DI]
                cmp ah, 41h
                jb short pass_del_longname_lastpart_1
                sub ah, 40h
                mov byte ptr [LN_Valid], ah
                mov byte ptr [LN_Last], ah
pass_del_longname_lastpart_1:
                cmp ah, 5 ; Overlength (> 13*5 chars)
                jna short pass_del_longname_lastpart_2
                xor al, al
                stc
                retn
pass_del_longname_lastpart_2:
                dec ah
                mov si, offset LN_Pointers
                mov al, 5
                mul ah
                add si, ax
                mov byte ptr [SI],cl
                inc si
                mov ax, word ptr [DirBuff_DirSector]
                mov word ptr [SI],ax
                mov dx, word ptr [DirBuff_DirSector]+2
                mov word ptr [SI]+2,dx
                dec byte ptr [LN_Valid]
                cmp byte ptr [LN_Valid], 0
                ja pass_del_longname_found_0

                inc  cl
                cmp  cl, 16
                jnb  pass_del_longname_found_1

loc_dln_check_sfn:
                mov     si, offset Directory_Buffer
                mov     al, 32
                mul     cl
                add     si, ax
                mov     di, offset Dir_File_Name
                push    cx
                mov     cx, 11
loc_dln_sn_comp:
                cmpsb
                jne     short pass_loop_dln_sn_comp
                loop    loc_dln_sn_comp
pass_loop_dln_sn_comp:
                cmp     cl, 0
                pop     cx
                jna     short loc_del_longname_found
                mov     byte ptr [LN_Valid], 0FFh
                jmp     check_dln_dirbuff_next_entry
loc_del_longname_found:
                cmp byte ptr [LN_Last], 0
                jna loc_del_longname_retn
              ; mov byte ptr [LN_Count], 0
                mov byte ptr [DirBuff_ValidData], 0 
                xor bl, bl
                mov bh, byte ptr [DirBuff_drv]
                mov si, offset Logical_DosDisks
                add si, bx
loc_dln_rw_sectors:
                mov ah, byte ptr [LN_Count]
                mov al, 5
                mul ah
                push si
                mov si, offset LN_Pointers
                add si, ax
                mov al, byte ptr [SI]
                mov byte ptr [LN_Valid], al
                inc si
                mov ax, word ptr [SI]
                mov dx, word ptr [SI]+2
                pop si
                mov cx, 1
                ; push ds
                ; pop es
                mov bx, offset Directory_Buffer
                call proc_load_disk_sectors
                jc  retn_delete_longname_stc
                mov si, offset Directory_Buffer
                mov bl, byte ptr [LN_Valid] ; entry offset
                mov al, 32
                mul bl
                add si, ax
                cmp byte ptr [SI]+0Bh, 0Fh
                jne loc_del_longname_retn ; safety against wrong write!
                mov byte ptr [SI], 0E5h ; deleted sign

                mov ah, byte ptr [LN_Count]
                mov al, 5
                mul ah
                mov si, offset LN_Pointers
                add si, ax
                mov al, byte ptr [SI]
                mov byte ptr [LN_Valid], al
                inc si
                mov ax, word ptr [SI]
                mov dx, word ptr [SI]+2

                mov cx, 1

                xor bl, bl
                mov bh, byte ptr [DirBuff_Drv]
                mov si, offset Logical_DosDisks
                add si, bx
                ; push ds
                ; pop es
                mov bx, offset Directory_Buffer
                call proc_save_disk_sectors
                jc short loc_dln_write_error

                inc byte ptr [LN_Count]
                mov al, byte ptr [LN_Last]
                cmp al, byte ptr [LN_Count]
                ja  short loc_dln_rw_sectors

loc_longname_deleted:
loc_del_longname_retn:
                xor ax, ax
                retn

loc_dln_write_error:
                mov ax, 2
                stc
                retn

pass_del_longname_found_0:
                inc cl
                cmp cl, 16
                jb check_dln_dirbuff_next_entry
pass_del_longname_found_1:
                mov bh, byte ptr [DirBuff_Drv]
                mov bl, byte ptr [DirBuff_SectorOffset]
                inc bl
                cmp byte ptr [Current_DirLevel], 0
                ja short pass_loc_dln_load_next_root_sec1
                cmp byte ptr [Current_FS], 2
                ja short pass_loc_dln_load_next_root_sec1                
                cmp bl, byte ptr [DirBuff_LastSector]
                jna loc_load_dln_fat_next_root_sector
                jmp short retn_delete_longname_notfound
pass_loc_dln_load_next_root_sec1:
                mov ax, word ptr [DirBuff_DirCluster]
                mov dx, word ptr [DirBuff_DirCluster]+2
                cmp bl, byte ptr [DirBuff_LastSector]
                jna loc_load_dln_next_sector
pass_loc_dln_load_next_root_sec2:
                push si
                xor bl, bl
                mov si, Offset Logical_DOSdisks
                add si, bx
                call proc_get_next_cluster
                pop si
                jnc loc_load_dln_next_sector
retn_delete_longname_notfound:
                xor ax, ax
                retn

LN_Count:       db 0
LN_Pointers:    db 25 dup(0)
LN_Valid:       db 0
LN_Last:        db 0

proc_delete_longname endp

proc_check_invalid_filename_chars proc near
                ; INPUT: DS:SI = ASCIIZ FileName 
                ; OUTPUT:
                ; stc -> Invalid
                ; clc -> Valid
               ; push es
               ; push ds
               ; pop es
                push si
                push di
                mov di, offset invalid_fname_chars
                push ax
                mov al, byte ptr [SI]
                push cx
check_filename_next_char:
                mov cx, sizeInvFnChars
                mov di, offset invalid_fname_chars
loop_scan_invalid_filename_char:
		scasb 
                je short loc_invalid_filename 
                loop loop_scan_invalid_filename_char
                inc si
                mov al, byte ptr [SI]
                cmp al, 0
                ja check_filename_next_char
loc_valid_filename:
                pop cx
                pop ax
                pop di
                pop si
               ; pop es
                retn
loc_invalid_filename:
                stc
                jmp short loc_valid_filename

invalid_fname_chars:
		db 22h, 27h, 28h, 29h, 2Ah, 2Bh, 2Ch, 2Fh
		db 3Ah, 3Bh, 3Ch, 3Dh, 3Eh, 3Fh, 40h
		db 5Bh, 5Ch, 5Dh, 5Eh, 60h
sizeInvFnChars  equ ($ - invalid_fname_chars)                

proc_check_invalid_filename_chars endp

proc_bcd_to_binary proc near

		; 07/05/2000

		; INPUT  -> AL = BCD number
		; OUTPUT -> AL = Binary (Hex) number 

		mov ah, al
		shr ah,1
		shr ah,1
		shr ah,1
		shr ah,1
		and al, 00001111b
		aad

		retn

proc_bcd_to_binary endp

proc_get_first_free_cluster proc near
               ; INPUT: DX:AX= Beginning Cluster,
               ; BH= TR-DOS Logical Drive Number

               ; For FAT32 FS, If DX:AX >= 2 then
               ; F.F.C. scan will be started from the requested cluster,
               ; otherwise, F.F.C. value will returned from FSINFO sector.
               ; For FAT12 & FAT16 file systems, if AX > 2 then
               ; scan will be started from AX,
               ; otherwise, scan will be started from cluster 2

               ; OUTPUT:
               ; clc -> DX:AX = First Free Cluster
               ; stc -> AX > 0 => Error
               ; stc -> AX = 0 => No Free Space

               xor bl,bl
               mov si, offset Logical_DOSdisks
               add si, bx

               push word ptr [SI][LD_Clusters]
               pop word ptr [LastCluster]
               push word ptr [SI][LD_Clusters]+2
               pop word ptr [LastCluster]+2

               add word ptr [LastCluster],1
               adc word ptr [LastCluster]+2, 0

               cmp byte ptr [SI][LD_FATType], 2
               ja short loc_FAT32_check_gffc_bcluster
               cmp ax, 2
               jb short loc_FAT_gffc_0
               jmp short loc_FAT_gffc_1
loc_FAT32_check_gffc_bcluster:
               cmp dx, 0
               ja short loc_FAT_gffc_1
               cmp ax, 2
               jnb short loc_FAT_gffc_1

               mov ax, word ptr [SI][LD_StartSector]
               mov dx, word ptr [SI][LD_StartSector]+2
               add ax, word ptr [SI][LD_BPB][FAT32_FSInfoSec]
               adc dx, 0

              ;push ds
              ;pop es
               mov bx, offset DOSBootSectorBuff
               mov cx, 1
               call proc_load_disk_sectors
               jnc short loc_check_gffc_FSINFO_signs
               mov ax, 1
               retn

loc_return_gffc_stc:
               mov ax, 2
               stc
               retn

loc_check_gffc_FSINFO_signs:
               cmp word ptr [DOSBootSectorBuff], 5252h
               jne short loc_return_gffc_stc
               cmp word ptr [DOSBootSectorBuff]+2, 4161h
               jne short loc_return_gffc_stc
               mov bx, offset DOSBootSectorBuff
               add bx, 484
               cmp word ptr [BX], 7272h
               jne short loc_return_gffc_stc
               cmp word ptr [BX]+2, 6141h
               jne short loc_return_gffc_stc
               add bx, 8
               mov ax, word ptr [BX]
               mov dx, word ptr [BX]+2
               cmp dx, word ptr [LastCluster]+2
               jb short loc_FAT_gffc_1
               cmp ax, word ptr [LastCluster]
               jna short loc_FAT_gffc_1
loc_FAT_gffc_0:
               mov ax, 2
               mov dx, 0
loc_FAT_gffc_1:
               push ax
               push dx
               call proc_get_next_cluster
               jnc short loc_count_gffc_free_clusters
               cmp ax, 0
               jna short pass_inc_cfs_gffc
               pop dx
               pop ax
               retn

loc_count_gffc_free_clusters:
               cmp dx, 0
               ja short pass_inc_cfs_gffc
               cmp ax, 0
               ja short pass_inc_cfs_gffc
               pop dx
               pop ax
               retn
pass_inc_cfs_gffc:
               pop dx
               pop ax
pass_inc_cfs_gffc_1:
               add ax, 1
               adc dx, 0
               cmp dx, word ptr [LastCluster]+2
               jb short loc_FAT_gffc_1
               ja short loc_count_gffc_return_stc
               cmp ax, word ptr [LastCluster]
               jna short loc_FAT_gffc_1
loc_count_gffc_return_stc:
               xor ax, ax
               xor dx, dx
               stc
               retn

proc_get_first_free_cluster endp

proc_check_filename proc near
                ; INPUT -> DS:SI = Dot File Name Location
               ; push si
                call proc_check_invalid_filename_chars
               ; pop si
                jnc short loc_check_filename_cont
                retn
loc_check_filename_cont:
                mov cx, 8
loc_check_filename_next_char:
                mov al, byte ptr [SI]
                cmp al, 2Eh
                jne short pass_check_fn_dot_check
loc_check_filename_ext_0:
                inc si
                mov al, byte ptr [SI]
                cmp al, 21h
                jc short loc_check_fn_rtn
                cmp al, 2Eh
                jne short loc_check_filename_ext_1
loc_check_fn_stc_rtn:
                stc
loc_check_fn_rtn:
                retn
loc_check_filename_ext_1:
                inc si
                mov al, byte ptr [SI]
                cmp al, 21h
                jc short loc_check_fn_clc_rtn
                cmp al, 2Eh
                je short loc_check_fn_stc_rtn
                inc si
                mov al, byte ptr [SI]
                cmp al, 21h
                jc short loc_check_fn_clc_rtn
                cmp al, 2Eh
                je short loc_check_fn_stc_rtn
                inc si
                mov al, byte ptr [SI]
                cmp al, 21h
                jnc short loc_check_fn_stc_rtn
loc_check_fn_clc_rtn:
                clc
                retn
pass_check_fn_dot_check:
                cmp al, 21h
                jc short loc_check_fn_clc_rtn
                inc si
                loop loc_check_filename_next_char
                mov al, byte ptr [SI]
                cmp al, 21h
                jc short loc_check_fn_clc_rtn
                cmp al, 2Eh
                jne short loc_check_fn_stc_rtn
                jmp short loc_check_filename_ext_0
proc_check_filename endp

proc_locate_file proc near
                ; INPUT -> DS:SI = TR-DOS FindFile Structure Address
                ; AX = Attributes Mask 
                ;      AL = AL AND EntryAttributes must be equal to AL
                ;      AH = AH AND EntryAttributes must be ZERO
                ;      AX = 1800h -> Files, no volume labels or Dirs
                ; NOTE: DS must be equal to CS at the beginning of this procedure
                ;       because TR-DOS FindFile structure is in code segment
                ;
                ; OUTPUT -> DS:SI = Directory Buffer Entry Address
                ; cf= 0 -> File Found (32 byte Directory Entry beginning at DS:SI)
                ;      AL > 0 -> Filename fits by using "?" wildcard
                ;      AH > 0 -> Filename fits by using "*" wildcard
                ;      AX = 0 -> Filename fits exactly
                ;      DL = Attributes 
                ;      DH = Previous Entry Attributes 
                ;      CL = Entry Offset
                ;      CH = The 1st name char
                ; cf= 1 -> Error (MS-DOS compatible Error Code in AX/AL)
                ; ES:DI will be changed (unknown)
                ; BX = Count of Dir Entries have been checked - 1 (CF=0)
                
                push si
                mov word ptr [AttributesMask], ax
                mov al, byte ptr [SI] ; Drive
                mov ah, byte ptr [Current_DosDisk]
                mov byte ptr [Current_DirReset], 1
                cmp al, ah
                je short pass_locatefile_chg_current_drive
                push ax
                call proc_change_current_drive
                pop ax
                mov byte ptr [Current_DosDisk], ah ; DOS DRV before RUN
                jc short loc_locatefile_drive_notready
                call proc_load_current_path
                call proc_change_current_directory
                jc short loc_locatefile_dir_notfound
pass_locatefile_chg_current_drive:
                pop si ; TR-DOS FindFile Structure
                push si
                add si, 2; Directory
                cmp byte ptr [SI], 0
                jna short pass_locatefile_change_directory
                call proc_parse_dir_name
                call proc_change_current_directory
                jc short loc_locatefile_dir_notfound
pass_locatefile_change_directory:
                pop si ; TR-DOS FindFile Structure
                push si
                add si, 66 ; Dot File Name
                mov di, offset Dir_File_Name ; Dir Entry Format Filename
                call proc_convert_file_name
                mov si, offset Dir_File_Name
                mov dx, word ptr [AttributesMask]
                xor ax, ax
                call proc_locate_current_dir_file
                pop si
                mov si, di
                retn

loc_locatefile_drive_notready:
                pop si
                mov ax, 15h ;Drive not ready or read error
                retn

loc_locatefile_dir_notfound:
                pop si
                mov ax, 3 ;Path not found
                retn

proc_locate_file endp

proc_load_executable_file proc near
                ; INPUT -> DS:SI = Directory Entry
                ; ES:DI -> (Loading) Buffer Adress
                cmp byte ptr [SI]+8, "C"
                jne short loc_check_exe_file
                cmp byte ptr [SI]+9, "O"
                jne short loc_lef_cmd_failed
                cmp byte ptr [SI]+10, "M"
                jne short loc_lef_cmd_failed
                mov byte ptr [EXE_ID], 0
                jmp short loc_cont_to_load_executable_file
loc_check_exe_file:
                cmp word ptr [SI]+8, "XE"
                jne short loc_lef_cmd_failed
                cmp byte ptr [SI]+10, "E"
                jne short loc_lef_cmd_failed
                mov byte ptr [EXE_ID], 'E'
loc_cont_to_load_executable_file:
                ; DS:SI = Directory Entry Address of the file
                mov ax, word ptr [SI]+28 ; FileSize Low Word
                mov dx, word ptr [SI]+30 ; FileSize High Word
                cmp dx, 0
                ja  short loc_lef_insufficient_memory
                cmp ax, 0
                jna short loc_lef_cmd_failed
                mov word ptr [Program_Size], ax
                mov word ptr [Program_Size]+2, dx
                mov ax, word ptr [SI]+26 ; First Cluster Low Word
                mov dx, word ptr [SI]+20 ; First Cluster High Word
                cmp dx, 0
                ja  short pass_executablefile_fc_check
                cmp ax, 2
                jb  short loc_lef_cmd_failed
pass_executablefile_fc_check:
                push ax
                push dx
                xor dx, dx
                mov ax, di
                mov bx, 16
                div bx
                mov bx, ES 
                add ax, bx
                mov word ptr [Run_Segment], ax
                mov word ptr [Run_Offset], 100h
                pop dx
                pop ax
                xor bl, bl
                mov bh, byte ptr [DirBuff_Drv]
                mov di, word ptr [Run_Offset]
                push word ptr [Run_Segment]
                pop es
                call proc_load_file
                retn

loc_lef_cmd_failed:
                mov ax, 1 ; "Bad command or file name !"
                stc
                retn
loc_lef_insufficient_memory:
                mov ax, 8
                stc
                retn

proc_load_executable_file endp

Proc_Find_First_File proc near
     
     ; INPUT -> DS:SI = Pointer to filename (ASCIIZ pathname address)
     ; AL = Attributes AND mask (The AND result must be equal to AL)
     ;       bit 0 = Read Only
     ;       bir 1 = Hidden
     ;       bit 2 = System
     ;       bit 3 = Volume Label
     ;       bit 4 = Directory
     ;       bit 5 = Archive
     ;       bit 6 = Reserved, must be 0
     ;       bit 7 = Reserved, must be 0
     ; AH = Attributes NAND mask (The AND result must be ZERO)

     
     ; OUTPUT -> CF = 1 : Error, Error Code in AX (AL)
     ; CF = 0 -> DS:SI = Directory Entry (FindFile_DirEntry) Location
     ;           ES:DI = Directory Buffer Directory Entry Location
     ;           DX:AX = File Size
     ;           CL = Attributes of The File/Directory
     ;           CH = Long Name Yes/No Status (>0 is YES)
     ;           BX > 0 : Ambiguous filename chars are used
                                    
     push cs
     pop es
     mov word ptr ES:[FindFile_AttributesMask], AX
     mov di, offset FindFile_DirEntry ; TR-DOS FindFile data buffer
     xor ax, ax
     mov cx, 23
     rep stosw      
     mov di, offset FindFile_Structure ; TR-DOS FindFile data buffer
     call proc_parse_pathname
     jc short loc_fff_retn
     push es
     pop ds
     mov si, offset FindFile_Structure
     mov ax, word ptr [FindFile_AttributesMask]
     call proc_locate_file 
     jc short loc_fff_retn
     ; DS:SI = Directory Entry
     
     cmp dh, 0Fh
     jne short pass_fff_longname_yes
     inc byte ptr [FindFile_LongNameYes]
pass_fff_longname_yes:
     mov byte ptr [FindFile_DirEntryOffset], cl

     mov cx, 16
     mov di, offset FindFile_DirEntry
     push si
     push di
     rep movsw
     pop si
     pop di
     mov cl, dl ; File Attributes
     mov ch, byte ptr [FindFile_LongNameYes]
     mov bl, byte ptr [DirBuff_SectorOffset]
     mov byte ptr [FindFile_DirSectorOffset], bl
     mov bx, ax ; Ambigouos Filename chars used sign > 0
     mov ax, word ptr [Current_DirFCluster]
     mov dx, word ptr [Current_DirFCluster]+2
     mov word ptr [FindFile_DirFirstCluster], ax
     mov word ptr [FindFile_DirFirstCluster]+2, dx
     mov ax, word ptr [DirBuff_DirCluster]
     mov dx, word ptr [DirBuff_DirCluster]+2
     mov word ptr [FindFile_DirCluster], ax
     mov word ptr [FindFile_DirCluster]+2, dx

     inc word ptr [FindFile_MatchCounter]

     mov ax, word ptr [FindFile_DirEntry]+28 ; File Size Low Word
     mov dx, word ptr [FindFile_DirEntry]+30 ; File Size High Word

     clc

loc_fff_retn:
     retn

FindFile_Structure:
FindFile_Drv: db 0
FindFile_DirLength: db 0
FindFile_Directory: db 64 dup(0)
FindFile_Name: db 13 dup(0)
FindFile_LongNameYes: db 0 ; Sign for longname procedures
;Above is 80 bytes
;is TR-DOS Source/Destination file pathname structure
FindFile_AttributesMask: dw 0
FindFile_DirEntry: db 32 dup(0)
FindFile_DirFirstCluster: dd 0
FindFile_DirCluster: dd 0
FindFile_DirSectorOffset: dw 0
FindFile_DirEntryOffset: dw 0
FindFile_MatchCounter: dw 0
; Above is 128 bytes

Proc_Find_First_File endp            

Proc_Find_Next_File proc near
     
     ; INPUT -> NONE, Find First File Parameters (CS=DS=ES)
     ; OUTPUT -> CF = 1 : Error, Error Code in AX (AL)
     ; CF = 0 -> DS:SI = Directory Entry (FindFile_DirEntry) Location
     ;           ES:DI = Directory Buffer Directory Entry Location
     ;           DX:AX = File Size
     ;           CL = Attributes of The File/Directory
     ;           CH = Long Name Yes/No Status (>0 is YES)
     ;           BX = Offset of FindFile (128 byte) Structure Address
                                    
                 cmp word ptr [FindFile_MatchCounter], 0
                 ja short loc_start_search_next_file
loc_fnf_stc_retn:
                 stc
loc_fnf_ax12_retn:
                 mov ax, 12 ; No More files
                 retn

loc_start_search_next_file:

                 xor ch, ch
                 mov cl, byte ptr [DirBuff_CurrentEntry]
                 inc cl
                 cmp cl, 15
                 jna short loc_lnf_search

loc_cont_search_next_file:
                 mov bh, byte ptr [DirBuff_Drv]
                 mov bl, byte ptr [DirBuff_SectorOffset]
                 inc bl 

                 cmp byte ptr [Current_DirLevel], 0
                 ja short loc_lnf_check_next_sector
                 cmp byte ptr [Current_FS], 2
                 ja short loc_lnf_check_next_sector

                 cmp bl, byte ptr [DirBuff_LastSector]
                 ja short loc_fnf_stc_retn
                 call proc_load_root_directory
                 jc short loc_fnf_ax12_retn
                 jmp short loc_lnf_search_xorcx

loc_lnf_check_next_sector:
                 mov ax, word ptr [DirBuff_DirCluster]
                 mov dx, word ptr [DirBuff_DirCluster]+2
                 cmp bl, byte ptr [DirBuff_LastSector]
                 jna short loc_lnf_load_next_sector
                 xor bl, bl
                 mov si, offset Logical_DosDisks
                 add si, bx
                 push bx
                 call proc_get_next_cluster
                 pop bx
                 jnc short loc_lnf_load_next_sector
                 jmp short loc_fnf_ax12_retn
loc_lnf_load_next_sector:
                 call proc_load_directory
                 jc short loc_fnf_ax12_retn
loc_lnf_search_xorcx:
                 xor cx, cx
loc_lnf_search:
                 mov si, offset Dir_File_Name
                 mov dx, word ptr [FindFile_AttributesMask]
                 call proc_find_direntry
                 jc short loc_cont_search_next_file

                 cmp dh, 0Fh
                 jne short pass_fnf_longname_exists
                 inc byte ptr [FindFile_LongNameYes]
pass_fnf_longname_exists:
                 mov byte ptr [FindFile_DirEntryOffset], cl
     
                 mov si, di
                 push di
                 mov cx, 16
                 mov di, offset FindFile_DirEntry
                 push di
                 rep movsw
                 pop si
                 pop di
     
                 mov cl, dl ; File Attributes
                 mov ch, byte ptr [FindFile_LongNameYes]
                 mov ax, word ptr [DirBuff_DirCluster]
                 mov dx, word ptr [DirBuff_DirCluster]+2
                 mov bl, byte ptr [DirBuff_SectorOffset]
                 mov word ptr [FindFile_DirCluster], ax
                 mov word ptr [FindFile_DirCluster]+2, dx
                 mov byte ptr [FindFile_DirSectorOffset], bl
  
                 inc word ptr [FindFile_MatchCounter]

                 mov bx, offset FindFile_Drv
    
                 mov ax, word ptr [FindFile_DirEntry]+28 ; File Size Low 
                 mov dx, word ptr [FindFile_DirEntry]+30 ; File Size High

                 clc

                 retn

Proc_Find_Next_File endp            

Get_File_Name    proc near
                 ; INPUT ->  DS:SI -> Directory Entry Format File Name
                 ;           ES:DI -> DOS Dot File Name Buffer
                 ;
                 ; OUTPUT -> DS:SI -> DOS Dot File Name Buffer
                 ;           ES:DI -> Directory Entry Format File Name
                            
                 push ds
                 push es
                 push si
                 push di
                 lodsb
                 cmp al, 20h
                 jna short pass_gfn_ext
                 push si
                 stosb
                 mov cx, 7
loc_gfn_next_char:
                 lodsb
                 cmp al, 20h
                 jna short pass_gfn_fn
                 stosb
                 loop loc_gfn_next_char
pass_gfn_fn:
                 pop si
                 add si, 7
                 lodsb
                 cmp al, 20h
                 jna short pass_gfn_ext
                 mov ah, "."
                 xchg ah, al
                 stosw
                 lodsb
                 cmp al, 20h
                 jna short pass_gfn_ext
                 stosb
                 lodsb
                 cmp al, 20h
                 jna short pass_gfn_ext
                 stosb
pass_gfn_ext:                 
                 xor al, al
                 stosb
                 pop si
                 pop di
                 pop ds
                 pop es
                 retn

Get_File_Name    endp

INCLUDE CMD_INTR.ASM ; TRDOS Command Interpreter
INCLUDE INT_21H.ASM ; TRDOS INT 21h Handler

AttributesMask: dw 0

SourceFile_Drv: db 0
SourceFile_DirLength: db 0
SourceFile_Directory: db 64 dup(0)
SourceFile_Name: db 13 dup(0)
SourceFile_LongNameYes: db 0
SourceFile_AttributesMask: dw 0
SourceFile_DirEntry: db 32 dup(0)
SourceFile_Cluster: dd 0
SourceFile_SecPerClust: db 0
SourceFile_SectorOffset: db 0
SourceFile_ByteCounter: dd 0
SourceFile_BufferOff: dw 0
SourceFile_BufferSeg: dw 0

DestinationFile_Drv: db 0
DestinationFile_DirLength: db 0
DestinationFile_Directory: db 64 dup(0)
DestinationFile_Name: db 13 dup(0)
DestinationFile_LongNameYes: db 0
DestinationFile_AttributesMask: dw 0
DestinationFile_DirEntry: db 32 dup(0)
DestinationFile_Cluster: dd 0
DestinationFile_SecPerClust: db 0
DestinationFile_SectorOffset: db 0
DestinationFile_ByteCounter: dd 0
DestinationFile_BufferOffset: dw 0
DestinationFile_BufferSegment: dw 0

CHS_RetryCount: db 0
PrintDir_RowCounter: db 0

; Disk Read Procedure Parameters
DAP_RetryCount: db 4
DAP_BuffCDRV_BPB: dw 0
DAP_BuffDisk: db 0
DAP_BuffLBAyes: db 0
DAP_Buffer:
DAP_BuffPacketSize: db 0
DAP_BuffReservd1: db 0
DAP_BuffNumOfBlocks: db 0
DAP_BuffReservd2: db 0
DAP_BuffDestination: dd 0
DAP_BuffLBA_Address: dd 0
DAP_BuffLBA_Addressq: dd 0

FAT_ClusterCounter: dd 0
FAT_BuffDescriptor:
FAT_CurrentCluster: dd 0
FAT_BuffValidData: db 0
FAT_BuffDrvName: db 0
FAT_BuffSector: dd 0
FAT_Buffer: db 1536 dup (0FFh)

Directory_BuffDescriptor:
DirBuff_ValidData: db 0
DirBuff_Drv: db 0
DirBuff_DirCluster: dd 0
DirBuff_NextCluster: dd 0
DirBuff_EntryCounter: dw 0
DirBuff_SectorOffset: db 0
DirBuff_LastSector: db 0
DirBuff_CurrentEntry: db 0
DirBuff_LastEntry: db 0
DirBuff_DirSector: dd 0
Directory_Buffer: db 512 dup (0)
                             
Current_DrvDescriptor:
Current_DirReset: db 0
Current_Media: db 0
Current_PhyDisk: db 0
Current_VolSerial1: dw 0
Current_VolSerial2: dw 0
Current_DosDisk: db 0
Current_FS: db 0 
Current_DirLevel: db 0
Current_DirFCluster: dd 0
Current_Path: db 12  dup(0)
Current_FS_RDFC: dd 0
Current_Path_L1_L7: db 112 dup(0)
Current_File: db 11 dup(0)
Current_File_FCluster: dd 0
Current_ClusterCount: dd 0

SectorBuffDescriptor:
SectorBuff_BeginSector: dd 0
SectorBuff_LastSector: dd 0
SectorBuff_CurrentSector: dd 0
SectorBuff_CurrentByte: dw 0
SectorBuff_BytesPerSec: dw 0
Sector_Buffer: db 2048 dup(0)

TRDOSPromptLabel: db "TRDOS"
                  db 0
                  db 5 dup(0)
                  db 0
TextBuffer:  db 80 dup(0)
CommandBuffer: db 80 dup(0)
CmdArgStart: db 0
CursorColumn: db 0
Program_Exit: db 0

File_Name:
		db  12 dup(20h)
		db  20h
Dir_Or_FileSize:
		db  10 dup(20h)
		db  20h
File_Attribute:
		db  4 dup(20h)
		db  20h
File_Day:
		db  2 dup('0')
		db  '/'
File_Month:
		db  2 dup('0')
		db  '/'
File_Year:
		db  4 dup('0')
		db  20h
File_Hour:
		db  2 dup('0')
		db  ':'
File_Minute:
		db  2 dup('0')
		db  0

Type_Dir:       db '<DIR>      '

Dir_Drive_Str:
                db "TR-DOS Drive "
Dir_Drive_Name:
                db "0:"
                db  0Dh, 0Ah
Vol_Str_Header:
                db "Volume Name: "
Vol_Name:       db 11 dup(0)
                db 0
Vol_Serial_Header:
                db 0Dh, 0Ah
                db "Volume Serial No: "
Vol_Serial2:    db "0000"
                db "-"
Vol_Serial1:    db "0000"
                db 0Dh, 0Ah
Dir_Str_Header:
                db "Directory: "
Dir_Str_Root:   db "/"
Dir_Str:        db 64 dup (0)
End_of_Dir_Str: db " ..."
                db 0
Starting_Msg:
                db 0Dh, 0Ah 
                db "Starting TRDOS ..."
                db 0Dh, 0Ah, 0
Magic_Bytes:
                   db 4
                   db 1
Program_Version:
                   db 7
                   db "[TRDOS] Main Program v1.0.220209"
                   db 0Dh, 0Ah
                   db "(c) Erdogan Tan 2005-2009"
                   db 0Dh, 0Ah, 0

;Memory_Allocation_Table:
;                   db 'M' ;0000h
;                   db 'A' ;0200h
;                   db 'T' ;0400h
;                   db 'R' ;0600h
;                   db 'D' ;0800h
;                   db 'O' ;0A00h
;                   db 'S' ;0C00h
;                   db ' ' ;0E00h
;                   db '1' ;1000h
;                   db 55 dup('@')
;                   db 80h ;8000h Kernel
;                   db 63 dup(80h) ;Kernel
;                   db 1920 dup(0) ;Program Start: 1000h:0000h
Shell_YesNo:       db 0
Shell_Filename:    db 11 dup (0)
Shell_Offset:      dw 0
Shell_Segment:     dw 0
Set_Page:          db 512 dup(0)
Path_Count:        db 0
Path_Page:         db "C:/DOS",0Dh,0Ah
                   db 504 dup(0)

Logical_DOSDisks:  dw 3328 dup(0)

RunFile_BuffPrefix:db 16 dup (0)
LoadFile_Buffer:   db 4096 dup(0)
End_Of_Run_Buffer: db 0

Present            ends

                   end start 

 
