%TITLE          "Atari 8bit Directory Lister with path - CHiPS bv 1997"
;**********************************************************************
;**                                                                  **
;**  Program   : XdirList                                            **
;**  Purpose   : Atari 8bit Directory Lister with path               **
;**                                                                  **
;**  Author    : B.F. Schreurs                                       **
;**              Computer High Performance Software (CHiPS) bv       **
;**  Date      : October 29th, 1997                                  **
;**                                                                  **
;**  Calls     : DC_DIRS  - Determine Current Directories            **
;**              DC_FILES - Determine Current Files                  **
;**              TO_UPPER - Convert string to UpperCase              **
;**                                                                  **
;**  Language  : Turbo Assembler                                     **
;**                                                                  **
;**********************************************************************
        IDEAL
        JUMPS

;----------------------------------------------------------------------
;--  Equates                                                         --
;----------------------------------------------------------------------
include ".\equ\at_drive.equ"
include ".\equ\dos.equ"
include ".\equ\sysdep.equ"

EIGHTBIT_FILE_NAME_LENGTH   EQU     11

;**********************************************************************
SEGMENT SSeg Para Stack 'STACK'
;**********************************************************************

        db       128 dup (0)            ; Stack

ENDS    SSeg

;**********************************************************************
SEGMENT DSeg Word Public 'DATA'
;**********************************************************************

;----------------------------------------------------------------------
;--  Structures                                                      --
;----------------------------------------------------------------------
include ".\str\direntry.str"
include ".\str\psp.str"

Struc   Loc_Entry                       ; Output record Layout
  File_Name             DB  12  dup (SPACE)
  Filler_1              DB   1  dup (SPACE)
  File_Size             DB   4  dup (SPACE)
  Filler_2              DB   1  dup (SPACE)
  File_Lck              DB   3  dup (SPACE)
  Filler_3              DB   1  dup (SPACE)
  File_Ext              DB   3  dup (SPACE)
  Filler_4              DB   1  dup (SPACE)
  File_Del              DB   3  dup (SPACE)
  Filler_5              DB   1  dup (SPACE)
  File_Path             DB   PATH_LENGTH  dup (SPACE)
ends                                    ; Locator_Entry

;----------------------------------------------------------------------
;--  Working Storage                                                 --
;----------------------------------------------------------------------
Dir_Map_Length       = ( MAX_DIRS * DIR_ENTRY_LENGTH )
File_Map_Length      = ( MAX_FILES * FILE_ENTRY_LENGTH )
Work_Dir_Map_Length  = ( MAX_DIRS * PATH_LENGTH)
Locator_Entry_Length = ( 30 + PATH_LENGTH )

GLOBAL Dir_Map:Byte:Dir_Map_Length
GLOBAL File_Map:Byte:File_Map_Length
GLOBAL Path_Spec:Byte:PATH_LENGTH
GLOBAL Return_Code:Byte:1

Work_Dir_Map            DB   Work_Dir_Map_Length dup (SPACE)
Path_Spec               DB   PATH_LENGTH dup (SPACE)
Input_Spec              DB   PATH_LENGTH dup (SPACE)
Return_Code             DB    0

Locator_File_Opened     DB    1 dup (FALSE)
Locator_File_Spec       DB   "C:\LOCATOR.TXT"
                        DB    1 dup (0)

File_Map_Entry          Dir_Entry <>
Locator_Entry           Loc_Entry <>

Search_Spec             DB   PATH_LENGTH dup (NULL)
                        DB    1 dup (0)

File_Mask               DB   "*.*         "
Dir_Mask                DB   "*.*         "

Dirs_To_Process         DB      0

Input_File              DW      0
Output_File             DW      0

Disk_I_O_Buffer         DB  DISK_BLOCK_SIZE dup (NULL)

ATR_Header_Single       DB   96h,02h,80h,16h,80h,00h,00h,00h
ATR_Header_Medium       DB   96h,02h,80h,20h,80h,00h,00h,00h
ATR_Header_Enhanced     DB   96h,02h,00h,23h,80h,00h,00h,00h
ATR_Header_Double       DB   96h,02h,00h,2Dh,80h,00h,00h,00h


Output_Header_1         DB   "Atari File   Size Lck Ext Del Pc Path"
Output_Space            DB   Locator_Entry_Length dup (SPACE)
Output_Header_2         DB   "------------ ---- --- --- --- -------"
Output_Underline        DB   Locator_Entry_Length dup (UNDERLINE)
Output_Yes              DB   "Yes"
Output_No               DB   "No "
Output_File_Size        DB   "    "
Output_Return_Linefeed  DB   CR, LF

Msg_Listing             DB      CR, LF, "XDIRLIST version 01.00.00 by B.F. Schreurs, CHiPS bv, November 1997"
                        DB      CR, LF, "Atari 8 bit ATR/XFD Image Directory Lister."
                        DB      CR, LF
                        DB      CR, LF
                        DB      CR, LF, "Directory Listing now in progress..."
                        DB      NULL
Msg_Processing          DB      CR, LF, "Processing "
                        DB      NULL
Msg_Listing_Completed   DB      CR, LF
                        DB      CR, LF
                        DB      CR, LF, "Directory Listing completed."
                        DB      NULL
Msg_Look                DB      CR, LF, "Look at the C:\LOCATOR.TXT file to view the results."
                        DB      NULL
Msg_No_Look             DB      CR, LF, "No Atari 8 bit Disk Image found!"
                        DB      NULL
Msg_Thank_You           DB      CR, LF, "Thank you for using XDIRLIST!"
                        DB      CR, LF, NULL

ENDS    DSeg

;**********************************************************************
;               Extended Segments
;**********************************************************************
SEGMENT DSeg1 Word Public 'LIBFILES'
Dir_Map                 DB   DIR_MAP_LENGTH dup ("D")

ENDS    DSeg1

;**********************************************************************
;               Extended Segments
;**********************************************************************
SEGMENT DSeg2 Word Public 'LIBFILES'
File_Map                 DB   FILE_MAP_LENGTH dup ("F")

ENDS    DSeg2

;**********************************************************************
SEGMENT CSeg Word Public 'CODE'
;**********************************************************************
;----------------------------------------------------------------------
;--  External Variables                                              --
;----------------------------------------------------------------------
        EXTRN   DC_DIRS:proc
        EXTRN   DC_FILES:proc
        EXTRN   TO_UPPER:proc



;**********************************************************************
Main:   
;**********************************************************************
        ASSUME  cs:CSeg
        ASSUME  ds:DSeg
        mov     ax, DSeg                    ; Initialize DS to address
        mov     ds, ax                      ; of data segment

        call    Check_Command_Line_Syntax
        call    Show_Msg_Listing
        call    Init_Program
        call    Process_Dirs_Files
        call    Show_Msg_Thank_You
        call    Exit_Program



;**********************************************************************
PROC    Check_Command_Line_Syntax
;**********************************************************************
; Check Command Line
        xor     cx, cx                      ; Clear cx
        mov     cl, [es:Psp.LengthByte]     ; Check if command line is empty
        cmp     cl, 0                       ; Parameter specified?
        je      @@50                        ; No
                                            ; Yes, so
; Copy Command Line To File Specification Buffer
        push    ds es
        push    es

        dec     cx
        mov     dx, cx                      ; Save Length
        mov     si, offset Search_Spec
        push    ds si
        pop     di es
        mov     si, Offset (es:Psp).CommandTail  ; Position to command line
        inc     si                          ; but skip space character

        pop     ds
        cld
        rep     movsb                       ; Copy Command_Tail
        pop     es ds

; Determine specified search file mask
        mov     si, offset Search_Spec
        push    ds si
        pop     di es
        mov     cx, dx                      ; Search length
        add     di, cx                      ; Go to end of path
        inc     cx
        inc     cx
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search uses es:di
        cld                                 ; Cancel the std setting


        mov     si, offset File_Mask
        push    ds si
        pop     di es
        mov     si, offset Search_Spec
        add     si, cx

        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy path to search path

@@10:
; Check input for "*."
        mov     si, offset Search_Spec
        cmp     [byte ds:si], ASTERISK
        jne     @@20
        cmp     [byte ds:si + 1], DOT
        je      @@50

@@20:
; Check input for ".\"
        mov     si, offset Search_Spec
        cmp     [byte ds:si], DOT
        jne     @@30
        cmp     [byte ds:si + 1], BACKSLASH
        jne     @@30

        mov     di, offset Input_Spec
        mov     cx, PATH_LENGTH
        rep     movsb

; Get current drive and directory
        mov     si, offset Search_Spec

; Get default drive
        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_GET_DEFAULT_DRIVE   ; Get Default Drive
        int     DOS_SERVICE 
        add     al, 041h                    ; Because of 0-based stuff

; Process Drive
        mov     [byte ds:si], al            ; Process Drive letter
        inc     si
        mov     [byte ds:si], COLON
        inc     si
        mov     [byte ds:si], BACKSLASH
        inc     si

; Get current directory
        push    dx

        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_GET_CURRENT_DIRECTORY
        xor     dx, dx                      ; Reset dx
        mov     dl, DOS_DEFAULT_DRIVE
        int     DOS_SERVICE

        pop     dx

; Add "\" character to end of current directory?
        mov     si, offset Search_Spec
        push    ds si
        pop     di es
        mov     cx, PATH_LENGTH             ; Search length
        xor     ax, ax                      ; Search for null character
        repne   scasb                       ; Search uses es:di
        dec     di                          ; Pointer adjustment after search
        cmp     [byte es:di - 1], BACKSLASH ; Is there a "\" already?
        je      @@25                        ; Yes
                                            ; No, so
; Add "\" character to end of current directory
        mov     [byte es:di], BACKSLASH
        inc     di

@@25:
        mov     si, offset Input_Spec
        inc     si
        inc     si
        mov     cx, dx
        rep     movsb

        jmp     @@99

@@30:
; Check input for ":\"
        mov     si, offset Search_Spec
        cmp     [byte ds:si + 1], COLON
        jne     @@50

        cmp     [byte ds:si + 2], BACKSLASH
        je      @@99

@@50:
; No parameters specified
        mov     si, offset Search_Spec

; Get default drive
        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_GET_DEFAULT_DRIVE   ; Get Default Drive
        int     DOS_SERVICE 
        add     al, 041h                    ; Because of 0-based stuff

; Process Drive
        mov     [byte ds:si], al            ; Process Drive letter
        inc     si
        mov     [byte ds:si], COLON
        inc     si
        mov     [byte ds:si], BACKSLASH
        inc     si

; Get current directory
        xor     ax, ax                      ; Reset ax
        mov     ah, DOS_GET_CURRENT_DIRECTORY
        xor     dx, dx                      ; Reset dx
        mov     dl, DOS_DEFAULT_DRIVE
        int     DOS_SERVICE

; Add "\" character to end of current directory?
        mov     si, offset Search_Spec
        push    ds si
        pop     di es
        mov     cx, PATH_LENGTH             ; Search length
        xor     ax, ax                      ; Search for null character
        repne   scasb                       ; Search uses es:di
        dec     di                          ; Pointer adjustment after search
        cmp     [byte es:di - 1], BACKSLASH ; Is there a "\" already?
        je      @@99                        ; Yes
                                            ; No, so
; Add "\" character to end of current directory
        mov     [byte es:di], BACKSLASH

@@99:
        ret

ENDP    Check_Command_Line_Syntax



;**********************************************************************
PROC    Show_Msg_Listing
;**********************************************************************
        mov     si, offset Msg_Listing
        push    ds si
        pop     di es
        call    Display_String

        ret

ENDP    Show_Msg_Listing



;**********************************************************************
PROC    Init_Program
;**********************************************************************
; Init Directory Map
        mov     si, offset Work_Dir_Map
        push    ds si
        pop     di es
        xor     ax, ax                      ; Reset table
        mov     cx, Work_Dir_Map_Length     ; Nr of Bytes in Dir Table
        rep     stosb

;
; Set up search path
;
        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset Search_Spec
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        call    Setup_Path_Spec_Dir

;
; Determine Current Directories
;
        call    DC_DIRS

;
; Process found directories
;
        mov     si, offset Work_Dir_Map
        push    ds si
        pop     di es

        call    Process_Pc_Dirs

        ret

ENDP    Init_Program



;**********************************************************************
PROC    Process_Dirs_Files
;**********************************************************************
@@00:
;
; Process Files in Dir
;
;
; Set up search path
;
        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset Search_Spec
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        call    Setup_Path_Spec_File

;
; Show which directory we are processing
;
        mov     si, offset Msg_Processing
        push    ds si
        pop     di es
        call    Display_String
        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        call    Display_String

;
; Determine Current Files
;
        call    DC_FILES

        call    Process_Pc_Files

@@10:
        cmp     [Dirs_To_Process], 0        ; Are there dirs to process?
        je      @@99                        ; No
                                            ; Yes, so
;
; Process last subdir
;
        dec     [Dirs_To_Process]

;
; Set up search path
;
        xor     cx, cx                      ; Reset cx
        mov     cl, [Dirs_To_Process]
        xor     ax, ax                      ; Reset ax
        mov     al, PATH_LENGTH
        mul     cx                          ; Calculate correct entry

        mov     di, offset Search_Spec
        mov     si, offset Work_Dir_Map
        add     si, ax                      ; Correct entry reached

        push    ds si

        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        mov     di, offset Path_Spec
        mov     si, offset Search_Spec
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        call    Setup_Path_Spec_Dir

;
; Determine Current Directories
;
        call    DC_DIRS

        pop     di es

        call    Process_Pc_Dirs

        jmp     @@00

@@99:
        ret

ENDP    Process_Dirs_Files



;**********************************************************************
PROC    Process_Pc_Dirs
;**********************************************************************
        mov     si, offset Dir_Map

@@10:
;
; Check if we have to process a found directory
;
        cmp     [byte ds:si], NULL          ; Something to process?
        je      @@99                        ; No
                                            ; Yes,so
;
; Determine specified search file mask
;
        push    es di                       ; Save Work_Dir_Map pointer
        push    ds si                       ; Save      Dir_Map pointer
        push    es di                       ; Another copy of Work_Dir_Map

        mov     si, offset Search_Spec
        push    ds si
        pop     di es
        mov     cx, PATH_LENGTH             ; Search length
        dec     cx                          ; Because of null terminator
        add     di, cx                      ; Go to end of path
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search uses es:di
        cld                                 ; Cancel the std setting
        inc     cx                          ; Pointer adjustment after search
        inc     cx                          ; Include the "\" character

        pop     di es                       ; Restore Work_Dir_Map pointer

        mov     si, offset Search_Spec
        rep     movsb                       ; Copy search spec to work map


; Add directory name to search spec
        pop     si ds
        push    ds si

        mov     cx, DIR_NAME_LENGTH
        rep     movsb

; Search the null terminator
        mov     cx, DIR_NAME_LENGTH         ; Search length
        sub     di, cx
        xor     ax, ax                      ; Search for null character
        repne   scasb                       ; Search uses es:di
        dec     di                          ; Pointer adjustment after search

; Add the "\" character to search spec
        mov     [byte es:di], BACKSLASH

; Increase number of directories to process
        inc     [Dirs_To_Process]

; Go to next entry
        pop     si ds di es

        add     si, DIR_ENTRY_LENGTH
        add     di, PATH_LENGTH

        jmp     @@10

@@99:
        ret

ENDP    Process_Pc_Dirs



;**********************************************************************
PROC    Process_Pc_Files
;**********************************************************************
        mov     si, offset File_Map

@@10:
;
; Check if we have to process a found file
;
        cmp     [byte ds:si], NULL          ; Something to process?
        je      @@99                        ; No

        push    ds si                       ; Save File_Map pointer

;
; Copy Entry
;
        mov     si, offset File_Map_Entry
        push    ds si
        pop     di es

        pop     si ds
        push    ds si

        mov     cx, FILE_ENTRY_LENGTH
        rep     movsb

;
; Determine specified search file mask
;
        mov     di, offset Path_Spec
        mov     cx, PATH_LENGTH             ; Search length
        dec     cx                          ; Because of null terminator
        add     di, cx                      ; Go to end of path
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search
        inc     di                          ; Skip the "\" character

; Add FileName to Path Spec
        mov     si, offset File_Map_Entry.File_Name
        mov     cx, FILE_NAME_LENGTH
        rep     movsb
        mov     [byte es:di], NULL

;
; Is this an Atari 8bit Disk Image File?
;
        call    Process_Atari_8bit_Image

;
; Go to next entry
;
        pop     si ds
        add     si, FILE_ENTRY_LENGTH

        jmp     @@10

@@99:
        ret

ENDP    Process_Pc_Files



;**********************************************************************
PROC    Process_Atari_8bit_Image
;**********************************************************************
; Check for valid 8bit image disk here
; Check file size
;                       ahal bhbl
; File Size Single   -> 0001:6800 for .XFD and 0001:6810 for .ATR
; File Size Medium   -> 0002:0800 for .XFD and 0002:0810 for .ATR
; File Size Enhanced -> 0002:3000 for .XFD and 0002:3010 for .ATR
; File Size Double   -> 0002:D000 for .XFD and 0002:D010 for .ATR
@@30:
        mov     si, offset File_Map_Entry.File_Size
        mov     bx, [ds:si]
        mov     ax, [ds:si + 2]
        cmp     ah, 000h                ; 00xx:xxxx?
        jne     @@99                    ; No
                                        ; Yes
        cmp     bl, 000h                ; xxxx:xx00?
        je      @@31                    ; Yes
                                        ; No, so
        cmp     bl, 010h                ; xxxx:xx10?
        jne     @@99                    ; No, incorrect disk size
                                        ; Yes
; Check Single
@@31:
        cmp     bh, 068h                ; xxxx:68xx?
        jne     @@32                    ; No
                                        ; Yes, so
        cmp     al, 001h                ; xx01:xxxx?
        je      @@40                    ; Yes
                                        ; No, so
; Check Medium
@@32:
        cmp     bh, 008h                ; xxxx:08xx?
        jne     @@33                    ; No
                                        ; Yes, so
        cmp     al, 002h                ; xx02:xxxx?
        je      @@40                    ; Yes
                                        ; No, so
; Check Enhanced
@@33:
        cmp     bh, 030h                ; xxxx:30xx?
        jne     @@34                    ; No
                                        ; Yes, so
        cmp     al, 002h                ; xx02:xxxx?
        je      @@40                    ; Yes
                                        ; No, so
; Check Double
@@34:
        cmp     bh, 0D0h                ; xxxx:D0xx?
        jne     @@99                    ; No
                                        ; Yes, so
        cmp     al, 002h                ; xx02:xxxx?
        jne     @@99                    ; No
                                        ; Yes, so
@@40:
; Open file
        mov     dx, offset Path_Spec
        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_ONLY
        int     DOS_SERVICE
        jc      @@99                    ; Open ERROR!

        mov     [Input_File], ax        ; Load handle

        cmp     bl, 000h                ; xxxx:xx00?
        je      @@50                    ; Yes, .XFD file
                                        ; No, so
; Read file header
        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [Input_File]
        mov     cx, ATR_HEADER_SIZE     ; Header size
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE             ; Read header
        jc      @@80                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@80                    ; Yes
                                        ; No, so
; Check file header single
        mov     si, offset ATR_Header_Single
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Single?
        je      @@50                    ; Yes
                                        ; No, so
; Check file header medium
        mov     si, offset ATR_Header_Medium
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Medium?
        je      @@50                    ; Yes
                                        ; No, so
; Check file header enhanced
        mov     si, offset ATR_Header_Enhanced
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Enhanced?
        je      @@50                    ; Yes,
                                        ; No, so
; Check file header double
        mov     si, offset ATR_Header_Double
        push    ds si
        pop     di es
        mov     si, offset Disk_I_O_Buffer
        mov     cx, ATR_HEADER_SIZE_COMPARE
        rep     cmpsb                   ; Header is .ATR Double?
        je      @@50                    ; Yes
                                        ; No, so

        jmp     @@80

@@50:
; Move to 8bit vtoc location (offset B400h, 8 sectors wide)
        mov     ah, DOS_MOVE_FILE_POINTER
        mov     al, DOS_MOVE_FILE_POINTER_CURR
        mov     bx, [Input_File]
        xor     cx, cx                  ; Reset Offset cx:dx
        mov     dx, EIGHTBIT_VTOC_OFFSET
        int     DOS_SERVICE             ; Position in dx:ax

; Read 8bit vtoc
        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [Input_File]
        mov     cx, EIGHTBIT_VTOC_SIZE  ; Sector size
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE             ; Read header
        jc      @@80                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@80                    ; Yes

@@54:
;
; Create locator file, if not done already
;
        cmp     [Locator_File_Opened], TRUE
        je      @@56

;
; Create Locator File
;
; Open output file
        mov     dx, offset Locator_File_Spec
        xor     cx, cx                  ; Normal attributes
        mov     ah, DOS_CREATE_FILE
        int     DOS_SERVICE
        jc      @@80                    ; Skip processing on error
        mov     [Output_File], ax       ; Store handle

        mov     [Locator_File_Opened], TRUE

;
; Write Headers
;
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Output_File]
        mov     cx, Locator_Entry_Length
        mov     dx, offset Output_Header_1
        int     DOS_SERVICE             ; Write character(s)

        call    Write_Return_Linefeed

        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Output_File]
        mov     cx, Locator_Entry_Length
        mov     dx, offset Output_Header_2
        int     DOS_SERVICE             ; Write character(s)

        call    Write_Return_Linefeed

@@56:
;
; Process 8 bit files
;
        mov     cx, EIGHTBIT_VTOC_FILES ; Maximum nr of 8bit vtoc files
        mov     si, offset Disk_I_O_Buffer

@@58:
        push    cx ds si

;
; Init Output Line
;
        push    ds si

        mov     si, offset Locator_Entry
        push    ds si
        pop     di es
        mov     ax, SPACE
        mov     cx, Locator_Entry_Length
        rep     stosb

        pop     si ds

;
; Entry present?
;
        cmp     [byte ds:si], NULL      ; Entry present?
        je      @@78                    ; No
                                        ; Yes, so
;
; Process Atari 8 bit filename
;
        xor     ax, ax                  ; Reset ax
        mov     al, [byte ds:si]        ; File Status
        mov     bh, [byte ds:si + 2]    ; File Size hi
        mov     bl, [byte ds:si + 1]    ; File Size lo

;
; Validate Filename
;
        add     si, 5                   ; Begin of filename, i.e. MYFILE  TXT
        push    ds si
        pop     di es
        mov     cx, EIGHTBIT_FILE_NAME_LENGTH

@@59:
        cmp     [byte ds:si], " "       ; Less than or equal " "?
        jl      @@77                    ; Yes
                                        ; No, so
        cmp     [byte ds:si], "Z"       ; greater than "Z"?
        jnle    @@77                    ; Yes
                                        ; No, so
        inc     si                      ; Next byte
        loop    @@59

        push    es di

;
; Move filename
;
        mov     si, offset Locator_Entry.File_Name
        push    ds si
        pop     di es
        pop     si ds
        mov     cx, 8                   ; Size of filename
        rep     movsb                   ; Move "MYFILE" part
;
; Search for space character
;
        cmp     [byte ds:si], SPACE     ; Is there an extension
        je      @@60                    ; No
                                        ; Yes, so
        push    ds si

        push    ax
        mov     si, offset Locator_Entry.File_Name
        push    ds si
        pop     di es

        mov     cx, FILE_NAME_LENGTH    ; Size of filename
        add     di, cx                  ; Go to end of filename
        inc     cx                      ; Because of search down
        std                             ; Search direction is down
        xor     ax, ax
        mov     ax, SPACE
        repe    scasb                   ; Find the non space
        cld                             ; Reset search direction
        inc     di                      ; Adjustment after search
        inc     di                      ; Adjustment after search
        pop     ax

        pop     si ds

;
; Append extension
;
        mov     [byte es:di], DOT       ; Insert a "."
        inc     di                      ; Move to extender part
        mov     cx, 3                   ; Size of extender
        rep     movsb                   ; Move "TXT" part

@@60:
;
; Check Atari 8 bit File Status
;
;
; Atari 8 bit File deleted?
;
        mov     di, offset Locator_Entry.File_Del
        mov     si, offset Output_No
        mov     cx, 3
        rep     movsb

        push    ax
        and     al, 080h                ; Check Delete Status
        cmp     al, 080h                ; File Deleted?
        pop     ax
        jne     @@63                    ; No
                                        ; Yes , so
        mov     di, offset Locator_Entry.File_Del
        mov     si, offset Output_Yes
        mov     cx, 3
        rep     movsb

@@63:
;
; Atari 8 bit File locked?
;
        mov     di, offset Locator_Entry.File_Lck
        mov     si, offset Output_No
        mov     cx, 3
        rep     movsb

        push    ax
        and     al, 020h                ; Check Lock Status
        cmp     al, 020h                ; File Locked?
        pop     ax
        jne     @@64                    ; No
                                        ; Yes , so
        mov     di, offset Locator_Entry.File_Lck
        mov     si, offset Output_Yes
        mov     cx, 3
        rep     movsb

@@64:
;
; Atari 8 bit File extended?
;
        mov     di, offset Locator_Entry.File_Ext
        mov     si, offset Output_No
        mov     cx, 3
        rep     movsb

        and     al, 001h                ; Check Extended Status
        cmp     al, 001h                ; File Extended?
        jne     @@65                    ; No
                                        ; Yes , so
        mov     di, offset Locator_Entry.File_Ext
        mov     si, offset Output_Yes
        mov     cx, 3
        rep     movsb

@@65:
;
; Atari 8 bit File Size
;
        mov     di, offset Locator_Entry.File_Size
        add     di, 3
        mov     ax, bx                      ; File Size
        mov     bx, 10                      ; Extract digits

; Convert hexadecimal size to textual digits
        call    Extract_Digit               ; Convert value below 10000
        call    Extract_Digit
        call    Extract_Digit
        call    Extract_Digit

;
; Surpress leading zeroes
;
        mov     bx, 4

@@67:                
        inc     di                          ; Move to digital character
        cmp     [byte es:di], ZERO          ; Character is leading zero?
        jne     @@68                        ; No
                                            ; Yes, so
        mov     [byte es:di], SPACE         ; Replace leading zero by space
        dec     bx                          ; More characters to check?
        jnz     @@67                        ; Yes
                                            ; No, so
;
; We have a comment here, skip processing
;
        jmp     @@77

@@68:
;
; Uppercase Path Spec
;
        mov     di, offset Path_Spec   ; set es:di to string to be upper-ed
        push    es di
        call    TO_UPPER
        pop     di es

;
; Specify Pc Pathname
;                
        mov     di, offset Locator_Entry.File_Path
        mov     si, offset Path_Spec
        mov     cx, PATH_LENGTH
        rep     movsb

;
; Write this puppy
;        
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Output_File]
        mov     cx, Locator_Entry_Length
        mov     dx, offset Locator_Entry
        int     DOS_SERVICE             ; Write character(s)
        jc      @@80                    ; Close files on error
        or      ax, ax                  ; Disk full?
        jz      @@80                    ; Yes
                                        ; No, so
        call    Write_Return_Linefeed

@@77:
        pop     si ds cx

        add     si, EIGHTBIT_FILE_ENTRY_SIZE    ; Move to next vtoc entry
        dec     cx                      ; Complete vtoc scanned?
        jnz     @@58                    ; No
                                        ; Yes, so
        jmp     @@80

@@78:
        pop     si ds cx

@@80:
; Close file
        mov     bx, [Input_File]
        mov     al, NULL
        mov     ah, DOS_CLOSE_FILE
        int     DOS_SERVICE

@@99:
        ret

ENDP    Process_Atari_8bit_Image



;**********************************************************************
PROC    Write_Return_Linefeed
;**********************************************************************
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Output_File]
        mov     cx, 2
        mov     dx, offset Output_Return_Linefeed
        int     DOS_SERVICE             ; Write character(s)
        ret

ENDP    Write_Return_Linefeed



;**********************************************************************
PROC    Setup_Path_Spec_Dir
;**********************************************************************
        mov     di, offset Path_Spec
        mov     cx, PATH_LENGTH             ; Search length
        dec     cx                          ; Because of null terminator
        add     di, cx                      ; Go to end of path
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search
        inc     di                          ; Skip the "\" character

; Add Dir Mask to Path Spec
        mov     si, offset Dir_Mask
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy path to search path

        ret

ENDP    Setup_Path_Spec_Dir



;**********************************************************************
PROC    Setup_Path_Spec_File
;**********************************************************************
        mov     di, offset Path_Spec
        mov     cx, PATH_LENGTH             ; Search length
        dec     cx                          ; Because of null terminator
        add     di, cx                      ; Go to end of path
        std                                 ; Search direction is down
        xor     ax, ax                      ; Reset ax
        mov     al, BACKSLASH               ; Search for the "\" character
        repne   scasb                       ; Search uses es:di
        cld                                 ; Cancel the std setting
        inc     di                          ; Pointer adjustment after search
        inc     di                          ; Skip the "\" character

; Add File Mask to Path Spec
        mov     si, offset File_Mask
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy path to search path

        ret

ENDP    Setup_Path_Spec_File



;**********************************************************************
PROC    Extract_Digit
;**********************************************************************
        xor     dx, dx                      ; Reset result
        div     bx                          ; Extract digit
        add     dx, 030h                    ; Turn digit into character
        cmp     [byte es:di], DECIMAL_SEPERATOR ; Character is decimal?
        jne     @@10                        ; No
                                            ; Yes, so
        dec     di                          ; Move to previous character

@@10:
        mov     [byte es:di], dl            ; Move character to text
        dec     di                          ; Move to previous character
        ret

ENDP    Extract_Digit



;**********************************************************************
PROC    Show_Msg_Thank_You
;**********************************************************************
        mov     si, offset Msg_Listing_Completed
        push    ds si
        pop     di es
        call    Display_String

        cmp     [Locator_File_Opened], TRUE ; Locator.txt file present?
        je      @@10                        ; Yes
                                            ; No, so
        mov     si, offset Msg_No_Look
        push    ds si
        pop     di es
        call    Display_String

        jmp     @@20

@@10:
        mov     si, offset Msg_Look
        push    ds si
        pop     di es
        call    Display_String

@@20:
        mov     si, offset Msg_Thank_You
        push    ds si
        pop     di es
        call    Display_String

        ret

ENDP    Show_Msg_Thank_You



;**********************************************************************
PROC    Display_String
;**********************************************************************
@@00:
        cmp     [byte es:di], NULL      ; Check for the NULL character
        je      @@99
        mov     dl, [byte es:di]
        mov     ah,DOS_WRITE_CHARACTER
        int     DOS_SERVICE
        inc     di                      ; Point to the next character
        jmp     @@00

@@99:
        ret

ENDP    Display_String



;**********************************************************************
PROC    Exit_Program
;**********************************************************************
        mov     ah, DOS_TERMINATE_EXE
        mov     al, [Return_Code]           ; Return code value
        int     DOS_SERVICE

ENDP    Exit_Program



ENDS    CSeg                                ; End of Code segment

END     Main
