                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Format Routines
;>
;>      This module contains all but the very most primitive of
;>      of procedures ( the routines that are resident are listed
;>      in the external spec's ) that concern themselves with performing
;>      a format operation.
;>
;>      PROCEDURE FormatTrack( Offset, InterLeave )
;>      PROCEDURE LocateSector
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: FormatTrack
;>
;>      This function is responsible for formatting the track at which
;>      the heads are currently positioned.
;>
;>      Inputs:
;>              Offset : BYTE { !r4 }
;>              InterLeave : BYTE { !r5 }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       For i := 1 TO LENGTH( FormatArray ) DO
;>           FormatArray[ i ] := 0
;>       WHILE NOT( Index ) DO BEGIN END
;>       Turn on AC erase { FmenL }
;>       IF IndexMark
;>        THEN
;>         Turn Off AC erase
;>         WHILE ( Offset > 0 ) DO
;>                WHILE NOT( SectorMark ) DO BEGIN END
;>                WHILE SectorMark DO BEGIN END
;>                Offset := Offset - 1
;>         InterLeaveFactor := InterLeaveTable[ InterLeave ]
;>         Sector := 0
;>         FOR i := 1 TO Number Of Sectors DO
;>           IF NOT( FormatBlock ) THEN Abort
;>           Sector := ( Sector + InterLeaveFactor ) MOD NbrSctrs
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
                .DO     W_10MB
InterTable:     .DB     2, 1, 7, 10, 8, 13, 3
                .ELSE
InterTable:     .DB     2, 1, 26, 10, 8, 13, 22
                .FIN
                
FormatTrack:
                 Ld     !r2,#.HIBYTE. Zero_Fmt
                 Ld     !r3,#.LOWBYTE. Zero_Fmt
                Call    Bank_Call
                Or      DiskStat,#Wr_Op
                
FmtT_1:         Tm      Port3,#IndexMark    ;WHILE NOT( Index )
                Jr      Z,FmtT_1
                
                And     Port0,#$FF-AcEraseL        ;turn on AC erase
                
FmtT_2:         Tm      Port3,#IndexMark    ;WHILE Index
                Jr      Nz,FmtT_2
                 
FmtT_3:         Tm      Port3,#IndexMark    ;WHILE NOT( Index )
                Jr      Z,FmtT_3
                
                Or      Port0,#AcEraseL    ;turn off AC erase
                
                Or      !r4,!r4 ;test for 0 offset
                Jr      Z,Fmt_Begin
                
Fmt_Off1:       And     Irq,#$FF-Irq_Sector ;clear old sector mark
                
Fmt_Off2:       Tm      Irq,#Irq_Sector ;wait for mark to pass
                Jr      Z,Fmt_Off2
                
                Djnz    !r4,Fmt_Off1
                
Fmt_Begin:      Ld      !r2,#.HIBYTE. InterTable
                Ld      !r3,#.LOWBYTE. InterTable
                Add     !r3,!r5 ;get offset into table
                Adc     !r2,#0
                
                Ldc     !r6,@!!r2
                Clr     Sector ;sector := 0
                
                Ld      !r5,#NbrSctrs
                
FmtTrk_2:        Ld     !r1,#Dmt_FmtTrk
                Call    FormatBlock
                Jr      Nz,FmtT_Until
                
                 Ld      !r9,!r0 ;pass reason for abort
                Call    Abort
                
FmtT_Until:     Add     Sector,!r6  ;Sector := Sector + InterLeaveFactor
                Cp      Sector,#NbrSctrs   ;Sector := Sector MOD NbrSctrs
                Jr      Lt,FmtT2_Until
                
                Sub     Sector,#NbrSctrs   ;do MOD by subtraction
                
FmtT2_Until:    Djnz    !r5,FmtTrk_2
                
                Jp      Bank_Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: LocateSector
;>
;>      This procedure returns to the caller just after the sector
;>      mark representing the sector JUST BEFORE the sector of the
;>      last seek address.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Global Variables Used:
;>              Sector
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Offset := SpareTable.FmtOffset
;>       InterL := SpareTable.InterLeave
;>       SectorCount := 0
;>       Temp := 0
;>       WHILE NOT( Index ) DO BEGIN END
;>       WHILE ( Offset <> 0 ) DO
;>              Wait For End of Sector Mark
;>       WHILE ( Temp MOD NbrSctrs <> Sector ) DO
;>              Temp := Temp + InterL
;>              i := i + 2 { count sectors at 2:1 interleave }
;>       WHILE ( i <> 0 ) DO
;>              Wait For End Of Sector Mark
;>              i := i - 1
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

LocateSector:
                 Ld     !r0,#Dmt_LctSctr
                Call    Set_Dmt
                
                Push    Rp ;save context
                Srp     #Wrk_Sys2
                
                Ld      !r2,#.HIBYTE. Fmt_Offset
                Ld      !r3,#.LOWBYTE. Fmt_Offset
                Lde     !r4,@!!r2 ;load offset value
                Or      Head,Head ;check for even/odd head
                Jr      Z,Lct_Offset
                Swap    !r4
Lct_Offset:     And     !r4,#$0F
                
                Incw    !!r2 ;point to interleave value
                Lde     !r5,@!!r2
                
                Ld      !r2,#.HIBYTE. InterTable
                Ld      !r3,#.LOWBYTE. InterTable
                Add     !r3,!r5 ;add in interleave value
                Adc     !r2,#0
                Ldc     !r5,@!!r2 ;get real interleave value
                
LctSctr1:       Tm      Port3,#IndexMark ;WHILE Index DO BEGIN END
                Jr      Nz,LctSctr1
                
LctSctr2:       Tm      Port3,#IndexMark ;WHILE Not( Index ) DO BEGIN END
                Jr      Z,LctSctr2
                
                And     Irq,#$FF-Irq_Sector ;clear any old sector marks
                
                Or      !r4,!r4 ;IF Offset = 0 THEN we're already here!
                Jr      Z,LctSctr4
                
                 Ld     !r2,!r4
                Call    LctSctr3
                
LctSctr4:       Or      Sector,Sector ;IF Sector = 0 THEN We're already there
                Jr      Z,LctDone
                
                Clr     !r2
                Clr     !r4
                
LctSctr5:       Cp      !r4,Sector ;see if we've found the sector
                Jr      Z,LctSctr6
                Add     !r2,#2
                Add     !r4,!r5 ;temp := Temp + InterLeave Factor
                Cp      !r4,#NbrSctrs ;temp := temp MOD NbrSctrs
                Jr      Lt,LctSctr5
                Sub     !r4,#NbrSctrs
                Jr      LctSctr5
                
LctSctr6:       Call    LctSctr3
                
LctDone:        Call    Clr_Dmt
                Pop     Rp ;restore original context
                Jp      Bank_Ret

LctSctr3:       Tm      Irq,#Irq_Sector ;wait for next sector
                Jr      Z,LctSctr3
                And     Irq,#$FF-Irq_Sector ;mask old interrupt
                Djnz    !r2,LctSctr3 ;count the number of sector in offset
                Ret
                
                .LSTOFF
                
