%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