[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

DOS 3.3 File Manager calls - stomping on Track 0, sector 0



I have my trusty copy of Beneath Apple Dos by Worth and Lechner in
front of me.  I've modified their sample "copy" program to do my
bidding.  Originally, the copy program opened a binary file, read it
in, opened a text file for writing, wrote the data out to the text
file, then closed everything up.  All I want to do is to "BSAVE" some
memory without going the Ctrl-D/print route.

My code correctly opens, writes and closes the file I want.  The data
in the file is exactly the right size, and the data is intact. It
complains correctly when the file already exists and is write
protected, the disk is out, etc.  So everything seems to work
correctly.

Except... track/sector 0/0 is overwritten with a repeating sequence of
(0x00 0x00 0xff 0xff) bytes.  Is there a common trap I'm falling into
here?  Code below...

;----------------------------------------
; BSAVE - Save a binary program in memory
;----------------------------------------

; Zero page locations

ptr	= $06	; 2 bytes
bufp	= $08	; 2 bytes

; Monitor pointer

a1l	= $3c

; Other addresses

doswrm	= $03d0
locrpl	= $03e3
locfpl	= $03dc
fm	= $03d6
prbyte	= $fdda

; File manager parmlist definition

fmocod	= $00	; Opcode
fmsbcd	= $01	; Subcode
fmprms	= $02	; Function-specific parameters

; Opcodes

fmocop	= $01	; Open
fmoccl	= $02	; Close
fmocrd	= $03	; Read
fmocwr	= $04	; Write
fmocde	= $05	; Delete
fmocca	= $06	; Catalog
fmoclo	= $07	; Lock
fmocun	= $08	; Unlock
fmocre	= $09	; Rename
fmocpo	= $0a	; Position
fmocin	= $0b	; Init
fmocve	= $0c	; Verify

; Subcodes

fmsbno	= $00	; No operation
fmsbon	= $01	; R/W one byte
fmsbra	= $02	; R/W range of bytes
fmsbpo	= $03	; Position and R/W one byte
fmsbpr	= $04	; Position and R/W range

; OPEN parameters

fmrcln	= $02	; Record length
fmvol	= $04	; Volume
fmdrv	= $05	; Drive
fmslt	= $06	; Slot
fmtype	= $07	; File type
fmname	= $08	; Pointer to file name

; File types

fmtypt	= $00	; Text
fmtypi	= $01	; Integer
fmtypa	= $02	; Applesoft
fmtypb	= $04	; Binary

; READ/WRITE parameters

fmrcnm	= $02	; Record number
fmoffs	= $04	; Byte offset
fmraln	= $06	; Range length
fmraad	= $08	; Range address
fmdata	= $08	; Data byte read/written (== fmraad)

; Common parms

fmrc	= $0a	; Return code
fmfmwa	= $0c	; File Manager work area pointer
fmtsl	= $0e	; Track/Sector list pointer
fmbuff	= $10	; Data buffer pointer

; File Manager return codes
fmrcok	= 0	; No error
fmrcbo	= 2	; Bad opcode
fmrcbs	= 3	; Bad subcode
fmrcwp	= 4	; Write protected
fmrced	= 5	; End of data
fmrcnf	= 6	; File not found
fmrcbv	= 7	; Bad volume
fmrcio	= 8	; I/O error
fmrcdf	= 9	; Disk full
fmrclk	= 10	; File locked

bsave:
	lda #$03
	sta $07ff
	lda #$08
	sta $0800
	jsr locfpl	; Locate File Manager parmlist
	sty ptr		; Save a pointer to it
	sta ptr+1

;	open output file

	ldy #fmname	; Store file name in
	lda #<oname	; parameter list
	sta (ptr),y
	iny
	lda #>oname
	sta (ptr),y
	ldy #fmtype	; Set file type to...
	lda #fmtypb	;  ...binary
	sta (ptr),y
	ldx #0		; If we have to create it,
	jsr open	; that's OK
	bcc outop
	ldy #fmrc
	lda (ptr),y
	cmp #fmrcnf	; File not found?
	beq outop	; If so, that's ok - it was allocated
	jmp error

outop:	lda bufp	; Save output file buffer
	sta obuff
	lda bufp+1
	sta obuff+1
	jsr rewind	; Rewind the file

;	Write memory out to the file

	ldy #fmraln	; Set range length (L$)
	lda length	; Length of program in memory
	clc
	adc #$04	; Add 4 bytes to length for binary header
	php
	sta (ptr),y	; Tell File Manager lsb of length
	sta $0801	; Prefix the file with the length too (lsb)
	lda length+1
	plp
	bcc :+
	adc #$00	; Bump msb if +4 of lsb had carried
:	iny
	sta (ptr),y	; Tell File Manager msb of length
	sta $0802	; Prefix the file with the length too (msb)
	jsr write

alldone:		; Close the file
	lda obuff
	sta bufp
	lda obuff+1
	sta bufp+1
	jsr close
	rts

error:
	ldy #fmrc
	lda (ptr),y
	pha
err:	lda #_'E'
	jsr cout
	lda #_'R'
	jsr cout
	jsr cout
	pla
	jsr prbyte
	rts

open:			; Finish up the parmlist and open the file
	lda doswrm+2	; Find DOS's entry point
	sta bufp+1
	ldy #0
	sty bufp	; Point at the buffer chain

;	scan DOS buffers for a free one
gbuf0:	lda (bufp),y
	pha
	iny
	lda (bufp),y
	sta bufp+1
	pla
	sta bufp
	bne gbuf
	lda bufp+1
	bne gbuf
	lda #12
	pha
	jmp err
gbuf:	ldy #0
	lda (bufp),y
	beq gotbuf
	ldy #36
	bne gbuf0
gotbuf:	lda #1
	sta (bufp),y

;	Finish the open parm list
	ldy #fmocod
	lda #fmocop
	sta (ptr),y
	lda #0
	ldy #fmrcln
	sta (ptr),y
	iny
	sta (ptr),y
	ldy #fmvol
	sta (ptr),y
	jsr locrpl
	sty a1l
	sta a1l+1
	ldy #1
	lda (a1l),y
	lsr
	lsr
	lsr
	lsr
	ldy #fmslt
	sta (ptr),y
	ldy #2
	lda (a1l),y
	ldy #fmdrv
	sta (ptr),y

;	Common interface for file manager
callfm:	ldy #30
cfmlp1:	lda (bufp),y
	pha
	iny
	cpy #36
	bcc cfmlp1
	ldy #fmbuff+1
cfmlp2:	pla
	sta (ptr),y
	dey
	cpy #fmfmwa
	bcs cfmlp2
	jmp fm			; Exit through file manager

;	Close DOS file
close:	ldy #fmocod
	lda #fmoccl
	sta (ptr),y
	jsr callfm
	bcc clok
	jmp error
clok:	ldy #0
	tya
	sta (bufp),y
	rts

;	Position to the start of a file
rewind:	ldy #fmrcnm
	lda #0
	clc
rewlp:	sta (ptr),y	; Clear record number
	iny
	cpy #fmoffs+2	; Clear byte offset
	bcc rewlp
	ldy #fmocod
	lda #fmocpo	; Positioning opcode
	sta (ptr),y
	jsr callfm	; Exit via File Manager
	bcc rewrts	; Check/report errors
	jmp error
rewrts:	rts

;	Write a range of bytes
write:	lda obuff
	sta bufp
	lda obuff+1
	sta bufp+1
	lda #fmocwr

;	Write the bytes
doio:	ldy #fmocod
	sta (ptr),y
	ldy #fmsbcd
	lda #fmsbpr
	sta (ptr),y
	ldy #fmraad		; Set address (A$)
	lda #$ff		; lsb of beginning address
	sta (ptr),y
	iny
	lda #$07		; msb of beginning address
	sta (ptr),y
	jsr callfm
	bcc doiort
	jmp error
doiort:	rts

oname:	asc	"FILE                          " ; 30 characters
obuff:	.res 2
length:	.word endasm-beginasm ; Length from main assembly