open/read any binary file in DOS filesystem by Peter Ferrie. searches the file system for the requested file. only 4 sectors long in memory. usage: jsr init ;one-time call to unhook DOS and relocate code to top of memory ;open and read a file lda #file_to_read sta namhi jsr opendir ;open and read entire file into memory at its load address format of request name is 30-character Apple text: e.g. !scrxor $80, "MYFILE " http://pferrie.tripod.com ;read any file slot 6 version ;copyright (c) Peter Ferrie 2013 !cpu 65c02 !to "trk",plain *=$800 adrlo = $26 ;constant from boot prom adrhi = $27 ;constant from boot prom tmpsec = $3c ;constant from boot prom reqsec = $3d ;constant from boot prom A1L = $3c ;constant from ROM A1H = $3d ;constant from ROM A2L = $3e ;constant from ROM A2H = $3f ;constant from ROM curtrk = $40 niblo = $41 nibhi = $42 A4L = $42 ;constant from ROM A4H = $43 ;constant from ROM sizelo = $44 sizehi = $45 secsize = $46 tmpsize = $47 namlo = $fb namhi = $fc step = $fd ;state for stepper motor tmptrk = $fe ;temporary copy of current track phase = $ff ;current phase for seek reloc = $bc00 dirbuf = $bf00 MOVE = $fe2c ;unhook DOS and build nibble table init jsr $fe93 jsr $fe89 lda #unreloc sta A1H lda #<(unreloc+(codeend-opendir)-1) sta A2L lda #>(unreloc+(codeend-opendir)-1) sta A2H stz A4L lda #>reloc sta A4H ldy #0 jsr MOVE ldx #3 -- stx $3c txa asl bit $3c beq + ora $3c eor #$ff and #$7e - bcs + lsr bne - tya sta nibtbl, x iny + inx bpl -- rts unreloc !pseudopc reloc { ;turn on drive and read volume table of contents opendir lda $c0e9 stz adrlo stz secsize lda #$11 ldx #0 jsr readdirsec firstent lda dirbuf+1 ;lock if entry not found beq * ;read directory sector ldx dirbuf+2 jsr seekread1 ldy #7 ;number of directory entries in a sector ldx #$2b ;offset of filename in directory entry nextent phy phx ldy #$1d ;match name backwards (slower but smaller) - lda (namlo), y cmp dirbuf, x beq foundname pla ;move to next directory in this block, if possible clc adc #$23 tax ply dey bne nextent bra firstent foundname dex dey bpl - ply pla ;read track/sector list lda dirbuf-32, y ldx dirbuf-31, y jsr seekread1 ;read load offset and length info only, initially lda #filbuf jsr seekread ;reduce load offset by 4, to account for offset and length sec lda filbuf sbc #4 sta filbuf sta adrlo lda filbuf+1 sbc #0 sta filbuf+1 sta adrhi ;save on stack bytes that will be overwritten by extra read ldy #3 - lda (adrlo), y pha dey bpl - ;increase load size by 4, to account for offst and length clc lda filbuf+2 adc #4 sta sizelo sta secsize lda filbuf+3 adc #0 sta sizehi beq readfirst stz secsize readfirst ldy #$0c ;read a file sector readnext lda dirbuf, y ldx dirbuf+1, y phy jsr seekread1 ply ;if low count is non-zero then we are done ;(can happen only for partial last block) lda secsize bne readdone ;continue if more than $100 bytes left dec sizehi bne + ;set read size to min(length, $100) lda sizelo beq readdone sta secsize + inc adrhi iny iny bne readnext ;save current address for after t/s read lda adrlo pha lda adrhi pha stz adrlo ;read next track/sector sector lda dirbuf+1 ldx dirbuf+2 jsr readdirsec ;restore current address pla sta adrhi pla sta adrlo bra readfirst readdone lda $c0e8 lda filbuf sta adrlo lda filbuf+1 sta adrhi ;restore from stack bytes that were overwritten by extra read ldx #3 ldy #0 - pla sta (adrlo), y iny dex bpl - rts readdirsec ldy #>dirbuf seekread sty adrhi seekread1 sta phase lda sectbl, x sta reqsec jsr readadr ;if track does not match, then seek lda curtrk cmp phase beq checksec jsr seek ;[re-]read sector - jsr readadr checksec cmp reqsec bne - ;read sector data lda #<(bit2tbl-170) sta niblo lda #>(bit2tbl-170) sta nibhi readdata stz tmpsize lda $c0ec bpl readdata -- eor #$d5 ;cmp #$D5, and set A to zero bne readdata - ldy $c0ec bpl - cpy #$aa ;we need Y=#$AA later bne -- - ldx $c0ec bpl - cpx #$ad bne readdata pha ;push zero (carry clear) php ;push carry set - ldx $c0ec bpl - eor nibtbl-128, x sta (niblo), y ;internal initially, and then the real address iny cpy tmpsize bne - ldy adrlo sty niblo ldy adrhi sty nibhi ;set real address ldy secsize sty tmpsize ldy #0 plp ;carry set on first pass, clear on second bcs - ;loop one time -- ldx #$a9 - inx beq -- lda (niblo), y lsr bit2tbl-170, x rol lsr bit2tbl-170, x rol sta (niblo), y iny cpy tmpsize bne - rts ;no tricks here, just the regular stuff readadr lda $c0ec bpl readadr -- eor #$d5 bne readadr - lda $c0ec bpl - cmp #$aa bne -- - lda $c0ec bpl - cmp #$96 bne readadr ldy #3 -- sta curtrk lda $c0ec bpl -- rol sta tmpsec - lda $c0ec bpl - and tmpsec dey bne -- rts stepdelay phx and #3 rol tax lda $c0e0, x pla -- ldx #$13 - dex bne - dec bne -- seekret rts seek asl curtrk stz step asl phase copy_cur lda curtrk sta tmptrk sec sbc phase beq seekret bcs + eor #$ff inc curtrk bcc ++ + dec dec curtrk ++ cmp step bcc + lda step + cmp #8 bcs + tay sec + lda curtrk ldx step1, y jsr stepdelay lda tmptrk ldx step2, y jsr stepdelay inc step bne copy_cur step1 !byte 1, $30, $28, $24, $20, $1e, $1d, $1c step2 !byte $70, $2c, $26, $22, $1f, $1e, $1d, $1c sectbl !byte 0, $0d, $0b, 9, 7, 5, 3, 1, $0e, $0c, $0a, 8, 6, 4, 2, $0f codeend = * nibtbl = * bit2tbl = nibtbl+128 filbuf = bit2tbl+86 dataend = filbuf+4 ;hack to error out when code is too large for current address !if ((dirbuf-(dataend-opendir))&$ff00)