%TITLE          "Pc Directory to XL/XE .ATR Disk Image File Creator - CHiPS bv 1997"
;**********************************************************************
;**                                                                  **
;**  Program   : DIR2ATR                                             **
;**  Purpose   : Pc Directory to XL/XE .ATR Disk Image Creator       **
;**                                                                  **
;**  Author    : B.F. Schreurs                                       **
;**              Computer High Performance Software (CHiPS) bv       **
;**  Date      : November 5th, 1997                                  **
;**                                                                  **
;**  Calls     : DC_FILES - Determine Current Files                  **
;**                                                                  **
;**  Language  : Turbo Assembler                                     **
;**                                                                  **
;**  Syntax    : DIR2ATR C:\FROM C:\TO /D          (for DOS 2.5)     **
;**              DIR2ATR C:\FROM C:\TO /M          (for MYDOS 4.53)  **
;**              DIR2ATR C:\FROM C:\TO /A          Add disks at end  **
;**                                                                  **
;**********************************************************************
        IDEAL
        JUMPS

;----------------------------------------------------------------------
;--  Equates                                                         --
;----------------------------------------------------------------------
include ".\equ\sysdep.equ"
include ".\equ\dos.equ"

ATR_HEADER_SIZE             EQU     16
EIGHTBIT_VTOC_OFFSET        EQU  0B400h
EIGHTBIT_VTOC_SECTOR_BITMAP EQU    360
EIGHTBIT_VTOC_SECTOR_FILES  EQU    361
EIGHTBIT_VTOC_SECTOR_BITEXT EQU   1023
EIGHTBIT_VTOC_SECTOR_BEGIN  EQU    360
EIGHTBIT_VTOC_SECTOR_END    EQU    368
EIGHTBIT_VTOC_FILES         EQU     64
EIGHTBIT_FILE_ENTRY_SIZE    EQU     16
EIGHTBIT_FILE_NAME_LENGTH   EQU     11
EIGHTBIT_SECTOR_PHANTOM     EQU    720
EIGHTBIT_SECTOR_SIZE        EQU    128
EIGHTBIT_SECTOR_DATA_SIZE   EQU    125
EIGHTBIT_VTOC_SIZE          EQU   1024
DISK_BOOTCODE_SIZE          EQU    384
DISK_BOOTCODE_SECTOR_SIZE   EQU      3
DISK_BLOCK_SIZE             EQU   1024
DISK_SECTORS_MEDIUM         EQU   1040
DISK_SECTORS_USABLE         EQU   1009
FILE_DOS_25_DOS_SECTOR_SIZE EQU     37
FILE_DOS_25_DUP_SECTOR_SIZE EQU     42
FILE_MYDOS_DOS_SECTOR_SIZE  EQU     35
FILE_MYDOS_DUP_SECTOR_SIZE  EQU     54
DOS_25_FORMAT               EQU     "D"
MYDOS_FORMAT                EQU     "M"

;**********************************************************************
SEGMENT SSeg Para Stack 'STACK'
;**********************************************************************

        db       128 dup (0)            ; Stack

ENDS    SSeg

;**********************************************************************
SEGMENT DSeg Word Public 'DATA'
;**********************************************************************

;----------------------------------------------------------------------
;--  Structures                                                      --
;----------------------------------------------------------------------
include ".\str\dta.str"
include ".\str\direntry.str"
include ".\str\psp.str"



;----------------------------------------------------------------------
;--  Working Storage                                                 --
;----------------------------------------------------------------------
File_Map_Length      = ( MAX_FILES * FILE_ENTRY_LENGTH )

GLOBAL File_Map:Byte:File_Map_Length
GLOBAL Path_Spec:Byte:PATH_LENGTH
GLOBAL Return_Code:Byte:1

Path_Spec               DB   PATH_LENGTH dup (SPACE)
Return_Code             DB    0

File_Map_Entry          Dir_Entry <>

ATR_Header_Medium       DB   96h,02h,80h,20h,80h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
VTOC_Header_DOS_25      DB   042h,025h,000h,004h,000h
                        DB  "DOS     SYS"
                        DB   042h,02Ah,000h,029h,000h
                        DB  "DUP     SYS"
VTOC_Header_MYDOS       DB   042h,023h,000h,004h,000h
                        DB  "DOS     SYS"
                        DB   042h,036h,000h,027h,000h
                        DB  "DUP     SYS"
Disk_Name               DB  "000"
                        DB  ".ATR     "
Disk_Seq_Nr             DW    0

Passed_Parameters       DB  PATH_LENGTH dup (0)

Disk_Path               DB  PATH_LENGTH dup (0)     ; C:\TO
File_Path               DB  PATH_LENGTH dup (0)     ; C:\FROM
File_DOS_25_DOS_SYS     DB  "C:\DOS25\DOS.SYS"
                        DB  PATH_LENGTH dup (0)
File_DOS_25_DUP_SYS     DB  "C:\DOS25\DUP.SYS"
                        DB  PATH_LENGTH dup (0)
File_MYDOS_DOS_SYS      DB  "C:\MYDOS\DOS.SYS"
                        DB  PATH_LENGTH dup (0)
File_MYDOS_DUP_SYS      DB  "C:\MYDOS\DUP.SYS"
                        DB  PATH_LENGTH dup (0)
Temp_File_Name          DB  "            "
File_Name_DOS_SYS       DB  "DOS.SYS     "
File_Name_DUP_SYS       DB  "DUP.SYS     "

Disk_Mask               DB   "*.ATR       "
File_Mask               DB   "*.*         "
ATR_Disk_Image_Open     DB    1 dup (FALSE)
ATR_Disk_Image_With_DOS DB    1 dup (FALSE)
Atari_Files_Processed   DB    64
File_Size_In_Sectors    DW     0
Disk_Sector_Start       DW     4
Disk_Sector_Current     DW     4
Disk_Sector_Next        DW     5
Disk_Sectors_Left       DW  1009
Bytes_In_Sector         DB     0

Old_Dta_Seg             DW    ?                 ; Old Dta Segment Address
Old_Dta_Ofs             DW    ?                 ; Old Dta Segment Offset
Own_Dta                 Dta <>

Disk_Handler            DW      0
File_Handler            DW      0
VTOC_I_O_Buffer         DB  EIGHTBIT_VTOC_SIZE dup (0)
VTOC_I_O_Bitmap         DB  EIGHTBIT_SECTOR_SIZE dup (0)
VTOC_I_O_Bitmap_Extend  DB  EIGHTBIT_SECTOR_SIZE dup (0)
Disk_I_O_Buffer         DB  EIGHTBIT_SECTOR_SIZE dup (0)
Disk_File_ID            DB      0
Remainder_Bytes         DB      0

; Supported DOS formats: D=DOS 2.5, M=MYDOS 4.53
DOS_Format              DB  "D"

; Continue adding disks after highest disk number found? N=NO A=YES
Disk_Adding             DB  "N"

;
;   Atari Disk sector layout
;    Byte 1      Byte 125           Byte 126                 Byte 127                 Byte 128
; +----------//------------+------------------------+------------------------+------------------------+
; ³                        ³ 6 bits File ID   ³ 10 bits for Next Sector Addr ³ Byte Count per Sector  ³
; +----------//------------+------------------------+------------------------+------------------------+
;
Bootcode_MYDOS          DB   04Dh,003h,000h,007h,0E0h,007h,04Ch,014h,007h,003h,009h,001h,0E8h,01Bh,001h,004h
                        DB   000h,07Dh,00Ah,00Bh,0ACh,012h,007h,0ADh,013h,007h,020h,058h,007h,0ADh,010h,007h
                        DB   0ACh,00Fh,007h,018h,0AEh,00Eh,007h,0F0h,01Dh,020h,063h,007h,030h,018h,0ACh,011h
                        DB   007h,0B1h,043h,029h,0FFh,048h,0C8h,011h,043h,0F0h,00Eh,0B1h,043h,048h,020h,04Dh
                        DB   007h,068h,0A8h,068h,090h,0DDh,0A9h,0C0h,0A0h,068h,00Ah,0A8h,060h,0ADh,011h,007h
                        DB   018h,065h,043h,0A8h,0A5h,044h,069h,000h,084h,043h,085h,044h,08Ch,004h,003h,08Dh
                        DB   005h,003h,060h,08Dh,00Bh,003h,08Ch,00Ah,003h,0A0h,003h,0A9h,052h,090h,002h,0A9h
                        DB   050h,084h,048h,08Dh,002h,003h,018h,08Ch,006h,003h,0A9h,080h,0CAh,0F0h,00Dh,0AEh
                        DB   00Bh,003h,0D0h,007h,0AEh,00Ah,003h,0E0h,004h,090h,001h,00Ah,08Dh,008h,003h,02Ah
                        DB   08Dh,009h,003h,0A0h,031h,08Ch,000h,003h,0C6h,048h,030h,016h,0AEh,002h,003h,0E8h
                        DB   08Ah,0A2h,040h,029h,006h,0D0h,002h,0A2h,080h,08Eh,003h,003h,020h,059h,0E4h,088h
                        DB   030h,0E6h,0A6h,02Eh,0C8h,098h,060h,010h,069h,001h,000h,080h,0F6h,000h,000h,000h
                        DB   023h,028h,050h,04Dh,001h,001h,000h,000h,000h,000h,000h,000h,052h,052h,0D2h,0D2h
                        DB   0D2h,0D2h,0D2h,0D2h,05Ch,00Ch,05Ch,00Eh,062h,00Dh,0C6h,00Dh,050h,00Eh,067h,010h
                        DB   0A9h,069h,08Dh,0B8h,007h,0A9h,001h,08Dh,0B9h,007h,0A2h,008h,08Eh,001h,003h,020h
                        DB   0B6h,00Bh,0BDh,0CBh,007h,030h,012h,020h,09Ah,00Bh,0F0h,00Dh,0BDh,0CBh,007h,0C9h
                        DB   040h,0B0h,006h,0BCh,0C3h,007h,020h,024h,00Bh,0CAh,0D0h,0E0h,0A0h,0AEh,08Ah,099h
                        DB   055h,008h,088h,0D0h,0FAh,0EEh,059h,008h,0ADh,00Ch,007h,08Dh,0E7h,002h,0ACh,00Dh
                        DB   007h,0A2h,00Fh,0ECh,009h,007h,090h,005h,0DEh,0DDh,008h,030h,005h,098h,09Dh,0EDh
                        DB   008h,0C8h,0CAh,010h,0EEh,08Ch,0E8h,002h,0E8h,0E8h,0E8h,0BDh,018h,003h,0F0h,004h
                        DB   0C9h,044h,0D0h,0F4h,0A9h,044h,09Dh,018h,003h,0A9h,0D4h,09Dh,019h,003h,0A9h,007h
                        DB   09Dh,01Ah,003h,04Ch,079h,01Ah,000h,000h,0FFh,001h,000h,000h,000h,000h,000h,000h
                        DB   000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0C8h,080h
                        DB   07Dh,000h,003h,004h,000h,000h,000h,000h,000h,069h,001h,000h,000h,000h,000h,000h

Bootcode_DOS25          DB   000h,003h,000h,007h,040h,015h,04Ch,014h
                        DB   007h,003h,003h,000h,0CCh,019h,001h,004h
                        DB   000h,07Dh,0CBh,007h,0ACh,00Eh,007h,0F0h
                        DB   035h,020h,05Fh,007h,0ADh,010h,007h,0ACh
                        DB   00Fh,007h,0A6h,024h,08Eh,004h,003h,0A6h
                        DB   025h,08Eh,005h,003h,018h,020h,06Ch,007h
                        DB   030h,01Ch,0ACh,011h,007h,0B1h,024h,029h
                        DB   003h,0AAh,0C8h,011h,024h,0F0h,011h,0B1h
                        DB   024h,048h,0C8h,0B1h,024h,020h,055h,007h
                        DB   068h,0A8h,08Ah,04Ch,022h,007h,0A9h,0C0h
                        DB   00Ah,0A8h,060h,0A9h,080h,018h,065h,024h
                        DB   085h,024h,090h,002h,0E6h,025h,060h,0ADh
                        DB   012h,007h,085h,024h,0ADh,013h,007h,085h
                        DB   025h,060h,000h,000h,08Dh,00Bh,003h,08Ch
                        DB   00Ah,003h,0A9h,052h,0A0h,040h,090h,004h
                        DB   0A9h,050h,0A0h,080h,008h,0A6h,021h,0E0h
                        DB   008h,0D0h,007h,028h,020h,081h,014h,04Ch
                        DB   0B9h,007h,028h,08Dh,002h,003h,0A9h,00Fh
                        DB   08Dh,006h,003h,08Ch,017h,013h,0A9h,031h
                        DB   08Dh,000h,003h,0A9h,003h,08Dh,009h,013h
                        DB   0A9h,080h,08Dh,008h,003h,00Ah,08Dh,009h
                        DB   003h,0ADh,017h,013h,08Dh,003h,003h,020h
                        DB   059h,0E4h,010h,005h,0CEh,009h,013h,010h
                        DB   0F0h,0A6h,049h,098h,060h,020h,0ADh,011h
                        DB   020h,064h,00Fh,020h,004h,00Dh,04Ch,0C7h
                        DB   012h,000h,000h,064h,008h,08Fh,00Ah,04Dh
                        DB   00Ah,08Fh,009h,0BCh,007h,02Ah,00Bh,080h
                        DB   040h,020h,010h,008h,004h,002h,001h,0FFh
                        DB   0ADh,00Ch,007h,085h,024h,0ADh,00Dh,007h
                        DB   085h,025h,0ADh,00Ah,007h,085h,043h,0A2h
                        DB   007h,0A9h,000h,006h,043h,090h,015h,0A0h
                        DB   005h,091h,024h,0A5h,024h,09Dh,029h,013h
                        DB   0A5h,025h,09Dh,031h,013h,0A9h,090h,020h
                        DB   055h,007h,0A9h,064h,09Dh,019h,013h,0CAh
                        DB   010h,0DFh,0A5h,024h,08Dh,039h,013h,0A5h
                        DB   025h,08Dh,03Ah,013h,0ACh,009h,007h,0A2h
                        DB   000h,088h,098h,09Dh,021h,013h,030h,003h
                        DB   020h,053h,007h,0E8h,0E0h,008h,0D0h,0F1h
                        DB   0A5h,024h,08Dh,0E7h,002h,0A5h,025h,08Dh
                        DB   0E8h,002h,0A9h,000h,0A8h,099h,081h,013h
                        DB   0C8h,010h,0FAh,0A8h,0B9h,01Ah,003h,0F0h
                        DB   00Ch,0C9h,044h,0F0h,008h,0C8h,0C8h,0C8h
                        DB   0C0h,01Eh,0D0h,0F0h,000h,0A9h,044h,099h
                        DB   01Ah,003h,0A9h,0CBh,099h,01Bh,003h,0A9h
                        DB   007h,099h,01Ch,003h,060h,020h,0ADh,011h
                        DB   020h,07Dh,00Eh,0BDh,04Ah,003h,09Dh,082h
                        DB   013h,029h,002h,0F0h,003h,04Ch,072h,00Dh
                        DB   020h,0ECh,00Eh,008h,0BDh,082h,013h,0C9h
Msg_Err_No_Parameters   DB      CR, LF, "ERROR - No parameters specified!"
                        DB      CR, LF, NULL
Msg_Err_Parameter       DB      CR, LF, "ERROR - Invalid parameter specified, should be M, D or A!"
                        DB      CR, LF, NULL
Msg_Err_Parameter_Combo DB      CR, LF, "ERROR - Invalid combination of parameters (M, D or A)!"
                        DB      CR, LF, NULL
Msg_Err_Disk_Creation   DB      CR, LF, "ERROR - Disk Creation Failure!"
                        DB      CR, LF, NULL
Msg_Err_Open            DB      CR, LF, "ERROR - Opening File!"
                        DB      CR, LF, NULL
Msg_Err_Allocation      DB      CR, LF, "ERROR - Sector Allocation Failure!"
                        DB      CR, LF, NULL
Msg_Err_Positioning     DB      CR, LF, "ERROR - Sector Positioning Failure!"
                        DB      CR, LF, NULL
Msg_Err_Read            DB      CR, LF, "ERROR - Sector Read Failure!"
                        DB      CR, LF, NULL
Msg_Err_Write           DB      CR, LF, "ERROR - Sector Write Failure!"
                        DB      CR, LF, NULL
Msg_Err_ATR_Header      DB      CR, LF, "ERROR - Writing ATR Header!"
                        DB      CR, LF, NULL
Msg_Err_Bootcode        DB      CR, LF, "ERROR - Writing DOS 2.5 bootcode!"
                        DB      CR, LF, NULL
Msg_Err_VTOC            DB      CR, LF, "ERROR - Writing VTOC!"
                        DB      CR, LF, NULL
Msg_Err_VTOC_Bitmap     DB      CR, LF, "ERROR - Writing VTOC Bitmap!"
                        DB      CR, LF, NULL
Msg_Err_DOS_SYS         DB      CR, LF, "ERROR - Opening DOS.SYS file fialed or not found!"
                        DB      CR, LF, NULL
Msg_Err_DUP_SYS         DB      CR, LF, "ERROR - Opening DUP.SYS file fialed or not found!"
                        DB      CR, LF, NULL
Msg_In_Progress         DB      CR, LF, "Creation of .ATR disk images in progress..."
                        DB      CR, LF, NULL
Msg_DOS_25_In_Progress  DB      CR, LF, "Creation of .ATR disk images with DOS 2.5 format in progress..."
                        DB      CR, LF, NULL
Msg_MYDOS_In_Progress   DB      CR, LF, "Creation of .ATR disk images with MYDOS format in progress..."
                        DB      CR, LF, NULL
Msg_Creating            DB      CR, LF, "Creating Disk "
Msg_Disk                DB      "            "
                        DB      CR, LF, NULL
Msg_Formatting          DB      "Formatting Disk Image"
                        DB      CR, LF, NULL
Msg_Processing          DB      "Processing File "
Msg_File                DB      "            "
                        DB      CR, LF, NULL
Msg_VTOC                DB      "Writing VTOC"
                        DB      CR, LF, NULL
Msg_Done                DB      CR, LF, "Creation of .ATR disk images completed!"
                        DB      CR, LF, NULL

ENDS    DSeg



;**********************************************************************
SEGMENT CSeg Word Public 'CODE'
;**********************************************************************
;----------------------------------------------------------------------
;--  External Variables                                              --
;----------------------------------------------------------------------
        EXTRN   DC_FILES: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_In_Progress
        call    Init_Program
        call    Process_Atari_Files
        call    Show_Msg_Done
        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      @@90                        ; 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 Passed_Parameters
        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 "FROM" file path
        mov     si, offset Passed_Parameters
        push    ds si
        pop     di es
        mov     cx, dx                      ; Search length
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Search for the " " character
        repne   scasb                       ; Search uses es:di
        mov     bx, dx
        sub     bx, cx                      ; Space location    
        mov     cx, bx
        dec     cx                          ; Don't include the space

        push    es di                       ; Save location of "TO" path

; "FROM" file path
        mov     si, offset File_Path
        push    ds si
        pop     di es
        mov     si, offset Passed_Parameters
        rep     movsb                       ; "FROM" path determined

; Determine specified "TO" disk path
        pop     di es
        push    es di
        mov     cx, dx                      ; Search length
        xor     ax, ax                      ; Reset ax
        mov     al, SPACE                   ; Search for the " " character
        repne   scasb                       ; Search uses es:di
        mov     bx, dx
        sub     bx, cx                      ; Space location    
        mov     cx, bx
        dec     cx                          ; Don't include the space

; "TO" disk path
        mov     si, offset Disk_Path
        push    ds si
        pop     di es
        pop     si ds
        rep     movsb                       ; "TO" path determined

; Determine if DOS should be included
        mov     [DOS_Format], SPACE
        mov     [Disk_Adding], "N"

        mov     [ATR_Disk_Image_With_DOS], FALSE
        mov     si, offset Passed_Parameters
        push    ds si
        pop     di es
        mov     cx, dx                      ; Search length
        xor     ax, ax                      ; Reset ax
        mov     al, SLASH                   ; Search for the "/" character
        repne   scasb                       ; Search uses es:di
        cmp     cx, 0                       ; "/" found?
        je      @@99                        ; No
                                            ; Yes, so
        cmp     [byte es:di], "D"           ; Include DOS?
        je      @@10                        ; Yes
                                            ; Not yet, so
        cmp     [byte es:di], "d"           ; Include DOS?
        je      @@10                        ; Yes
                                            ; Not yet, so
        cmp     [byte es:di], "M"           ; Include DOS?
        je      @@15                        ; Yes
                                            ; Not yet, so
        cmp     [byte es:di], "m"           ; Include DOS?
        je      @@15                        ; Yes
                                            ; No, so
        cmp     [byte es:di], "A"           ; Continue adding disks?
        je      @@20                        ; Yes
                                            ; No, so
        cmp     [byte es:di], "a"           ; Continue adding disks?
        je      @@20                        ; Yes
                                            ; No, so
        mov     si, offset Msg_Err_Parameter
        jmp     @@98

@@10:
        mov     [DOS_Format], "D"
        mov     [ATR_Disk_Image_With_DOS], TRUE
        jmp     @@30

@@15:
        mov     [DOS_Format], "M"
        mov     [ATR_Disk_Image_With_DOS], TRUE
        jmp     @@30

@@20:
        mov     [Disk_Adding], "A"
        
@@30:
        mov     si, offset Passed_Parameters
        push    ds si
        pop     di es
        mov     cx, dx                      ; Search length
        xor     ax, ax                      ; Reset ax
        mov     al, SLASH                   ; Search for the "/" character
        repne   scasb                       ; Search uses es:di
        repne   scasb                       ; Search the second "/" character
        cmp     cx, 0                       ; "/" found?
        je      @@99                        ; No
                                            ; Yes, so
        cmp     [byte es:di], "D"           ; Include DOS?
        je      @@40                        ; Yes
                                            ; Not yet, so
        cmp     [byte es:di], "d"           ; Include DOS?
        je      @@40                        ; Yes
                                            ; Not yet, so
        cmp     [byte es:di], "M"           ; Include DOS?
        je      @@45                        ; Yes
                                            ; Not yet, so
        cmp     [byte es:di], "m"           ; Include DOS?
        je      @@45                        ; Yes
                                            ; No, so
        cmp     [byte es:di], "A"           ; Continue adding disks?
        je      @@50                        ; Yes
                                            ; No, so
        cmp     [byte es:di], "a"           ; Continue adding disks?
        je      @@50                        ; Yes
                                            ; No, so
        mov     si, offset Msg_Err_Parameter
        jmp     @@98

@@40:
        cmp     [DOS_Format], SPACE
        je      @@41
        mov     si, offset Msg_Err_Parameter_Combo
        jmp     @@98

@@41:
        mov     [DOS_Format], "D"
        mov     [ATR_Disk_Image_With_DOS], TRUE
        jmp     @@99

@@45:
        cmp     [DOS_Format], SPACE
        je      @@46
        mov     si, offset Msg_Err_Parameter_Combo
        jmp     @@98

@@46:
        mov     [DOS_Format], "M"
        mov     [ATR_Disk_Image_With_DOS], TRUE
        jmp     @@99

@@50:
        cmp     [Disk_Adding], "N"
        je      @@51
        mov     si, offset Msg_Err_Parameter_Combo
        jmp     @@98

@@51:
        mov     [Disk_Adding], "A"
        jmp     @@99

@@90:
; No parameters specified
        mov     si, offset Msg_Err_No_Parameters

@@98:
        push    ds si
        pop     di es
        call    Display_String
        call    Exit_Program

@@99:
        ret

ENDP    Check_Command_Line_Syntax



;**********************************************************************
PROC    Show_Msg_In_Progress
;**********************************************************************
        mov     si, offset Msg_DOS_25_In_Progress
        cmp     [DOS_Format], DOS_25_FORMAT
        je      @@98
        mov     si, offset Msg_MYDOS_In_Progress
        cmp     [DOS_Format], MYDOS_FORMAT
        je      @@98
        mov     si, offset Msg_In_Progress

@@98:
        push    ds si
        pop     di es
        call    Display_String

@@99:
        ret

ENDP    Show_Msg_In_Progress



;**********************************************************************
PROC    Init_Program
;**********************************************************************
;
; Set VTOC bitmaps to high values
;
        mov     si, offset VTOC_I_O_Bitmap
        push    ds si
        pop     di es
        xor     ax, ax
        mov     al, HIGH_VALUES
        mov     cx, EIGHTBIT_SECTOR_SIZE
        rep     stosb

        mov     si, offset VTOC_I_O_Bitmap_Extend
        push    ds si
        pop     di es
        xor     ax, ax
        mov     al, HIGH_VALUES
        mov     cx, EIGHTBIT_SECTOR_SIZE
        rep     stosb

;
; Continue adding disks after highest disk number found?
;
        cmp     [Disk_Adding], "N"              ; Continue adding disks?
        je      @@30                            ; No
                                                ; Yes, so
;
; Determine disk name to start with
;
        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset Disk_Path
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        mov     di, offset Path_Spec
        mov     cx, PATH_LENGTH             ; Search length
        xor     ax, ax                      ; Search for the null character
        repne   scasb                       ; Search uses es:di

; Add "\" character
        mov     [byte es:di - 1], BACKSLASH

; Add Disk Mask
        mov     si, offset Disk_Mask
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy path to search path

;
; Determine Current Disks
;
        call    DC_FILES

;
; Retrieve highest disks, if any
;
        mov     si, offset File_Map
        mov     cx, 999                     ; Maximum nr of disks

@@10:
        cmp     [byte ds:si], NULL          ; More files?
        je      @@30                        ; No
                                            ; Yes, so
;
; Check for valid disk name
;
        cmp     [byte ds:si], "0"
        jl      @@20
        cmp     [byte ds:si], "9"
        jnle    @@20
        cmp     [byte ds:si + 1], "0"
        jl      @@20
        cmp     [byte ds:si + 1], "9"
        jnle    @@20
        cmp     [byte ds:si + 2], "0"
        jl      @@20
        cmp     [byte ds:si + 2], "9"
        jnle    @@20
        cmp     [byte ds:si + 3], DOT
        jne     @@20

        xor     ax, ax
        xor     bx, bx
        xor     dx, dx
        mov     bl, [byte ds:si + 2]
        sub     bl, ZERO
        mov     al, [byte ds:si + 1]
        sub     al, ZERO
        mov     cx, 10
        mul     cx
        add     bx, ax
        xor     ax, ax
        mov     al, [byte ds:si]
        sub     al, ZERO
        mov     cx, 100
        mul     cx
        add     bx, ax
        cmp     bx, [Disk_Seq_Nr]
        jle     @@20
        
        mov     [Disk_Seq_Nr], bx

@@20:
        add     si, FILE_ENTRY_LENGTH
        loop    @@10

@@30:
;
; Set up search path
;
        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset File_Path
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        call    Setup_Path_Spec_Dir_Files

;
; Determine Current Files
;
        call    DC_FILES

@@99:
        ret

ENDP    Init_Program



;**********************************************************************
PROC    Process_Atari_Files
;**********************************************************************
        mov     si, offset File_Map

        cmp     [byte ds:si], NULL          ; Anything to process at all?
        je      @@90                        ; No
                                            ; Yes, so
@@10:
;
; Check if we have to process a found file
;
        cmp     [byte ds:si], NULL          ; Something left 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 File Size in Sectors
;
        mov     [Remainder_Bytes], EIGHTBIT_SECTOR_SIZE
        xor     bx, bx
        mov     bx, EIGHTBIT_SECTOR_DATA_SIZE
        mov     si, offset File_Map_Entry.File_Size
        mov     dh, [byte ds:si + 3]
        mov     dl, [byte ds:si + 2]
        mov     ah, [byte ds:si + 1]
        mov     al, [byte ds:si]
        div     bx
        cmp     dx, NULL                    ; No remainder?
        jz      @@15                        ; No
                                            ; Yes, so
        inc     ax                          ; We need another sector
        mov     [Remainder_Bytes], dl       ; Save remainder

@@15:
        mov     [File_Size_In_Sectors], ax

;
; File Size in sectors > remaining nr of sectors left?
;
        cmp     ax, [Disk_Sectors_Left]
        jnle    @@20

;
; Nr of files processed > nr of files in 8bit vtoc?
;
        cmp     [byte Atari_Files_Processed], EIGHTBIT_VTOC_FILES
        jl      @@30

@@20:
        call    Process_Write_8bit_VTOC
        call    Process_Close_ATR_Image_Disk
        call    Process_Open_ATR_Image_Disk

@@30:
;
; Process 8 bit File
;
        call    Process_Open_8bit_File
        call    Process_Move_File_To_Image
        call    Process_Close_8bit_File
        call    Process_Update_8bit_VTOC
        inc     [Atari_Files_Processed]

;
; Go to next entry
;
        pop     si ds
        add     si, FILE_ENTRY_LENGTH

        jmp     @@10

@@90:
; No Files to process
        call    Process_Open_ATR_Image_Disk

@@99:
        call    Process_Write_8bit_VTOC
        call    Process_Close_ATR_Image_Disk

        ret

ENDP    Process_Atari_Files



;**********************************************************************
PROC    Process_Open_ATR_Image_Disk
;**********************************************************************
        mov     [Atari_Files_Processed], 0
        mov     [Disk_Sector_Current], 4
        mov     [Disk_Sectors_Left], DISK_SECTORS_USABLE
        mov     [ATR_Disk_Image_Open], FALSE
        inc     [Disk_Seq_Nr]

;
; Determine Diskname
;
        mov     di, offset Disk_Name
        add     di, 2
        mov     ax, [Disk_Seq_Nr]
        mov     bx, 10                      ; Extract digits

; Convert hexadecimal size to textual digits
        call    Extract_Digit               ; Convert value below 10000
        call    Extract_Digit
        call    Extract_Digit

;
; Show what which disk we're creating
;
        mov     si, offset Msg_Disk
        push    ds si
        pop     di es
        mov     si, offset Disk_Name
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

        mov     si, offset Msg_Disk
        mov     cx, FILE_NAME_LENGTH

@@05:
        cmp     [byte ds:si], NULL
        jne     @@06
        mov     [byte ds:si], SPACE

@@06:
        inc     si
        loop    @@05

        mov     si, offset Msg_Creating
        push    ds si
        pop     di es
        call    Display_String

        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset Disk_Path
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        call    Setup_Path_Spec_Disk

;
; Create ATR Disk Image
;
        mov     dx, offset Path_Spec
        xor     cx, cx                  ; Normal attributes
        mov     ah, DOS_CREATE_FILE
        int     DOS_SERVICE
        jc      @@90                    ; Error
        mov     [Disk_Handler], ax      ; Store handle

;
; Reset I/O buffer
;
        mov     si, offset Disk_I_O_Buffer
        push    ds si
        pop     di es
        xor     ax, ax
        mov     cx, EIGHTBIT_SECTOR_SIZE
        rep     stosb

;
; Message "Formatting Disk"
;
        mov     si, offset Msg_Formatting
        push    ds si
        pop     di es
        call    Display_String

;
; "Format" ATR Disk Image
;
        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, ATR_HEADER_SIZE
        mov     dx, offset ATR_Header_Medium
        int     DOS_SERVICE             ; Write ATR header
        jc      @@91                    ; Error
        or      ax, ax                  ; Disk full?
        jz      @@91                    ; Error

;
; Number of sectors to format
;
        mov     cx, DISK_SECTORS_MEDIUM

;
; Include DOS?
;
        cmp     [ATR_Disk_Image_With_DOS], FALSE
        je      @@10                    ; No
                                        ; Yes, so
        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, DISK_BOOTCODE_SIZE

        mov     dx, offset Bootcode_DOS25
        cmp     [DOS_Format], MYDOS_FORMAT
        jne     @@07
        mov     dx, offset Bootcode_MYDOS

@@07:
        int     DOS_SERVICE             ; Write bootcode
        jc      @@92                    ; Error
        or      ax, ax                  ; Disk full?
        jz      @@92                    ; Error

        mov     cx, DISK_SECTORS_MEDIUM
        sub     cx, DISK_BOOTCODE_SECTOR_SIZE

@@10:
        push    cx

        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, EIGHTBIT_SECTOR_SIZE
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE             ; Write sector
        jc      @@93                    ; Error
        or      ax, ax                  ; Disk full?
        jz      @@93                    ; Error

        pop     cx
        loop    @@10

;
; Close ATR Disk Image
;
        mov     bx, [Disk_Handler]
        mov     ah, DOS_CLOSE_FILE
        int     DOS_SERVICE

;
; Open ATR Disk Image for update
;
        mov     dx, offset Path_Spec
        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_WRITE_ONLY
        int     DOS_SERVICE
        jc      @@94                    ; Open ERROR!

        mov     [Disk_Handler], ax      ; Load handle

;
; Include DOS (files)?
;
        cmp     [ATR_Disk_Image_With_DOS], FALSE
        je      @@99                    ; No
                                        ; Yes, so

        call    Process_Include_DOS_Files
        jmp     @@99

@@90:
; E R R O R S
        mov     si, offset Msg_Err_Disk_Creation
        jmp     @@98

@@91:
        mov     si, offset Msg_Err_ATR_Header
        jmp     @@98

@@92:
        mov     si, offset Msg_Err_Bootcode
        jmp     @@98

@@93:
        mov     si, offset Msg_Err_Write
        jmp     @@98

@@94:
        mov     si, offset Msg_Err_Open

@@98:
        push    ds si
        pop     di es
        call    Display_String
        call    Exit_Program

@@99:
;
; Update status
;
        mov     [ATR_Disk_Image_Open], TRUE

        ret

ENDP    Process_Open_ATR_Image_Disk



;**********************************************************************
PROC    Process_Include_DOS_Files
;**********************************************************************
;
; Save current values
;
        mov     cx, [File_Size_In_Sectors]
        push    cx
        xor     cx, cx
        mov     cl, [Remainder_Bytes]
        push    cx

        mov     si, offset Temp_File_Name
        push    ds si
        pop     di es
        mov     si, offset File_Map_Entry.File_Name
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

;
; Write DOS.SYS file
;
        mov     si, offset File_Map_Entry.File_Name
        push    ds si
        pop     di es
        mov     si, offset File_Name_DOS_SYS
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

;
; Assume DOS 2.5 format
;
        mov     [File_Size_In_Sectors], FILE_DOS_25_DOS_SECTOR_SIZE
        mov     [Remainder_Bytes], 125

        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset File_DOS_25_DOS_SYS
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path

        cmp     [DOS_Format], MYDOS_FORMAT
        jne     @@10

;
; MYDOS format
;
        mov     [File_Size_In_Sectors], FILE_MYDOS_DOS_SECTOR_SIZE
        mov     [Remainder_Bytes], 125

        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset File_MYDOS_DOS_SYS
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path

@@10:
;
; Open 8bit file
;
        mov     dx, offset Path_Spec
        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_ONLY
        int     DOS_SERVICE
        jc      @@90                    ; Open ERROR!

        mov     [File_Handler], ax      ; Load handle

;
; Move file to image
;
        call    Process_Move_File_To_Image
        call    Process_Close_8bit_File
        inc     [Atari_Files_Processed]

;
; Write DUP.SYS file
;
        mov     si, offset File_Map_Entry.File_Name
        push    ds si
        pop     di es
        mov     si, offset File_Name_DUP_SYS
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

;
; Assume DOS 2.5 format
;
        mov     [File_Size_In_Sectors], FILE_DOS_25_DUP_SECTOR_SIZE
        mov     [Remainder_Bytes], 1

        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset File_DOS_25_DUP_SYS
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path

        cmp     [DOS_Format], MYDOS_FORMAT
        jne     @@20

;
; MYDOS format
;
        mov     [File_Size_In_Sectors], FILE_MYDOS_DUP_SECTOR_SIZE
        mov     [Remainder_Bytes], 83

        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset File_MYDOS_DUP_SYS
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path

@@20:
;
; Open 8bit file
;
        mov     dx, offset Path_Spec
        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_ONLY
        int     DOS_SERVICE
        jc      @@91                    ; Open ERROR!

        mov     [File_Handler], ax      ; Load handle

;
; Move file to image
;
        call    Process_Move_File_To_Image
        call    Process_Close_8bit_File
        inc     [Atari_Files_Processed]

;
; Update vtoc
;
        mov     si, offset VTOC_I_O_Buffer
        push    ds si
        pop     di es
        mov     si, offset VTOC_Header_DOS_25
        cmp     [DOS_Format], MYDOS_FORMAT
        jne     @@30
        mov     si, offset VTOC_Header_MYDOS

@@30:
        mov     cx, EIGHTBIT_FILE_ENTRY_SIZE
        shl     cx, 1
        rep     movsb

        jmp     @@99

@@90:
;
; 8 bit file Open failure
;
        mov     si, offset Msg_Err_DOS_SYS
        jmp     @@98

@@91:
;
; 8 bit file Open failure
;
        mov     si, offset Msg_Err_DUP_SYS

@@98:
        push    ds si
        pop     di es
        call    Display_String
        call    Exit_Program

@@99:
        mov     si, offset File_Map_Entry.File_Name
        push    ds si
        pop     di es
        mov     si, offset Temp_File_Name
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

        pop     cx
        mov     [Remainder_Bytes], cl
        pop     cx
        mov     [File_Size_In_Sectors], cx

        ret

ENDP    Process_Include_DOS_Files



;**********************************************************************
PROC    Process_Move_File_To_Image
;**********************************************************************
        mov     si, offset Msg_File
        push    ds si
        pop     di es
        mov     si, offset File_Map_Entry.File_Name
        mov     cx, FILE_NAME_LENGTH
        rep     movsb

        mov     si, offset Msg_File
        mov     cx, FILE_NAME_LENGTH

@@05:
        cmp     [byte ds:si], NULL
        jne     @@06
        mov     [byte ds:si], SPACE

@@06:
        inc     si
        loop    @@05

        mov     si, offset Msg_Processing
        push    ds si
        pop     di es
        call    Display_String

        mov     cx, [Disk_Sector_Current]
        mov     [Disk_Sector_Start], cx

        mov     cx, [File_Size_In_Sectors]

@@10:
;
; Read Data Sector from 8 bit file
;
        mov     ah, DOS_READ_FROM_HANDLE
        mov     bx, [File_Handler]
        mov     dx, EIGHTBIT_SECTOR_DATA_SIZE

        push    cx

;
; Are we processing the "last" sector?
;
        cmp     cx, 1
        jne     @@20

;
; Process the "remainder" bytes
;
        mov     si, offset Disk_I_O_Buffer
        push    ds si
        pop     di es
        xor     ax, ax
        mov     cx, EIGHTBIT_SECTOR_SIZE
        rep     stosb

        mov     ah, DOS_READ_FROM_HANDLE
        xor     dx, dx
        mov     dl, [Remainder_Bytes]
        
@@20:
;
; Process Data bytes
;
        push    dx

        mov     cx, dx                  ; Data Size
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE             ; Read data bytes
        jc      @@90                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@90                    ; Yes
                                        ; No, so
        pop     dx

;
; Setup number of data bytes in current sector
;
        mov     si, offset DISK_I_O_Buffer
        mov     [byte ds:si + 127], dl

;
; Determine Next Disk Sector
;
        mov     [Disk_Sector_Next], 0

        pop     cx
        push    cx

        cmp     cx, 1                   ; Is there a next sector?
        je      @@30                    ; No
                                        ; Yes, so
        call    Process_Find_Free_Sector

@@30:
;
; Setup Sector File ID
;
        xor     ax, ax
        mov     al, [Atari_Files_Processed]
        mov     cx, 10

@@35:
        shl     ax, 1
        loop    @@35

;
; Setup Next Sector Number
;
        mov     bx, [Disk_Sector_Next]

;
; Combine File ID and Next Sector Number
;
        or      ax, bx

;
; Store information at end of current sector
;
        mov     [byte ds:si + 125], ah
        mov     [byte ds:si + 126], al

@@40:
;
; Determine offset to write to
;
        xor     ax, ax                  ; Reset ax
        xor     bx, bx                  ; Reset bx
        mov     ax, [Disk_Sector_Current]
        dec     ax                      ; Because of positioning before sector
        mov     cx, EIGHTBIT_SECTOR_SIZE
        mul     cx
        mov     cx, dx
        mov     dx, ax
        add     dx, ATR_HEADER_SIZE
        mov     ah, DOS_MOVE_FILE_POINTER
        mov     al, DOS_MOVE_FILE_POINTER_BEGIN
        mov     bx, [Disk_Handler]
        int     DOS_SERVICE             ; Position in dx:ax
        jc      @@91                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@91                    ; Yes
                                        ; No, so
;
; Write Current Disk Sector to Image
;
        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, EIGHTBIT_SECTOR_SIZE
        mov     dx, offset Disk_I_O_Buffer
        int     DOS_SERVICE             ; Write sector
        jc      @@92                    ; Error
        or      ax, ax                  ; Disk full?
        jz      @@92                    ; Error

        dec     [Disk_Sectors_Left]

        mov     cx, [Disk_Sector_Next]
        cmp     cx, 0
        je      @@50
        mov     [Disk_Sector_Current], cx

@@50:
        pop     cx
        loop    @@10

        jmp     @@99

@@90:
        mov     si, offset Msg_Err_Read
        jmp     @@98

@@91:
        mov     si, offset Msg_Err_Positioning
        jmp     @@98

@@92:
        mov     si, offset Msg_Err_Write

@@98:
        push    ds si
        pop     di es
        call    Display_String
        call    Exit_Program

@@99:
        call    Process_Find_Free_Sector
        mov     cx, [Disk_Sector_Next]
        mov     [Disk_Sector_Current], cx

        ret

ENDP    Process_Move_File_To_Image



;**********************************************************************
PROC    Process_Find_Free_Sector
;**********************************************************************
;
; The following sectors cannot be used
; Sector 1 thru 3 (boot sectors)
; Sector 360 (bitmap sector)
; Sector 361 thru 368 (vtoc sectors)
; Sector 720 (to be compatible with DOS 2.0S)
; Sector 1023 (extended bitmap sector)
; Sector 1024 thru 1040 (or 1024 and up being Free Space)
;
        mov     cx, [Disk_Sector_Current]
        inc     cx

        cmp     cx, EIGHTBIT_VTOC_SECTOR_BEGIN
        jl      @@20
        cmp     cx, EIGHTBIT_VTOC_SECTOR_END
        jnle    @@20
        mov     cx, EIGHTBIT_VTOC_SECTOR_END

@@10:
        inc     cx

@@20:
;
; Sector = 720?
;
        cmp     cx, EIGHTBIT_SECTOR_PHANTOM
        je      @@10

;
; Sector < 1023?
;
        cmp     cx, EIGHTBIT_VTOC_SECTOR_BITEXT
        jl      @@99

@@90:
        mov     si, offset Msg_Err_Allocation

@@98:
        push    ds si
        pop     di es
        call    Display_String
        call    Exit_Program

@@99:
        mov     [Disk_Sector_Next], cx
        ret

ENDP    Process_Find_Free_Sector



;**********************************************************************
PROC    Process_Update_8bit_VTOC
;**********************************************************************
        mov     si, offset VTOC_I_O_Buffer
        xor     cx, cx
        mov     cl, [Atari_Files_Processed]
        cmp     cx, 0
        je      @@20

@@10:
        add     si, EIGHTBIT_FILE_ENTRY_SIZE
        loop    @@10

@@20:
;
; File is unlocked and active
;
        mov     [byte ds:si], 042h
        inc     si

;
; File Size in Sectors
;
        mov     cx, [File_Size_In_Sectors]
        mov     [byte ds:si], cl
        inc     si
        mov     [byte ds:si], ch
        inc     si

;
; Starting Sector
;
        mov     cx, [Disk_Sector_Start]
        mov     [byte ds:si], cl
        inc     si
        mov     [byte ds:si], ch
        inc     si

        push    ds si

;
; "Initialize" filename area
;
        push    ds si
        pop     di es
        xor     ax, ax
        mov     al, SPACE
        mov     cx, EIGHTBIT_FILE_NAME_LENGTH
        rep     stosb

;
; Move filename
;
        pop     di es
        mov     si, offset File_Map_Entry.File_Name
        mov     cx, 8

@@30:
        mov     al, [byte ds:si]
        cmp     al, NULL                            ; End of file?
        je      @@99                                ; Yes
                                                    ; No, so
        cmp     al, DOT                             ; "." found?
        je      @@40                                ; Yes
                                                    ; No, so
        mov     [byte es:di], al
        inc     si
        inc     di
        loop    @@30

@@40:
        inc     di
        loop    @@40
        inc     si
        mov     cx, 3

@@50:
        mov     al, [byte ds:si]
        cmp     al, NULL                            ; End of file?
        je      @@99                                ; Yes
                                                    ; No, so
        mov     [byte es:di], al
        inc     si
        inc     di
        loop    @@50

@@99:
        ret

ENDP    Process_Update_8bit_VTOC



;**********************************************************************
PROC    Process_Write_8bit_VTOC
;**********************************************************************
        cmp     [ATR_Disk_Image_Open], TRUE
        jne     @@99

        mov     si, offset Msg_VTOC
        push    ds si
        pop     di es
        call    Display_String

;
; Determine offset to write to
;
        xor     ax, ax                  ; Reset ax
        xor     bx, bx                  ; Reset bx
        mov     ax, EIGHTBIT_VTOC_SECTOR_BITMAP
        dec     ax                      ; Because of positioning before sector
        mov     cx, EIGHTBIT_SECTOR_SIZE
        mul     cx
        mov     cx, dx
        mov     dx, ax
        add     dx, ATR_HEADER_SIZE
        mov     ah, DOS_MOVE_FILE_POINTER
        mov     al, DOS_MOVE_FILE_POINTER_BEGIN
        mov     bx, [Disk_Handler]
        int     DOS_SERVICE             ; Position in dx:ax
        jc      @@90                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@90                    ; Yes
                                        ; No, so
;
; Write VTOC bitmap
;
        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, EIGHTBIT_SECTOR_SIZE
        mov     dx, offset VTOC_I_O_Bitmap
        int     DOS_SERVICE             ; Write bitmap
        jc      @@91                    ; Error
        or      ax, ax                  ; Disk full?
        jz      @@91                    ; Error
        
;
; Write Current Disk Sector to Image
;
        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, EIGHTBIT_VTOC_SIZE
        mov     dx, offset VTOC_I_O_Buffer
        int     DOS_SERVICE             ; Write vtoc
        jc      @@92                    ; Error
        or      ax, ax                  ; Disk full?
        jz      @@92                    ; Error

;
; Determine offset to write to
;
        xor     ax, ax                  ; Reset ax
        xor     bx, bx                  ; Reset bx
        mov     ax, EIGHTBIT_VTOC_SECTOR_BITEXT
        dec     ax                      ; Because of positioning before sector
        mov     cx, EIGHTBIT_SECTOR_SIZE
        mul     cx
        mov     cx, dx
        mov     dx, ax
        add     dx, ATR_HEADER_SIZE
        mov     ah, DOS_MOVE_FILE_POINTER
        mov     al, DOS_MOVE_FILE_POINTER_BEGIN
        mov     bx, [Disk_Handler]
        int     DOS_SERVICE             ; Position in dx:ax
        jc      @@90                    ; Stop on error
        or      ax, ax                  ; End of file?
        jz      @@90                    ; Yes
                                        ; No, so
;
; Write VTOC bitmap extend
;
        xor     ax, ax
        mov     ah, DOS_WRITE_TO_HANDLE
        mov     bx, [Disk_Handler]
        mov     cx, EIGHTBIT_SECTOR_SIZE
        mov     dx, offset VTOC_I_O_Bitmap_Extend
        int     DOS_SERVICE             ; Write bitmap extend
        jc      @@91                    ; Error
        or      ax, ax                  ; Disk full?
        jz      @@91                    ; Error

;
; Initialize VTOC map
;        
        mov     si, offset VTOC_I_O_Buffer
        push    ds si
        pop     di es
        xor     ax, ax
        mov     cx, EIGHTBIT_VTOC_SIZE
        rep     stosb

        jmp     @@99

@@90:
        mov     si, offset Msg_Err_Positioning

@@91:
        mov     si, offset Msg_Err_VTOC

@@92:
        mov     si, offset Msg_Err_VTOC_Bitmap

@@98:
        push    ds si
        pop     di es
        call    Display_String
        call    Exit_Program

@@99:
        ret

ENDP    Process_Write_8bit_VTOC



;**********************************************************************
PROC    Process_Close_ATR_Image_Disk
;**********************************************************************
        cmp     [ATR_Disk_Image_Open], TRUE
        jne     @@99

;
; Close ATR Disk Image
;
        mov     bx, [Disk_Handler]
        mov     ah, DOS_CLOSE_FILE
        int     DOS_SERVICE

;
; Update status
;
        mov     [ATR_Disk_Image_Open], FALSE

@@99:
        ret

ENDP    Process_Close_ATR_Image_Disk



;**********************************************************************
PROC    Process_Open_8bit_File
;**********************************************************************
;
; Determine Filename path
;
        mov     si, offset Path_Spec
        push    ds si
        pop     di es
        mov     si, offset File_Path
        mov     cx, PATH_LENGTH             ; Copy length
        rep     movsb                       ; Copy path to search path

        call    Setup_Path_Spec_File

;
; Open 8bit file
;
        mov     dx, offset Path_Spec
        mov     ah, DOS_OPEN_FILE
        mov     al, DOS_FILE_READ_ONLY
        int     DOS_SERVICE
        jc      @@90                    ; Open ERROR!

        mov     [File_Handler], ax      ; Load handle
        jmp     @@99

@@90:
; 8 bit file Open failure
        mov     si, offset Msg_Err_Open

@@98:
        push    ds si
        pop     di es
        call    Display_String
        call    Exit_Program

@@99:
        ret

ENDP    Process_Open_8bit_File



;**********************************************************************
PROC    Process_Close_8bit_File
;**********************************************************************
        mov     bx, [File_Handler]
        mov     ah, DOS_CLOSE_FILE
        int     DOS_SERVICE

@@99:
        ret

ENDP    Process_Close_8bit_File



;**********************************************************************
PROC    Setup_Path_Spec_Dir_Files
;**********************************************************************
        mov     di, offset Path_Spec
        mov     cx, PATH_LENGTH             ; Search length
        xor     ax, ax                      ; Search for the null character
        repne   scasb                       ; Search uses es:di

; Add "\" character
        mov     [byte es:di - 1], BACKSLASH

; 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_Dir_Files



;**********************************************************************
PROC    Setup_Path_Spec_Disk
;**********************************************************************
        mov     di, offset Path_Spec
        mov     cx, PATH_LENGTH             ; Search length
        xor     ax, ax                      ; Search for the null character
        repne   scasb                       ; Search uses es:di

; Add "\" character
        mov     [byte es:di - 1], BACKSLASH

; Add File Specification
        mov     si, offset Disk_Name
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy path to search path

        ret

ENDP    Setup_Path_Spec_Disk



;**********************************************************************
PROC    Setup_Path_Spec_File
;**********************************************************************
        mov     di, offset Path_Spec
        mov     cx, PATH_LENGTH             ; Search length
        xor     ax, ax                      ; Search for the null character
        repne   scasb                       ; Search uses es:di

; Add "\" character
        mov     [byte es:di - 1], BACKSLASH

; Add File Specification
        mov     si, offset File_Map_Entry.File_Name
        mov     cx, FILE_NAME_LENGTH        ; Copy length
        rep     movsb                       ; Copy path to search path

        ret

ENDP    Setup_Path_Spec_File



;**********************************************************************
PROC    Show_Msg_Done
;**********************************************************************
        mov     si, offset Msg_Done
        push    ds si
        pop     di es
        call    Display_String

@@99:
        ret

ENDP    Show_Msg_Done



;**********************************************************************
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    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
