*================================
* PRENIBBLE DATA ($B800-$B829).
* CONVERT 256 MEMORY BYTES TO 342
* SIX-BIT NIBBLES AS SHOWN BELOW.
*================================

* ON ENTRY:  PTR2BUF PTS AT DATA BUF.
* ON EXIT:  (A) = ?.
*           (X) = #$FF.
*           (Y) = #$FF.
*           (C) = 1.

*              RWTSBUF1
* BB00: 0 0 00-7 00-6 00-5 00-4 00-3 00-2
* BB01: 0 0 01-7 01-6 01-5 01-4 01-3 01-2
* BB02: 0 0 02-7 02-6 02-5 02-4 02-3 02-2
*   .
*   .
*   .
* BBFF: 0 0 FF-7 FF-6 FF-5 FF-4 FF-3 FF-2
*
*              RWTSBUF2
* BC00: 0 0 01-0 01-1 AB-0 AB-1 55-0 55-1
* BC01: 0 0 00-0 00-1 AA-0 AA-1 54-0 54-1
* BC02: 0 0 FF-0 FF-1 A9-0 A9-1 53-0 53-1
*   .
*   .
*   .
* BC54: 0 0 AD-0 AD-1 57-0 57-1 01-0 01-1
* BC55: 0 0 AC-0 AC-1 56-0 56-1 00-0 00-1

* WHERE "AC-0" = BIT0 OF MEMORY BYTE
*                WHICH IS OFFSET
*                #$AC BYTES INTO
*                THE DATA SECTOR.
* THE FOLLOWING BITS ARE DUPLICATED
* IN $BC00-$BC01 & $BC54-$BC55 BUT
* ARE IGNORED IN $BC00-$BC01:
*             01-0,01-1,00-0,00-1.

PRENIBL LDX #0
 LDY #2
PRENIB1 DEY
 LDA (PTR2BUF),Y ;GET BYTE FROM "DATA" BUFFER.
 LSR ;PUT ITS LWR 2 BITS IN2 RWTSBUF1.
 ROL RWTSBUF2,X
 LSR
 ROL RWTSBUF2,X
 STA RWTSBUF1,Y ;PUT REMAINING 6 BITS N RWTSBUF1.
 INX
 CPX #$56
 BCC PRENIB1
 LDX #0
 TYA
 BNE PRENIB1 ;REPEAT UNTIL @ BYTE OF RWTSBUF2
;HAS 6 BITS.
 LDX #$55 ;MAKE SURE BITS 6 & 7 OF RWTSBUF2
PRENIB2 LDA RWTSBUF2,X ;ARE ZEROES.
 AND #%00111111
 STA RWTSBUF2,X
 DEX
 BPL PRENIB2
 RTS


*====================================
* WRITE SECTOR TO DISK ($B82A-$B8B7).
*====================================

* ON ENTRY: (X) = SLOT*16
* ON EXIT:  (C) = 1 = WRIT PROT ERR.
*           IF NO ERROR: (C) = 0
*                        (A) = ?
*                        (X) = SLOT*16
*                        (Y) = #$00


WRITESEC SEC ;(C)=1, ASSUME WRITE PROTECTED
;ERROR AS DEFAULT CONDITION.
 STX FRMTSLOT ;SAVE SLOT*16 IN PAGES 0 & 6.
 STX SLOTPG6
 LDA Q6H,X ;CHK IF DISK IS WRITE PROTECTED.
 LDA Q7L,X
 BMI PROTECTD ;BRANCH IF WRITE PROTECTED.
 LDA RWTSBUF2 ;GET 1RST 2-ENCODED BYTE AND SAVE
 STA HOLDNIBL ;IT FOR LATER USE.

* WRITE 5-SYNC GAP BETWEEN ADDRESS
* EPILOGUE & DATA PROLOGUE.

 LDA #$FF ;(A) = SYNC BYTE.
 STA Q7H,X ;WRITE 1 SYNC BYTE.
 ORA Q6L,X
 PHA ;(3 CYC)
 PLA ;(4 CYC)
 NOP ;(2 CYC)
 LDY #4 ;WRITE 4 MORE SYNCS (2 CYC).
WRITE4FF PHA ;(3 CYC)
 PLA ;(4 CYC)
 JSR WRITE2 ;(12 CYC BEFORE, 6 AFTER.)
 DEY ;(2 CYC)
 BNE WRITE4FF ;(2 OR 3 CYC)

* WRITE DATA PROLOGUE ("D5 AA AD").

 LDA #$D5 ;(2 CYC)
 JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
 LDA #$AA ;(2 CYC)
 JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
 LDA #$AD ;(2 CYC)
 JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)

* CONVERT & WRITE CONTENTS OF RWTS
* BUFFERS TO DISK.  (WHEN FORMATTING,
* THESE BUFS ARE ZEROED OUT.  THE
* "$00" BYTES IN BUF ARE LATER TRANS-
* LATED TO "$96" BYTES ON THE DISK.)

* CONVERT & WRITE 2-ENCODED
* NIBBLES FROM RWTSBUF2.
* (EOR TO CALC (X) & THEN USE (X)
* AS INDEX TO TBL OF DISK BYTES.)
*
*    #0 EOR $BC55 = (X)
* $BC55 EOR $BC54 = (X)
* $BC54 EOR $BC53 = (X)
*    .   .     .     .
*    .   .     .     .
*    .   .     .     .
* $BC01 EOR $BC00 = (X)

 TYA ;(A) = 0.
 LDY #$56 ;(DEC #86.)
 BNE DOEOR ;ALWAYS.
GETNIBL LDA RWTSBUF2,Y
DOEOR EOR RWTSBUF2-1,Y
 TAX ;INDEX TO DISK BYTE.
 LDA DSKNBTBL,X ;GET DISK BYTE.
 LDX FRMTSLOT ;(X) = SLOT*16.
 STA Q6H,X ;WRITE BYTE.
 LDA Q6L,X
 DEY ;(Y) = $56 --> #$00.
 BNE GETNIBL ;(WRITE $56 OR DEC #86 BYTES.)

* CONVERT & WRITE 6-ENCODED
* NIBBLES FROM RWTSBUF1.
*
* $BC00 EOR $BB00 = (X)
* $BB00 EOR $BB01 = (X)
* $BB01 EOR $BB02 = (X)
*   .    .    .      .
*   .    .    .      .
*   .    .    .      .
* $BBFE EOR $BBFF = (X)

 LDA HOLDNIBL ;NORMALLY = CONTENTS OF $BC00.
 NOP
SCNDEOR EOR RWTSBUF1,Y
 TAX ;INDEX TO DISK BYTE.
 LDA DSKNBTBL,X ;GET DISK BYTE TO WRITE.
 LDX SLOTPG6 ;(X) = SLOT*16.
 STA Q6H,X ;WRITE 87TH ---> 341ST BYTES.
 LDA Q6L,X
 LDA RWTSBUF1,Y
 INY ;(Y) = #$00 ---> #$FF.
 BNE SCNDEOR

* CONVERT & WRITE DATA CHECKSUM.
* (342ND BYTE, $BBFF ------> (X).)

 TAX ;INDEX TO TABLE OF DISK BYTES.
 LDA DSKNBTBL,X ;GET DISK BYTE TO WRITE.
 LDX FRMTSLOT ;(X) = SLOT*16.
 JSR WRITE3 ;(5 CYCS BEFORE, 6 AFTER.)

* WRITE DATA EPILOGUE ("DE AA EB").

 LDA #$DE ;(2 CYC)
 JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
 LDA #$AA ;(2 CYC)
 JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
 LDA #$EB ;(2 CYC)
 JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)

* WRITE A SYNC BYTE.

 LDA #$FF ;(2 CYC)
 JSR WRITE1 ;(14 CYCS BEFORE, 6 AFTER.)
 LDA Q7L,X ;SET READ MODE.
PROTECTD LDA Q6L,X
 RTS


*====================================
* WRITE BYTE WITH VARIOUS DELAYS.
* (DELAYS PRIOR TO ENTRY & THOSE
* SHOWN BELOW RESULT IN WRITING BYTES
* EVERY 32 MACHINE CYCLES.)
*====================================

WRITE1 CLC ;(2 CYC)
WRITE2 PHA ;(3 CYC)
 PLA ;(4 CYC)
WRITE3 STA Q6H,X ;(5 CYC) - SHIFT REGISTER)
 ORA Q6L,X ;(4 CYC - STROBE LATCH)
 RTS ;(6 CYC)


*=================================
* POSTNIBBLE DATA ($B8C2 - $B8DB).
* CONVERT 6- & 2-ENCODED BYTES IN
* RWTS'S TWO BUFFERS TO NORMAL
* MEMORY BYTES (USUALLY PLACED IN
* DOS DATA SECTOR BUFFER).
*=================================

* ON ENTRY:  (X) = SLOT*16.
*            PTR2BUF = PTS TO DATA BUF.
* ON EXIT:  (A) = ?
*           (X) = ?
*           (Y) = BYTE COUNT USED
*                 FOR RWTBUF2.
*           (C) = 1.

POSTNB16 LDY #0
POSTNIB1 LDX #$56 ;(DEC #86.)
POSTNIB2 DEX
 BMI POSTNIB1
 LDA RWTSBUF1,Y ;SET (A) = 6-ENCODED BYTE.
 LSR RWTSBUF2,X ;PUT LWR 2 BITS OF 2-ENCODED BYTE
 ROL ;INTO ORIGNAL 6-ENCODED BYTE TO
 LSR RWTSBUF2,X ;CREATE A NORMAL MEMORY BYTE.
 ROL
 STA (PTR2BUF),Y ;PUT NORMAL MEMORY BYTE IN RWTS'S
 INY ;BUF (NORMALLY DOS DATA SEC BUF).
 CPY PROSCRTH
 BNE POSTNIB2
 RTS


*===================================
* READ DATA SECTOR INTO RWTS'S BUFS.
*===================================

* CONDITIONS FOR $B8DC - $B943:
* ON ENTRY:  (X) = SLOT*16
*  ON EXIT:  (C) = 1 IF ERROR
*            IF NO ERR: (C) = 0.
*                       (A) = #$AA.
*                       (X) = SLOT*16.
*                       (Y) = #$00.

* FIND DATA PROLOGUE ("D5 AA AD").

READATA LDY #32 ;SET (Y) = 32 ATTEMPTS TO FIND
REDUCEY DEY ;THE DATA PROLOGUE.
 BEQ ERRTN ;ERROR - CAN'T FIND DAT PROLOGUE.
PRODATD5 LDA Q6L,X ;GET BYTE FROM DATA PROLOGUE.
 BPL PRODATD5 ;WAIT FOR FULL BYTE.
VERSD5 EOR #$D5 ;CHK IF BYTE WAS "D5".
 BNE REDUCEY ;WASN'T "D5", REDUCE COUNTER.
 NOP ;STALL 2 CYCLES.
PRODATAA LDA Q6L,X ;READ NEXT DATA PROLOGUE BYTE.
 BPL PRODATAA ;WAIT FOR FULL BYTE.
 CMP #$AA ;WAS IT AN "AA"?
 BNE VERSD5 ;NO - GO RESTART SEQUENCE.
 LDY #$56 ;SET (Y) FOR LATER USE IN READ
;DATA ROUTINE.
PRODATAD LDA Q6L,X ;READ NEXT BYTE IN DATA PROLOGUE.
 BPL PRODATAD ;WAIT FOR FULL BYTE.
 CMP #$AD ;WAS IT AN "AD"?
 BNE VERSD5 ;NO - GO RESTART SEQUENCE.

* READ 1RST 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.
* (IE. WE ARE JUST DOING OPPOSITE
* OF WRITING.)
* EOR VALUE FROM NDX2NIBL TABLE
* WITH PREVIOUS EOR RESULT.  (ON
* ENTRY, USE #$00 FOR PREVIOUS
* EOR RESULT.)

 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 FULL BYTE.
 EOR NDX2NIBL-$96,Y ;USE (Y) AS INDEX TO TABLE OF
;2-ENCODED NIBBLES.
 LDY PROSCRTH ;RETRIEVE INDEX TO SECOND BUF.
 STA RWTSBUF2,Y ;STORE 2-ENCODED NIBL N RWTSBUF2.
 BNE RDUCY ;Z-FLG CONDITIONED FRM THE "LDY".

* READ REST OF SEC 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.
* (IE. WE ARE JUST DOING OPPOSITE
* OF WRITING.)
* EOR VALUE FROM NDX2NIBL TABLE
* WITH PREVIOUS EOR RESULT.

SAVYNDX STY PROSCRTH ;SAVE INDEX TO RWTSBUF1.
RDSKBYT2 LDY Q6L,X ;(Y) = DISK BYTE.
 BPL RDSKBYT2 ;WAIT FOR FULL BYTE.
 EOR NDX2NIBL-$96,Y ;GET 6-ENCODED NIBL FRM TBL.
 LDY PROSCRTH ;GET INDEX TO RWTSBUF1.
 STA RWTSBUF1,Y ;STORE 6-ENCODED NIBL N RWTSBUF1.
 INY
 BNE SAVYNDX ;MORE DISK BYTES TO READ.

* READ DATA CHECKSUM.

RDCHECK LDY Q6L,X ;GET DATA CHECKSUM BYTE FROM DSK.
 BPL RDCHECK ;WAIT FOR FULL BYTE.
 CMP NDX2NIBL-$96,Y ;DOES CONVERTED CHKSUM EQUAL
;THE VALUE 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!!!
 BNE ERRTN ;ERROR -DIDN'T MATCH WITH CHKSUM.
;HACKERS OFTEN CHANGE THESE TWO
;BYTES 2 "CLC" AND "RTS" INSTRUCS
;IN ORDER TO DEFEAT DATA CHECKSUM
;AND IGNORE THE DATA EPILOGUE.

* READ 1RST TWO BYTES (ONLY) OF
* DATA EPILOGUE ("DE AA EB").

EPIRDDE LDA Q6L,X ;READ 1RST BYTE OF DATA EPILOGUE.
 BPL EPIRDDE ;WAIT FOR FULL BYTE.
 CMP #$DE ;IS IT A "DE"?
 BNE ERRTN ;NO - GOT AN ERROR.
 NOP ;STALL 2 CYCLES.
EPIRDAA LDA Q6L,X ;READ 2ND BYTE OF DATA EPILOGUE.
 BPL EPIRDAA ;WAIT FOR FULL BYTE.
 CMP #$AA ;IS IT AN "AA"?
 BEQ GOODRTN ;YES - GOT A GOOD READ.
ERRTN SEC ;SIGNAL BAD READ.
 RTS ;HACKERS OFTEN CHANGE THE "SEC" 2
;"CLC" TO DEFEAT ERROR CHECKING.


*====================================
* READ ADDRESS ROUTINE ($B944-$B99F).
*====================================

* ON ENTRY:  (X) = SLOT*16.
* ON EXIT:  (C) = 1 IF ERROR.
*           IF NO ERRS: (A) = #$AA.
*                       (Y) = #$00.
*                       (X) = SLOT*16.
*                       $2C = CHECKSUM VAL FOUND.
*                       $2D = SEC # FOUND.
*                       $2E = TRK # FOUND.
*                       $2F = VOL # FOUND.

* READ THE ADDRESS HEADER.

RDADDR LDY #$FC ;SET 772 CHANCES TO FIND CORRECT
 STY PROSCRTH  ;ADR PROLOGUE (#$FCFC-#$10000).
KICKNTR INY
 BNE TRYD5
 INC PROSCRTH
 BEQ ERRTN ;ERROR - CAN'T FIND PROLOGUE.

* FIND ADR PROLOGUE ("D5 AA 96").

TRYD5 LDA Q6L,X
 BPL TRYD5 ;WAIT FOR A FULL BYTE.
VERSUSD5 CMP #$D5 ;WAS IT "D5"?
 BNE KICKNTR ;NO - TRY AGAIN.
 NOP ;WAIT 2 CYCLES.
TRYAA LDA Q6L,X
 BPL TRYAA ;WAIT FOR FULL BYTE.
 CMP #$AA ;WAS IT "AA"?
 BNE VERSUSD5 ;NO - RETRY SEQUENCE.
 LDY #3 ;SET (Y) 4 LATER READING OF VOL,
;TRK, SEC & CHKSUM INFO FROM THE
;ADRRESS FIELD.
TRY96 LDA Q6L,X
 BPL TRY96 ;WAIT FOR A FULL BYTE.
 CMP #$96 ;WAS IT "96"?
 BNE VERSUSD5 ;NO - RETRY SEQUENCE.

* READ ODD-EVEN ENCODED VOL, TRK,
* SEC & CHECKSUM FROM ADR FIELD.
* (DURING READING, CALC A RUNNING
* CHECKSUM.)
* FROM: BYTE1: 1  B7  1 B5  1 B3  1  B1
*       BYTE1: B6 1  B4 1  B2 1  B0  1
*       ---------------------------------
* TO:   BYTE:  B7 B6 B5 B4 B3 B2 B1 B0

 LDA #0 ;INTIALIZE FOR RUNNING CHECKSUM.
CALCK STA CKSUMCAL
GETHDR LDA Q6L,X ;GET ODD-ENCODED BYTE.
 BPL GETHDR ;WAIT FOR A FULL BYTE.
 ROL ;SHIFT BITS, PUT (C)=1 IN BIT0.
 STA PROSCRTH ;SAVE SHIFTED VERSION.
RDHDR LDA Q6L,X ;GET EVEN-CODED BYTE.
 BPL RDHDR ;WAIT FOR A FULL BYTE.
 AND PROSCRTH ;MERGE & CREATE NORM MEMORY BYTE.
 STA: CKSUMDSK,Y ;STORE INFO READ FROM ADDR FIELD
;IN Z-PAGE:
;2F = VOL FND, 2E = TRK FND,
;2D = SEC FND, 2C = CHECKSUM FND.
;(NOTE "STA:" FORCES 3-BYT CODE.)
 EOR CKSUMCAL ;UPDATE RUNNING CHECKSUM.
 DEY
 BPL CALCK
 TAY ;PUT CHECKSUM FOUND IN (Y).
 BNE ERRTN ;IF CHKSUM FOUND < > 0 THEN ERR.
;HACKERS OFTEN CHANGE THESE TWO
;BYTES 2 "CLC" AND "RTS" INSTRUCS
;IN ORDER 2 DEFEAT THE ADR CHKSUM
;AND IGNORE THE ADR EPILOGUE.

* READ 1RST 2 BYTES (ONLY) OF
* ADDRESS EPILOGUE ("DE AA EB").

TRYEPIDE LDA Q6L,X ;GET 1RST 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 2ND BYTE.
 BPL TRYEPIAA ;WAIT FOR A FULL BYTE.
 CMP #$AA ;WAS IT AN "AA"?
 BNE ERRTN ;NO - RETRY SEQUENCE.
GOODRTN CLC ;SIGNAL GOOD READ.
 RTS


*======================================
*  MOVE DISK ARM TO A GIVEN HALFTRACK
*  POSITION ($B9A0-$B9FF).
*======================================

* ON ENTRY: (X) = SLOT*16
*           (A) = DESTINATION HALFTRK.
*       PRESTRK = CURRENT HALFTRK.
* ON EXIT:  (A) = ?
*           (X) = SLOT*16.
*           (Y) = ?
*        DESTRK = FINAL HALFTRK.
*       PRESTRK = FINAL HALFTRK.
*      HOLDPRES = PREVIOUS HALFTRK.

SEEKABS STX SLT16ZPG ;SAVE SLOT*16 IN ZERO PAGE.
 STA DESTRK ;SAVE DESTINATION HALFTRK#.
 CMP PRESTRK ;DESTINATION 1/2TRK=PRES 1/2TRK?
 BEQ ARRIVED ;YES-WE'RE ALREADY THERE, SO XIT.
 LDA #0 ;INIT COUNTER 4 # OF TRKS MOVED.
 STA STPSDONE

* SAVE CURRENT HALFTRK POS'N AND CALC #
* OF HALFTRKS NEED TO MOVE MINUS 1.

SAVCURTK LDA PRESTRK ;SAVE CURRENT HALFTRK POSITON.
 STA HOLDPRES
 SEC ;CALC (PRESTRK-DESTRK).
 SBC DESTRK
 BEQ ATDESTN ;AT DESTINATION SO GO SHUTDOWN.
 BCS MOVDOWN ;PRES 1/2TRK > DESTINATION 1/2TRK
;SO WANT 2 MOVE 2 LOWER 1/2TRK#.

* WANT TO MOVE TO HIGHER HALFTRK#.
* (PRESTRK - DESTRK = NEG RESULT.)

 EOR #$FF ;CONVERT NEG TO POS.
 INC PRESTRK ;MOVING UP,SO INC CURRENT HALFTRK
;POS'N FOR NEXT TIME AROUND.
 BCC CKDLYNDX ;ALWAYS.

* WANT TO MOVE TO LOWER HALFTRK#.
* (PRESTRK - DESTRK = POS RESULT.)

MOVDOWN ADC #$FE ;SIMULATE A SUBTRATION OF 1.
;ACTUALLY ADDING MINUS 1 (#$FF)
;CAUSE (C)=1.  WANT (A) TO EQUAL
;1 LESS THAN # OF HALFTRKS 2 MOV.
 DEC PRESTRK ;MOVING DOWN, REDUCE PRES HALFTRK
;NUMBER FOR NEXT TIME AROUND.

* CHECK TO SEE WHICH INDEX TO USE
* TO ACCESS THE DELAY TABLE.  IF
* WE ARE WITHIN 12 STEPS OF THE
* DESTINATION OR START POS'NS, USE
* CLOSEST DISTANCE TO START OR END
* POS'N TO INDEX THE DELAY TABLES.
* DELAY TABLES ARE ONLY 12 BYTES
* LONG, SO IF MORE THAN 12 STEPS
* AWAY FROM BOTH START & DEST'N,
* USE LAST INDEX (Y=12) TO ACCESS
* THE TABLE.

* CHECK IF CLOSER TO DEST'N OR
* START POS'N.

CKDLYNDX CMP STPSDONE ;COMPARE # OF HALFTRKS ALREADY
;MOVED VS # HALFTRKS NEED 2 MOVE.
 BCC CLSR2ND ;CLOSER TO DEST'N THAN START.

* CLOSER TO START.

 LDA STPSDONE ;(A) = DISTANCE FROM START POS'N.

* ENTRY PT IF CLOSER TO END.

CLSR2ND CMP #12 ;ARE WE WITHIN 12 STEPS OF START
;OR DESTINATION POS'N?
 BCS TURNON ;WE ARE AT OR BEYOND 12 STEPS FRM
;START OR DEST'N POS'N SO USE OLD
;INDEX TO ACCESS DELAY TABLE.
PRESNDX TAY ;USE PRES DISTANCE 2 INDEX TABLE.
TURNON SEC ;(C)=1 SO GET ODD INDEX TO BASE
;ADR SO MAGNET WILL BE TURNED ON.
 JSR ONOROFF ;TURN MAGNET ON TO SUCK STEPPER
;MOTOR 2 CORRECT HALFTRACK POS'N.
 LDA ONTABLE,Y ;GET TIME TO LEAVE MAGNET ON.
 JSR DELAY ;DELAY TO GIVE DRIVE TIME TO ACT
;BEFORE MAGNET TURNED OFF AGAIN
;CAUSE COMPUTER IS TOO FAST FOR
;PERIPHERAL & WANT SMOOTH MOV'T.
 LDA HOLDPRES ;(A) = LAST HALFTRK POS'N.
 CLC ;CLR (C) SO INDEX WILL COME OUT
;EVEN & THERE4 MAGNET WILL BE
;TURNED OFF.
 JSR ENTRYOFF ;TURN OFF THE MAGNET ASSOC WITH
;PREVIOUS POS'N.
 LDA OFFTABLE,Y ;GET TIME TO LEAVE MAGNET OFF.
 JSR DELAY ;LEAVE MAGNET OFF FOR A WHILE TO
;GIVE ARM TIME TO BE PROPERLY
;ALIGNED.  (NEED TIME TO SUCK IT
;OVER & ALSO TO DECREASE BOUNCE
;OR OVER SHOOT.)
 INC STPSDONE
 BNE SAVCURTK ;ALWAYS.


*----------------------------------
* ARRIVED AT DESTINATION HALFTRACK.
*----------------------------------

ATDESTN JSR DELAY ;WAIT ON PERIPHERAL AGAIN.

* TURN LAST-USED MAGNET OFF SO EXIT
* WITH ALL PHASES (IE.MAGNETS) OFF.
* NOTE:  THIS IS VERY IMPORTANT
* CAUSE MAG1ON IS WIRED INTO THE
* WRITE-PROTECT SWITCH!!!

 CLC ;CLR (C) SO NDX WILL COME OUT AS
;EVEN & THERE4 MAGNET WILL BE
;TURNED OFF.

*---------------------------------
*     TURN MAGNET ON OR OFF.
*---------------------------------

ONOROFF LDA PRESTRK ;USE HALFTRK POS'N 2 INDEX MAGNET
ENTRYOFF AND #%00000011 ;ONLY KEEP LWR 2 BITS OF HALFTRK#
;BECAUSE ONLY 4 MAGNETS (0,1,2,3)
 ROL ;MULTIPLY HALFTRK * 2 & ADD (C).
;IF (C)=0, RESULT EVEN, MAG OFF
;IF (C)=1, RESULT ODD, MAGNET ON.
 ORA SLT16ZPG ;MERGE INDEX 2 MAGNET WITH SLOT#.
 TAX ;USE (X) TO INDEX MAGNET ON/OFF.
 LDA MAG0FF,X ;USE MAGNET-0-OFF AS BASE ADR.
 LDX SLT16ZPG ;RESTORE (X) = SLOT*16.
ARRIVED RTS


*=================================
*    FREE SPACE ($B9FD-$B9FF).
*=================================

 HEX AAA0A0 ;UNUSED.


*==================================
* MAIN DELAY ROUTINE IN DOS.
* AMT OF DELAY = 100*(A) MICROSECS.
*==================================

DELAY LDX #17
DLY1 DEX
 BNE DLY1
 INC MTRTIME
 BNE DLY2
 INC MTRTIME+1
DLY2 SEC
 SBC #1
 BNE DELAY
 RTS


*=================================
* DELAY TIMES FOR STEPPER MOTOR
* MOVEMENTS. (VALUE * 100 = DELAY
* IN MICROSECONDS.)
*=================================


*---------------------------------
*    TIMES TO LEAVE MAGNET ON.
*         ($BA11 - $BA1C)
*---------------------------------

ONTABLE HEX 01302824201E1D1C1C1C1C1C


*---------------------------------
*   TIMES TO LEAVE MAGNET OFF.
*         ($BA1D - $BA28)
*---------------------------------

OFFTABLE HEX 702C26221F1E1D1C1C1C1C1C


*=================================
*      TABLE OF DISK BYTES.
*        ($BA29 - $BA68)
*=================================

DSKNBTBL HEX 96979A9B9D9E9F
 HEX A6A7ABACADAEAF
 HEX B2B3B4B5B6B7B9BABBBCBDBEBF
 HEX CBCDCECF
 HEX D3D6D7D9DADBDCDDDEDF
 HEX E5E6E7E9EAEBECEDEEEF
 HEX F2F3F4F5F6F7F9FAFBFCFDFEFF


*=================================
*   CHECK IF USING APPEND CMD.
*   (RECENT PATCH, $BA69-$BA75)
*=================================

* RAN OUT OF DATA SO BETTER CHECK
* IF WE ARE APPENDING.

CKIFAPND LDX NDX2CMD ;GET COMMAND INDEX.
 CPX #$1C ;ARE WE APPENDING?
 BEQ RTNCKAPN ;YES - LEAVE APPEND FLAG ON.
 LDX #0 ;NO - MAKE SURE APPEND FLG OFF.
 STX APPNDFLG
RTNCKAPN RTS


*=================================
*   CLOBBER THE 80-COLUMN CARD.
*   (RECENT PATCH, $BA76-$BA83)
*=================================

CONTCLOB LDA #$FF ;SET MODE FLAG FOR CARD.
 STA $4FB ;SCRATCH PAD MEMORY FOR SLOT3.
 STA $C00C ;TURN OFF THE ALTERNATE CHAR SET.
 STA $C00E
 JMP INIT ;SIMULATE A TEXT STATEMENT.


*=================================
*           FREE SPACE
*         ($BA84 - $BA95)
*=================================

 DS 18


*==================================
* TABLE OF BYTES USED WHEN READING.
*         ($BA96 - $BAFF)
* - USED TO TRANSLATE A DISK BYTE
*   TO A 2- OR 6-ENCODED NIBBLE
*   NEEDED FOR THE RWTS BUFFERS).
*==================================

* NUMBERS > $3F REPRESENT ILLEGAL
* DISK BYTES VALUES THAT ARE SIMPLY
* USED AS SPACERS IN TABLE.

NDX2NIBL HEX 0001 ;     VALID INDICES.
 HEX 9899 ;     2 SPACERS.
 HEX 0203 ;     VALID INDICES.
 HEX 9C ;     1 SPACER.
 HEX 040506 ;     VALID INDICES.
 HEX A0A1A2A3A4A5 ;   6 SPACERS.
 HEX 0708 ;     VALID INDICES.
 HEX A8A9AA ;     3 SPACERS.
 HEX 090A0B0C0D ;     VALID INDICES.
 HEX B0B1 ;     2 SPACERS.
 HEX 0E0F10111213 ;   VALID INDICES.
 HEX B8 ;     1 SPACER.
 HEX 1415161718191A ; VALID INDICES.
 HEX C0C1C2C3C4C5 ;   6 SPACERS.
 HEX C6C7C8C9CA ;     5 SPACERS.
 HEX 1B ;     VALID INDEX.
 HEX CC ;     1 SPACER.
 HEX 1C1D1E ;     VALID INDICES.
 HEX D0D1D2 ;     3 SPACERS.
 HEX 1F ;     VALID INDEX.
 HEX D4D5 ;     2 SPACERS.
 HEX 2021 ;     VALID INDICES.
 HEX D8 ;     1 SPACER.
 HEX 22232425262728 ; VALID INDICES.
 HEX E0E1E2E3E4 ;     5 SPACERS.
 HEX 292A2B ;     VALID INDICES.
 HEX E8 ;     1 SPACER.
 HEX 2C2D2E2F303132 ; 7 INDICES.
 HEX F0F1 ;     2 SPACERS.
 HEX 333435363738 ;   VALID INDICES.
 HEX F8 ;     1 SPACER.
 HEX 393A3B3C3D3E3F ; VALID INDICES.


*=================================
* BUFFER ($BB00-BBFF) OF 6-ENCODED
* NIBBLES (IE. 00XXXXXX, WHERE
* X = 0 OR 1, BITS 6 & 7 ARE
* ALWAYS 0).
* USED AS A TRANSITION BUFFER
* BETWEEN NORMAL MEMORY BYTES
* AND DISK BYTES.
*=================================

RWTSBUF1 DS 256


*==================================
* BUFFER ($BC00-$BC55) OF 2-ENCODED
* NIBBLES.
*==================================

* NIBBLES ARE OF THE FORM:
* 0  0  JJ-0 JJ-1 KK-0 KK-1 LL-0 LL-1
* WHERE BITS 6 & 7 ARE ALWAYS 0.
* HOWEVER THE OTHER BITS REPRESENT
* A MIXTURE OF BITS FROM DIFFERENT
* ORIGINAL MEMORY BYTES.
* (IE. JJ-0 REPRESENTS BIT 0 FROM
* ORIGINAL MEMORY BYTE JJ.)

RWTSBUF2 DS 86


*======================================
* WRITE ADDRESS HEADER ($BC56-$BCC3).
* (ONLY USED BY RWTS'S FORMAT COMMAND).
*======================================

* ON ENTRY: (X) = SLOT*16.
*           (Y) = # OF SELF SYNCS
*                 TO WRITE.
*       HOLDAA  = #$AA.
*       FRMTSEC = SEC #.
*       FRMTVOL = VOL #.
*      FRMTKCTR = TRK #.
* ON EXIT:  (A) = ?
*           (X) = SLOT*16.
*           (Y) = #$00.
*           (C) = 0 IF NOT PROTECTED.
*               = 1 IF WRITE PROTECTED.

WRITADR SEC ;(C)=1, ASSUME ERROR AS DEFAULT.
 LDA Q6H,X ;CHK IF DISK IS WRITE PROTECTED.
 LDA Q7L,X
 BMI SET4RD ;BRANCH IF WRITE PROTECTED.


* NOT WRITE PROTECTED SO PREP TO
* WRITE A GAP OF 40-CYCLE SYNC
* BYTES BTWN SECS.  (THIS ROUTINE
* WRITES 2 DIF SIZES OF GAPS. GAP1
* PRECEEDS SEC $00.  IT INITIALLY
* CONSISTS OF 128 SELF-SYNC BYTES
* BUT IS LATER PARTIALLY OVER-
* WRITTEN BY SEC $0F.  GAP3 OCCURS
* BTWN THE ADDR FIELD OF THE
* PRECEEDING SEC & THE DATA FIELD
* OF THE NEXT SEC.  ITS LENGTH
* VARIES WITH THE TRK # AND THE
* SPEED OF THE SPECIFIC DRIVE
* BEING USED.)


 LDA #$FF ;(A) = SYNC BYTE.
 STA Q7H,X ;SET WRITE MODE.
 CMP Q6L,X
 PHA ;(3 CYC)
 PLA ;(4 CYC)
WRTSYNC JSR WTADDRTN ;(12 CYC)
 JSR WTADDRTN ;(12 CYC)
 STA Q6H,X ;(5 CYC)
 CMP Q6L,X ;(4 CYC), WRITE BYTE.
 NOP ;(2 CYC)
 DEY ;(2 CYC)
 BNE WRTSYNC ;(3 CYC ON BRNCH, 2 ON FALL THRU)

* WRITE ADDRESS PROLOGUE.
* ("D5 AA 96", 32-CYCLE BYTES.)

 LDA #$D5 ;(2 CYC)
 JSR WRBYTE3 ;(24 CYC BEFORE, 6 AFTER)
 LDA #$AA ;(2 CYC)
 JSR WRBYTE3 ;(24 CYC BEFORE, 6 AFTER)
 LDA #$96 ;(2 CYC)
 JSR WRBYTE3 ;(24 CYC BEFORE, 6 AFTER)

* WRITE VOL, TRK & SECTOR AS
* ODD/EVEN ENCODED BYTES.
* (32 CYCLES BETWEEN BYTES.)

 LDA FRMTVOL ;(A) = VOLUME #, (3 CYC).
 JSR WRBYTE1 ;WRITE BYTES FOR VOLUME.
;(JSR INSTRUCTION = 6 CYC.)
 LDA FRMTKCTR ;WRITE BYTES FOR TRK.
;(3 CYC + 6 FROM BEFORE.)
 JSR WRBYTE1 ;(6 CYC + 17 MORE CYC, WITH
;6 RESIDUAL CYC.)
 LDA FRMTSEC ;WRITE BYTES FOR SEC.
 JSR WRBYTE1 ;(CYCLES AS PER ABOVE.)

* CALCULATE ADDRESS CHECKSUM.

 LDA FRMTVOL ;(3 CYC + 6 FROM BEFORE)
 EOR FRMTKCTR ;(3 CYC)
 EOR FRMTSEC ;(3 CYC)
 PHA ;SAVE CKSUM ON STK (3 CYC).

* ODD ENCODE THE ADDRESS CHECKSUM.

 LSR ;(2 CYC)
 ORA HOLDAA ;(3 CYC)
 STA Q6H,X ;(5 CYC - WRITE BYTE)
 LDA Q6L,X ;(4 CYC)

* EVEN ENCODE THE ADDRESS CHECKSUM.

 PLA ;(3 CYC)
 ORA #%10101010 ;(2 CYC)
 JSR WRBYTE2 ;(26 CYC BEFORE WRITE, 6 AFTER)

* WRITE ADDRESS EPILOGUE.
* ("DE AA EB", 32-CYCLE BYTES.)

 LDA #$DE ;(2 CYC + 6 LEFT OVER FRM B4.)
 JSR WRBYTE3 ;(24 CYC BEFORE WRITE, 6 AFTER)
 LDA #$AA ;(2 CYC + 6 LEFT OVER FROM B4)
 JSR WRBYTE3 ;(24 CYC B4 WRITE, 6 LFT OVER)
 LDA #$EB ;(2 CYC + 6 LEFT OVER FROM B4)
 JSR WRBYTE3 ;(24 CYC BEFORE WRITE, 6 AFTER)
 CLC
SET4RD LDA Q7L,X ;SET READ MODE.
 LDA Q6L,X
WTADDRTN RTS


*=================================
*  WRITE DOUBLE AND SINGLE BYTE
*  SUBR'TNS WITH DIFFERENT DELAYS.
*=================================

* NOTE:  A "JSR" INSTRUCTION
* REQUIRES 6 CYCLES.  THEREFORE
* 6 CYCLES + ANY OTHER OVERHEAD
* SHOULD BE ADDED TO THE SUBRTNS
* GIVEN BELOW IN ORDER TO ARRIVE
* AT A 32-CYCLE COUNT BETWEEN @
* BYTE WRITTEN.

WRBYTE1 PHA ;(3 CYC)

* CALC & WRITE ODD-ENCODED BYTE.

 LSR ;(2 CYC)
 ORA HOLDAA ;(3 CYC)
 STA Q6H,X ;(5 CYC)
 CMP Q6L,X ;(4 CYC)

* CALC & WRITE EVEN-ENCODED BYTE.

 PLA ;(4 CYC)
 NOP ;(2 CYC)
 NOP ;(2 CYC)
 NOP ;(2 CYC)
 ORA #$AA ;(2 CYC)
WRBYTE2 NOP ;(2 CYC)
WRBYTE3 NOP ;(2 CYC)
 PHA ;(3 CYC)
 PLA ;(4 CYC)
 STA Q6H,X ;(5 CYC)
 CMP Q6L,X ;(4 CYC)
 RTS  ;(6 CYC LEFT OVER AFTER WRITE)


*=================================
*           FREE SPACE
*         ($BCDF - $BCFF)
*=================================

 DS 33 ;UNUSED  GARBAGE - CONSIDER FREE.
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������