                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Module: Resident
;>
;>      This module contains all the routines ( besides the Z8 initialization
;>      procedures ) that must be resident within the Z8.
;>
;>      RESIDENT PROCEDURE Bsy_Clr( MemAdr : PTR { !!Wrk_Io+C } )
;>                                  Response     : BYTE { Wrk_Io+$A }
;>                                  Cmnd_Pending : BIT { Wrk_Io+$B/Bit 7 }
;>                                  IBsy         : BIT { Wrk_Io+$B/Bit 6 }
;>                                )
;>      RESIDENT PROCEDURE Wait_Cmd( Cmnd_Pending : BOOLEAN { !rB/bit 7 }
;>                                   Response : BYTE { !rA }
;>                                   IBsy     : BOOLEAN { !rB/bit 6 }
;>                                   MemAdr   : PTR { !!rC }
;>                                 )
;>      RESIDENT PROCEDURE Get_Wr_Data( Response : BYTE { !r9 } )
;>      RESIDENT PROCEDURE Ack_Read( Response )
;>      RESIDENT FUNCTION Wr_Resident : Status : BYTE { !r0 }
;>      RESIDENT FUNCTION Fmt_Resident : Status : BYTE { !r0 }
;>      RESIDENT FUNCTION RdHdr_Resident : Status : BYTE { !r0 }
;>      RESIDENT FUNCTION Rd_Resident : Status : BYTE { !r0 }
;>      RESIDENT SubFUNCTION Start_StMach
;>      FUNCTION Sub3( A, B : 3 BYTES { !r0:2, !rC:E } ) : 3 BYTES { !r0:2 }
;>      FUNCTION Add3( A, B : 3 BYTES { !r0:2, !rC:E } ) : 3 BYTES { !r0:2 }
;>      PROCEDURE Set_RamBank( Ram_Bank : BYTE { !r0 } )
;>      PROCEDURE Set_Led( State : BIT { !r0/bit 0 } )
;>      FUNCTION LoadStatus : BYTE { !r0 }
;>      PROCEDURE SetStatus( StatusByte : BYTE { !r0 }
;>                           Value : BYTE { !r1 }
;>                         )
;>      PROCEDURE Set_Dmt( Parent1, Parent2 : BYTE { !rB, !r0 } )
;>      PROCEDURE Clr_Dmt
;>      FUNCTION FormatBlock( Paraent : BYTE { !r8 } ) :
;>                          BOOLEAN
;>                          Status : BYTE { !r0 }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Bsy_Clr
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      BEGIN
;>       AB_Return
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Clr_Bsy:         Ld     !r2,#.HIBYTE. AB_Return
                 Ld     !r3,#.LOWBYTE. AB_Return
                Call    Bank_Call
                
Sys_Exit:       Call    Ext_Push
                Call    Ld_Stand_Stat
                 Ld     !r2,#.HIBYTE. AB_Multi_Ret
                 Ld     !r3,#.LOWBYTE. AB_Multi_Ret
                Call    Bank_Call
                
Sys_Ret:        Call    Ext_Pop
                Tm      Wrk_Io+$B,#Cmnd_Pending ;check if legal Multi_Ret
                Jr      Z,Sys_Ret_Abort
                
                Pop     !r0 ;get AB's return address off the stack
                Pop     !r1
                Ret
                
Sys_Ret_Abort:  Call    Abort
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>              RESIDENT ROUTINE  { source code is in Resident.Assem }
;>
;>      Procedure: Get_Wr_Data  { Get Write Data from Host }
;>
;>      Inputs:
;>             Response     : BYTE, { Wrk_Io+$A }
;>
;>
;>      BEGIN
;>       NOP
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Get_Wr_Data:    Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>              RESIDENT ROUTINE  { source code is in Resident.Assem }
;>
;>      Procedure: Ack_Read     { Acknowledge read command, set BSY }
;>
;>      Inputs:
;>              Response : BYTE { Wrk_Io+$A }
;>
;>      Outputs: { none }
;>
;>      BEGIN
;>       NOP
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Ack_Read:       Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Wr_Resident  { Write Resident }
;>
;>      This function exists primarily because the architecture of the
;>      Widget Controller prevents the Z8 from executing instructions
;>      from external program memory while thr state machine is running.
;>
;>      Inputs: { none }
;>
;>      Outputs:
;>              Status: BYTE { !r0 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Msel0:1 := Disk <--> Mem
;>       Set-up external ram address counter for WRITE
;>       DiskRW := Write
;>       RdHdrH := False
;>       IF ( Cylinder > RWI_Cylinder )
;>        THEN
;>              PC := True
;>              RWI := True
;>        ELSE
;>              PC := False
;>              RWI := False
;>       StartStateMachine
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN


Wr_Resident:    Srp     #Wrk_Io
                
                Ld      !Port2,#Not_StartL+Bsy+Disk_Mem
                
                 Ld     !rE,Hi_Rwi_Reg
                 Ld     !rF,Lo_Rwi_Reg
                 Sub    !rF,Cylinder+1 ;check for  ( > RWI_Cylinder )
                 Sbc    !rE,Cylinder
                Jr      Lt,WPC_Else
                
                Ld      !rA,#$7F ;bits inactive
                Jr      WPC_End
                
WPC_Else:       Ld      !rA,#$7F-RWI-PC
                
WPC_End:        Jr      Rd_Res2
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Fmt_Resident  { Format Resident }
;>
;>      This function exists primarily because the architecture of the
;>      Widget Controller prevents the Z8 from executing instructions
;>      from external program memory while thr state machine is running.
;>
;>      Inputs: { none }
;>
;>      Outputs:
;>              Status: BYTE { !r0 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Msel0:1 := Disk <--> Mem
;>       Set-up external ram address counter for FORMAT
;>       DiskRW := Write
;>       RdHdrH := True
;>       IF ( Cylinder > RWI_Cylinder )
;>        THEN
;>              PC := True
;>              RWI := True
;>        ELSE
;>              PC := False
;>              RWI := False
;>       StartStateMachine
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN


Fmt_Resident:   Srp     #Wrk_Io
                
                Ld      !Port2,#Not_StartL+Bsy+Disk_Mem
                
                 Ld     !rE,Hi_Rwi_Reg
                 Ld     !rF,Lo_Rwi_Reg
                 Sub    !rF,Cylinder+1 ;check for  ( > RWI_Cylinder )
                 Sbc    !rE,Cylinder
                Jr      Lt,FPC_Else
                
                Ld      !rA,#$FF ;bits inactive
                Jr      FPC_End
                
FPC_Else:       Ld      !rA,#$FF-RWI-PC
                
FPC_End:        Ld      !rE,#.HIBYTE. FormatArray
                Ld      !rF,#.LOWBYTE. FormatArray
                
                Jr      Start_StMach
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: RdHdr_Resident  { Read Header Resident }
;>
;>      This function exists primarily because the architecture of the
;>      Widget Controller prevents the Z8 from executing instructions
;>      from external program memory while thr state machine is running.
;>
;>      Inputs: { none }
;>
;>      Outputs:
;>              Status: BYTE { !r0 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Msel0:1 := Disk <--> Mem
;>       Set-up external ram address counter for READ
;>       DiskRW := Read
;>       RdHdrH := True
;>       RWI := False
;>       PC := False
;>       StartStateMachine
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

RdHdr_Resident: 
                Srp     #Wrk_Io
                
                Ld      !rA,#$FF ;bits inactive
                
                Jr      Rd_Res1
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Rd_Resident  { Read Resident }
;>
;>      This function exists primarily because the architecture of the
;>      Widget Controller prevents the Z8 from executing instructions
;>      from external program memory while thr state machine is running.
;>
;>      Inputs: { none }
;>
;>      Outputs:
;>              Status: BYTE { !r0 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Msel0:1 := Disk <--> Mem
;>       Set-up external ram address counter for READ
;>       DiskRW := Read
;>       RdHdrH := False
;>       PC := False
;>       RWI := False
;>       StartStateMachine
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN


Rd_Resident:    
                Srp     #Wrk_Io
                Ld      !rA,#$7F ;bits inactive
                
Rd_Res1:        Ld      !Port2,#Not_StartL+Bsy+Disk_Mem+DrwL_Read
                
Rd_Res2:        Ld      !rE,#.HIBYTE. ReadArray
                Ld      !rF,#.LOWBYTE. ReadArray
                
;               \ /  ;In-Line code for Speed!!
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      SubFunction: Start_StMach  { StartStateMachine }
;>
;>      This is a routine that is shared by all the resident state machine
;>      routines and exists primarily for the purpose of saving space. It's
;>      function is to complete the set-up for the state machine and then 
;>      start it up and wait for it to finish.
;>
;>      BEGIN
;>       Z8 Port 3, Bit 4 := 0  { instead of DM it is an I/O port }
;>       Z8 Port 1 := Input  { keep Z8 from conflicting with Disk data }
;>       SectorsRead := 2 * NumberOfSectors
;>       WHILE SectorMark DO BEGIN END
;>       StartL := True
;>       WHILE NOT( SectorDnL ) AND ( SectorsRead <> 0 ) DO
;>              BEGIN
;>                      IF SectorMark
;>                        THEN
;>                              SectorsRead := SectorsRead - 1
;>                              WHILE SectorMark DO BEGIN END
;>              END       
;>       Z8 Port 3, Bit 4 := DM
;>       Z8 Port 1 := Address/Data
;>       Msel0:1 := Z8 <--> Mem
;>       Status := Status_Port
;>       IF EccErr
;>        THEN Status.CrcError := True
;>       StartL := False
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Start_StMach:
                Lde     @!!rE,!rE       ;set buffer address
                
                Ld      P3m,!P3m_StMach
                And     !Port3,!Dm_Mask  ;set DM/IoPort Low
                
                Ld      P01m,!P01m_StMach
                Ld      !Port0,!rA
                
St_Res_1:       Tm      !Port3,#SectorMark  ;test for sector mark
                Jr      Nz,St_Res_1
                
                And     !Port2,!Start_Mask        ;start state machine
                
                Ld      !rA,#Not_StartL
                Ld      !rB,#Not_EccErr
                Ld      !rE,#SectDnL    ;load mask
                Ld      !rF,#SectorMark
                Ld      Wrk_Sys+$A,#( NbrSctrs+2 ) ;timeout after 21 sectors
                Call    Set_Dmt
                
St_Res_2:       Tm      !Port3,!rF               ;count sector marks
                Jr      Z,St_Res_3
                Dec     Wrk_Sys+$A
                Jr      Z,St_Res_4
                
St_Res_25:      Tm      !Port3,!rF        
                Jr      Nz,St_Res_2_5   ;wait for mark to go away
                
St_Res_3:       Tcm     !Port3,!rE  ;wait for state machine to finish
                Jr      Z,St_Res_2
                Tcm     !Port3,!rE  ;sample it twice
                Jr      Z,St_Res_2
                
St_Res_4:       Ld      P01m,!P01m_Image
                Ld      !Port2,#Bsy+Z8_Mem+DrwL_Read
                Ld      P3m,!P3m_Image
                
                Ld      !rC,#.HIBYTE. StatusPort
                Ld      !rD,#.LOWBYTE. StatusPort
                Lde     !rF,@!!rC
                
                Tm      !Port2,!rB
                Jr      Z,Res_EccErr
                
Res_StMach:     Or      !Port2,!rA       ;reset state machine
                Di                       ;clear the dead man timer
                
                Srp     #Wrk_Sys
                Ld      !r0,Wrk_Io+$F ;return StMach status
                Ret
                
                
Res_EccErr:     Tm      DiskStat,#Wr_Op
                Jr      Nz,Res_StMach
                And     !rF,#$FF-WrtNvldL ;if ECC error
                Jr      Res_StMach
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Sub3, Add3
;>
;>              { RESIDENT ROUTINES!! }
;>
;>      These functions perform the following 24 bit arithmetic operations:
;>
;>        Sub3: A <-- A - B
;>        Add3: A <-- A + B
;>
;>      Inputs:
;>              A: 3 BYTES { !r0, !r1, !r2 }
;>              B: 3 BYTES { !rC, !rD, !rE }
;>
;>      Outputs:
;>              A: 3 BYTES { !r0, !r1, !r2 }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Sub3:
                Sub     !r2,!rE
                Sbc     !r1,!rD
                Sbc     !r0,!rC
                Ret

Add3:
                Add     !r2,!rE
                Adc     !r1,!rD
                Adc     !r0,!rC
                
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Set_RamBank
;>
;>      This procedure activates the 2k bank of ram that is indicated by
;>      the input parameter.
;>
;>      Inputs:
;>              Ram_Bank : BYTE { !r0 }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       IF ( Ram_Bank > 3 ) THEN Abort
;>       deselect all ram bits
;>       select the ram bit pointed to by Ram_Bank
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Set_RamBank:    Cp      !r0,#4
                Jr      Lt,Set_RB_Start
                
                Call    Abort
                
Set_RB_Start:   Ld      !r2,#.HIBYTE. Ram_Table
                Ld      !r3,#.LOWBYTE. Ram_Table
                Rl      !r0 ;multiply index by 2
                Add     !r3,!r0 ;index into table
                Adc     !r2,#0
                Ldc     !r1,@!!r2
                Incw    !!r2
                Ldc     !r0,@!!r2
                
                Ld      !r2,#.HIBYTE. RamBank0 ;set the adr bits
                Ld      !r3,!r0
                Lde     @!!r2,!r3
                Inc     !r2
                Ld      !r3,!r1
                Lde     @!!r2,!r3
                Ret
                
Ram_Table:      .DB     0,0 ;adr 13 := 0, adr 12 := 0 
                .DB     0,1 ;adr 13 := 0, adr 12 := 1
                .DB     1,0 ;adr 13 := 1, adr 12 := 0 
                .DB     1,1 ;adr 13 := 1, adr 12 := 1
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Set_Led
;>
;>      This procedure changes the state of the controller LED. The
;>      state is determined by the value of State ( if State is Odd
;>      then the Led is lit, otherwise it is turned off ).
;>
;>      Inputs:
;>              State : BIT { !r0/bit 0 }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       Led[ State ] := State
;>       Bank_Image.Led := State
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

Set_Led:
                And     Excpt_Stat,#$FF-Led_Stat
                Or      Excpt_Stat,!r0
                Ld     !r2,#.HIBYTE. Led
                Ld     !r3,!r0
                Lde    @!!r2,!r3
                
                Ret
                
Invert_Led:      Ld     !r0,Excpt_Stat
                 Xor    !r0,#$FF-Led_Mask ;invert only the Led bit
                Jr     Set_Led
                 
Led_Wait:        Ld     !r2,#.HIBYTE. 50 ;wait a second
                 Ld     !r3,#.LOWBYTE. 50
                Call    MsWait
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: LoadStatus
;>
;>      This function returns the current value of the
;>      controller status port.
;>
;>      Inputs: { none }
;>
;>      Outputs:
;>              LoadStatus : BYTE { !r0 }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

LoadStatus:
                Ld      !r2,#.HIBYTE. Status_Port
                Ld      !r3,#.LOWBYTE. Status_Port
                Lde     !r0,@!!r2
                
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: SetStatus
;>
;>      This procedure is used to set a particular bit or bits
;>      within a specific byte of standard status.
;>
;>      Inputs:
;>              StatusByte : BYTE { !r0 }
;>              Value      : BYTE { !r1 }
;>
;>      Outputs: { none }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       StandardStatus[ StatusByte ] := StandardStatus[ StatusByte ] OR
;>                                              Value
;>      END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

SetStatus:
                Ld      !r2,#.HIBYTE. CStatus0
                Ld      !r3,#.LOWBYTE. CStatus0
                Add     !r3,!r0
                Adc     !r2,#0
                Lde     !r0,@!!r2
                Or      !r0,!r1
                Lde     @!!r2,!r0
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Set_Dmt  { SetDeadManTimer }
;>
;>      This procedure sets the DeadManTimer bit, thus enabling the
;>      decrementing of the DeadManCounter every time a timer interrupt
;>      occurs. The Set_Dmt routine also initializes the DeadManCounter
;>      as well as storing away information concerning the process(s)
;>      that started the Dmt.
;>
;>      Inputs: { none }
;>
;>      Outputs: { none }
;>
;>      Algorithm :
;>
;>       BEGIN
;>        Disable Interrupts { entering critical section }
;>        Dmt_Par1 := Parent1
;>        Dmt_Par2 := Parent2
;>        DeadManCounter := 0 { assume timer interrupts every 10 msecs }
;>        Enable Interrupts { leaving critical section }
;>       END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Set_Dmt:
                Di                              ;enter critical section
                
                Ld      Dmt_Counter,#.HIBYTE. Dmt_Val
                Ld      Dmt_Counter+1,#.LOWBYTE. Dmt_Val
                
                And     Irq,#$FF-Timer1 ;clear old events
                Ei
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure: Clr_Dmt  { ClearDeadManTimer }
;>
;>      This procedure clears the DeadManTimer bit, thus disabling the
;>      decrementing of the DeadManTimerCounter. This routine also
;>      enables the NormalTimer.
;>
;>      Inputs : none
;>
;>      Outputs : none
;>
;>      Algorithm :
;>
;>       BEGIN
;>        Disable Interrupts { entering critical section }
;>       END
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
Clr_Dmt:
                Di                              ;enter critical section
                Ret
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Procedure Fragment: FreeP_Leave
;>
;>      This part of Strt_FreeProcess was moved to resident program
;>      space mainly for debugging purposes. I wanted a place in the
;>      code where the DM could be halted AFTER the host had released
;>      the controller as a process.
;>
;>      Inputs: { none }
;>
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN

FreeP_Leave:    Call    Clr_BankSwitch ;get to a known state

                 Ld     !r2,#.HIBYTE. AB_Main
                 Ld     !r3,#.LOWBYTE. AB_Main
                Call    Bank_Call
                
                .LSTOFF
                .DO     External
                .LSTON
                .Page
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>
;>      Function: Format Block
;>
;>      This function performs the actual formatting of a sector.
;>      It is assumed that the heads are positioned over the correct
;>      cylinder and that the correct head has been selected. The
;>      header that is laid down on the track is derived from the
;>      information in the global variables in cylinder, head, and
;>      sector. It is also assumed that memory space FormatArray has
;>      initialized to all zeros before entering this routine.
;>
;>      Inputs:
;>              Parent : BYTE { !r8 }
;>
;>      Outputs:
;>              FmtBlock    : BOOLEAN { Zero flag, true if error in ReadBlock }
;>              Status      : BYTE { !r0 }
;>
;>      Global Variables Used:
;>              Cylinder, Head, Sector, Recovery
;>
;>      Local Variables Used:
;>              FmtError    : BOOLEAN { !r9/bit 7 }
;>              FmtExcept   : BOOLEAN { !r9/bit 6 }
;>              FmtSuccess  : BOOLEAN { !r9/bit 5 }
;>
;>      Algorithm:
;>
;>      BEGIN
;>       SetDeadManTimer( FormatBlock, Parent )
;>       FmtRetryCnt := 10
;>       FmtErrCnt := 0
;>       FmtError := False
;>       FmtExcept := False
;>       SectorsRead := 2 * NbrSctrs { try to find header for two rotations }
;>        FHdrSync := $0100
;>        FHeader[ 1 ] := HiCylinder
;>        FHeader[ 2 ] := LoCylinder
;>        FHeader[ 3 ]/bits 7:6 := Head
;>        FHeader[ 3 ]/bits 5:0 := Sector
;>        FHeader[ 4 ] := Invert( FHeader[ 1 ] )
;>        FHeader[ 5 ] := Invert( FHeader[ 2 ] )
;>        FHeader[ 6 ] := Invert( FHeader[ 3 ] )
;>       _
;>      /
;>   R  |  Set-up external ram address counter for FORMAT
;>   E  |  Msel0:1 := Disk <--> Mem
;>   S  |  WHILE SectorMark DO BEGIN END
;>   I  |  StartL := True
;>   D  |  WHILE NOT( SectorDnL ) DO BEGIN END
;>   E  |  Status := Status_Port
;>   N  |  StartL := False
;>   T  |  Msel0:1 := Z8 <--> Mem
;>      \_
;>
;>        IF NOT( Status.State = NormFmtState )
;>          THEN 
;>              Reset_StateMachine
;>              Abort
;>
;>        IF Status.ServoErr OR NOT( ServoRdy )
;>          THEN
;>              FmtError := True
;>              FmtExcept := True
;>
;>        IF Status.WtNvldL
;>         THEN FmtError := True
;>       ClearDeadManTimer
;>       Status/bit 7 := FmtError
;>       Status/bit 6 := FmtExcept
;>      END
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .LSTOFF
                .FIN
                .DO     Internal
                .LSTON
                .Page
                .FIN
                
FormatBlock:
                Clr     !r9     ;clear booleans
                
FmtBlk_Rpt:     Ld      !r2,#.HIBYTE. FmtDelay
                Ld      !r3,#.LOWBYTE. FmtDelay
                Ldc     !r1,@!!r2
                Ld      !r2,#.HIBYTE. FormatArray ;initialize gaps
                Ld      !r3,#.LOWBYTE. FormatArray
                Clr     !r0
FmtBlk_1:       Lde     @!!r2,!r0
                Incw    !!r2
                Djnz    !r1,FmtBlk_1
                
                Ld      !r2,#.HIBYTE. FHdrSync
                Ld      !r3,#.LOWBYTE. FHdrSync
                Ld      !r0,#$01        ;load header sync
                Lde     @!!r2,!r0
                Incw    !!r2
                Clr     !r0
                Lde     @!!r2,!r0
                Incw    !!r2
                
                Call    LH_Vector
                
                Ld      !r2,#.HIBYTE. FDataSync ;load data sync bit
                Ld      !r3,#.LOWBYTE. FDataSync
                Ld      !r0,#$01
                Lde     @!!r2,!r0
                
                Call    Fmt_Resident     ;go internal to the Z8

                Ld      !r1,!r0         ;CASE Status.State
                And     !r1,#$0F
                Cp      !r1,#NormFmt_State
                Jr      Z,Fmt_Norm
                
                 Call   Reset_StMach
                 Ld     !rA,!r0
                Call    Abort
                
Fmt_Norm:       Ld      !r1,!r0         ;IF ServorErr OR NOT( ServoRdy )
                Tm      !r1,#ServoErr
                Jr      Nz,Fmt_ServoErr
                Tm      !r1,#ServoRdy
                Jr      Nz,Fmt_SrvoOk
                
Fmt_ServoErr:   Or      !r9,#FmtError + FmtSrvoErr ; THEN FmtError AND FmtSrvoErr
                Jr      FmtBlk_End
                
Fmt_SrvoOk:    Tm      !r0,#WrtNvldL    ;IF Status.WrtNvldL
                Jr      Nz,FmtBlk_End
                
                Or      !r9,#FmtError
                
FmtBlk_End:     Ld      !r0,!r9 ;send status back to caller
                Ld      WrStat,!r9
                
                Tcm     !r0,#FmtError ;set zero flag if error
                Ret
                
                .LSTOFF
                
