home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff312.lzh / TrackSalve / Source / patch.a < prev    next >
Text File  |  1990-02-12  |  82KB  |  1,653 lines

  1. *  Patch.a  --  TrackSalve
  2. *
  3. *   #    date    by    Comment
  4. *  -- --------- ---- ---------------------
  5. *   0 29-Oct-89  DWR   Created for Tracksalve
  6. *
  7.  
  8. *               nolist
  9.                 ifnd    IFILES
  10. IFILES          set     1
  11.                 INCLUDE "Call.i"
  12.                 INCLUDE "globdefs.i"
  13.                 INCLUDE "ts.i"
  14.                 INCLUDE "exec/tasks.i"
  15.                 INCLUDE "hardware/custom.i"
  16.                 include "graphics/text.i"
  17.                 include "graphics/rastport.i"
  18. *               include "intuition/intuitionbase.i"
  19. *               include "intuition/intuition.i"
  20. *               include "intuition/screens.i"
  21.                 include "devices/inputevent.i"
  22.  
  23.                 ifnd    INTUITION_INTUITION_I
  24. GADGETUP        equ     $00000040
  25. RAWKEY          equ     $00000400
  26. WINDOWDEPTH     equ     $0004
  27. WINDOWDRAG      equ     $0002
  28. SIMPLE_REFRESH  equ     $0040
  29. NOCAREREFRESH   equ     $00020000
  30. ACTIVATE        equ     $1000
  31. GADGHCOMP       equ     $0000
  32. GADGHBOX        equ     $0001
  33. GADGIMAGE       equ     $0004
  34. GADGHIMAGE      equ     $0002
  35. BOOLGADGET      equ     $0001
  36. REQGADGET       equ     $1000
  37. RELVERIFY       equ     $0001
  38. ENDGADGET       equ     $0004
  39. wd_LeftEdge     equ     4
  40. wd_UserPort     equ     86
  41. im_Class        equ     20
  42. im_Code         equ     24
  43. im_IAddress     equ     28
  44.                 endc
  45.  
  46.                 ifnd    INTUITION_SCREENS_I
  47. WBENCHSCREEN    equ     $0001
  48. sc_DetailPen    equ     $14a
  49.                 endc
  50.  
  51.                 ifnd    INTUITION_INTUITIONBASE_I
  52. ib_FirstScreen  equ     $3c
  53.                 endc
  54.  
  55.                 endc
  56.  
  57. *               list
  58.  
  59.                 SECTION text,code
  60.  
  61.  
  62. *********************************************************
  63. *
  64. *  Begin of code that extents/replaces Trackdisk code.  This is made globally known because some
  65. *  routine must copy us from here to an allocated space.  Because all references to the location-
  66. *  counter until TSCodeEnd are done from within this part or from patched Trackdisk code, none
  67. *  of these locations should be made external available.
  68. *
  69.  
  70.                 Func    TSCodeBegin,_TSCodeBegin
  71.  
  72.  
  73. *********************************************************
  74. *
  75. *  We jump to this address when changing from ROM to TS.  Special inits must be done here.
  76. *
  77.  
  78.                 move.b  #F_RAM,UNIT_pad(a3)             Set flags to executing in RAM and clear all others
  79.                 ;bra.s  TDE_TaskLoop                    Continue normal loop
  80.  
  81.  
  82. *********************************************************
  83. *
  84. *  Extension of Trackdisks main task loop.  The first thing we do is a check whether we
  85. *  initiated a terminal state.  If so, we do not check external commands anymore, but
  86. *  continue to finish the special functions and return to ROM-code in the end.
  87. *  Otherwise we compare the external commands with the already active functions and
  88. *  if they differ, we see that they are initiated.
  89. *  We are free to use a2, but its value may have been changed upon entry.
  90. *  A6 contains SysBase and the device pointer must be restored by a pull from the stack.
  91. *
  92. *  Upon entry:  a3      TDU structure (Trackdisk unit)
  93. *               a6      SysBase
  94. *
  95. *  Usage:       a2      UnitData structure
  96. *
  97.  
  98. TDE_TaskLoop    move.l  (a7)+,a6                        Perform replaced instruction. Restore device pointer
  99.                 move.l  TDU_TCB+TC_Userdata(a3),a2      Lea UnitData structure
  100.                 btst    #B_TERM,UNIT_pad(a3)            Change of control?
  101.                 bne.s   TDE_TermTS                      Yes..
  102.                 move.b  UD_Cmd1(a2),d0                  Command from outside
  103.                 cmp.b   UNIT_pad(a3),d0                 Same as presently active?
  104.                 beq     TD_TaskLoop                     Yes, continue task..
  105.  
  106.                 btst    #B_TERM,d0                      Change of control?
  107.                 bne     TDE_TermTS                      Yes..
  108.                 bsr     CheckReadOnly                   Check change of write protection
  109.                 move.b  UD_Cmd1(a2),d0                  Get commands
  110.                 bsr     CheckSalve                      Check change of readerror handling
  111.                 move.b  UD_Cmd1(a2),d0                  Get commands
  112.                 bsr     CheckNoClick                    Check change of diskchange detection
  113.                 move.b  UD_Cmd1(a2),d0                  Get commands
  114.                 bsr     CheckVerify                     Check change of verify function
  115.                 bra     TD_TaskLoop                     Continue task..
  116.  
  117. *--     Initiate or continue terminal state.  Stay in the taskloop until all functions are switched off.
  118.  
  119. TDE_TermTS      bset.b  #B_TERM,UNIT_pad(a3)            Set status of TS to terminating
  120.                 moveq.l #0,d0                           Readonly off
  121.                 bsr     CheckReadOnly                   Check change of write protection
  122.                 moveq.l #0,d0                           Salve off
  123.                 bsr     CheckSalve                      Check change of readerror handling
  124.                 moveq.l #0,d0                           NoClick off
  125.                 bsr     CheckNoClick                    Check change of diskchange detection
  126.                 moveq.l #0,d0                           Verify off
  127.                 bsr     CheckVerify                     Check change of verify function
  128.                 move.b  UNIT_pad(a3),d0                 Current active functions
  129.                 and.b   #FUNCTIONS-F_RAM,d0             All extra functions terminated?
  130.                 bne     TD_TaskLoop                     No, continue task..
  131.  
  132. *--     We realy stop here.  The taskloop hereafter continues in ROM-code.
  133.  
  134.                 move.l  a6,-(a7)                        Preserve a6 AND undo the already executed "move.l (a7)+,a6"
  135.                 move.l  TDD_SysBase(a6),a6              Trackdisk's SysBase
  136.                 move.l  UD_ReturnTD(a2),-(a7)           Push ROM-address. With a "rts" we are back in ROM
  137.                 movem.l a4/a5,-(a7)
  138.                 LibCall Forbid                          We do daring things here, like freeing code we are executing!
  139.                 move.l  UD_TSControl(a2),a5             Lea the Control structure
  140.                 move.l  TSC_TSHook(a5),a4               Lea anchor of all our knowledge
  141.                 move.l  a4,a0
  142.                 LibCall ObtainSemaphore                 We want to be blocked here until others are ready with TSC
  143.  
  144.                 moveq.l #0,d0
  145.                 move.b  TDU_UnitNr(a3),d0               Trackdisk unit number
  146.                 bclr.b  d0,TSC_InUse(a5)                Tell global structure we stopped using it.
  147.                 lsl.l   #2,d0                           Scale to pointer-index
  148.                 clr.l   TSC_UnitData(a5,d0)             Clear UnitData pointer in TSC structure
  149.                 move.l  UD_Userdata(a2),TDU_TCB+TC_Userdata(a3) Restore original value in Task control block
  150.                 move.b  #0,UNIT_pad(a3)                 Back to what it was perhaps
  151.                 lea.l   UD_TDReq(a2),a1                 Trackdisk IORequest
  152.                 cmp.l   IO_UNIT(a1),a3                  Our request? (of course it is)
  153.                 bne.s   10$                             No, skip close..
  154.                 LibCall CloseDevice
  155. 10$
  156.  
  157. *--     Return memory of the TSControl structure if there are no other users of it anymore.
  158.  
  159.                 tst.b   TSC_InUse(a5)                   Any users left?
  160.                 bne.s   30$                             Yes, do not free it..
  161.                 move.l  TSC_Buffer(a5),d1               The install program allocates this buffer.  Its presence may
  162.                                                         ;       not yet have been processed
  163.                 beq.s   20$                             No buffer..
  164.                 move.l  d1,a1                           Buffer
  165.                 move.l  #SB_SIZE,d0                     Its size
  166.                 LibCall FreeMem                         Back to the system
  167. 20$             move.l  TSC_IntuBase(a5),a1             Close Intuition
  168.                 LibCall CloseLibrary
  169.                 move.l  a5,a1                           TSControl structure
  170.                 move.l  TSC_Size(a5),d0                 Its size (about 10k)
  171.                 LibCall FreeMem                         Free it
  172.                 clr.l   TSH_TSControl(a4)               No TSControl structure anymore in TSHook
  173. 30$
  174.  
  175. *--     Maybe the TSControl structure does not exist anymore.  We cannot return from Permit() here, so we jump to it.
  176. *       The return address is already on the stack and points to the correct position in ROM-code.
  177.  
  178.                 move.l  a4,a0                           Lea TSHook structure
  179.                 LibCall ReleaseSemaphore                We are (almost) ready with the TSControl structure
  180.                 movem.l (a7)+,a4/a5
  181.                 xref    _LVOPermit
  182.                 jmp     _LVOPermit(a6)                  Taskswitching on and back to ROM
  183.  
  184.  
  185. *-------------------------------------------------------*
  186. *
  187. *  CheckSalve
  188. *
  189. *  This routine handles the switch from salve function on and off.  If there are no other
  190. *  users of this function left, release the large chip-buffer (about 25k).  If the function
  191. *  is switched on, check the presence of the buffer.  If not there, allocate it.
  192. *
  193. *  Input:       d0      UD_Cmd1
  194. *               a2      UnitData structure
  195. *               a3      Trackdisk unit structure
  196. *               a6      Trackdisk device base
  197. *
  198. *  Return:      -
  199. *
  200.  
  201. CheckSalve      move.b  UNIT_pad(a3),d1                 Presently active functions
  202.                 and.b   #F_SALVE,d0                     Select salve-bit in command
  203.                 and.b   #F_SALVE,d1                     Select salve-bit in active functions
  204.                 cmp.b   d0,d1                           Salve-action changed?
  205.                 bne.s   CheckSalve10                    Yes, see that it is done..
  206.                 rts
  207.  
  208. *--     We must protect the allocation, freeing and administration of the salve buffer with the TSC semaphore.
  209.  
  210. CheckSalve10    movem.l d2/d3/a5/a6,-(a7)
  211.                 move.l  d0,d2                           Keep salve command
  212.                 move.b  TDU_UnitNr(a3),d3               Unit number
  213.                 move.l  UD_TSControl(a2),a5             TSControl structure
  214.                 move.l  TDD_SysBase(a6),a6              SysBase for Semaphore calls
  215.                 move.l  TSC_TSHook(a5),a0               Lea semaphore
  216.                 LibCall ObtainSemaphore                 We want to be blocked here until others are ready with TSC
  217.                 btst    #B_SALVE,d2                     Salve requested?
  218.                 beq.s   CS_SalveOff                     No..
  219.  
  220. CS_SalveOn      bsr     CheckBufAvail                   Check presence and allocate if necessary
  221.                 beq.s   CS_Rtn                          No success..
  222.                 bset.b  #B_SALVE,UNIT_pad(a3)           Set function active
  223.                 bset.b  d3,TSC_Salve(a5)                Tell global structure that we use the buffer
  224.                 bra.s   CS_Rtn                          Done..
  225.  
  226. CS_SalveOff     bclr.b  #B_SALVE,UNIT_pad(a3)           Set function off
  227.                 bclr.b  d3,TSC_Salve(a5)                We do not use the buffer into global structure
  228.                 bsr     CheckBufFree
  229.  
  230. CS_Rtn          move.l  TSC_TSHook(a5),a0               Lea semaphore
  231.                 LibCall ReleaseSemaphore                We are ready with the TSControl structure
  232.                 movem.l (a7)+,d2/d3/a5/a6
  233.                 rts
  234.  
  235. *-------------------------------------------------------*
  236. *
  237. *  CheckVerify
  238. *
  239. *  Handle the switch from verify function on and off.  If there are no other users of this
  240. *  function left, release the large chip-buffer (about 25k). If the function is switched on,
  241. *  check the presence of the buffer.  If not there, allocate it.
  242. *
  243. *  Input:       d0      UD_Cmd1
  244. *               a2      UnitData structure
  245. *               a3      Trackdisk unit structure
  246. *               a6      Trackdisk device base
  247. *
  248. *  Return:      -
  249. *
  250.  
  251. CheckVerify     move.b  UNIT_pad(a3),d1                 Presently active functions
  252.                 and.b   #F_VERIFY,d0                    Select Verify-bit in command
  253.                 and.b   #F_VERIFY,d1                    Select Verify-bit in active functions
  254.                 cmp.b   d0,d1                           Verify-action changed?
  255.                 bne.s   CheckVerify10                   Yes, see that it is done..
  256.                 rts
  257.  
  258. *--     We must protect the allocation, freeing and administration of the salve buffer with the TSC semaphore.
  259.  
  260. CheckVerify10   movem.l d2/d3/a5/a6,-(a7)
  261.                 move.l  d0,d2                           Keep Verify command
  262.                 move.b  TDU_UnitNr(a3),d3               Unit number
  263.                 move.l  UD_TSControl(a2),a5             TSControl structure
  264.                 move.l  TDD_SysBase(a6),a6              SysBase for Semaphore calls
  265.                 move.l  TSC_TSHook(a5),a0               Lea semaphore
  266.                 LibCall ObtainSemaphore                 We want to be blocked here until others are ready with TSC
  267.                 btst    #B_VERIFY,d2                    Verify requested?
  268.                 beq.s   CV_VerifyOff                    No..
  269.  
  270. CV_VerifyOn     bsr     CheckBufAvail                   Check presence and allocate if necessary
  271.                 beq.s   CV_Rtn                          No success..
  272.                 bset.b  #B_VERIFY,UNIT_pad(a3)          Set function active
  273.                 bset.b  d3,TSC_Verify(a5)               Tell global structure that we use the buffer
  274.                 bra.s   CV_Rtn                          Done..
  275.  
  276. CV_VerifyOff    bclr.b  #B_VERIFY,UNIT_pad(a3)          Set function off
  277.                 bclr.b  d3,TSC_Verify(a5)               We do not use the buffer into global structure
  278.                 bsr     CheckBufFree
  279.  
  280. CV_Rtn          move.l  TSC_TSHook(a5),a0               Lea semaphore
  281.                 LibCall ReleaseSemaphore                We are ready with the TSControl structure
  282.                 movem.l (a7)+,d2/d3/a5/a6
  283.                 rts
  284.  
  285. *-------------------------------------------------------*
  286. *
  287. *  Local subroutine of CheckSalve and CheckVerify
  288. *
  289.  
  290. CheckBufAvail   tst.l   TSC_Buffer(a5)                  Is a buffer present?
  291.                 bne.s   10$                             Yes, skip allocation
  292.                 move.l  #SB_SIZE,d0                     No, its size
  293.                 move.l  #MEMF_CHIP,d1                   And type
  294.                 LibCall AllocMem                        Ask system about 25k chip
  295.                 move.l  d0,TSC_Buffer(a5)               Into global structure. This buffer is shared
  296. 10$             rts
  297.  
  298.  
  299. CheckBufFree    tst.b   TSC_Salve(a5)                   Any users left?
  300.                 bne.s   10$                             Yes, done..
  301.                 tst.b   TSC_Verify(a5)                  Any users left?
  302.                 bne.s   10$                             Yes, done..
  303.                 move.l  TSC_Buffer(a5),d1               Get buffer
  304.                 beq.s   10$                             No buffer..
  305.                 move.l  d1,a1                           Buffer
  306.                 move.l  #SB_SIZE,d0                     Its size
  307.                 LibCall FreeMem                         Back to system
  308.                 clr.l   TSC_Buffer(a5)                  No buffer anymore
  309. 10$             rts
  310.  
  311.  
  312. *-------------------------------------------------------*
  313. *
  314. *  CheckNoClick
  315. *
  316. *  Handle the switch from the NoClick function on and off.
  317. *
  318. *  Input:       d0      UD_Cmd1
  319. *               a2      UnitData structure
  320. *               a3      Trackdisk unit structure
  321. *               a6      Trackdisk device base
  322. *
  323. *  Return:      -
  324. *
  325.  
  326. CheckNoClick    btst    #B_NOCLICK,d0
  327.                 beq.s   10$
  328.                 bset.b  #B_NOCLICK,UNIT_pad(a3)
  329.                 rts
  330. 10$             bclr.b  #B_NOCLICK,UNIT_pad(a3)
  331.                 rts
  332.  
  333. *-------------------------------------------------------*
  334. *
  335. *  CheckReadOnly
  336. *
  337. *  Switching ReadOnly on and off must be done a little careful.  Although we have nothing to
  338. *  do with DOS, (and we do not want too, do we?) it would be inconvenient to switch to
  339. *  readonly when DOS is writing.  There is no way to be sure, but an indication might be the
  340. *  state of the motor.  It is the user who initiates the switch.  He must do it at a quiet
  341. *  moment.  Tell him in the manual!  Again we cannot tell DOS directly that we changed the
  342. *  write protection of the disk, but we simulate a disk-extraction, a shift of the disk
  343. *  protect tab and a disk insertion.  We can skip this if the drive is empty or if the
  344. *  present disk is already write protected by its tab.
  345. *
  346. *  Input:       d0      UD_Cmd1
  347. *               a2      UnitData structure
  348. *               a3      Trackdisk unit structure
  349. *               a6      Trackdisk device base
  350. *
  351. *  Return:      -
  352. *
  353.  
  354. CheckReadOnly   btst    #B_READONLY,d0                  This drive to be protected?
  355.                 beq.s   RO_Off                          No, check reverse action..
  356.                 btst.b  #B_READONLY,UNIT_pad(a3)        Check real bit
  357.                 beq.s   RO_CheckChange                  We have to change from r/w to ro..
  358.                 rts
  359.  
  360. RO_Off          btst.b  #B_READONLY,UNIT_pad(a3)        Check active function bit
  361.                 bne.s   RO_CheckChange                  Was set to write-protect, try change to R/W..
  362.                 rts
  363.  
  364. RO_CheckChange  btst.b  #1,TDU_Flags(a3)                Is there a disk in the drive?
  365.                 bne.s   RO_ChangeROSec                  No, just flip RO-bit..
  366.                 btst.b  #4,TDU_Flags(a3)                Is there a protected disk in the drive?
  367.                 bne.s   RO_ChangeROSec                  Yes, just flip RO-bit..
  368.                 btst.b  #CIAB_DSKMOTOR,TDU_CiabPb(a3)   Motor off? (We TRY to avoid change during disk (write) access)
  369.                 beq.s   RO_Rtn                          No, try again later..
  370. RO_ChangeRO     bchg.b  #B_READONLY,UNIT_pad(a3)        Change real bit. This will be checked before the hardware
  371. *               pea.l   RO_Rtn(pc)                      Push return address, now we are inside a subroutine
  372.                 movem.l d2/a2,-(a7)                     Imitate the disk-presence-check inits
  373.                 lea.l   _ciab+ciaprb,a2                 CIAB-PRB
  374.                 bra     TD_NoDisk                       Continue subroutine handling disk absence..
  375.  
  376. RO_ChangeROSec  bchg.b  #B_READONLY,UNIT_pad(a3)        Change function bit. This is checked before the hardware is
  377. RO_Rtn          rts
  378.  
  379.  
  380. *********************************************************
  381. *
  382. *  NoClick extentions
  383. *
  384.  
  385. TDE_NoClick     btst.b  #B_NOCLICK,UNIT_pad(a3)         Do we use this feature?
  386.                 bne.s   10$                             Yes..
  387.                 bchg.b  #CIAB_DSKDIREC,TDU_CiabPb(a3)   No, change direction bit in cia B image
  388.                 rts
  389. 10$             bset.b  #CIAB_DSKDIREC,TDU_CiabPb(a3)   Set direction bit to outwards in cia B image
  390.                 rts
  391.  
  392.  
  393. *********************************************************
  394. *
  395. *  ReadOnly extentions
  396. *
  397. *  We can modify here the protect status of the disk
  398. *
  399.  
  400. TDE_WriteProt   btst.b  #B_READONLY,UNIT_pad(a3)        Is this drive readonly?
  401.                 bne.s   TDE_ReadOnly                    Yes..
  402.                 btst.b  #CIAB_DSKPROT,_ciaa+ciapra      No, but perhaps this disk?
  403.                 rts
  404.  
  405. TDE_WriteProt1  btst.b  #B_READONLY,UNIT_pad(a3)        Is this drive readonly?
  406.                 bne.s   TDE_ReadOnly                    Yes..
  407.                 btst    #CIAB_DSKPROT,d2                No, but perhaps this disk?
  408.                 rts
  409.  
  410. TDE_ReadOnly    cmp.l   d0,d0                           Set zero bit, meaning write protected
  411.                 rts
  412.  
  413.  
  414. *********************************************************
  415. *
  416. *  Readerror extentions
  417. *
  418. *  When arrived here, there is a read error.  Some original code is executed here (%).
  419. *  When Trackdisk has finished its retry scheme without success, we will give it a try
  420. *
  421.  
  422. TDE_ReadError   addq.b  #1,TDU_Retries(a3)              % Increment retry counter
  423.                 move.b  TDU_Retries(a3),d0              % Get present value of it
  424.                 cmp.b   TDU_RETRYCNT(a3),d0             % Lower or equal to limit?
  425.                 ble     TD_ReadTrkRetry                 A9EA Yes, retry..
  426.                 btst.b  #B_SALVE,UNIT_pad(a3)           No, TD stops, are we going to do something about it?
  427.                 beq     TD_ReadTrkRtn                   A9F8 No, function not active, continue TD's error handling..
  428.  
  429. *
  430. *  We now are going to try to salve this track.  We will read the track in a large buffer.
  431. *  This read is so big that there will be an unbroken track in the buffer.  If we find a
  432. *  valid sector address in this unbroken track, we can calculate the position of the
  433. *  track in the buffer.
  434. *
  435. *  We have:     a2      TD's trackbuffer
  436. *               a3      TD's Unit structure
  437. *
  438. *  We will use: a4      UnitData structure
  439. *               a5      TrackSalveControl structure/ SalveBuffer structure
  440. *
  441.  
  442.                 movem.l a4/a5,-(a7)
  443.                 move.l  TDU_TCB+TC_Userdata(a3),a4      Lea UnitData structure
  444.                 move.l  UD_TSControl(a4),a5             Lea TSControl structure
  445.                 bsr     ObtainBuffer
  446.                 move.l  a0,a5                           Extra large read buffer
  447.                 moveq.l #-1,d0                          Motor on
  448.                 bsr     TD_SwitchMotor
  449.                 lea.l   SB_Data(a5),a0                  Begin of data in buffer
  450.                 move.l  a0,SB_Begin(a5)
  451.                 lea.l   (2*SPT-1)*SE_SIZE+GAPSIZE(a0),a0 Add size we search in for syncs
  452.                 move.l  a0,SB_End(a5)
  453.                 move.w  #BADTRACKBITS,UD_SavedL(a4)     Init log saved labels
  454.                 move.w  #BADTRACKBITS,UD_SavedD(a4)     Init log saved data
  455.                 moveq.l #3,d6                           Init retry number
  456.  
  457. RE_SalveLoop    lea.l   SB_Data(a5),a0                  Destination for disk-read
  458.                 move.l  #2*SPT*SE_SIZE+GAPSIZE,d0       Number of bytes to read
  459.                 bsr     TD_ReadDisk                     A524 Read d0 bytes into (a0)
  460.                 tst.l   d0                              DiskChange?
  461.                 beq.s   10$                             No..
  462.                 move.b  d0,TB_FirstSec(a2)              Yes, store error in trackbuffer for TD
  463.                 bra.s   RE_Rtn                          Leave..
  464. 10$             clr.w   SB_CorrectTrk(a5)               Reset counter of headers with good tracknumber
  465.                 clr.w   SB_WrongTrk(a5)                 Reset counter of headers with wrong tracknumber
  466.                 bsr     Salve                           Analyse the buffer and save what is possible
  467.                 beq.s   RE_Rtn                          All sectors and labels salved
  468.                 move.w  SB_CorrectTrk(a5),d0            How many times did we encounter good tracknumbers
  469.                 cmp.w   SB_WrongTrk(a5),d0              And how many bad?
  470.                 bpl.s   20$                             More good..
  471.                 subq.l  #1,d6                           Restore, just subtract one
  472.                 ble.s   RE_Rtn
  473.                 move.w  #-1,TDU_PTrack(a3)              Set current track to "Unknown"
  474.                 moveq.l #0,d0
  475.                 move.w  TDU_XTrack(a3),d0               Get track number we want
  476.                 bsr     TD_Seek                         A3DA Restore and seek
  477.                 bra.s   RE_SalveLoop                    Try again to salve the track
  478. 20$             subq.l  #2,d6                           No restore, we read the correct track already, subtract two
  479.                 bhi.s   RE_SalveLoop
  480.  
  481. RE_Rtn          bsr     ReleaseBuffer
  482.                 movem.l (a7)+,a4/a5
  483.                 bra     TD_ReadTrkRtn                   Continue TD
  484.  
  485.  
  486. *-------------------------------------------------------*
  487. *
  488. *  --  Salve  --
  489. *
  490. *  We search for a sync.  If found we try to get a reliable sector address from the
  491. *  succeeding data.  This address tells us how much and the position of the track preceding
  492. *  this sector.  We try to recover these sectors if we did not already.  The area after the
  493. *  found sector is also checked for sector presence, but if no success search will continue
  494. *  from the found sync.
  495. *
  496. *  Input:       a2      TB_  Trackdisk trackbuffer
  497. *               a3      TDU_ Trackdisk Unit structure
  498. *               a4      UD_  TrackSalve UnitData structure
  499. *               a5      SB_  TrackSalve SalveBuffer structure
  500. *
  501. *  Usage:       d2      Scratch
  502. *               d5      Pointer to sector in imaginary track
  503. *               d6      Pointer to sector of last detected sync
  504. *               d7      Shiftfactor
  505. *
  506. *  Returns:     d0      Zero if all sectors and labels saved
  507. *
  508.  
  509.  
  510. Salve           movem.l d2/d5-d7,-(a7)
  511.                 subq.l  #HE_SIZE,a7                     Four bytes local storage
  512.  
  513.                 move.l  SB_Begin(a5),d6                 Begin of buffer
  514.                 subq.l  #8,d6                           Undo next instruction
  515.  
  516. *--     Scan buffer for syncs.  If found, test it for a valid header.
  517.  
  518. ST_SearchLoop   addq.l  #8,d6                           Point to word past previous sync found
  519.                 move.l  SB_End(a5),d0                   End of search area
  520.                 sub.l   d6,d0                           Minus begin of search area is search size
  521.                 ble     ST_EndSearch                    End of buffer reached..
  522.                 move.l  d6,a0                           Actual begin of search
  523.                 bsr     SearchSync                      Search next sync on this track
  524.                 bmi     ST_EndSearch                    No sync found, leave..
  525.                 subq.l  #6,a0                           Point to begin of potential sector
  526.                 move.l  a0,d6                           Keep potential sector found
  527.                 bsr     GetHeader                       Test validity and decode header
  528.                 ble.s   ST_SearchLoop                   Not valid
  529.  
  530. *--     We have a sector header.  Figure a track around it.
  531.  
  532.                 move.l  d0,(a7)                         Local header for loop control
  533.                 moveq.l #SPT,d0                         Number of sectors per track
  534.                 sub.b   HE_ToGap(a7),d0                 Subtract ahead of us, leaves us with number of sectors before us
  535.                 sub.b   d0,HE_SecNo(a7)                 Set number of first sector, still positive?
  536.                 bpl.s   10$                             Yes..
  537.                 add.b   #SPT,HE_SecNo(a7)               No, wrap
  538. 10$             move.b  #SPT,HE_ToGap(a7)               New gap countdown
  539.                 mulu    #SE_SIZE,d0                     Convert number of sectors to bytes before our position
  540.                 move.l  d6,d5                           Pointer to present sector
  541.                 sub.l   d0,d5                           Pointer to first potential sector
  542.  
  543. *--     Scan imaginary track for storable sectors
  544.  
  545. ST_TrackLoop    cmp.l   SB_Begin(a5),d5                 Are we before begin of the buffer?
  546.                 bmi     ST_NextSector                   Yes, next sector..
  547.                 cmp.l   SB_End(a5),d5                   Are we past the end of the buffer?
  548.                 bpl.s   ST_SearchLoop                   Yes, stop with this track..
  549.                 move.b  HE_SecNo(a7),d0                 Sector number
  550.                 move.l  UD_SavedL(a4),d1                Log of stored labels and sectors
  551.                 beq     ST_AllSaved                     All stored, leave this routine..
  552.                 btst    d0,d1                           Is the data of this sector already stored?
  553.                 bne.s   ST_SaveSector                   No, try to..
  554.                 swap    d1                              Yes, test the label
  555.                 btst    d0,d1                           This label aready saved?
  556.                 beq     ST_NextSector                   Yes, try next sector in our imaginary track..
  557.  
  558. *--     Try to store as much as possible from the sector d5 is pointing to.
  559.  
  560. ST_SaveSector   move.l  d5,a0                           Ea of present sector
  561.                 bsr     GetHeader                       Get its header if possible
  562.                 bmi     ST_NextSector                   Wrong track..
  563.                 beq.s   ST_SaveData                     No header, perhaps the sector's data is OK
  564.                 cmp.l   (a7),d0                         This MUST be the same or what?
  565.                 bne     ST_VeryBad                      Very bad indeed
  566.                 move.l  d5,a0                           Ea of present sector
  567.                 lea.l   SE_SumD(a0),a0                  Lea data checksum
  568.                 bsr     DecodeLong                      Decode it
  569.                 move.l  d0,d2                           Keep for compare
  570.                 move.l  #TD_SECTOR/2,d0                 Size of data-part of sector in longs
  571.                 bsr     CheckSum                        Calculate checksum over data
  572.                 cmp.l   d2,d0                           Same as found on disk?
  573.                 beq.s   ST_CopySector                   Yes, save to copy the complete sector..
  574.                 move.b  HE_SecNo(a7),d0                 No, but we have a valid header, the numbers are ok and if this
  575.                 move.w  UD_SavedD(a4),d1                  sector is not yet saved, we better still copy it
  576.                 btst    d0,d1                           Sector already saved?
  577.                 beq     ST_SaveLabel                    Yes, skip bad sector copy
  578.                 bra.s   ST_LabelOK                      We copy the sector, but skip the bitclear..
  579. ST_CopySector   move.b  HE_SecNo(a7),d0                 Number of this sector
  580.                 move.w  UD_SavedD(a4),d1                Data save-log
  581.                 bclr    d0,d1                           Set data saved
  582.                 move.w  d1,UD_SavedD(a4)
  583. ST_LabelOK      move.b  HE_SecNo(a7),d0                 Number of this sector
  584.                 move.w  UD_SavedL(a4),d1                Label save-log
  585.                 bclr    d0,d1                           Set label saved
  586.                 move.w  d1,UD_SavedL(a4)
  587.                 ext.w   d0                              Cnv sectornumber byte to word
  588.                 mulu    #SE_SIZE,d0                     To byte offset
  589.                 lea.l   TB_Data(a2),a1                  TD's buffer, begin of sectors
  590.                 lea.l   SE_Label(a1,d0),a1              Lea destination of our data
  591.                 move.l  d5,a0                           Ea of present source sector
  592.                 lea.l   SE_Label(a0),a0                 Lea begin of part to copy
  593.                 move.w  #((SSIZE/2)<<HSIZEBITS)+1,d0    Size of sector for blitter
  594.                 move.w  #SSIZE,d2                       Bytesize
  595.                 bsr     BlitMove                        Copy to TD's buffer
  596.                 bra     ST_NextSector                   Loop for next sector
  597.  
  598. ST_SaveData     move.b  HE_SecNo(a7),d0                 Sector number
  599.                 move.w  UD_SavedD(a4),d1                Saved data log
  600.                 btst    d0,d1                           Data of this sector already saved?
  601.                 beq.s   ST_NextSector                   Yes..
  602.                 move.l  d5,a0                           Ea of present sector
  603.                 lea.l   SE_SumD(a0),a0                  Lea data checksum
  604.                 bsr     DecodeLong                      Decode it
  605.                 move.l  d0,d2                           Keep for compare
  606.                 move.l  #TD_SECTOR/2,d0                 Size of data-part of sector in longs
  607.                 bsr     CheckSum                        Calculate checksum over data
  608.                 cmp.l   d2,d0                           Same as found on disk?
  609.                 bne.s   ST_NextSector                   No, no header and bad data, skip copy, next perhaps..
  610.                 moveq.l #0,d0
  611.                 move.b  HE_SecNo(a7),d0                 Number of present sector
  612.                 move.w  UD_SavedD(a4),d1                Saved data log
  613.                 bclr    d0,d1                           Set data of this sector saved
  614.                 move.w  d1,UD_SavedD(a4)
  615.                 mulu    #SE_SIZE,d0                     Sector number times sectorsize to find offset in TD's buffer
  616.                 lea.l   TB_Data(a2),a1                  TD's buffer, begin of sectors
  617.                 lea.l   SE_SumD(a1,d0),a1               Lea destination of our data
  618.                 move.l  d5,a0                           Ea of source sector
  619.                 lea.l   SE_SumD(a0),a0                  Lea Data checksum, begin of copy to TD's buffer
  620.                 move.w  #((DSIZE/2)<<HSIZEBITS)+1,d0    Size of datapart and its checksum ready for the blitter
  621.                 move.w  #DSIZE,d2                       Bytesize of block
  622.                 bsr     BlitMove                        Copy to TD's buffer
  623.                 bra.s   ST_NextSector                   Continue loop..
  624.  
  625.  
  626. ST_SaveLabel  ; move.b  HE_SecNo(a7),d0                 Present sector number
  627.                 move.l  UD_SavedL(a4),d1                Saved labels log
  628.                 bclr    d0,d1                           We have a good one here
  629.                 beq.s   ST_NextSector                   Was already saved, continue..
  630.                 move.l  d1,UD_SavedL(a4)                Nice, we can save a label
  631.                 ext.w   d0
  632.                 mulu.w  #SE_SIZE,d0                     To byte offset
  633.                 lea.l   TB_Data(a2),a1                  Lea begin of sectors
  634.                 lea.l   SE_Label(a1,d0),a1              Lea of label in destination sector in TD's buffer
  635.                 move.l  d5,a0                           Ea of present sector
  636.                 lea.l   SE_Label(a0),a0                 Lea label in source sector
  637.                 move.w  #((LSIZE/2)<<HSIZEBITS)+1,d0    Size of label ready for the blitter
  638.                 moveq.l #LSIZE,d2                       Bytesize of block to move
  639.                 bsr     BlitMove                        Move label to Trackdisks buffer
  640.                 bra.s   ST_NextSector                   Continue loop..
  641.  
  642. *--     Track-scan loop control.
  643.  
  644. ST_NextSector   move.b  HE_SecNo(a7),d0                 Sector number
  645.                 addq.b  #1,d0                           Next sector
  646.                 cmp.b   #SPT,d0                         Must we wrap?
  647.                 bcs.b   10$                             No..
  648.                 moveq.l #0,d0                           Yes, sector 0
  649. 10$             move.b  d0,HE_SecNo(a7)
  650.                 add.l   #SE_SIZE,d5                     Present sector pointer to next sector
  651.                 subq.b  #1,HE_ToGap(a7)                 Decrement remaining sectors in our track, any left?
  652.                 bhi     ST_TrackLoop                    Yes, process it..
  653.                 bra     ST_SearchLoop                   No, we are ready with our track, try to find a new one..
  654.  
  655. ST_EndSearch
  656. ST_AllSaved     move.l  UD_SavedL(a4),d0
  657.  
  658. ST_Rtn          addq.l  #HE_SIZE,a7                     Clean up local
  659.                 tst.l   d0                              Return proper condition codes
  660.                 movem.l (a7)+,d2/d5-d7
  661.                 rts
  662.  
  663. ST_VeryBad      move.l  #BADTRACKBITS<<16+BADTRACKBITS,d0 Assume all labels and sectors to be unreliable
  664.                 move.l  d0,UD_SavedL(a4)
  665.                 bra.s   ST_Rtn
  666.  
  667.  
  668. *-------------------------------------------------------*
  669. *
  670. *  GetHeader
  671. *
  672. *  Subroutine for Salve.  Test validity of the first part of a Trackdisk sector.  Set sector
  673. *  address in SB_Header and return in d0 if valid.  Update statistics regarding tracknumber.
  674. *  Return wrong track as a special case.
  675. *
  676. *  Input:       d7      Shift factor
  677. *               a0      Sector structure, SE_
  678. *               a2      Trackdisk trackbuffer structure, TB_
  679. *               a5      SalveBuffer structure, SB_
  680. *
  681. *  Return:      d0      Header, -1 on wrong track, 0 on other errors.
  682. *               a0      Ea of SE_Label
  683. *
  684.  
  685. GetHeader       addq.l  #SE_Header,a0
  686.                 moveq.l #HE_SIZE/2+TD_LABELSIZE/2,d0    Size of checksum area (longs)
  687.                 bsr     CheckSum                        Calculate checksum
  688.                 move.l  d0,-(a7)                        Keep checksum
  689.                 bsr     DecodeLong                      Decode it
  690.                 cmp.l   (a7)+,d0                        The same?
  691.                 bne.s   GH_NotGood                      No..
  692.                 add.w   #(SE_Header-SE_SumD),a0         Lea header again
  693.                 bsr     DecodeLong
  694.                 move.l  d0,(a5)                         Make header available
  695.                 cmp.b   #DISKFORMAT,(a5)                Our format?
  696.                 bne.s   GH_NotGood                      No..
  697.                 move.w  TB_TrkNo(a2),d1                 Track number under head
  698.                 cmp.b   HE_TrkNo(a5),d1                 Same as in header?
  699.                 bne.s   GH_WrongTrack                   No..
  700.                 addq.w  #1,SB_CorrectTrk(a5)            Yes, one for us
  701.                 rts
  702. GH_WrongTrack   addq.w  #1,SB_WrongTrk(a5)              One for them
  703.                 moveq.l #-1,d0                          Error (restore?)
  704.                 rts
  705. GH_NotGood      moveq.l #0,d0                           Error
  706.                 rts
  707.  
  708. *-------------------------------------------------------*
  709. *
  710. *  DecodeLong
  711. *
  712. *  Get two longwords from shifted memory and decode them into one longword
  713. *
  714. *  Input:       d7      Shift factor
  715. *               a0      Data source
  716. *
  717. *  Return:      d0      Decoded longword
  718. *               a0      Proper aligned for next access
  719. *
  720.  
  721. DecodeLong      movem.l d2/d3,-(a7)
  722.                 moveq.l #16,d3                          Shift modulus
  723.                 sub.l   d7,d3                           Complementary shift number
  724.                 move.l  (a0)+,d0                        Get 48 bits (long + max shift)
  725.                 move.w  (a0),d2
  726.                 lsl.l   d7,d0                           Shift first 32 bits left
  727.                 lsr.w   d3,d2                           Shift last 16 bits right
  728.                 or.w    d2,d0                           Put them together into one longword
  729.                 move.l  (a0)+,d1                        Get 48 bits (long + max shift)
  730.                 move.w  (a0),d2
  731.                 lsl.l   d7,d1                           Shift first 32 bits left
  732.                 lsr.w   d3,d2                           Shift last 16 bits right
  733.                 or.w    d2,d1                           Put them together into one longword
  734.                 and.l   #$55555555,d0                   Remove MFM bits
  735.                 and.l   #$55555555,d1
  736.                 lsl.l   #1,d0                           Line up
  737.                 or.l    d1,d0                           Melt
  738.                 movem.l (a7)+,d2/d3
  739.                 rts
  740.  
  741.  
  742. *-------------------------------------------------------*
  743. *
  744. *  CheckSum
  745. *
  746. *  Calculate checksum over shifted memory
  747. *
  748. *  Input:       d0      Length in longs
  749. *               d7      Shift factor
  750. *               a0      Begin of block
  751. *
  752. *  Return:      d0      Checksum
  753. *               a0      Aligned to begin of next block
  754. *
  755.  
  756. CheckSum        movem.l d2/d3,-(a7)
  757.                 moveq.l #-1,d1                          Build mask for first access
  758.                 lsr.l   d7,d1                           Shift mask
  759.                 move.l  (a0)+,d2                        Get part of first long
  760.                 and.l   d1,d2                           Mask non-involved bits
  761.                 subq.l  #2,d0
  762. 10$             move.l  (a0)+,d3                        Get longs
  763.                 eor.l   d3,d2                           Checksum algorithm
  764.                 dbra    d0,10$                          Loop
  765.                 move.l  (a0),d3                         Get last part of last long
  766.                 not.l   d1                              Flip mask
  767.                 and.l   d1,d3                           Mask non-involved bits
  768.                 eor.l   d3,d2                           Checksum algorithm
  769.                 rol.l   d7,d2                           Unshift
  770.                 and.l   #$55555555,d2                   Select relevant bits
  771.                 move.l  d2,d0                           Checksum
  772.                 movem.l (a7)+,d2/d3
  773.                 rts
  774.  
  775. *-------------------------------------------------------*
  776. *
  777. *  SearchSync
  778. *
  779. *  Search for a Sync. If found, return its address on word boundary and
  780. *  how many bits it is shifted to the right. (max 15)
  781. *
  782. *  Input:       d0.w    Number of words to check
  783. *               a0      Start address to search
  784. *
  785. *  Returns:     d0      Words left
  786. *               d7      Bitshift
  787. *               a0      Sync
  788. *
  789.  
  790. SearchSync      move.w  (a0)+,d1
  791.                 cmp.w   #SYNCSYNC>>0,d1
  792.                 beq.s   SS_Found0
  793.                 cmp.w   #SYNCSYNC>>1,d1
  794.                 beq.s   SS_Found1
  795.                 cmp.w   #SYNCSYNC>>2,d1
  796.                 beq.s   SS_Found2
  797.                 cmp.w   #SYNCSYNC>>3,d1
  798.                 beq.s   SS_Found3
  799.                 cmp.w   #SYNCSYNC>>4,d1
  800.                 beq.s   SS_Found4
  801.                 cmp.w   #SYNCSYNC>>5,d1
  802.                 beq.s   SS_Found5
  803.                 cmp.w   #SYNCSYNC>>6,d1
  804.                 beq.s   SS_Found6
  805.                 cmp.w   #SYNCSYNC>>7,d1
  806.                 beq.s   SS_Found7
  807.                 cmp.w   #SYNCSYNC>>8,d1
  808.                 beq.s   SS_Found8
  809.                 cmp.w   #SYNCSYNC>>9,d1
  810.                 beq.s   SS_Found9
  811.                 cmp.w   #SYNCSYNC>>10,d1
  812.                 beq.s   SS_Found10
  813.                 cmp.w   #SYNCSYNC>>11,d1
  814.                 beq.s   SS_Found11
  815.                 cmp.w   #SYNCSYNC>>12,d1
  816.                 beq.s   SS_Found12
  817.                 cmp.w   #SYNCSYNC>>13,d1
  818.                 beq.s   SS_Found13
  819.                 cmp.w   #SYNCSYNC>>14,d1
  820.                 beq.s   SS_Found14
  821.                 cmp.w   #SYNCSYNC>>15,d1
  822.                 beq.s   SS_Found15
  823.                 dbra    d0,SearchSync                   Loop d0 words
  824.                 moveq.l #-1,d7                          Set not found
  825. SS_Rtn          subq.l  #2,a0
  826. SS_Rtn10        rts
  827.  
  828. SS_Found0       moveq.l #0,d7
  829.                 bra.s   SS_Rtn10
  830. SS_Found1       moveq.l #1,d7
  831.                 bra.s   SS_Rtn
  832. SS_Found2       moveq.l #2,d7
  833.                 bra.s   SS_Rtn
  834. SS_Found3       moveq.l #3,d7
  835.                 bra.s   SS_Rtn
  836. SS_Found4       moveq.l #4,d7
  837.                 bra.s   SS_Rtn
  838. SS_Found5       moveq.l #5,d7
  839.                 bra.s   SS_Rtn
  840. SS_Found6       moveq.l #6,d7
  841.                 bra.s   SS_Rtn
  842. SS_Found7       moveq.l #7,d7
  843.                 bra.s   SS_Rtn
  844. SS_Found8       moveq.l #8,d7
  845.                 bra.s   SS_Rtn
  846. SS_Found9       moveq.l #9,d7
  847.                 bra.s   SS_Rtn
  848. SS_Found10      moveq.l #10,d7
  849.                 bra.s   SS_Rtn
  850. SS_Found11      moveq.l #11,d7
  851.                 bra.s   SS_Rtn
  852. SS_Found12      moveq.l #12,d7
  853.                 bra.s   SS_Rtn
  854. SS_Found13      moveq.l #13,d7
  855.                 bra.s   SS_Rtn
  856. SS_Found14      moveq.l #14,d7
  857.                 bra.s   SS_Rtn
  858. SS_Found15      moveq.l #15,d7
  859.                 bra.s   SS_Rtn
  860.  
  861.  
  862. *-------------------------------------------------------*
  863. *
  864. *  BlitMove
  865. *
  866. *  Move a block of data from source to destination and shift it left by some bits.
  867. *
  868. *  Input:       d0.w    Blitsize ready to pass to the blitter
  869. *               d2.w    Bytesize of block to move
  870. *               d7.w    Shift factor: number of bits that memory IS shifted to the right
  871. *               a0      Source
  872. *               a1      Destination
  873. *
  874. *  In linear mode the blitter can move at most 2^10 (1024) words. Therefore we use      its
  875. *  rectancular mode. We can set the horizontal size to 1 to 128 words, thus limiting our
  876. *  blit to multiples of these.
  877.  
  878. BlitMove        movem.l d3-d5,-(a7)
  879.                 sub.w   #TSBN_SIZE,a7                   Extended blitnode on the stack
  880.                 moveq.l #0,d4                           First let's clear all unused and undefined
  881.                 move.l  d4,(a7)                            parts of the blinode as stated in
  882.                 move.w  d4,bn_stat(a7)                     I&A Introduction-5 Obey 3&4
  883.                 move.l  d4,bn_cleanup(a7)
  884.  
  885. *  We use the blitter in ascending mode. Then the blitter performs shifts to the right.
  886. *  Therfore we translate our order to shift left into shift right.  IF we shift, and we
  887. *  stick to our blitsize, we loose some bits. This is because we express in blitsize
  888. *  the size of the track in words instead of bits.  If these bits do not begin on a
  889. *  word-boundary they do not end either.   Because the blitter can move maximal 1024
  890. *  block of 1 to 128 words, and we do not determine the blocksize (the calling routine is),
  891. *  we take care of this word by hand (the cpu).
  892.  
  893.                 move.l  d7,d4                           Shiftfactor (to left)
  894.                 neg.w   d4                              We want 16 minus shift results in requested shift to right, zero?
  895.                 beq.s   10$                             Yes, no shift..
  896.                 subq.l  #2,a1                           Destination one word lower
  897.                 move.w  (a1),d3                         Keep first word to restore after blit
  898.                 move.l  -2(a0,d2.w),d5                  Get last two words of block (out of reach of the blitter)
  899.                 lsl.l   d7,d5                           Do the shift of the last word here
  900.                 swap.w  d5                              D5 holds now the last word
  901. 10$             move.w  d0,bn_blitsize(a7)              The calling routine has aready assembled the correct value
  902.                 moveq.l #BSHIFTSHIFT,d0                 Shift shift factor 12 bits left, thus clearing all other
  903.                 lsl.w   d0,d4                             bits: no fill, ascending and area mode
  904.                 move.w  d4,TSBN_C1(a7)                  Prepared blitter command
  905.                 move.l  a0,TSBN_SceB(a7)                Source
  906.                 move.l  a1,TSBN_Dest(a7)                Destination
  907.                 move.l  a3,TSBN_Unit(a7)                TD-Unit structure
  908.                 lea.l   QF_Shift(pc),a0                 Lea blitter function
  909.                 move.l  a0,bn_function(a7)              Function into blitnode
  910.                 move.l  a7,a1                           Pointer to our blitnode
  911.                 move.l  a6,-(a7)
  912.                 move.l  TDD_GfxBase(a6),a6              The graphics library coordinates blitter usage
  913.                 LibCall QBlit                           Control is returned immedately so we must wait here
  914.                 move.l  (a7)+,a6
  915.                 bsr     TD_WaitTDPort                   A70A Wait for a message we sent to ourself from within Gfx
  916.                 tst.w   TSBN_C1(a7)                     Shift not zero?: Did we modify the destination pointer?
  917.                 beq.s   20$                             No, blit fitted in word boundary..
  918.                 move.l  TSBN_Dest(a7),a0                Yes, get destination (pointing one word earlier)
  919.                 move.w  d3,(a0)                         Restore original value of word before desired destination
  920.                 move.w  d5,0(a0,d2.w)                   Last word which was out of reach of the blitter
  921. 20$             add.w   #TSBN_SIZE,a7                   Free blitnode
  922.                 movem.l (a7)+,d3-d5
  923.                 rts
  924.  
  925.  
  926. *-------------------------------------------------------*
  927. *
  928. *  QBlit function. Parameters are passed via the blitnode structure.  We have exclusive control
  929. *  over the blitter here.
  930. *  NB!  This code is executed under control of other regimes. Behave well.
  931. *  We tell the blitter to move and shift our block.
  932. *
  933. *  Input:       a0      Pointer to blitter
  934. *               a1      Pointer to blitnode
  935. *
  936. *  Returns:     d0      -1, meaning not ready
  937. *
  938.  
  939. QF_Shift        moveq.l #0,d0
  940.                 move.w  d0,bltbmod(a0)                  No modulus for B
  941.                 move.w  d0,bltdmod(a0)                  No modulus for D
  942. BLITLF          set     ABC+ABNC+NABC+NABNC             D=B
  943. BLITUSE         set     SRCB+DEST                       B is source and D destination
  944.                 move.w  #BLITLF+BLITUSE,bltcon0(a0)
  945.                 move.w  TSBN_C1(a1),bltcon1(a0)         Shift factor into BSH (B-shift) ascending
  946.                 move.l  TSBN_SceB(a1),bltbpt(a0)        Source into  B
  947.                 move.l  TSBN_Dest(a1),bltdpt(a0)        Destination into  D
  948.                 move.w  bn_blitsize(a1),bltsize(a0)     Start blit by writing size
  949.                 lea.l   QF_End(pc),a0                   Lea terminating function
  950.                 move.l  a0,bn_function(a1)              Function into blit node
  951.                 moveq.l #-1,d0
  952.                 rts
  953.  
  954. *-------------------------------------------------------*
  955. *
  956. *  QBlit function. Parameters are passed via the blitnode structure.  We have exclusive control
  957. *  over the blitter here.
  958. *  NB!  This code is executed under control of other regimes. Behave well.
  959. *  We signal the td task that the blit is done. (Here we are NOT the TD task)
  960. *
  961. *  Input:       a0      Pointer to blitter
  962. *               a1      Pointer to blitnode
  963. *
  964. *  Returns:     d0      0, meaning ready
  965. *
  966.  
  967. QF_End          move.l  TSBN_Unit(a1),a1                TD unit pointer
  968.                 bsr     TD_Reply
  969.                 moveq.l #0,d0                           Return 0 to stop QBlit
  970.                 rts
  971.  
  972.  
  973. *********************************************************
  974. *
  975. *  Read extensions.
  976. *
  977. *  Adapt reads (and writes) to error handling based on error flags for each sector apart.
  978. *  Trackdisk sets the tracknumber in its trackbuffer to -1, meaning no valid track in the
  979. *  buffer.  TD does this if it finds a TB_FirstSec larger than possible.  We prevent TD doing
  980. *  so. Instead we check TD_FirstSec each time TD_TrkNo would have been checked.  This enables
  981. *  us to access a faulty trackbuffer when we use the salve function.
  982. *
  983.  
  984.  
  985. TDE_Read        cmp.b   #SPT,TB_FirstSec(a0)            Error in this track?
  986.                 bmi     TD_CmdRead                      A890 No..
  987.                 btst.b  #B_SALVE,UNIT_pad(a3)           Yes, but is the track salved?
  988.                 bne.s   10$                             Yes..
  989.                 move.b  TB_FirstSec(a0),IO_ERROR(a2)    No, set error in IORequest
  990.                 bra     TD_EndRW                        A920 Return error..
  991. 10$
  992.  
  993. *--     Here we have a read command on a salved track.  Always copy data, but if this data is bad, set IO_ERROR
  994.  
  995.                 move.l  TDU_TCB+TC_Userdata(a3),a1      Lea UnitData structure
  996.                 move.l  UD_SavedL(a1),d1                Get pattern with bad sectors and labels
  997.                 moveq.l #0,d0
  998.                 move.b  TDU_IOSector(a3),d0             Current sector number
  999.                 btst    d0,d1                           Faulting sector?
  1000.                 bne.s   20$                             Yes, set error..
  1001.                 btst.b  #0,TDU_Flags(a3)                No, label transfer?
  1002.                 beq     TD_CmdRead10                    A8A0 No, no error, continue..
  1003.                 swap.w  d1                              Yes, label transfer, get label log
  1004.                 btst    d0,d1                           A8A0 Faulting label?
  1005.                 beq     TD_CmdRead10                    No..
  1006. 20$             move.b  TB_FirstSec(a0),IO_ERROR(a2)    Set error
  1007.                 bra     TD_CmdRead10                    A8A0
  1008.  
  1009.  
  1010.  
  1011.  
  1012. *********************************************************
  1013. *
  1014. *  ObtainBuffer -  ReleaseBuffer
  1015. *
  1016. *  Handling of permission to use the buffer
  1017. *
  1018. *  Input:       a3      TD unit structure
  1019. *
  1020. *  Returns:     a0      buffer
  1021. *
  1022.  
  1023. ObtainBuffer    move.l  a2,-(a7)
  1024.                 move.l  TDU_TCB+TC_Userdata(a3),a2      Lea UnitData structure
  1025.                 move.l  UD_TSControl(a2),a2             Lea TSControl structure
  1026.                 lea.l   TSC_OwnBuffer(a2),a0            Lea Semaphore for salvage system usage
  1027.                 move.l  a6,-(a7)
  1028.                 move.l  TDD_SysBase(a6),a6              Trackdisk's SysBase
  1029.                 LibCall AttemptSemaphore                Try to lock Salve system
  1030.                 move.l  (a7)+,a6
  1031.                 tst.l   d0                              Locked?
  1032.                 bne.s   10$                             Yes..
  1033.                 moveq.l #0,d0                           No, motor off
  1034.                 bsr     TD_SwitchMotor
  1035.                 lea.l   TSC_OwnBuffer(a2),a0            Lea Semaphore for salvage system usage
  1036.                 move.l  a6,-(a7)
  1037.                 move.l  TDD_SysBase(a6),a6              Trackdisk's SysBase
  1038.                 LibCall ObtainSemaphore                 Wait for permission to use it
  1039.                 move.l  (a7)+,a6
  1040. 10$             move.l  TSC_Buffer(a2),a0               The buffer itself
  1041.                 move.l  (a7)+,a2
  1042.                 rts
  1043.  
  1044.  
  1045. ReleaseBuffer   move.l  TDU_TCB+TC_Userdata(a3),a0      Lea UnitData structure
  1046.                 move.l  UD_TSControl(a0),a0             Lea TSControl structure
  1047.                 lea.l   TSC_OwnBuffer(a0),a0            Lea Semaphore for salvage system usage
  1048.                 move.l  a6,-(a7)
  1049.                 move.l  TDD_SysBase(a6),a6              Trackdisk's SysBase
  1050.                 LibCall ReleaseSemaphore
  1051.                 move.l  (a7)+,a6
  1052.                 rts
  1053.  
  1054.  
  1055. *********************************************************
  1056. *
  1057. *  At one point in TD_NormTrack all data has been moved to their definitive position.  After this point
  1058. *  all sectorheaders are recalculated.  If we are verifying we do not want any changes, just the move.
  1059. *  So at this position we want to leave TD_NormTrack.  TD_NormTrack calls some subroutine at that point
  1060. *  and we are there to check whether we are verifying or not.
  1061. *
  1062.  
  1063. TDE_NormTrack   tst.l   24(a7)                          The original caller of TD_NormTrack had zero saved here
  1064.                 beq.w   TD_CorrectEdge                  Zero, proceed normal..
  1065.                 ;addq.l #4,a7                           Non-zero: TD_NormTrack was called by the verify routine
  1066.                 bra.w   TD_NormTrackRtn                 Skip header revision..
  1067.  
  1068.  
  1069. *********************************************************
  1070. *
  1071. *  Write extensions.
  1072. *
  1073. *  Write Trackdisks buffer to disk and check whether verify is enabled.  Do not verify if the
  1074. *  TD_WriteTrack returned an error.  Get the verify buffer and read the just written track into
  1075. *  it.  Tidy the buffer up and compare it with the just written.  In case of some error, display
  1076. *  a requester and rewrite if asked for.
  1077. *
  1078. *  Input:       a3      Trackdisk Unit structure
  1079. *               a6      Trackdisk device base
  1080. *
  1081. *  Returns:     d0      Write error
  1082. *
  1083. *  Usage        d2      Error
  1084. *               a2      Verify buffer
  1085. *               a4      Trackdisk buffer written to disk
  1086. *
  1087.  
  1088. TDR_WriteTrackF clr.b   TB_FirstSec(a0)                 Format does not use and set this field
  1089. TDR_WriteTrack  bsr     TD_WriteTrack                   Normal write track
  1090.                 btst.b  #B_VERIFY,UNIT_pad(a3)          Is write-verify enabled?
  1091.                 bne.s   20$                             Yes..
  1092. 10$             rts
  1093.  
  1094. 20$             tst.l   d0                              Did TD_WriteTrack had an error?
  1095.                 bne.s   10$                             Yes, we do not verify..
  1096.  
  1097.                 movem.l d2/a2/a4,-(a7)
  1098.                 bsr     ObtainBuffer                    Get buffer to read into from disk
  1099.                 move.l  a0,a2
  1100.                 move.l  TDU_DiskBuf(a3),a4              The buffer which was written to disk
  1101.                 move.l  a2,TDU_DiskBuf(a3)              The buffer into we will read from disk
  1102.                 move.w  (a4),(a2)                       Tracknumber
  1103.                 moveq.l #1,d0                           Motor on
  1104.                 bsr     TD_SwitchMotor
  1105.                 moveq.l #0,d0
  1106.                 move.w  (a2),d0                         Tracknumber
  1107.                 bsr     TD_Seek                         A3DA Seek to it
  1108.                 lea.l   TB_Data+4(a2),a0                Position in buffer to begin to read
  1109.                 move.w  #(SPT+1)*SE_SIZE+GAPSIZE,d0     Size of read
  1110.                 bsr     TD_ReadDisk                     Read from disk
  1111.                 tst.l   d0                              DiskChange?
  1112.                 bne.s   30$                             Yes, that is a verify error..
  1113.                 move.w  TDU_XTrack(a3),d2               Keep current value
  1114.                 move.w  (a4),TDU_XTrack(a3)             TD_NormTrack uses this value as the current track
  1115.                 moveq.l #-1,d0                          Tell (modified) TD_NormTrack to skip header revision
  1116.                 bsr     TD_NormTrack                    Tidy the track up
  1117.                 move.w  d2,TDU_XTrack(a3)               Restore original value
  1118.                 move.l  a4,TDU_DiskBuf(a3)              TD's write buffer back into TD's global
  1119.                 cmp.b   #SPT,d0                         Error?
  1120.                 bcc.s   30$                             Yes..
  1121.                 move.b  d0,TB_FirstSec(a2)              First sector in the verify buffer
  1122.                 move.l  a2,a0                           Verify buffer
  1123.                 move.l  a4,a1                           Original written buffer
  1124.                 bsr     CompareTracks                   Compare both buffers (they are not exactly the same)
  1125.                 beq.s   VT_Rtn                          No error..
  1126.  
  1127. *--     Let's request. TD has a 512 byte stack. Not enough to call Intuition..  But we have here a buffer of 26k!
  1128.  
  1129. 30$             moveq.l #0,d0                           Motor off during request
  1130.                 bsr     TD_SwitchMotor
  1131.                 add.w   #10000,a2                       Make a little room for stack
  1132.                 exg     a2,a7                           Set a7 to the buffer
  1133.                 move.w  TB_TrkNo(a4),d0                 Tracknumber
  1134.                 bsr     VerifyAlert                     Display the requester
  1135.                 move.l  a2,a7                           TD's stack again
  1136. VT_Rtn          move.l  d0,d2                           Answer of user: zero is ignore
  1137.                 bsr     ReleaseBuffer                   We do not need the verify buffer anymore
  1138.                 move.l  d2,d0                           Rewrite?
  1139.                 movem.l (a7)+,d2/a2/a4
  1140.                 bne     TDR_WriteTrack                  The user wanted a rewrite..
  1141.                 rts
  1142.  
  1143.  
  1144. *-------------------------------------------------------*
  1145. *
  1146. *  CompareTracks
  1147. *
  1148. *  Compare data in two trackbuffers.  A simple compare is not possible.  The data should be
  1149. *  the same but may be arranged differently.
  1150. *
  1151. *
  1152. *  Input:       a0      Trackbuffer
  1153. *               a1      Trackbuffer
  1154. *
  1155. *  Returns:     d0      Zero if buffers are the same, -1 in case of error
  1156. *
  1157.  
  1158. CompareTracks   moveq.l #SPT,d0                         Total number of sectors
  1159.                 add.b   TB_FirstSec(a0),d0              Add first sector of the first buffer
  1160.                 sub.b   TB_FirstSec(a1),d0              Subtract first sector of the other buffer
  1161.                 divu    #SPT,d0                         Subtract SPT if larger than SPT
  1162.                 swap.w  d0                              Remainder is sector shift between both buffers
  1163.                 mulu    #SE_SIZE,d0                     Byte size of first part
  1164.                 move.w  #SPT*SE_SIZE,d1                 Total size
  1165.                 sub.w   d0,d1                           Size of second part
  1166.  
  1167.                 lea.l   TB_Data(a0),a0                  Begin of compare in first buffer
  1168.                 lea.l   TB_Data(a1),a1                  Begin of sectors in second buffer
  1169.                 add.w   d0,a1                           Add to find first sector to compare in second buffer
  1170.                 lsr.w   #2,d0                           Cnv to long counter
  1171.                 lsr.w   #2,d1                           Cnv to long counter
  1172.                 cmp.w   d0,d0                           Preset equal condition
  1173.                 bra.s   CT_Loop01                       Enter loop
  1174.  
  1175. CT_Loop0        cmp.l   (a0)+,(a1)+
  1176. CT_Loop01       dbne    d1,CT_Loop0                     Terminates on not equal or d1==-1
  1177.                 bne.s   CT_Error                        Buffers are not the same..
  1178.                 subq.w  #1,d0                           We do not compare the first long
  1179.                 bmi.s   CT_OK                           Nothing to compare anymore
  1180.                 addq.l  #4,a0                           Skip SectStart
  1181.                 lea.l   -SPT*SE_SIZE+4(a1),a1           Compare buffer to one long past begin
  1182.                 cmp.w   d0,d0                           Preset equal condition
  1183.                 bra.s   CT_Loop11                       Enter loop
  1184. CT_Loop1        cmp.l   (a0)+,(a1)+
  1185. CT_Loop11       dbne    d0,CT_Loop1                     Terminates on not equal or d1==-1
  1186.                 beq.s   CT_OK                           Buffers are the same..
  1187. CT_Error        moveq.l #-1,d0                          I'm so sorry
  1188.                 bra.s   CT_Rtn
  1189. CT_OK           moveq.l #0,d0                           No error
  1190. CT_Rtn          rts
  1191.  
  1192.  
  1193. *-------------------------------------------------------*
  1194. *
  1195. *  VerifyAlert  -  Notify user of the verity error and ask him what to do.
  1196. *
  1197. *  To do so, we use a requester with the choise to ignore the event (inherent in TD) or to
  1198. *  rewrite the track.  This is more complicated as it looks at first sight.  It would be
  1199. *  nice if an AutoRequest could be used (simple & small), but the idea behind write verify
  1200. *  requires an airtight approach.  If there is not enough memory to build the AutoRequest,
  1201. *  Intuition defaults to an Alert.  But if there is not enough memory to build the Alert,
  1202. *  Intuition simply returns FALSE.  As if the user selected "Ignore".  Useless for our
  1203. *  purposes.  So we have to build our own requester.  We have no window open, so we open a
  1204. *  window for just one use:  to show the requester.  A requester has the fe. ff feature to
  1205. *  block all input to the window.  Intuition permits all kinds of events to penetrate to
  1206. *  the SysRequest.  I do not know an easy way (we are patching TD, remember?) to get the same
  1207. *  result.  The other approach is to build the gadgets directly in the window.  Then we
  1208. *  receive all kind of events, including Left-Amiga-V and Left-Amiga-N.  Pity that DMouse
  1209. *  cannot see that we are requesting.  But otherwise we have no shortcuts.  So?
  1210. *
  1211. *  Input:       d0      Tracknumber
  1212. *               a3      TD Unit structure
  1213. *               a6      TD device pointer
  1214. *
  1215. *  Returns:     d0      TRUE for rewrite, FALSE for ignore
  1216. *
  1217.  
  1218.  
  1219. VerifyAlert     movem.l d2-d4/a2/a4/a5,-(a7)
  1220.  
  1221. *--     Insert head number in requester string
  1222.  
  1223.                 moveq.l #'0'>>1,d1                      Prepare for asci conversion
  1224.                 lsr.b   #1,d0                           Get head number in X-bit
  1225.                 roxl.b  #1,d1                           Make asci zero or one
  1226.                 lea.l   TXT_HeadNr(pc),a0               Destination
  1227.                 move.b  d1,(a0)                         Store into requester string
  1228.  
  1229. *--     D0 now contains the cylinder number.  Convert via BCD to asci and store into string
  1230.  
  1231.                 move.l  a7,a2                           Predecrement pointer to local word
  1232.                 clr.w   -(a7)                           One word local
  1233.                 moveq.l #7,d1                           Binary 2 nibbles to 2 bcd nibbles conversion
  1234. 10$             move.l  a2,a0                           Destination
  1235.                 move.l  a2,a1                           Destination
  1236.                 lsl.b   #1,d0                           Binary shift left
  1237.                 abcd.b  -(a0),-(a1)                     Bcd shift left
  1238.                 dbra    d1,10$                          Loop for eigth bits
  1239.  
  1240.                 move.w  (a7)+,d1                        Get bcd word
  1241.                 lea.l   TXT_TrackNr(pc),a0              Destination
  1242.                 move.b  d1,d0                           Bcd value
  1243.                 lsr.b   #4,d1                           Next nibble
  1244.                 or.b    #'0',d1                         Convert to asci
  1245.                 move.b  d1,(a0)+                        Store in alert string
  1246.                 and.b   #$0f,d0                         Mask nibble
  1247.                 or.b    #'0',d0                         Convert to asci
  1248.                 move.b  d0,(a0)                         Store in alert string
  1249.  
  1250. *--     Unit number in string
  1251.  
  1252.                 moveq.l #'0',d0                         Asci first unit
  1253.                 add.b   TDU_UnitNr(a3),d0               Unit number
  1254.                 lea.l   TXT_UnitNr(pc),a0               Position in requester string
  1255.                 move.b  d0,(a0)                         Store unit number
  1256.  
  1257. *--     Open a window on the Workbench screen and show a requester in it.
  1258.  
  1259.                 moveq.l #-1,d2                          Set flag to requester failed
  1260.                 move.l  TDU_TCB+TC_Userdata(a3),a0      Lea UnitData structure
  1261.                 move.l  UD_TSControl(a0),a0             TSControl structure
  1262.                 move.l  a6,-(a7)                        Trackdisk device base
  1263.                 move.l  TDD_SysBase(a6),a5              ExecBase
  1264.                 move.l  TSC_IntuBase(a0),a6             Our starter got IntuitionBase already for us
  1265.                 LibCall WBenchToFront
  1266.                 move.l  ib_FirstScreen(a6),a0
  1267.                 move.w  sc_DetailPen(a0),d0             Negative
  1268.                 lea.l   TSCodeBegin(pc),a0
  1269.                 move.w  d0,IT_Body0-TSCodeBegin(a0)
  1270.                 move.w  d0,IT_Body1-TSCodeBegin(a0)
  1271.                 move.b  d0,IMG_ReqOnOff-TSCodeBegin(a0)
  1272.                 rol.w   #8,d0                           Positive
  1273.                 move.w  d0,IT_Positive-TSCodeBegin(a0)
  1274.                 move.w  d0,IT_Negative-TSCodeBegin(a0)
  1275.                 move.b  d0,IMG_GadOnOff-TSCodeBegin(a0)
  1276.                 lea.l   NEW_Requester(pc),a0            NewWindow structure
  1277.                 LibCall OpenWindow
  1278.                 move.l  d0,a4                           Window structure, success?
  1279.                 beq.s   NoReqWindow                     No..
  1280.  
  1281. *--     Wait for an answer of the user
  1282.  
  1283.                 exg.l   a5,a6                           SysBase in a6
  1284. IDCMP_Loop      move.l  wd_UserPort(a4),a0              IDCMP message port
  1285.                 LibCall WaitPort                        Wait for a message from Intuition
  1286.                 move.l  wd_UserPort(a4),a0              IDCMP message port
  1287.                 LibCall GetMsg                          Remove message from queue
  1288.                 move.l  d0,a1
  1289.                 move.l  im_Class(a1),d3                 Keep Class
  1290.                 move.l  im_IAddress(a1),d2              Keep message initiator
  1291.                 move.l  im_Code(a1),d4                  Keep Code AND Qualifier
  1292.                 LibCall ReplyMsg                        Message back to Intuition
  1293.  
  1294. *--     Perhaps the user clicked one of the gadgets
  1295.  
  1296.                 cmp.l   #GADGETUP,d3                    Gadget clicked?
  1297.                 bne.s   VA_ChkRawkey                    No, check keyboard shortcut
  1298.                 lea.l   GAD_Negative(pc),a0             Get one of both message inititors
  1299.                 sub.l   a0,d2                           Set return value to zero if this gadget was clicked
  1300.                 beq.s   CloseReqWindow                  "Ignore" was clicked..
  1301.                 moveq.l #1,d2                           Not equal, other gadget must have been clicked, return positive
  1302.                 bra.s   CloseReqWindow
  1303.  
  1304. *--     Perhaps the user pressed a 'B' or 'V'
  1305.  
  1306. VA_ChkRawkey    cmp.l   #RAWKEY,d3                      Keyboard event?
  1307.                 bne.s   IDCMP_Loop                      No, ignore message..
  1308.                 and.w   #IEQUALIFIER_LCOMMAND,d4        Left-Amiga pressed?
  1309.                 beq.s   IDCMP_Loop                      No, ignore..
  1310.                 swap.w  d4                              Select code field
  1311.                 moveq.l #0,d2                           Returnvalue for "Ignore"
  1312.                 cmp.w   #$0035,d4                       Keycode for 'B'
  1313.                 beq.s   CloseReqWindow                  Same, return ignore..
  1314.                 moveq.l #1,d2                           Returnvalue for "Rewrite"
  1315.                 cmp.w   #$0034,d4                       Keycode for 'V'
  1316.                 bne.s   IDCMP_Loop                      Not what we want, ignore message..
  1317.  
  1318. *--     Get present position of the window and close it
  1319.  
  1320. CloseReqWindow  exg.l   a5,a6                           IntuitionBase again
  1321.                 lea.l   NEW_Requester(pc),a0            NewWindow structure
  1322.                 move.l  wd_LeftEdge(a4),(a0)            Install present window position into new window
  1323.                 move.l  a4,a0                           Window structure
  1324.                 LibCall CloseWindow
  1325. NoReqWindow     move.l  a6,a5                           IntuitionBase
  1326.                 move.l  (a7)+,a6                        TD base
  1327.                 move.l  d2,d0                           Result
  1328.                 bpl.s   VA_Rtn                          Positive, user replied on requester..
  1329.  
  1330. *--     For some reason there was no requester, so bleep screens and blink drive led, return rewrite
  1331.  
  1332.                 exg     a5,a6                           Negative, no requester, get IntuBase
  1333.                 sub.l   a0,a0                           All screens
  1334.                 LibCall DisplayBeep                     Bleep
  1335.                 exg     a5,a6                           TD Base
  1336.                 moveq.l #6,d2                           Blink drive led 3 times
  1337. 10$             move.l  d2,d0                           Get counter
  1338.                 and.l   #1,d0                           Select LSB (toggles)
  1339.                 bsr.w   TD_SwitchMotor                  Motor on and off
  1340.                 move.l  #200000,d0                      Sleep for a while
  1341.                 bsr.w   TD_Sleep
  1342.                 dbra    d2,10$                          Loop
  1343.                 moveq.l #-1,d0                          Set rewrite as result
  1344.  
  1345. VA_Rtn          movem.l (a7)+,d2-d4/a2/a4/a5
  1346.                 rts
  1347.  
  1348.  
  1349. *-------------------------------------------------------*
  1350. *
  1351. *  Requester data structures.
  1352. *
  1353. *  These structures have pointers to each other.  Therefore we cannot move them without making
  1354. *  adaptions.  We can do two things.  Normal relocation followed by an adaption after the move,
  1355. *  or not relocate at loadtime and perform complete relocation later.  We choose the latter
  1356. *  because this saves relocation info in the exe and the relocation routine is not
  1357. *  larger/smaller/easyer/harder.
  1358. *  Because the relocation table is not to be included in the resident structure, it is
  1359. *  physically placed somewhere at the end of this file.
  1360. *  The "Body text" is tied to the "positve text".  This saves us Intuprinting the requester text.
  1361. *  Because code is outgrowing already the pan, the font is fixed to topaz 8.  All calculations
  1362. *  regarding window size, gadget positions, text postitions are done by hand and here and now.
  1363. *
  1364.  
  1365. NEW_Requester   dc.w    0,0
  1366.                 dc.w    242,55
  1367.                 dc.b    -1,-1
  1368.                 dc.l    GADGETUP+RAWKEY
  1369.                 dc.l    WINDOWDEPTH+WINDOWDRAG+SIMPLE_REFRESH+NOCAREREFRESH+ACTIVATE
  1370. NEW_ReqGadget   dc.l    GAD_Positive-TSCodeBegin
  1371.                 dc.l    0
  1372. NEW_ReqTitle    dc.l    TXT_VerTitle-TSCodeBegin
  1373.                 dc.l    0,0
  1374.                 dc.w    0,0,0,0
  1375.                 dc.w    WBENCHSCREEN
  1376.  
  1377. GAD_Positive    dc.l    GAD_Negative-TSCodeBegin
  1378.                 dc.w    26,35
  1379.                 dc.w    82,16
  1380.                 dc.w    GADGIMAGE+GADGHCOMP
  1381.                 dc.w    RELVERIFY+ENDGADGET
  1382.                 dc.w    BOOLGADGET+REQGADGET
  1383. GAD_PosRender   dc.l    IMG_Gadgets-TSCodeBegin
  1384.                 dc.l    0
  1385. GAD_PosIText    dc.l    IT_Positive-TSCodeBegin
  1386.                 dc.l    0
  1387.                 dc.l    0
  1388.                 dc.w    0
  1389.                 dc.l    0
  1390.  
  1391. GAD_Negative    dc.l    0
  1392.                 dc.w    134,35
  1393.                 dc.w    82,16
  1394.                 dc.w    GADGIMAGE+GADGHCOMP
  1395.                 dc.w    RELVERIFY+ENDGADGET
  1396.                 dc.w    BOOLGADGET+REQGADGET
  1397. GAD_NegRender   dc.l    IMG_Request-TSCodeBegin
  1398.                 dc.l    0
  1399. GAD_NegIText    dc.l    IT_Negative-TSCodeBegin
  1400.                 dc.l    0
  1401.                 dc.l    0
  1402.                 dc.w    0
  1403.                 dc.l    0
  1404.  
  1405. IMG_Request     dc.w    -130,-23
  1406.                 dc.w    234,41,0
  1407.                 dc.l    0
  1408.                 dc.b    0
  1409. IMG_ReqOnOff    dc.b    0
  1410. IMG_ReqNext     dc.l    IMG_Gadgets-TSCodeBegin
  1411.  
  1412. IMG_Gadgets     dc.w    0,0
  1413.                 dc.w    82,16,0
  1414.                 dc.l    0
  1415.                 dc.b    0
  1416. IMG_GadOnOff    dc.b    0
  1417.                 dc.l    0
  1418.  
  1419. IT_Positive     dc.b    0,0,RP_JAM2,0
  1420.                 dc.w    13,4
  1421. IT_PosFont      dc.l    TA_Topaz8-TSCodeBegin
  1422. IT_PosText      dc.l    TXT_Positive-TSCodeBegin
  1423. IT_PosNext      dc.l    IT_Body0-TSCodeBegin
  1424.  
  1425. IT_Negative     dc.b    0,0,RP_JAM2,0
  1426.                 dc.w    17,4
  1427. IT_NegFont      dc.l    TA_Topaz8-TSCodeBegin
  1428. IT_NegText      dc.l    TXT_Negative-TSCodeBegin
  1429.                 dc.l    0
  1430.  
  1431. IT_Body0        dc.b    0,0,RP_JAM2,0
  1432.                 dc.w    -14,-20                         Relative to the positive gadget
  1433. IT_B0Font       dc.l    TA_Topaz8-TSCodeBegin
  1434. IT_B0Text       dc.l    TXT_Body0-TSCodeBegin
  1435. IT_B0Next       dc.l    IT_Body1-TSCodeBegin
  1436.  
  1437. IT_Body1        dc.b    0,0,RP_JAM2,0
  1438.                 dc.w    -14,-11                         Relative to the positive gadget
  1439. IT_B1Font       dc.l    TA_Topaz8-TSCodeBegin
  1440. IT_B1Text       dc.l    TXT_Body1-TSCodeBegin
  1441.                 dc.l    0
  1442.  
  1443. TA_Topaz8       dc.l    TXT_FontName-TSCodeBegin
  1444.                 dc.w    8
  1445.                 dc.b    FS_NORMAL,0
  1446.  
  1447. TXT_VerTitle    dc.b    ' TrackSalve 1.0 ',0
  1448. TXT_FontName    dc.b    'topaz.font',0
  1449. TXT_Body0       dc.b    'Write verify error detected',0
  1450. TXT_Body1       dc.b    'on unit '
  1451. TXT_UnitNr      dc.b            'x, track '
  1452. TXT_TrackNr     dc.b                     'xx, head '
  1453. TXT_HeadNr      dc.b                              'x',0
  1454.  
  1455. TXT_Positive    dc.b    'Rewrite',0
  1456. TXT_Negative    dc.b    'Ignore',0
  1457.  
  1458.                 cnop    0,2
  1459.  
  1460.  
  1461. *********************************************************
  1462. *
  1463. *  End of code to be copied to the allocated space.  Would this be the allocted space,
  1464. *  then the TD-copy would begin here.
  1465. *  From here it is allowed again to make the location counter external available.
  1466. *
  1467.  
  1468. TSCodeEnd
  1469. TD
  1470.  
  1471.  
  1472. TD_NoDisk       equ     TD+$00DE        99C2
  1473. TD_Seek         equ     TD+$0AF6        A3DA
  1474. TD_SwitchMotor  equ     TD+$0B7E        A462
  1475. TD_ReadDisk     equ     TD+$0C40        A524
  1476. TD_WaitTDPort   equ     TD+$0E26        A70A
  1477. TD_ReadTrkRetry equ     TD+$1106        A9Ea
  1478. TD_ReadTrkRtn   equ     TD+$1114        A9F8
  1479. TD_TaskLoop     equ     TD+$1580        AE64
  1480. TD_Reply        equ     TD+$0E0E        A6F2
  1481. TD_CmdWrite     equ     TD+$0F34        A818
  1482. TD_CmdRead      equ     TD+$0FAC        A890
  1483. TD_CmdRead10    equ     TD+$0FBC        A8A0
  1484. TD_EndRW        equ     TD+$103C        A920
  1485. TD_P101b        equ     TD+$0F04        A7E8
  1486. TD_WriteTrack   equ     TD+$1074        A958
  1487. TD_NormTrack    equ     TD+$16FE        AFE2
  1488. TD_NormTrackRtn equ     TD+$18F0        B1D4
  1489. TD_CorrectEdge  equ     TD+$14DA        ADBE
  1490. TD_Sleep        equ     TD+$0C0C        A4F0
  1491.  
  1492.  
  1493. *********************************************************
  1494. *
  1495. *  This table contains data which will be put into the trackdisk code we copied from ROM.  Its location must
  1496. *  directly follow TSCodeEnd for offset calculations.  So do not reposition this table without an adaption of
  1497. *  the Patch macro.
  1498. *  The format of the table is a stucture of this form:
  1499. *
  1500. *  WORD         OffsetInTD              Offset relative to rt_MatchTag
  1501. *  UWORD        PatchSize               Size of patch in words
  1502. *  STRUCT       Patch,PatchSize*2       The patch itself
  1503. *
  1504. *  The Patch table consists of a series of patch structures following each other.  The end of the table
  1505. *  is reached when a patch is met with a PatchSize of zero.
  1506. *
  1507.  
  1508. Patch           MACRO   <Offset in TD>,<Patchsize in bytes>
  1509.                 dc.w    \1
  1510.                 dc.w    (\2)/2
  1511. TS              set     *-TD-\1
  1512.                 ENDM
  1513.  
  1514.                 Func    TSPatchTable,_TSPatchTable
  1515.  
  1516. *--     Bug patches
  1517.  
  1518.                 Patch   $1A38,P000e-P000b               B31C Bug in td_RawWrite
  1519. P000b           cmp.l   #$8000,d0
  1520. P000e
  1521.                 Patch   $00E6,P001e-P001b               AAAAAAAAARRRRRRRGGGHHHH...
  1522. P001b           dc.w    $0016                           GetUnit before GiveUnit patch
  1523. P001e
  1524.  
  1525. *--     Let toplevel task loop flow through our code
  1526.  
  1527.                 Patch   $1592,P100e-P100b               AE76 Toplevel task loop
  1528. P100b           bra.w   TS+TDE_TaskLoop
  1529. P100e
  1530.  
  1531. *--     Check first with us befire clicking
  1532.  
  1533.                 Patch   $0104,P200e-P200b               99E8 Presence test
  1534. P200b           bsr.w   TS+TDE_NoClick
  1535.                 nop
  1536. P200e
  1537.  
  1538. *--     Check readonly simutation before writes or returning td_ProtStatus
  1539.  
  1540.                 Patch   $0D22,P300e-P300b               A606 Write routine
  1541. P300b           bsr.w   TS+TDE_WriteProt
  1542.                 nop
  1543.                 nop
  1544. P300e
  1545.                 Patch   $1194,P301e-P301b               AA78 Tab-test for td_ProtStatus
  1546. P301b           bsr.w   TS+TDE_WriteProt1
  1547. P301e
  1548. *               Patch   $0162,P302e-P302b               9A46 Disk login, firt detection disk presence
  1549. *P302b          bsr.w   TS+TDE_WriteProt1
  1550. *P302e
  1551.  
  1552. *--     Read (write) adaptions to the salve function
  1553.  
  1554.                 Patch   $10F8,P400e-P400b               A9DC Read error after normalisation
  1555. P400b           bra.w   TS+TDE_ReadError
  1556. P400e
  1557.                 Patch   $0EC8,P401e-P401b               A7AC
  1558. P401b           bne.s   TS+TD_P101b                     A7E8 The track we want is in the buffer..
  1559. P401e
  1560.                 Patch   $0F04,P402e-P402b               A7E8
  1561. P402b           move.l  TDU_IOReq(a3),a2                Get IORequest
  1562.                 move.l  TDU_DiskBuf(a3),a0              Track buffer
  1563.                 cmp.b   #CMD_WRITE,IO_COMMAND+1(a2)     Write?
  1564.                 bne     TS+TDE_Read                     No, read..
  1565.                 cmp.b   #SPT,TB_FirstSec(a0)            Yes, write. No error in track?
  1566.                 bcs.s   TS+TD_CmdWrite                  A818 No, go write
  1567.                 move.b  TB_FirstSec(a0),IO_ERROR(a2)
  1568.                 bra     TS+TD_EndRW                     A920 Bad return
  1569. P402e
  1570.                 Patch   $102A,P403e-P403b               A90E
  1571. P403b           blt     TS+TD+$0F04                     A7E8
  1572. P403e
  1573.  
  1574. *--     Verify adaptions to write routines
  1575.  
  1576.                 Patch   $07C4,P500e-P500b               A0A8
  1577. P500b           bsr     TS+TDR_WriteTrack
  1578. P500e
  1579.                 Patch   $0EDC,P502e-P502b               A7C0
  1580. P502b           bsr     TS+TDR_WriteTrack
  1581. P502e
  1582.                 Patch   $11D6,P503e-P503b               AABA
  1583. P503b           bsr     TS+TDR_WriteTrack
  1584. P503e
  1585.                 Patch   $15D2,P504e-P504b               AEB6
  1586. P504b           bsr     TS+TDR_WriteTrack
  1587. P504e
  1588.                 Patch   $16FE,P505e-P505b               AFE2
  1589. P505b           movem.l d0/d2-d6/a2,-(a7)               D0 added to list, has become an argument
  1590. P505e
  1591.                 Patch   $18FA,P506e-P506b
  1592. P506b           movem.l (a7)+,d1/d2-d6/a2               D1 added to list as a dummy pull to compensate above
  1593. P506e
  1594.                 Patch   $180E,P507e-P507b               B0F2
  1595. P507b           bsr.w   TS+TDE_NormTrack
  1596. P507e
  1597.  
  1598. *--     Verify adaption to Format routine
  1599.  
  1600.                 Patch   $0864,P551e-P551b               A148
  1601. P551b           move.w  d2,TB_TrkNo(a0)
  1602.                 move.l  a0,TDU_DiskBuf(a3)
  1603.                 bsr.w   TS+TDR_WriteTrackF
  1604. P551e
  1605.                 Patch   0,0
  1606.  
  1607.  
  1608. *********************************************************
  1609. *
  1610. *  The relocation table of the code between TSCodeBegin and TSCodeEnd.
  1611. *
  1612.  
  1613.                 Func    TSCodeRelocTable
  1614.  
  1615.                 dc.w    NEW_ReqGadget-TSCodeBegin
  1616.                 dc.w    NEW_ReqTitle-TSCodeBegin
  1617.                 dc.w    IMG_ReqNext-TSCodeBegin
  1618.                 dc.w    GAD_Positive-TSCodeBegin
  1619.                 dc.w    GAD_PosRender-TSCodeBegin
  1620.                 dc.w    GAD_PosIText-TSCodeBegin
  1621.                 dc.w    GAD_NegRender-TSCodeBegin
  1622.                 dc.w    GAD_NegIText-TSCodeBegin
  1623.                 dc.w    IT_B0Font-TSCodeBegin
  1624.                 dc.w    IT_B0Text-TSCodeBegin
  1625.                 dc.w    IT_B0Next-TSCodeBegin
  1626.                 dc.w    IT_B1Font-TSCodeBegin
  1627.                 dc.w    IT_B1Text-TSCodeBegin
  1628.                 dc.w    IT_PosFont-TSCodeBegin
  1629.                 dc.w    IT_PosText-TSCodeBegin
  1630.                 dc.w    IT_PosNext-TSCodeBegin
  1631.                 dc.w    IT_NegFont-TSCodeBegin
  1632.                 dc.w    IT_NegText-TSCodeBegin
  1633.                 dc.w    TA_Topaz8-TSCodeBegin
  1634.                 dc.w    0
  1635.  
  1636.  
  1637. *********************************************************
  1638. *
  1639. *  The size of the code to be copied is EndTSCode-_TSCode.  The size of the buffer is
  1640. *  also assembler laid down.
  1641. *  How do we pass these values to a C-module?
  1642. *  For now with globals, but constants would be more appropriate..
  1643. *
  1644.  
  1645.                 SECTION __MERGED,data
  1646.  
  1647.                 gc_l    _TSCodeSize,TSCodeEnd-TSCodeBegin
  1648.                 gc_l    _BufferSize,SB_SIZE
  1649.  
  1650. *********************************************************
  1651.  
  1652.                 END
  1653.