;*****************************************************************************
; FILE.ASM  [ TRDOS KERNEL - COMMAND EXECUTER SECTION - FILE FUNCTIONS ]
; (c) 2009 Erdogan Tan [29/10/2009] Last Update: 10/07/2010
; ! Under Development !

; Directory Entry Structure
; 29/10/2009 (According to Microsoft FAT32 File System Specicifation)
DirEntry_Name equ 0
DirEntry_Attr equ 11
DirEntry_NTRes equ 12
DirEntry_CrtTimeTenth equ 13
DirEntry_CrtTime equ 14
DirEntry_CrtDate equ 16
DirEntry_LastAccDate equ 18
DirEntry_FstClusHI equ 20
DirEntry_WrtTime equ 22
DirEntry_WrtDate equ 24
DirEntry_FstClusLO equ 26
DirEntry_FileSize equ 28

; Open_File_List Structure
; 25/01/2010, Bugfix for OFDT (OFL Number offset of PSP is 4)
;             OF_OFL_SN was 0ffset 2 and it is changed to offset 4  
; 29/10/2009, Structure for max. 32 Open Files or TSR programs
OFL_Owner equ 0 ; Owner program
OFL_Drive equ 1 ; Logical dos drive of file
OFL_Cluster equ 2 ; First cluster (or FDT address) of file
OFL_Handle equ 6  ; Open File Descriptor Table (256 bytes) Segment
;
OFL_EntrySize equ 8
;
; Open File Descriptor Table (File Handle Structure)
; Open File Read/Write Parameters
OF_Type equ 0 ; db '0CD' is PSP sign otherwise OFDT
OF_Owner equ 1 ; db 0, OFL Sequence number of owner program
OF_OpenMode equ 2 ; db 0
OF_WriteStatus equ 3 ; db 0
OF_OFL_SN equ 4 ; db 0, OFL Sequence Number of file
OF_Drive equ 5 ; db 0
OF_VolumeID equ 6 ; dd 0, Check for removable disks
OF_Segment equ 10 ; dw 0, ! Segment value of file (data) address !
OF_Size equ 12 ; dd 0, File size at memory
OF_Pointer equ 16 ; dd 0, File seek/read/write pointer
;Above 20 bytes
;
OF_LongName equ 20 ; db 64 dup(0)
;Above 84 bytes
;
;Following 42 bytes is just from FFF structure
OF_DirEntry equ 84 ; db 32 dup(0)
OF_DirFirstCluster equ 116 ; dd 0
OF_DirCluster equ 120 ; dd 0
OF_DirEntryOffset equ 124 ; dw 0
OF_FATType equ 126 ; db 0
OF_CDIR_Level equ 127 ; db 0
; Above is 128 bytes
; Open File Current Directory
OF_CDIR: db 128 dup (0)
;

proc_open_file proc near
        ; 07/12/2009 -> error return in al (it was in ah)
        ; 08/11/2009
        ; 29/10/2009
        ; INPUT -> al = open mode
        ;           0 = File opened for reading 
        ;           1 = File opened for writing
        ;           2 = File opened for reading and writing
        ;           3 = File opened for running
        ;                          (NO duplication)
        ;           4 = File opened for running 
        ;                          (duplication YES)
        ; 1/11/2009
        ;          ah = Owner of file (0 => mainprog/kernel) 
        ; 
        ; INPUT -> DS:SI = ASCIZZ file name address
        ;
        ; OUTPUT -> 
        ;          ax = Program/File Segment
        ; cf=0 ->  cx = Allocation size in 100h units (memory cells)
        ;
        ; cf=1 : Error code in AL... 

        mov cx, 32
        mov di, offset Open_Files_List
        add di, OFL_Handle
loc_check_ofl_free_entry:
        cmp word ptr [DI], 0
        jna short loc_openfile_find_file
        add di, OFL_EntrySize
        loop loc_check_ofl_free_entry
        mov ah, 04h ; Too many open files (no file handles available)
        xchg ah, al 
        stc
        retn

loc_openfile_find_file:
       ;mov byte ptr [File_Open_Mode], al
        mov word ptr [File_Open_Mode], ax
        mov al, 33
        sub al, cl
        mov byte ptr [File_OFL_Number], al

        mov ax, 1800h ; Only files 
        call proc_find_first_file
        jnc short loc_check_open_file_if_same_0
        retn 

File_Open_Mode: db 0
File_Owner: db 0
File_OFL_Number: db 0
Open_File_Drive: db 0
Open_File_Size1: dw 0
Open_File_Size2: dw 0
Open_File_FClust1: dw 0
Open_File_FClust2: dw 0
Open_File_Handle: dw 0
Open_File_Type: db 0
Open_File_FATType: db 0
Open_File_Sectors: dw 0
Open_File_Alloc_Size1: dw 0
Open_File_Alloc_Size2: dw 0
Allocation_Size: dw 0 
         
loc_check_open_file_if_same_0:
        ; 07/11/2009
        ; 31/10/2009
       
        mov word ptr [Open_File_Size1], ax
        mov word ptr [Open_File_Size2], dx

        mov bx, word ptr [SI][DirEntry_FstClusLO]
        mov word ptr[Open_File_FClust1], bx
        mov bx, word ptr [SI][DirEntry_FstClusHI]
        mov word ptr[Open_File_FClust2], bx

        xor bx, bx  ; bx = 0 (free space is not compared yet)
                    ; otherwise bx > 0 (free space less than required)

        or dh, dh
        jnz loc_openfile_insufficient_memory_xor_ah

        or ax, dx
        jnz short pass_openfile_check_empty_file

        mov al, byte ptr [File_Open_Mode]
        cmp al, 2
        jna short pass_openfile_check_empty_file
        mov ah, 0Eh ; 0Eh = msdos reserved error code
                    ; TRDOS error code 0Eh = Zero length
        xchg ah, al
        stc
        retn  
        
pass_openfile_check_empty_file:
        mov bh, byte ptr [Current_Drv]   ; Temporary !!!
                                         ; FindFile_Drv is not functional
                                         ; for yet; because find_first_file
                                         ; only runs for currrent drv for now
                                         ; 29/10/2009

        mov byte ptr [Open_File_Drive], bh

        push si
        
        mov si, offset Logical_DosDisks
        add si, bx
        mov al, byte ptr [SI][LD_FATType]
        mov byte ptr [Open_File_FATType], al
	cmp al, 1
        jb short loc_openfile_get_FS_vol_id
        mov bx, word ptr [SI][LD_BPB][BytesPerSec]
        cmp al, 2
        ja short loc_openfile_get_FAT32_vol_id
loc_openfile_get_FAT_vol_id:
        mov ax, word ptr [SI][LD_BPB][VolumeID]
        mov dx, word ptr [SI][LD_BPB][VolumeID]+2
        jmp short loc_openfile_move_volume_id

loc_openfile_get_FS_vol_id:
        mov ax, word ptr [SI][LD_FS_VolumeSerial]
        mov dx, word ptr [SI][LD_FS_VolumeSerial]+2
        mov bx, word ptr [SI][LD_FS_BytesPerSec]
        jmp short loc_openfile_move_volume_id
 
loc_openfile_get_FAT32_vol_id:
        mov ax, word ptr [SI][LD_BPB][FAT32_VolID]
        mov dx, word ptr [SI][LD_BPB][FAT32_VolID]+2         
          
loc_openfile_move_volume_id:
        mov word ptr [Current_VolSerial1], ax
        mov word ptr [Current_VolSerial2], dx

        mov ax, word ptr [Open_File_Size1]
        mov dx, word ptr [Open_File_Size2]

        or dx, dx
        jz short pass_openfile_check_com_file_sizelimit

        cmp byte ptr [EXE_ID], 'E'
        jne loc_openfile_insufficient_memory_xor_ah

pass_openfile_check_com_file_sizelimit:

        mov cx, bx  ; Bytes per sector
        dec bx
        add ax, bx
        adc dx, 0
        call Rx_Dos_Div32
                    ; DX:AX = Sector count
                    ; DX = 0
        mov word ptr [Open_File_Sectors], ax

        mov bx, cx  ; Bytes per sector
        call proc_mul32
        
        ; 25/11/2009 (COM file stack space allocation)
        cmp byte ptr [File_Open_Mode], 2
        jna short pass_fix_program_stackspace
        cmp byte ptr [EXE_ID], 'E'
        je short pass_fix_program_stackspace
        or dx, dx
        jnz short loc_openfile_insufficient_memory_xor_ah
        cmp ax, 64000 ; 65536-(1024+256+256)
        jna short loc_fix_program_stackspace
        mov ax, 65535
        jmp short pass_fix_program_stackspace  
loc_fix_program_stackspace:
        add ax, 400h ; 1024 bytes stack space will be allocated
        adc dx, 0
pass_fix_program_stackspace:
        mov word ptr [Open_File_Alloc_Size1], ax
        mov word ptr [Open_File_Alloc_Size2], dx
 
        pop si
                                        
        mov ax, word ptr [SI]+DirEntry_FstClusLO
        mov dx, word ptr [SI]+DirEntry_FstClusHI
                                         ; DX:AX = First cluster
        mov si, offset Open_Files_List
        mov cx, 32
loc_check_open_file_if_same_1:
        cmp byte ptr [SI]+1, bh ; 0
        jne short pass_check_open_file_if_same_1
        cmp word ptr [SI]+2, ax
        jne short pass_check_open_file_if_same_1
        cmp word ptr [SI]+4, dx
        jne short pass_check_open_file_if_same_1

        mov di, word ptr [SI]+6
        mov es, di
        xor di, di
        cmp byte ptr [DI], 0CDh
        je  short pass_check_open_file_if_same_1
  
        add di, 4 ; OF_VolumeID
        mov ax, word ptr ES:[DI]
        mov dx, word ptr ES:[DI]+2

        cmp ax, word ptr [Current_VolSerial1]
        jne short loc_openfile_allocate_memory
        cmp dx, word ptr [Current_VolSerial2]
        jne short loc_openfile_allocate_memory
        mov al, byte ptr [File_Open_Mode]
        or al, 3
        jz short loc_openfile_allocate_memory
        mov ah, 05h  ; Access denied
        xchg ah, al
        stc
        retn

pass_check_open_file_if_same_1:
        add si, OFL_EntrySize
        loop loc_check_open_file_if_same_1

loc_openfile_allocate_memory:
        mov ax, 352 ; 22*16, beginning segment
        call proc_get_free_memory
             	; AX= Total free allocation units (100h bytes)
            	; DX= Max. Free consequtive allocation units (100h bytes)
        	; CX= Total usable (conventional TRDOS) memory (100h bytes)
   	        ; BX= First free segment (valid if < FFFFh)
                ; cf= 1 -> no free memory 
        jnc short loc_open_file_compare_memory_size
loc_openfile_insufficient_memory_xor_ah:
        xor ah, ah
loc_openfile_insufficient_memory:
        mov al, 08h ; Insufficient memory 
        stc
        retn 

loc_open_file_compare_memory_size:
        push bx
        push dx
        mov ax, word ptr [Open_File_Alloc_Size1]
        mov dx, word ptr [Open_File_Alloc_Size2]
        mov cx, 100h
        call Rx_Dos_Div32
        ;or dx, dx
        pop dx
        pop bx
       ;jnz short loc_openfile_insufficient_memory_xor_ah

        cmp ax, dx      ; dx =  Max. Free consequtive allocation units
        jnb short loc_openfile_insufficient_memory_xor_ah
                        ; dx >= ax + 100h (100h = OFDT or PSP size)

        mov word ptr [Allocation_Size], ax 

        mov byte ptr [Open_File_Type], 40h
        cmp byte ptr [File_Open_Mode], 2
        ja short loc_openfile_allocate_file_space1
loc_openfile_allocate_file_space0:
        add byte ptr [Open_File_Type], 20h
loc_openfile_allocate_file_space1:
        mov ax, word ptr [Open_File_Alloc_Size1]
        mov dx, word ptr [Open_File_Alloc_Size2]
loc_openfile_allocate_file_space2:
        or dx, dx
        jnz short loc_openfile_huge_file_allocation1
loc_openfile_allocate_file_space3:
        mov cx, ax
        mov ah, 1
        mov al, byte ptr [Open_File_Type]
        add al, byte ptr [File_OFL_Number]
        call proc_allocate_memory
        jmp short loc_openfile_set_ofl_entry
loc_openfile_huge_file_allocation1:
        push dx
        push ax
        mov ah, 1
        mov al, byte ptr [Open_File_Type]
        add al, byte ptr [File_OFL_Number]
        mov cx, 0FFF0h
        call proc_allocate_memory
        mov word ptr [Open_File_Handle], bx
        add bx, 0FFFh
        pop ax
        pop dx
        sub ax, cx
        sbb dx, 0
loc_openfile_allocate_file_space4:
       ;or dx, dx
        ja short loc_openfile_huge_file_allocation2
        or ax, ax
        jz short loc_openfile_allocate_file_space5
        mov cx, ax
        mov ah, 1
        mov al, byte ptr [Open_File_Type]
        add al, byte ptr [File_OFL_Number]
        call proc_allocate_memory
        jmp short loc_openfile_allocate_file_space5
loc_openfile_huge_file_allocation2:
        push dx
        push ax
        mov ah, 1
        mov al, byte ptr [Open_File_Type]
        add al, byte ptr [File_OFL_Number]
        mov cx, 0FFF0h
        call proc_allocate_memory
        add bx, 0FFFh
        pop ax
        pop dx
        sub ax, cx
        sbb dx, 0
        jmp short loc_openfile_allocate_file_space4

loc_openfile_allocate_file_space5:
        mov bx, word ptr [Open_File_Handle]
 
loc_openfile_set_ofl_entry:
        mov al, byte ptr [File_OFL_Number]
        dec al 
        mov ah, OFL_EntrySize
        mul ah
        mov si, offset Open_Files_List
        add si, ax
        mov al, byte ptr [File_Owner]
        mov byte ptr [SI], al

        mov al, byte ptr [Open_File_Drive]
        mov byte ptr [SI]+1, al
        mov ax, word ptr [Open_File_FClust1]
        mov dx, word ptr [Open_File_FClust2]
        mov word ptr [SI]+2, ax
        mov word ptr [SI]+4, dx
        mov word ptr [SI]+6, bx ; Handle (PSP or OFDT)

        cmp byte ptr [File_Open_Mode], 2
        jna short loc_openfile_set_ofdt

loc_openfile_set_psp:
        ; input -> bx = program (psp) segment
        call proc_create_psp
        ; return -> bx = program (psp) segment
        mov es, bx
        mov di, 4
        mov al, byte ptr [File_OFL_Number]
        mov byte ptr ES:[DI], al
       ;xor al, al
       ;mov byte ptr ES:[DI]+1, al  
        mov ax, word ptr [Current_VolSerial1]
        mov dx, word ptr [Current_VolSerial2]
        mov word ptr ES:[DI]+2, ax
        mov word ptr ES:[DI]+4, dx 

        mov ax, word ptr [Open_File_Size1]
        mov dx, word ptr [Open_File_Size2]
        mov cx, 16
        call Rx_Dos_Div32
                    ; DX:AX = Count of paragraphs
                    ; DX = 0
        mov dx, es
        add ax, dx
        shr di, 1   ; mov di, 2
        mov word ptr ES:[DI], ax

loc_openfile_load_file:
        mov di, 100h 

        mov cx, word ptr [Open_File_Sectors]
        mov ax, word ptr [Open_File_FClust1]
        mov dx, word ptr [Open_File_FClust2]
        mov bh, byte ptr [Open_File_Drive]
        xor bl, bl

        call proc_load_file

        push ds
        pop es

        ; 22/11/2009
        mov cx, word ptr [Allocation_Size]

        retn

loc_openfile_set_ofdt:
        mov es, bx
        mov byte ptr ES:[OF_Type], 'F'
        mov al, byte ptr [File_Owner]
        mov byte ptr ES:[OF_OWNER], al ; 0 => Mainprog/Kernel
       ;mov al, byte ptr [File_OFL_Number]
       ;mov byte ptr ES:[OF_OFL_SN], al
       ;mov al, byte ptr [Open_File_Drive]
       ;mov byte ptr ES:[OF_Drive], al
        mov ax, word ptr [File_OFL_Number]
        mov word ptr ES:[OF_OFL_SN], ax
        mov ax, word ptr [Current_VolSerial1]
        mov dx, word ptr [Current_VolSerial2]
        mov word ptr ES:[OF_VolumeId], ax
        mov word ptr ES:[OF_VolumeId]+2, dx
        mov word ptr ES:[OF_Segment], bx
        mov ax, word ptr [Open_File_Size1]
        mov dx, word ptr [Open_File_Size2]
        mov word ptr ES:[OF_Size], ax
        mov word ptr ES:[OF_Size]+2, dx
        xor ax, ax
        mov byte ptr ES:[OF_WriteStatus], al
        mov word ptr ES:[OF_Pointer], ax
        mov word ptr ES:[OF_Pointer]+2, ax

        mov di, OF_LongName 
        mov cx, 64
       
        cmp byte ptr [FindFile_LongNameYes], 0
        jna short pass_openfile_move_longname

        mov si, offset LongFileName  

        ; DS:SI : Unicode LongName
        ; ES:DI : Destination
        ; CX: Destination name length (max.)
        call proc_convert_longname_from_unicode

        jmp short loc_openfile_move_direntry

pass_openfile_move_longname:
        ; AL = 0
        rep stosb

loc_openfile_move_direntry:
        mov di, OF_DirEntry
        mov si, offset FindFile_DirEntry
        mov cx, 21
        rep movsw

        mov al, byte ptr [Open_File_FATType]
        mov byte ptr ES:[OF_FATType], al

loc_openfile_move_cdir:
        mov bh, byte ptr [Open_File_Drive]
        xor bl, bl
        mov si, offset Logical_DOSDisks
        add si, bx
        add si, LD_CDirLevel
        mov di, OF_CDIR_Level
        movsb
        mov cx, 64
        rep movsw
       
        mov ax, word ptr ES:[OF_Segment]
        mov es, ax
 
        jmp loc_openfile_load_file
        
proc_open_file endp


proc_create_psp proc near
        ; 17/11/2009 Temporary
        ;
        push es
        mov es, bx
        xor bx, bx
        mov word ptr ES:[BX], 20CDh
        mov bx, es 
        pop es

        retn  

proc_create_psp endp


proc_convert_longname_from_unicode proc near
        ; 1/11/2009 Temporary
        ;
        ; cx = max. length
loc_pclfu:       
        lodsw
        stosb 
        or al, al
        jnz short retn_from_pclfu
        loop loc_pclfu
retn_from_pclfu:
        retn

proc_convert_longname_from_unicode endp


proc_load_file  proc near
              ; 16/01/2010 Load FS File
              ; 07/12/2009 -> error code in al (it was in ah)
              ; 07/11/2009
              ; INPUT ->
              ; ES:DI = File Buffer
              ; DX:AX = First Cluster Number
              ; BL = 0
              ; BH = DRV
              ; CX = Sector Count
              ; OUTPUT ->
              ; AX = File Segment 
              ; STC -> Error Code in AL

             
                mov si, offset Logical_DOSDisks
                add si, bx

                cmp byte ptr [SI][LD_FATType],0
                ja short loc_load_FAT_file_sectors

               ;16/01/2010
                call proc_load_fs_file

                retn

loc_load_FAT_file_sectors:
                push es
                pop word ptr [LoadFile_Segment]

                mov word ptr [LoadFile_SectorCount], cx
                xor bh, bh
                mov bl, byte ptr [SI][LD_BPB][SecPerClust]
                mov word ptr [LoadFile_SecPerClust], bx
                mov word ptr [LoadFile_BufferOff], di
loc_load_FAT_file_next_sectors:
                cmp cx, bx
                jna short loc_loadfile_calculate_address
                mov cx, bx
loc_loadfile_calculate_address:
                mov word ptr [LoadFile_Cluster], ax
                mov word ptr [LoadFile_Cluster]+2, dx          
                sub ax, 2
                sbb dx, 0
                call proc_mul32
                add ax, word ptr [SI][LD_DATABegin]
                adc dx, word ptr [SI][LD_DATABegin]+2
                mov bx, word ptr [LoadFile_BufferOff]
                push dx
                push ax
                mov ax, word ptr [SI][LD_BPB][BytesPerSec]
                mul cx
                add ax, bx
                adc dx, 0
                mov word ptr [LoadFile_BufferOff], ax
                mov ax, dx
                mov dx, 1000h
                mul dx
                mov dx, es
                add dx, ax
                mov es, dx
                pop ax
                pop dx
                ; cx <= Sectors per Cluster
                push cx
                call proc_disk_read
                pop cx
                jc short loc_load_file_stc_retn

                sub word ptr [LoadFile_SectorCount], cx
                jna short loc_load_file_retn 
                mov ax, word ptr [LoadFile_Cluster]
                mov dx, word ptr [LoadFile_Cluster]+2
                call proc_get_next_cluster
                jnc short loc_cont_load_file
                cmp ax, 0
                jna short loc_load_file_retn
                stc
loc_load_file_stc_retn:
                retn 
loc_load_file_retn:
                mov ax, word ptr [LoadFile_Segment]
                retn
loc_cont_load_file:
                mov bx, word ptr [LoadFile_SecPerClust]
                mov cx, word ptr [LoadFile_SectorCount] 
                jmp short loc_load_FAT_file_next_sectors

LoadFile_SectorCount: dw 0
LoadFile_BufferOff: dw 0
LoadFile_Segment: dw 0
LoadFile_SecPerClust: dw 0
LoadFile_Cluster: dd 0

proc_load_file  endp


proc_close_file proc near
        ; 17/11/2009
        ; INPUT -> 
        ;      AX = PSP Address, OFDT Address, File Handle
        ; OUTPUT ->
        ;      ES = DS, AX= PSP/OFDT Segment, BX= OFL Number
        ;      SI = Open File List, DI = 0

        mov es, ax
        xor di, di
        mov bl, byte ptr ES:[DI]+4 ; OFL_Number
        xor bh, bh
        dec bl
        mov si, offset Open_Files_List
        mov al, OFL_EntrySize
        mul bl
        add si, ax
        mov ax, es
         
        cmp ax, word ptr [SI]+OFL_Handle
        je short loc_close_file1

        push ds
        pop es

        retn

loc_close_file1:
       push ds
       push es
       push bx
 
       mov byte ptr [SI]+OFL_Drive, 0FFh
       cmp byte ptr ES:[DI], 0CDh
       mov ax, 140h  
       je short loc_closefile1_set_al_40h
loc_closefile1_set_al_60h:
       add al, 20h
loc_closefile1_set_al_40h:
       add al, bl  ; ah = 1
       inc al
       mov bx, es
       call proc_deallocate_memory
       push ds
       pop es 
       xor ax, ax
       mov word ptr [SI]+OFL_Handle, ax

       mov cx, 32
       mov si, offset Open_Files_List
loc_close_file2:
       mov bx, word ptr [SI]+OFL_Handle
       or bx, bx
       jz short pass_closefile_2
       cmp byte ptr [SI]+OFL_Drive, 0FFh
       je short pass_closefile_2
       mov al, byte ptr [SI] ; Owner
       or al, al
       jz short pass_closefile_2 
      ;cmp al, 32
      ;ja short pass_closefile_2
       dec al
       mov ah, OFL_EntrySize
       mul ah
       mov di, offset Open_Files_List
       add di, ax
       cmp word ptr [DI]+OFL_Handle, 0
       jna short pass_closefile_check_FFh
       cmp byte ptr [DI]+OFL_Drive, 0FFh
       jne short pass_closefile_2
pass_closefile_check_FFh:       
       mov byte ptr [SI]+OFL_Drive, 0FFh
pass_closefile_2:
       add si, OFL_EntrySize
       loop loc_close_file2

       mov cl, 32
       mov si, offset Open_Files_List
       xor di, di
loc_close_file3:
       cmp byte ptr [SI]+OFL_Drive, 0FFh
       jne short pass_closefile_3
       mov bx, word ptr [SI]+OFL_Handle
       or bx, bx
       jz short pass_closefile_3 
       mov es, bx
       cmp byte ptr ES:[DI], 0CDh
       mov ax, 0140h  
       je short loc_closefile3_set_al_40h
loc_closefile3_set_al_60h:
       add al, 20h
loc_closefile3_set_al_40h:
       add al, byte ptr ES:[DI]+4 ; OFL_Number
       mov bx, es
       push cx
       call proc_deallocate_memory
       pop cx
       push ds
       pop es 
      ;xor di, di
       mov word ptr [SI]+OFL_Handle, di
pass_closefile_3:
       add si, OFL_EntrySize
       loop loc_close_file3

       mov si, offset Open_Files_List
       xor ax, ax
       mov cl, 32
loc_closefile_reset_OFL_entry:      
       cmp byte ptr [SI]+OFL_Drive, 0FFh
       jne short pass_closefile_reset_OFL_entry
       push cx 
       mov cx, 4
       mov di, si
       rep stosw
       pop cx 
pass_closefile_reset_OFL_entry:
       add si, OFL_EntrySize
       loop loc_closefile_reset_OFL_entry

       mov si, offset Open_Files_List
       xor di, di
       pop bx 
       pop ax ; pushed ES, PSP/OFDT segment
       pop es ; pushed DS

       retn

proc_close_file endp


proc_check_filename proc near
               ; 10/07/2010
               ; Derivation from proc_check_filename
               ; in the old TRDOS.ASM 09/02/2005
               ;
               ; INPUT -> DS:SI = Dot File Name Location
               ; OUTPUT -> stc -> error code in AL
               ;           AL= 0Bh -> Invalid file name   
               ; OUTPUT -> clc -> valid file name
               ; 10/07/2010
               ; AX, CX, SI, DI will be changed
               ; (BX, DX, ES will not be changed)
               ;  
                call proc_check_invalid_filename_chars
                jc short loc_check_fn_stc_rtn

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_check_invalid_filename_chars proc near
               ; 10/07/2010
               ; Derivation from proc_check_invalid_filename_chars
               ; in the old TRDOS.ASM 09/02/2005

                ; INPUT: DS:SI = ASCIIZ FileName 
                ; OUTPUT:
                ; stc -> Invalid
                ; clc -> Valid
                ; 10/02/2010
                ; AX, CX, DI will be changed

                push es
                push ds
                pop es
                push si
                mov di, offset invalid_fname_chars
                mov al, byte ptr [SI]
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]
               ;10/07/2010
                cmp al, 1Fh  ; 20h and above 
                ja check_filename_next_char
                xor ah, ah 
loc_check_invalid_filename_retn:
                pop si
                pop es
                retn
loc_invalid_filename:
              ; 10/07/2010
                mov ax, 0Bh ; Invalid format
                            ; Invalid file name chars
                stc
                jmp short loc_check_invalid_filename_retn

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


Open_Files_List: db 256 dup(0)

