title ATARI Disk I/O Library public _savefb public _restfb public _aread public _awrite public _aformat public _cd public _md public _dmainit public _getds public _ffirst public _fnext DGROUP group _DATA _DATA segment byte public 'DATA' extrn _tracks:byte extrn _track_offset:byte extrn _sector_offset:byte _DATA ends IGROUP group _TEXT _TEXT segment byte public 'CODE' assume cs:IGROUP,ds:DGROUP ; ; Return first address of a 512-byte buffer in a character array ; _dmainit proc near push bp mov bp,sp mov ax,4[bp] mov bx,ds mov cl,4 shl bx,cl add bx,ax cmp bx,0FE00h jbe dmax sub ax,bx dmax: pop bp ret _dmainit endp ; ; Save Current Disk Format in 10-Byte Save Area ; ; savefb(sectorsize, sectorcount, savearea) ; int sectorsize, sectorcount; ; char savearea[10]; ; _savefb proc near push bp mov bp,sp push ds push di push si cld xor si,si push ds pop es ;Segment address of save area mov ds,si lds si,dword ptr ds:[4*1Eh] ;Address of ctl block to DS:SI mov di,8[bp] ;Get address of save area mov cx,5 ;length in words rep movsw ;copy block to local memory sub si,10 ;point back to 1-st of ctl blk mov al,byte ptr 4[bp] ;ARG1 = sector size code mov ah,byte ptr 6[bp] ;ARG2 = sectors/track mov word ptr [si+3],ax ;Store data back into block mov byte ptr [si+5],28 ;Inter-sector gap length (was 42) mov byte ptr [si+7],24 ;Leading gap length (was 80) mov byte ptr cs:secptk,ah mov ah,0 ;reset the disk system mov bx,ax shl bx,1 mov bx,cs:sec_size[bx] mov cs:data_ln,bx int 13H pop si pop di pop ds pop bp ret _savefb endp ; ; Restore MSDOS Format to Disk Control Block ; ; restfb(savearea) ; char savearea[10]; ; _restfb proc near push bp mov bp,sp push ds push di push si xor cx,cx loop $ cld mov si,4[bp] xor ax,ax mov es,ax les di,dword ptr es:[4*1Eh] mov cl,5 rep movsw int 13H pop si pop di pop ds pop bp ; xor cx,cx ; loop $ ret _restfb endp ; ; Read a MYDOS Sector ; ; aread(sector, drive, bufad) ; int sector, drive; ; char bufad[512]; ; _aread proc near push bp mov bp,sp push es push si push di call reg_set call vread ;Read one sector jc reterr xor ax,ax ;Return zero if no error reterr: pop di pop si pop es ;Return it directly pop bp ret _aread endp ; vread proc near call io_setup retry: push dx push cx push bx mov ax,0201h ;Command code/Number of sectors int 13H pushf ;Save CY flag push ax jnc flip dec cs:errcnt je flip pop ax popf mov ah,00h ;Recalibrate disk system int 13H pop bx pop cx pop dx jmp short retry ; flip: pop ax popf pop bx pop cx pop dx pushf mov cx,128 ;Complement data bits fliplp: not word ptr es:[bx] inc bx inc bx loop fliplp popf ;Restore CY flag ret ;and return (CY/AX contain status) vread endp ; ; Write a MYDOS Sector ; ; awrite(sector, drive, bufad) ; int sector, drive; ; char bufad[512]; ; _awrite proc near push bp mov bp,sp push es push si push di call reg_set call vwrite ;Write one sector pop di pop si pop es pop bp ret _awrite endp ; vwrite proc near call io_setup wrtry: push dx push cx push bx mov cx,128 wrcomp: not word ptr es:[bx] inc bx inc bx loop wrcomp pop bx pop cx push cx push bx mov ax,0301h ;Command code/Number of sectors int 13H jnc vw_xit push ax mov ah,00h ;Recalibrate disk system int 13H pop ax pop bx pop cx pop dx dec cs:errcnt jne wrtry push cx push bx mov cx,128 errcmp: not word ptr es:[bx] inc bx inc bx loop errcmp pop cx pop bx stc ret ;and return (CY/AX contain status) vw_xit: pop bx push bx mov cx,128 wrrcmp: not word ptr es:[bx] inc bx inc bx loop wrrcmp mov ax,0 ;Indicate no error pop bx pop cx pop dx ret vwrite endp ; ; Format a MYDOS Track ; ; aformat(track, drive, buf, seq) ; int sector, drive; ; char buf[512]; ; char seq[26]; ; _aformat proc near push bp mov bp,sp push ds push es push di mov di,8[bp] ;Point to the buffer mov ax,ds mov es,ax mov ah,1 mov bx,10[bp] ;Point to sector sequence table mov ch,4[bp] ;Get track no. cld bldft: mov al,ds:[bx] cmp al,0FFh je endbft inc bx mov es:[di],ch ;Track No. inc di mov byte ptr es:[di],0 ;Head No. inc di stosw ;Sector No. and Bytes/Sector jmp short bldft endbft: sub bx,10[bp] mov ax,bx mov bx,8[bp] ;368h mov cl,1 ;Sector number (junk) mov dh,0 ;Head number mov dl,byte ptr 6[bp] ;Drive number mov ah,05h ;Format command int 13h mov ax,0 jnc afex ;Return 0 if OK, -1 if error dec ax afex: pop di pop es pop ds pop bp ret _aformat endp io_setup proc near dec ax ;Make sector number 0-based xor dx,dx ;and 64-bit long div word ptr cs:secptk ;convert to track/sector format inc dl fmt_su: mov ch,al ;track number mov cl,dl ;sector number mov dh,0 ;Head number cmp ch,_tracks ;Second side? jb dord inc dh test _track_offset+1,80h ;Same or different directions jz dorev add ch,_track_offset ;track = track - [40|80] jmp short doadj dorev: mov ch,_track_offset ;track = [80|160] - track sub ch,al doadj: test _sector_offset+1,80h jnz dord ;if < 0, no change mov cl,_sector_offset sub cl,dl ;else sector = K - sector cmp cl,byte ptr cs:secptk jbe dord ;Where K can be > max sector # sub cl,byte ptr cs:secptk dec ch ;presume reversed sequence test _track_offset+1,80h jz dord add ch,2 ;if forward track sequence dord: mov dl,byte ptr 6[bp] ;Drive number mov cs:errcnt,5 ;Retry 5 times only! ret io_setup endp reg_set proc near mov bx,8[bp] ;ARG2 = buffer address mov ax,ds mov es,ax mov ax,4[bp] ;Get ATARI FMS sector no. ret reg_set endp ; ; Change to a new current directory ; cd(ptr) ; char *ptr; /* new directory name */ ; returns 0 if successful, 3 if invalid directory ; _cd proc near push bp mov bp,sp mov dx,4[bp] mov ah,3Bh int 21h jc ret_cd xor ax,ax ret_cd: pop bp ret _cd endp ; ; Make a new directory ; md(ptr) ; char *ptr; /* new directory name */ ; returns 0 if successful, 3 if invalid path ; 5 if access denied ; _md proc near push bp mov bp,sp mov dx,4[bp] mov ah,39h int 21h jc ret_md xor ax,ax ret_md: pop bp ret _md endp ; ; Parse and search for files with wild card names ; ; ffirst(dta,name) ; _ffirst proc near push bp mov bp,sp mov dx,6[bp] mov ah,4Eh mov cx,7 jmp short getfile _ffirst endp ; ; fnext(dta) ; _fnext proc near push bp mov bp,sp mov ah,2Fh int 21h push si mov si,4[bp] mov cx,22 ;Size of buffer in words rstdata: lodsw mov es:[bx],ax inc bx inc bx loop rstdata pop si mov ah,4Fh getfile: int 21h jc reten mov ah,2Fh int 21h push di mov di,4[bp] mov cx,22 ;Size of buffer in words cpydata: mov ax,es:[bx] mov ds:[di],ax inc di inc di inc bx inc bx loop cpydata pop di xor ax,ax pop bp ret reten: push ax mov di,4[bp] mov cx,22 mov ax,0FFFFh rep stosw pop ax pop bp ret _fnext endp _getds proc near mov ax,ds ret _getds endp sec_size dw 128,256,512,1024,2048,4096 data_ln dw 256 ;size of a sector in bytes secptk dw 0 errcnt db 0 _TEXT ends end