textfiles/apple/ANATOMY/rwtsd1.format.2.txt

509 lines
44 KiB
Plaintext

*-----------------------*
* *
* RWTSDRV1 USING FORMAT *
* CONTinued *
* *
*-----------------------*
.
.
.
(BF1F) BCS VRFYRTN ;Irrelevant -already chkd write-protect
;switch when we wrote the address.
(BF21) INC FRMTSEC ;Increase sec #.
LDA FRMTSEC
CMP #$10 ;Done all 16 secs yet?
(BF27) BCC FRMTASEC ;No - go do some more.
* VERIFY a single track.
* Note: We just finished formatting
* sector $0F. Because sector $OF
* shouldn't overwrite too much of the
* sync gap (originally 128 syncs long)
* that was written prior to sec $00, and
* because we don't waste too much time
* between writing the last byte of sec $0F
* and looking for the next addr header, we
* expect to begin our verification with
* sec $00.
* Initialize counters.
(BF29) LDY #$0F ;SET COUNTER FOR # OF SECS VERIFIED.
STY FRMTSEC
LDA #48 ;SET COUNTER FOR # OF ATTEMPTS.
(BF2F) STA READCNTR
* Fill sector map with POSITIVE #'s.
(BF32)
FILSECMP STA SECFLGS,Y
DEY
(BF36) BPL FILSECMP
* Delay to let some syncs pass by.
(BF38) LDY SYNCNTR ;Initialize (y).
BYPSYNCS JSR VRFYRTN ;(12 cyc)
JSR VRFYRTN ;(12 cyc)
JSR VRFYRTN ;(12 cyc)
PHA ;(3 cyc)
PLA ;(4 cyc)
NOP ;(2 cyc)
DEY ;(2 cyc)
(BF47) BNE BYPSYNCS ;(3 cyc on branch, 2 on fall thru)
* Read address of first sector encountered.
* (THIS BETTER BE SECTOR 0!!!! If it isn't,
* our drive is a bit too fast & we will
* eventually have to reformat the track.)
(BF49) JSR RDADDR ;Read addr of first sec encountered.
;(See dis'mbly below.)
(BF4C) BCS REREADDR ;Bad read, try again.
LDA SECDSK ;Was sec read = sector 0?
(BF50) BEQ RDNXTDAT ;Yes - go read next data sec.
* DIDN'T FIND SECTOR $00 WHEN EXPECTED.
* Drive must be faster than anticipated
* because sector $0F overlaid too much of
* the long sync gap (gap 1) that was
* originally written before sector $00.
* We will have to reformat this track using
* 128 self-syncs before sector $00 (gap 1)
* and less sync bytes between other sectors
* (gap 3). This will insure that less gap-1
* syncs will be overwritten by sector $0F.
* Note that, depending on just how much too
* fast the drive is, we may have to reformat
* this track several times before we get it
* right. Each time we reformat, we reduce
* the number of gap-3 syncs. If the sync
* counter is greater than or equal to 16,
* we write two less syncs. If the counter
* is less than 16, we only reduce the gap-3
* by one sync. In order to give the machine
* time to decode information, we won't
* allow a gap less than five syncs long.
* (Note that we won't reformat the track
* until we find the address header for sec $0F.
* This presumably keeps like-numbered sectors
* in adjacent tracks in some semblance of order.)
(BF52) LDA #16
CMP SYNCNTR ;Condition carry.
LDA SYNCNTR ;If sync count < 16, subtract 1.
SBC #1 ;Else subtract 2.
STA SYNCNTR
CMP #5 ;Do we have at least 5 syncs?
BCS REREADDR ;Yes.
SEC ;No - signal error cause need
(BF61) RTS ;at least 5 syncs. Drive is
============ ;so fast that it is out-to-lunch.
* Read the sector address.
(BF62)
RDNXTADR JSR RDADDR ;Read the address header.
;(See dis'mbly below.)
(BF65) BCS BADREAD ;Branch if addr read was bad.
* Read the data proper.
(BF67)
RDNXTDAT JSR READATA ;Read the actual data bytes.
(BF6A) BCC CKSECMAP ;Read was good so chk if this
;sec has already been read.
(BF6C)
BADREAD DEC READCNTR ;Either got a bad read or else we
;already verified this sector.
;Reduce the number of chances left.
(BF6F) BNE RDNXTADR ;More chances left. Go try again.
* Doing a re-read. Will definitely
* have to reformat.
(BF71)
REREADDR JSR RDADDR ;See dis'mbly below.
(BF74) BCS NOTLAST ;Got a bad read.
* We will reformat but we don't want
* to do so until we read sector $0F.
* Have we found sector $0F yet?
(BF76) LDA SECDSK ;Get phys # of sec just read.
CMP #$0F ;Was it sector 15?
BNE NOTLAST ;No, go look some more.
(BF7C) JSR READATA ;Yes. Read the data in sec $0F.
;(See dis'mbly below.)
(BF7F) BCC FORMATRK ;Good read on sec 15 so now the timing
(BF81) ;is right to GO REFORMAT THIS TRACK.
NOTLAST DEC READCNTR ;Bad read, chk if more chances left.
BNE REREADDR ;Yes - go try again.
SEC ;Exhausted all chances, so set
VRFYRTN RTS ;(c) as error flag & exit.
(BF87) ============
* Check if this sector was previously
* verified. If not, update sector
* verification map. (If timing is
* right, should never encounter an
* already verified sec before FRMTSEC
* decrements from $00 to $FF.)
(BF88)
CKSECMAP LDY SECDSK ;Use # of sec found as index
;to the verification map.
(BF8A) LDA SECFLGS,Y ;Get map byte (neg = prev verified).
BMI BADREAD ;Oh Oh! Already verified this one.
LDA #$FF ;Set byte in map to signal that
STA SECFLGS,Y ;this sector was just verified.
DEC FRMTSEC ;Any secs left to verify?
(BF96) BPL RDNXTADR ;Yes - go do some more.
* All secs verified. Check if
* we just did track $00.
(BF98) LDA FRMTKCTR ;Was trk just formatted = trk $00?
(BF9A) BNE NOTRK0 ;No - so exit cleanly.
* Just formatted & verified trk $00.
* Trk $00 is the outside track and
* therefore has the largest length
* in which to write bytes. Because
* subsequent tracks have a smaller
* circumference, we must reduce the
* number of syncs to write between
* sectors (gap-3) so we can get all
* the needed info into a smaller space.
(BF9C) LDA SYNCNTR ;Check sync count.
CMP #16 ;Less than 16 syncs?
(BFA0) BCC VRFYRTN ;Yes - exit cleanly.
;Don't want to start off with a
;smaller gap, so skip the following
;code which reduces the gap size.
* Reduce the size of gap-3.
(BFA2) DEC SYNCNTR ;Gap > = 16 syncs long, so can afford to
DEC SYNCNTR ;reduce it by two, so can accommodate
NOTRK0 CLC ;a tighter track. Exit cleanly.
(BFA7) RTS
===========
(BEDC) LDA #8 ;Set (a) as default value in case
;couldn't format.
(BEDF) BCS ERRFRMT ;Branch if couldn't format.
* Do a read of trk just formatted.
* (Eventhough track verified, read
* it again until locate track 0.
* Presumably, this (partially)
* double checks verification and
* keeps sectors in different tracks
* somewhat adjacent?)
(BEE0) LDA #48 ;Set 48 attempts to read.
STA READCNTR
RDAGAIN SEC ;Default (c)=1 to signal error.
DEC READCNTR ;Reduce chances to read.
BEQ ERRFRMT ;Exhausted all chances.
(BEEB) JSR RDADDR ;Go read addr header to find sector
;that we want to read or write.
* Read the address header.
(B944)
RDADDR LDY #$FC ;Designate 772 chances (#$FCFC to #$10000)
;to find the correct address prologue.
(B946) STY PROSCRTH
KICKNTR INY
BNE TRYD5
INC PROSCRTH
(B94D) BEQ ERRTN ;Error - can't find proglogue.
* Look for address prologue ("D5 AA 96").
(B94F)
TRYD5 LDA Q5L,X
BPL TRYD5 ;Wait for a full byte.
VERSUSD5 CMP #$D5 ;Was it a "D5"?
BNE KICKNTR ;No - try again.
NOP ;Wait 2 cycles.
TRYAA LDA Q6L,X
BPL TRYAA ;Wait for full byte.
CMP #$AA ;Was it an "AA"?
BNE VERSUSD5 ;No - retry sequence.
(B962) LDY #3 ;Set (y) for later reading of
;vol, trk, sec, checksum info
;from address field.
(B964)
TRY96 LDA Q6L,X
BPL TRY96 ;Wait for full byte.
CMP #$96 ;Was it a "96"?
(B96B) BNE VERSUSD5 ;No - retry sequence.
* Read odd-even encoded volume, track,
* sector and checksum values from the
* address field. (When reading,
* calculate a running checksum.)
* From: byte1: 1 b7 1 b5 1 b3 1 b1
* byte2: b6 1 b4 1 b2 1 b0 1
* -------------------------------
* To: byte: b7 b6 b5 b4 b3 b2 b1 b0
(B96D) LDA #0 ;Initialize running checksum val.
CALCK STA CKSUMCAL
GETHDR LDA Q6L,X ;Get odd-encoded byte.
BPL GETHDR ;Wait for a full byte.
(B976) ROL ;Shift bits & put set
;carry in bit0 pos'n.
(B977) STA PROSCRTH ;Save shifted version.
RDHDR LDA Q6L,X ;Get even-encoded byte.
BPL GETHDR ;Wait for full byte.
AND PROSCRTH ;Merge the bytes to normal.
(B980) STA: CKSUMDSK,Y ;Store info read from addr
;field in zero page:
;$2F = vol found, $2E = trk found,
;$2D = sec found, $2C = checksum found.
;(Use ":" to force 3-byte instruction.)
(B983) EOR CKSUMCAL ;Update running checksum.
DEY
BPL CALCK
TAY ;Put checksum found in (y).
(B989) BNE ERRTN ;If chec sum found < > 0, then error.
;Hackers often change these two bytes
;to "CLC" and "RTS" instructions in
;order to defeat the address checksum
;and ignore the address epilogue.
* Read first 2 bytes (only) of
* the address epilogue ("DE AA").
(B98B)
TRYEPIDE LDA Q6L,X ;Get first byte.
BPL TRYEPIDE ;Wait for a full byte.
CMP #$DE ;Was it a "DE"?
BNE ERRTN ;No - try again.
NOP ;Stall 2 cycles.
TRYEPIAA LDA Q6L,X ;Get second byte.
BPL TRYEPIAA ;Wait for a full byte.
CMP #$AA ;Was it an "AA"?
BNE ERRTN ;No - retry sequence.
GOODRTN CLC ;Signal good read.
(B99F) RTS
============
(B942)
ERRTN SEC ;Signal bad read.
(B943) RTS ;Hackers often change the "SEC" to
============ ;a "CLC" in order to defeat error
;checking.
(BEEE) BCS RDAGAIN ;Bad read - try again.
LDA SECDSK ;Was it sector 0?
BNE RDAGAIN ;No - try again.
(BEF4) JSR READATA ;Last chance to read data.
* Read data sector into RWTS's buffers.
* Look for data prologue.
(B8DC)
READATA LDY #32 ;Set (y) to designate 32
REDUCEY DEY ;attempts to find data prologue.
BEQ ERRTN ;Error - couldn't find data prologue.
PRODATD5 LDA Q6L,X ;Get byte from data prologue.
BPL PRODATD5 ;Wait for a full byte.
VERSD5 EOR #$D5 ;Check if byte was a "D5".
BNE REDUCEY ;Wasn't a "D5, reduce counter.
NOP ;Stall 2 cycles.
PRODATAA LDA Q6L,X ;Read next data prologue byte.
BPL PRODATAA ;Wait for a full byte.
CMP #$AA ;Was it an "AA"?
BNE VERSD5 ;No - restart sequence.
(B8F4) LDY #86 ;Set (y) for later use
;in the read data routine.
(B8F6)
PRODATAD LDA Q6L,X ;Read next byte in data prologue.
BPL PRODATAD ;Wait for a full byte.
CMP #$AD ;Was it an "AD"?
(B8FD) BNE VERSD5 ;No - restart search sequence.
* Read first 86 bytes of data into
* RWTSBUF2 ($BC55 --> $BC00).
*
* Use disk byte as index to the
* NDX2NIBL table which contains
* offsets that we would be using
* if we were accessing a table
* of disk bytes when writing.
* (That is, we are just doing
* the opposite of writing.)
* EOR value from NDX2NIBL table
* with the previous EOR result.
* (On entry, use #$00 for previous
* EOR result.)
(B8FF) LDA #0 ;Initialize (a) for later EORing.
RDUCY DEY ;Reduce index to RWTSBUF2.
STY PROSCRTH ;Save index.
RDSKBYT LDY Q6L,X ;(y) = disk byte.
BPL RDSKBYT ;Wait for a full byte.
(B909) EOR NDX2NIBL-$96,Y ;Use (y) as index to tbl
; of 2-encoded nibbles.
(B90C) LDY PROSCRTH ;Store 2-encoded nibble in RWTSBUF2.
STA RWTSBUF2,Y
(B911) BNE RDUCY ;Conditioned from the "LDY PROSCRTH".
* Read rest of sector into RWTSBUF1
* ($BB00 --> $BBFF).
*
* Use disk byte as index to the
* NDX2NIBL table which contains
* offsets that we would be using
* if we were accessing a table
* of disk bytes when writing.
* (That is, we are just doing
* the opposite of writing.)
* EOR value from NDX2NIBL table
* with the previous EOR result.
(B913)
SAVYNDX STY PROSCRTH ;Save index to RWTSBUF1.
RDSKBYT2 LDY Q6L,X ;(y) = disk byte.
BPL RDSKBYT2 ;Wait for a full byte.
EOR NDX2NIBL-$96,Y ;Get 6-encoded nibble from tbl.
LDY PROSCRTH ;Get index to RWTSBUF1.
STA RWTSBUF1,Y ;Store 6-encoded nibble in RWTSBUF1.
INY
(B923) BNE SAVYNDX ;More disk bytes to read.
* Read the data checksum.
(B925)
RDCHECK LDY Q6L,X ;Get data checksum.
BPL RDCHECK ;Wait for full byte.
(B92A) CMP NDX2NIBL-$96,Y ;Converted checksum = val in $BBFF?
;Remember: Val in $#BBFF is result of
;previous cummulative EORing. There4,
;this comparison with (a) detects any
;(non-cancelling) error(s) that may
;have occurred in the entire sector!!!
(B92D) BNE ERRTN ;No - got an error.
;Hackers often change these two bytes
;to "CLC" and "RTS" instructions in
;order to defeat the data checksum
;and ignore the data epilogue.
* Read the first two bytes (only)
* of the data epilogue ("DE AA").
(B92F)
EPIRDDE LDA Q6L,X ;Read first byte of data epilogue.
BPL EPIRDDE ;Wait for a full byte.
CMP #$DE ;Was it a "DE"?
BNE ERRTN ;No - got an error.
NOP ;Stall for 2 cycles.
EPIRDAA LDA Q6L,X ;Read 2nd data epilogue byte.
BPL EPIRDAA ;Wait for a full byte.
CMP #$AA ;Was it an "AA"?
BEQ GOODRTN ;Yes - got a good read.
ERRTN SEC ;Signal bad read.
(B943) RTS ;Hackers often change the "SEC" to a
============ ;"CLC" in order to defeat error checking.
(B99E)
GOODRTN CLC ;Signal good read.
(B99F) RTS
=============
(BEF7) BCS RDAGAIN ;Last chance bombed out!!!
INC FRMTKCTR ;Kick up trk counter.
LDA FRMTKCTR ;Set (a) for next trk count.
CMP #$23 ;Done all trks yet (#0 to #34)?
BCC FRMNXTRK ;No - GO FORMAT THE NEXT TRACK.
CLC ;Signal finished all tracks.
(BF02) BCC DONEFRMT ;ALWAYS - ONLY GOOD EXIT.
------------
* Note: No matter what kind of error we
* might have encountered when formatting,
* the IOB error code is always set to $08.
* This is later translated to an FM error
* code (also $08) which DOS displays as
* a I/O error message. (This is why trying
* to format a write-protected disk results
* in a an I/O error message instead of a
* disk-write-protected message.)
* If no error occurred, the IOB error byte
* will be set to some random number (as a result of
* referencing a hardware switch).
(BF04)
ERRFRMT LDY #13 ;Index to return code in IOB.
STA (PTR2IOB),Y ;Store return code.
SEC ;Signal that an error occurred.
DONEFRMT LDA MTROFF,X ;Turn motor off & exit with (c)
(BF0C) RTS ;denoting success status.
============
(B7BA) BCS ERRENTER ;Branch if operation unsuccessful.
PLP ;Throw status off stk.
CLC ;Signal successful.
(B7BE) RTS
============
(B7BF)
ERRENTER PLP ;Throw status off stk.
SEC ;Signal UNsuccessful.
(B7C1) RTS
============
(B093) LDA IBSMOD ;Get vol found from IOB
STA VOLFM ;& put it in Fm parm list.
LDA #$FF ;Designate vol wanted in
(B09B) STA IBVOL ;IOB as 255 for next time.
;(Actually using 0 cause FF EOR FF = 0.)
(B09E) BCS ERRWTSDR ;Branch if UNsuccessful operation.
(B0A0) RTS
=============
* Operation was NOT successful.
(B0A1)
ERRWTSDR LDA IBSTAT ;Get RWTS'S error code.
* Translate IOB error code (a) to
* FM error code (y). (DOS later employs
* the FM error code in the routine used
* to print error messages.)
(B0A4) LDY #7 ;Set (y) for FM vol mismatch.
CMP #$20 ;Vol mismatch?
BEQ SETFMERR ;Yes.
LDY #$04 ;No.
CMP #$10 ;Write protected?
BEQ SETFMERR ;Yes.
LDY #8 ;Must have been other, so
SETFMERR TYA ;designate as general I/O error.
(B0B3) JMP BADFMXIT ;Go handler error.
------------
(B385)
BADFMXIT SEC ;(c) = 1 to signal UNsuccessful.
FMEXIT PHP ;Preserve success of operation on stk.
STA RTNCODFM ;Put appropriate return code in FM parm list.
LDA #0 ;Avoid that infamous $48 bug.
STA STATUS
(B38E) JSR CPYFMWA
(AE7E)
CPYFMWA JSR SELWKBUF
* Point the A4L/H pointer at the DOS work buffer (chain).
(AF08)
SELWKBUF LDX #0 ;Designate work area buffer.
(AF0A) BEQ PT2FMBUF ;ALWAYS.
(AF12)
PT2FMBUF LDA WRKBUFFM,X ;Get addr of DOS's work buffer
STA A4L ;(chain) from FM parm list and put
LDA WRKBUFFM+1,X ;it in the A4L/H pointer.
STA A4L+1
(AF1C) RTS
* Copy work area buffer (non-chain)
* to DOS work buffer (chain).
(AE81) LDY #0
STORWRK LDA FMWKAREA,Y
STA (A4L),Y
INY
CPY #45
BNE STORWRK
(AE8D) RTS
(B391) PLP ;Exit with (c) conditioned accordingly.
LDX STKSAV ;Reset the stack pointer so execution will
TXS ;return to the caller of the function.
(B396) RTS ;(Normally returns to AFTRFUNC ($A6AB)
============ ;located in the FMDRIVER routine ($A6A8).)