	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[11];
;
_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)
;	cmp	al,0
;	jne	savefb1
	mov	byte ptr [si+6],128		;Set to 128 when sector size code is 0
savefb1:
	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[11];
;
_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
	mov	al,ah
	mov	ah,0
	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

	mov	al,ah
	mov	ah,0
	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				;and return (CY/AX contain status)
vwrite	endp
;
;	Format a MYDOS Track
;
;	aformat(track, drive, buf, seq, head)
;	   int sector, drive;
;	   char buf[512];
;	   char seq[26];
;		int head;
;
_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	bx,10[bp]	;Point to sector sequence table
	mov	ch,4[bp]		;Get track no.
	mov	cl,12[bp]	;Head

	cmp	ch,0
	jne l2
	mov	ax,1702h
	mov	dx,0
	int	13h			;Set DASD type for format

l2:
	cld
bldft:
	mov	al,ds:[bx]
	cmp	al,0FFh
	je	endbft
	inc	bx
	mov	es:[di],ch		;Track No.
	inc	di
	mov	es:[di],cl		;Head No.
	inc	di
	mov	es:[di],al		;Sector number
	inc	di
	cmp	ch,0
	jne normsec
	mov	ah,0			;Sector size
	mov	es:[di],ah		;Sector size
	jmp	short l1
normsec:
	mov	ah,1			;Sector size
	mov	es:[di],ah		;Sector size
l1:
	inc	di
	jmp	short bldft

endbft:
	sub	bx,10[bp]
	mov	ax,bx			;Sector count
	mov	bx,8[bp]		;Buffer
	mov	dh,cl			;Head number
	mov	dl,6[bp]		;Drive number
	mov	cl,1			;Sector number (junk)
	mov	ah,05h		;Format command
	int	13h
	mov	al,ah
	mov	ah,0
	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
