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 >
Wrap
Text File
|
1990-02-12
|
82KB
|
1,653 lines
* Patch.a -- TrackSalve
*
* # date by Comment
* -- --------- ---- ---------------------
* 0 29-Oct-89 DWR Created for Tracksalve
*
* nolist
ifnd IFILES
IFILES set 1
INCLUDE "Call.i"
INCLUDE "globdefs.i"
INCLUDE "ts.i"
INCLUDE "exec/tasks.i"
INCLUDE "hardware/custom.i"
include "graphics/text.i"
include "graphics/rastport.i"
* include "intuition/intuitionbase.i"
* include "intuition/intuition.i"
* include "intuition/screens.i"
include "devices/inputevent.i"
ifnd INTUITION_INTUITION_I
GADGETUP equ $00000040
RAWKEY equ $00000400
WINDOWDEPTH equ $0004
WINDOWDRAG equ $0002
SIMPLE_REFRESH equ $0040
NOCAREREFRESH equ $00020000
ACTIVATE equ $1000
GADGHCOMP equ $0000
GADGHBOX equ $0001
GADGIMAGE equ $0004
GADGHIMAGE equ $0002
BOOLGADGET equ $0001
REQGADGET equ $1000
RELVERIFY equ $0001
ENDGADGET equ $0004
wd_LeftEdge equ 4
wd_UserPort equ 86
im_Class equ 20
im_Code equ 24
im_IAddress equ 28
endc
ifnd INTUITION_SCREENS_I
WBENCHSCREEN equ $0001
sc_DetailPen equ $14a
endc
ifnd INTUITION_INTUITIONBASE_I
ib_FirstScreen equ $3c
endc
endc
* list
SECTION text,code
*********************************************************
*
* Begin of code that extents/replaces Trackdisk code. This is made globally known because some
* routine must copy us from here to an allocated space. Because all references to the location-
* counter until TSCodeEnd are done from within this part or from patched Trackdisk code, none
* of these locations should be made external available.
*
Func TSCodeBegin,_TSCodeBegin
*********************************************************
*
* We jump to this address when changing from ROM to TS. Special inits must be done here.
*
move.b #F_RAM,UNIT_pad(a3) Set flags to executing in RAM and clear all others
;bra.s TDE_TaskLoop Continue normal loop
*********************************************************
*
* Extension of Trackdisks main task loop. The first thing we do is a check whether we
* initiated a terminal state. If so, we do not check external commands anymore, but
* continue to finish the special functions and return to ROM-code in the end.
* Otherwise we compare the external commands with the already active functions and
* if they differ, we see that they are initiated.
* We are free to use a2, but its value may have been changed upon entry.
* A6 contains SysBase and the device pointer must be restored by a pull from the stack.
*
* Upon entry: a3 TDU structure (Trackdisk unit)
* a6 SysBase
*
* Usage: a2 UnitData structure
*
TDE_TaskLoop move.l (a7)+,a6 Perform replaced instruction. Restore device pointer
move.l TDU_TCB+TC_Userdata(a3),a2 Lea UnitData structure
btst #B_TERM,UNIT_pad(a3) Change of control?
bne.s TDE_TermTS Yes..
move.b UD_Cmd1(a2),d0 Command from outside
cmp.b UNIT_pad(a3),d0 Same as presently active?
beq TD_TaskLoop Yes, continue task..
btst #B_TERM,d0 Change of control?
bne TDE_TermTS Yes..
bsr CheckReadOnly Check change of write protection
move.b UD_Cmd1(a2),d0 Get commands
bsr CheckSalve Check change of readerror handling
move.b UD_Cmd1(a2),d0 Get commands
bsr CheckNoClick Check change of diskchange detection
move.b UD_Cmd1(a2),d0 Get commands
bsr CheckVerify Check change of verify function
bra TD_TaskLoop Continue task..
*-- Initiate or continue terminal state. Stay in the taskloop until all functions are switched off.
TDE_TermTS bset.b #B_TERM,UNIT_pad(a3) Set status of TS to terminating
moveq.l #0,d0 Readonly off
bsr CheckReadOnly Check change of write protection
moveq.l #0,d0 Salve off
bsr CheckSalve Check change of readerror handling
moveq.l #0,d0 NoClick off
bsr CheckNoClick Check change of diskchange detection
moveq.l #0,d0 Verify off
bsr CheckVerify Check change of verify function
move.b UNIT_pad(a3),d0 Current active functions
and.b #FUNCTIONS-F_RAM,d0 All extra functions terminated?
bne TD_TaskLoop No, continue task..
*-- We realy stop here. The taskloop hereafter continues in ROM-code.
move.l a6,-(a7) Preserve a6 AND undo the already executed "move.l (a7)+,a6"
move.l TDD_SysBase(a6),a6 Trackdisk's SysBase
move.l UD_ReturnTD(a2),-(a7) Push ROM-address. With a "rts" we are back in ROM
movem.l a4/a5,-(a7)
LibCall Forbid We do daring things here, like freeing code we are executing!
move.l UD_TSControl(a2),a5 Lea the Control structure
move.l TSC_TSHook(a5),a4 Lea anchor of all our knowledge
move.l a4,a0
LibCall ObtainSemaphore We want to be blocked here until others are ready with TSC
moveq.l #0,d0
move.b TDU_UnitNr(a3),d0 Trackdisk unit number
bclr.b d0,TSC_InUse(a5) Tell global structure we stopped using it.
lsl.l #2,d0 Scale to pointer-index
clr.l TSC_UnitData(a5,d0) Clear UnitData pointer in TSC structure
move.l UD_Userdata(a2),TDU_TCB+TC_Userdata(a3) Restore original value in Task control block
move.b #0,UNIT_pad(a3) Back to what it was perhaps
lea.l UD_TDReq(a2),a1 Trackdisk IORequest
cmp.l IO_UNIT(a1),a3 Our request? (of course it is)
bne.s 10$ No, skip close..
LibCall CloseDevice
10$
*-- Return memory of the TSControl structure if there are no other users of it anymore.
tst.b TSC_InUse(a5) Any users left?
bne.s 30$ Yes, do not free it..
move.l TSC_Buffer(a5),d1 The install program allocates this buffer. Its presence may
; not yet have been processed
beq.s 20$ No buffer..
move.l d1,a1 Buffer
move.l #SB_SIZE,d0 Its size
LibCall FreeMem Back to the system
20$ move.l TSC_IntuBase(a5),a1 Close Intuition
LibCall CloseLibrary
move.l a5,a1 TSControl structure
move.l TSC_Size(a5),d0 Its size (about 10k)
LibCall FreeMem Free it
clr.l TSH_TSControl(a4) No TSControl structure anymore in TSHook
30$
*-- Maybe the TSControl structure does not exist anymore. We cannot return from Permit() here, so we jump to it.
* The return address is already on the stack and points to the correct position in ROM-code.
move.l a4,a0 Lea TSHook structure
LibCall ReleaseSemaphore We are (almost) ready with the TSControl structure
movem.l (a7)+,a4/a5
xref _LVOPermit
jmp _LVOPermit(a6) Taskswitching on and back to ROM
*-------------------------------------------------------*
*
* CheckSalve
*
* This routine handles the switch from salve function on and off. If there are no other
* users of this function left, release the large chip-buffer (about 25k). If the function
* is switched on, check the presence of the buffer. If not there, allocate it.
*
* Input: d0 UD_Cmd1
* a2 UnitData structure
* a3 Trackdisk unit structure
* a6 Trackdisk device base
*
* Return: -
*
CheckSalve move.b UNIT_pad(a3),d1 Presently active functions
and.b #F_SALVE,d0 Select salve-bit in command
and.b #F_SALVE,d1 Select salve-bit in active functions
cmp.b d0,d1 Salve-action changed?
bne.s CheckSalve10 Yes, see that it is done..
rts
*-- We must protect the allocation, freeing and administration of the salve buffer with the TSC semaphore.
CheckSalve10 movem.l d2/d3/a5/a6,-(a7)
move.l d0,d2 Keep salve command
move.b TDU_UnitNr(a3),d3 Unit number
move.l UD_TSControl(a2),a5 TSControl structure
move.l TDD_SysBase(a6),a6 SysBase for Semaphore calls
move.l TSC_TSHook(a5),a0 Lea semaphore
LibCall ObtainSemaphore We want to be blocked here until others are ready with TSC
btst #B_SALVE,d2 Salve requested?
beq.s CS_SalveOff No..
CS_SalveOn bsr CheckBufAvail Check presence and allocate if necessary
beq.s CS_Rtn No success..
bset.b #B_SALVE,UNIT_pad(a3) Set function active
bset.b d3,TSC_Salve(a5) Tell global structure that we use the buffer
bra.s CS_Rtn Done..
CS_SalveOff bclr.b #B_SALVE,UNIT_pad(a3) Set function off
bclr.b d3,TSC_Salve(a5) We do not use the buffer into global structure
bsr CheckBufFree
CS_Rtn move.l TSC_TSHook(a5),a0 Lea semaphore
LibCall ReleaseSemaphore We are ready with the TSControl structure
movem.l (a7)+,d2/d3/a5/a6
rts
*-------------------------------------------------------*
*
* CheckVerify
*
* Handle the switch from verify function on and off. If there are no other users of this
* function left, release the large chip-buffer (about 25k). If the function is switched on,
* check the presence of the buffer. If not there, allocate it.
*
* Input: d0 UD_Cmd1
* a2 UnitData structure
* a3 Trackdisk unit structure
* a6 Trackdisk device base
*
* Return: -
*
CheckVerify move.b UNIT_pad(a3),d1 Presently active functions
and.b #F_VERIFY,d0 Select Verify-bit in command
and.b #F_VERIFY,d1 Select Verify-bit in active functions
cmp.b d0,d1 Verify-action changed?
bne.s CheckVerify10 Yes, see that it is done..
rts
*-- We must protect the allocation, freeing and administration of the salve buffer with the TSC semaphore.
CheckVerify10 movem.l d2/d3/a5/a6,-(a7)
move.l d0,d2 Keep Verify command
move.b TDU_UnitNr(a3),d3 Unit number
move.l UD_TSControl(a2),a5 TSControl structure
move.l TDD_SysBase(a6),a6 SysBase for Semaphore calls
move.l TSC_TSHook(a5),a0 Lea semaphore
LibCall ObtainSemaphore We want to be blocked here until others are ready with TSC
btst #B_VERIFY,d2 Verify requested?
beq.s CV_VerifyOff No..
CV_VerifyOn bsr CheckBufAvail Check presence and allocate if necessary
beq.s CV_Rtn No success..
bset.b #B_VERIFY,UNIT_pad(a3) Set function active
bset.b d3,TSC_Verify(a5) Tell global structure that we use the buffer
bra.s CV_Rtn Done..
CV_VerifyOff bclr.b #B_VERIFY,UNIT_pad(a3) Set function off
bclr.b d3,TSC_Verify(a5) We do not use the buffer into global structure
bsr CheckBufFree
CV_Rtn move.l TSC_TSHook(a5),a0 Lea semaphore
LibCall ReleaseSemaphore We are ready with the TSControl structure
movem.l (a7)+,d2/d3/a5/a6
rts
*-------------------------------------------------------*
*
* Local subroutine of CheckSalve and CheckVerify
*
CheckBufAvail tst.l TSC_Buffer(a5) Is a buffer present?
bne.s 10$ Yes, skip allocation
move.l #SB_SIZE,d0 No, its size
move.l #MEMF_CHIP,d1 And type
LibCall AllocMem Ask system about 25k chip
move.l d0,TSC_Buffer(a5) Into global structure. This buffer is shared
10$ rts
CheckBufFree tst.b TSC_Salve(a5) Any users left?
bne.s 10$ Yes, done..
tst.b TSC_Verify(a5) Any users left?
bne.s 10$ Yes, done..
move.l TSC_Buffer(a5),d1 Get buffer
beq.s 10$ No buffer..
move.l d1,a1 Buffer
move.l #SB_SIZE,d0 Its size
LibCall FreeMem Back to system
clr.l TSC_Buffer(a5) No buffer anymore
10$ rts
*-------------------------------------------------------*
*
* CheckNoClick
*
* Handle the switch from the NoClick function on and off.
*
* Input: d0 UD_Cmd1
* a2 UnitData structure
* a3 Trackdisk unit structure
* a6 Trackdisk device base
*
* Return: -
*
CheckNoClick btst #B_NOCLICK,d0
beq.s 10$
bset.b #B_NOCLICK,UNIT_pad(a3)
rts
10$ bclr.b #B_NOCLICK,UNIT_pad(a3)
rts
*-------------------------------------------------------*
*
* CheckReadOnly
*
* Switching ReadOnly on and off must be done a little careful. Although we have nothing to
* do with DOS, (and we do not want too, do we?) it would be inconvenient to switch to
* readonly when DOS is writing. There is no way to be sure, but an indication might be the
* state of the motor. It is the user who initiates the switch. He must do it at a quiet
* moment. Tell him in the manual! Again we cannot tell DOS directly that we changed the
* write protection of the disk, but we simulate a disk-extraction, a shift of the disk
* protect tab and a disk insertion. We can skip this if the drive is empty or if the
* present disk is already write protected by its tab.
*
* Input: d0 UD_Cmd1
* a2 UnitData structure
* a3 Trackdisk unit structure
* a6 Trackdisk device base
*
* Return: -
*
CheckReadOnly btst #B_READONLY,d0 This drive to be protected?
beq.s RO_Off No, check reverse action..
btst.b #B_READONLY,UNIT_pad(a3) Check real bit
beq.s RO_CheckChange We have to change from r/w to ro..
rts
RO_Off btst.b #B_READONLY,UNIT_pad(a3) Check active function bit
bne.s RO_CheckChange Was set to write-protect, try change to R/W..
rts
RO_CheckChange btst.b #1,TDU_Flags(a3) Is there a disk in the drive?
bne.s RO_ChangeROSec No, just flip RO-bit..
btst.b #4,TDU_Flags(a3) Is there a protected disk in the drive?
bne.s RO_ChangeROSec Yes, just flip RO-bit..
btst.b #CIAB_DSKMOTOR,TDU_CiabPb(a3) Motor off? (We TRY to avoid change during disk (write) access)
beq.s RO_Rtn No, try again later..
RO_ChangeRO bchg.b #B_READONLY,UNIT_pad(a3) Change real bit. This will be checked before the hardware
* pea.l RO_Rtn(pc) Push return address, now we are inside a subroutine
movem.l d2/a2,-(a7) Imitate the disk-presence-check inits
lea.l _ciab+ciaprb,a2 CIAB-PRB
bra TD_NoDisk Continue subroutine handling disk absence..
RO_ChangeROSec bchg.b #B_READONLY,UNIT_pad(a3) Change function bit. This is checked before the hardware is
RO_Rtn rts
*********************************************************
*
* NoClick extentions
*
TDE_NoClick btst.b #B_NOCLICK,UNIT_pad(a3) Do we use this feature?
bne.s 10$ Yes..
bchg.b #CIAB_DSKDIREC,TDU_CiabPb(a3) No, change direction bit in cia B image
rts
10$ bset.b #CIAB_DSKDIREC,TDU_CiabPb(a3) Set direction bit to outwards in cia B image
rts
*********************************************************
*
* ReadOnly extentions
*
* We can modify here the protect status of the disk
*
TDE_WriteProt btst.b #B_READONLY,UNIT_pad(a3) Is this drive readonly?
bne.s TDE_ReadOnly Yes..
btst.b #CIAB_DSKPROT,_ciaa+ciapra No, but perhaps this disk?
rts
TDE_WriteProt1 btst.b #B_READONLY,UNIT_pad(a3) Is this drive readonly?
bne.s TDE_ReadOnly Yes..
btst #CIAB_DSKPROT,d2 No, but perhaps this disk?
rts
TDE_ReadOnly cmp.l d0,d0 Set zero bit, meaning write protected
rts
*********************************************************
*
* Readerror extentions
*
* When arrived here, there is a read error. Some original code is executed here (%).
* When Trackdisk has finished its retry scheme without success, we will give it a try
*
TDE_ReadError addq.b #1,TDU_Retries(a3) % Increment retry counter
move.b TDU_Retries(a3),d0 % Get present value of it
cmp.b TDU_RETRYCNT(a3),d0 % Lower or equal to limit?
ble TD_ReadTrkRetry A9EA Yes, retry..
btst.b #B_SALVE,UNIT_pad(a3) No, TD stops, are we going to do something about it?
beq TD_ReadTrkRtn A9F8 No, function not active, continue TD's error handling..
*
* We now are going to try to salve this track. We will read the track in a large buffer.
* This read is so big that there will be an unbroken track in the buffer. If we find a
* valid sector address in this unbroken track, we can calculate the position of the
* track in the buffer.
*
* We have: a2 TD's trackbuffer
* a3 TD's Unit structure
*
* We will use: a4 UnitData structure
* a5 TrackSalveControl structure/ SalveBuffer structure
*
movem.l a4/a5,-(a7)
move.l TDU_TCB+TC_Userdata(a3),a4 Lea UnitData structure
move.l UD_TSControl(a4),a5 Lea TSControl structure
bsr ObtainBuffer
move.l a0,a5 Extra large read buffer
moveq.l #-1,d0 Motor on
bsr TD_SwitchMotor
lea.l SB_Data(a5),a0 Begin of data in buffer
move.l a0,SB_Begin(a5)
lea.l (2*SPT-1)*SE_SIZE+GAPSIZE(a0),a0 Add size we search in for syncs
move.l a0,SB_End(a5)
move.w #BADTRACKBITS,UD_SavedL(a4) Init log saved labels
move.w #BADTRACKBITS,UD_SavedD(a4) Init log saved data
moveq.l #3,d6 Init retry number
RE_SalveLoop lea.l SB_Data(a5),a0 Destination for disk-read
move.l #2*SPT*SE_SIZE+GAPSIZE,d0 Number of bytes to read
bsr TD_ReadDisk A524 Read d0 bytes into (a0)
tst.l d0 DiskChange?
beq.s 10$ No..
move.b d0,TB_FirstSec(a2) Yes, store error in trackbuffer for TD
bra.s RE_Rtn Leave..
10$ clr.w SB_CorrectTrk(a5) Reset counter of headers with good tracknumber
clr.w SB_WrongTrk(a5) Reset counter of headers with wrong tracknumber
bsr Salve Analyse the buffer and save what is possible
beq.s RE_Rtn All sectors and labels salved
move.w SB_CorrectTrk(a5),d0 How many times did we encounter good tracknumbers
cmp.w SB_WrongTrk(a5),d0 And how many bad?
bpl.s 20$ More good..
subq.l #1,d6 Restore, just subtract one
ble.s RE_Rtn
move.w #-1,TDU_PTrack(a3) Set current track to "Unknown"
moveq.l #0,d0
move.w TDU_XTrack(a3),d0 Get track number we want
bsr TD_Seek A3DA Restore and seek
bra.s RE_SalveLoop Try again to salve the track
20$ subq.l #2,d6 No restore, we read the correct track already, subtract two
bhi.s RE_SalveLoop
RE_Rtn bsr ReleaseBuffer
movem.l (a7)+,a4/a5
bra TD_ReadTrkRtn Continue TD
*-------------------------------------------------------*
*
* -- Salve --
*
* We search for a sync. If found we try to get a reliable sector address from the
* succeeding data. This address tells us how much and the position of the track preceding
* this sector. We try to recover these sectors if we did not already. The area after the
* found sector is also checked for sector presence, but if no success search will continue
* from the found sync.
*
* Input: a2 TB_ Trackdisk trackbuffer
* a3 TDU_ Trackdisk Unit structure
* a4 UD_ TrackSalve UnitData structure
* a5 SB_ TrackSalve SalveBuffer structure
*
* Usage: d2 Scratch
* d5 Pointer to sector in imaginary track
* d6 Pointer to sector of last detected sync
* d7 Shiftfactor
*
* Returns: d0 Zero if all sectors and labels saved
*
Salve movem.l d2/d5-d7,-(a7)
subq.l #HE_SIZE,a7 Four bytes local storage
move.l SB_Begin(a5),d6 Begin of buffer
subq.l #8,d6 Undo next instruction
*-- Scan buffer for syncs. If found, test it for a valid header.
ST_SearchLoop addq.l #8,d6 Point to word past previous sync found
move.l SB_End(a5),d0 End of search area
sub.l d6,d0 Minus begin of search area is search size
ble ST_EndSearch End of buffer reached..
move.l d6,a0 Actual begin of search
bsr SearchSync Search next sync on this track
bmi ST_EndSearch No sync found, leave..
subq.l #6,a0 Point to begin of potential sector
move.l a0,d6 Keep potential sector found
bsr GetHeader Test validity and decode header
ble.s ST_SearchLoop Not valid
*-- We have a sector header. Figure a track around it.
move.l d0,(a7) Local header for loop control
moveq.l #SPT,d0 Number of sectors per track
sub.b HE_ToGap(a7),d0 Subtract ahead of us, leaves us with number of sectors before us
sub.b d0,HE_SecNo(a7) Set number of first sector, still positive?
bpl.s 10$ Yes..
add.b #SPT,HE_SecNo(a7) No, wrap
10$ move.b #SPT,HE_ToGap(a7) New gap countdown
mulu #SE_SIZE,d0 Convert number of sectors to bytes before our position
move.l d6,d5 Pointer to present sector
sub.l d0,d5 Pointer to first potential sector
*-- Scan imaginary track for storable sectors
ST_TrackLoop cmp.l SB_Begin(a5),d5 Are we before begin of the buffer?
bmi ST_NextSector Yes, next sector..
cmp.l SB_End(a5),d5 Are we past the end of the buffer?
bpl.s ST_SearchLoop Yes, stop with this track..
move.b HE_SecNo(a7),d0 Sector number
move.l UD_SavedL(a4),d1 Log of stored labels and sectors
beq ST_AllSaved All stored, leave this routine..
btst d0,d1 Is the data of this sector already stored?
bne.s ST_SaveSector No, try to..
swap d1 Yes, test the label
btst d0,d1 This label aready saved?
beq ST_NextSector Yes, try next sector in our imaginary track..
*-- Try to store as much as possible from the sector d5 is pointing to.
ST_SaveSector move.l d5,a0 Ea of present sector
bsr GetHeader Get its header if possible
bmi ST_NextSector Wrong track..
beq.s ST_SaveData No header, perhaps the sector's data is OK
cmp.l (a7),d0 This MUST be the same or what?
bne ST_VeryBad Very bad indeed
move.l d5,a0 Ea of present sector
lea.l SE_SumD(a0),a0 Lea data checksum
bsr DecodeLong Decode it
move.l d0,d2 Keep for compare
move.l #TD_SECTOR/2,d0 Size of data-part of sector in longs
bsr CheckSum Calculate checksum over data
cmp.l d2,d0 Same as found on disk?
beq.s ST_CopySector Yes, save to copy the complete sector..
move.b HE_SecNo(a7),d0 No, but we have a valid header, the numbers are ok and if this
move.w UD_SavedD(a4),d1 sector is not yet saved, we better still copy it
btst d0,d1 Sector already saved?
beq ST_SaveLabel Yes, skip bad sector copy
bra.s ST_LabelOK We copy the sector, but skip the bitclear..
ST_CopySector move.b HE_SecNo(a7),d0 Number of this sector
move.w UD_SavedD(a4),d1 Data save-log
bclr d0,d1 Set data saved
move.w d1,UD_SavedD(a4)
ST_LabelOK move.b HE_SecNo(a7),d0 Number of this sector
move.w UD_SavedL(a4),d1 Label save-log
bclr d0,d1 Set label saved
move.w d1,UD_SavedL(a4)
ext.w d0 Cnv sectornumber byte to word
mulu #SE_SIZE,d0 To byte offset
lea.l TB_Data(a2),a1 TD's buffer, begin of sectors
lea.l SE_Label(a1,d0),a1 Lea destination of our data
move.l d5,a0 Ea of present source sector
lea.l SE_Label(a0),a0 Lea begin of part to copy
move.w #((SSIZE/2)<<HSIZEBITS)+1,d0 Size of sector for blitter
move.w #SSIZE,d2 Bytesize
bsr BlitMove Copy to TD's buffer
bra ST_NextSector Loop for next sector
ST_SaveData move.b HE_SecNo(a7),d0 Sector number
move.w UD_SavedD(a4),d1 Saved data log
btst d0,d1 Data of this sector already saved?
beq.s ST_NextSector Yes..
move.l d5,a0 Ea of present sector
lea.l SE_SumD(a0),a0 Lea data checksum
bsr DecodeLong Decode it
move.l d0,d2 Keep for compare
move.l #TD_SECTOR/2,d0 Size of data-part of sector in longs
bsr CheckSum Calculate checksum over data
cmp.l d2,d0 Same as found on disk?
bne.s ST_NextSector No, no header and bad data, skip copy, next perhaps..
moveq.l #0,d0
move.b HE_SecNo(a7),d0 Number of present sector
move.w UD_SavedD(a4),d1 Saved data log
bclr d0,d1 Set data of this sector saved
move.w d1,UD_SavedD(a4)
mulu #SE_SIZE,d0 Sector number times sectorsize to find offset in TD's buffer
lea.l TB_Data(a2),a1 TD's buffer, begin of sectors
lea.l SE_SumD(a1,d0),a1 Lea destination of our data
move.l d5,a0 Ea of source sector
lea.l SE_SumD(a0),a0 Lea Data checksum, begin of copy to TD's buffer
move.w #((DSIZE/2)<<HSIZEBITS)+1,d0 Size of datapart and its checksum ready for the blitter
move.w #DSIZE,d2 Bytesize of block
bsr BlitMove Copy to TD's buffer
bra.s ST_NextSector Continue loop..
ST_SaveLabel ; move.b HE_SecNo(a7),d0 Present sector number
move.l UD_SavedL(a4),d1 Saved labels log
bclr d0,d1 We have a good one here
beq.s ST_NextSector Was already saved, continue..
move.l d1,UD_SavedL(a4) Nice, we can save a label
ext.w d0
mulu.w #SE_SIZE,d0 To byte offset
lea.l TB_Data(a2),a1 Lea begin of sectors
lea.l SE_Label(a1,d0),a1 Lea of label in destination sector in TD's buffer
move.l d5,a0 Ea of present sector
lea.l SE_Label(a0),a0 Lea label in source sector
move.w #((LSIZE/2)<<HSIZEBITS)+1,d0 Size of label ready for the blitter
moveq.l #LSIZE,d2 Bytesize of block to move
bsr BlitMove Move label to Trackdisks buffer
bra.s ST_NextSector Continue loop..
*-- Track-scan loop control.
ST_NextSector move.b HE_SecNo(a7),d0 Sector number
addq.b #1,d0 Next sector
cmp.b #SPT,d0 Must we wrap?
bcs.b 10$ No..
moveq.l #0,d0 Yes, sector 0
10$ move.b d0,HE_SecNo(a7)
add.l #SE_SIZE,d5 Present sector pointer to next sector
subq.b #1,HE_ToGap(a7) Decrement remaining sectors in our track, any left?
bhi ST_TrackLoop Yes, process it..
bra ST_SearchLoop No, we are ready with our track, try to find a new one..
ST_EndSearch
ST_AllSaved move.l UD_SavedL(a4),d0
ST_Rtn addq.l #HE_SIZE,a7 Clean up local
tst.l d0 Return proper condition codes
movem.l (a7)+,d2/d5-d7
rts
ST_VeryBad move.l #BADTRACKBITS<<16+BADTRACKBITS,d0 Assume all labels and sectors to be unreliable
move.l d0,UD_SavedL(a4)
bra.s ST_Rtn
*-------------------------------------------------------*
*
* GetHeader
*
* Subroutine for Salve. Test validity of the first part of a Trackdisk sector. Set sector
* address in SB_Header and return in d0 if valid. Update statistics regarding tracknumber.
* Return wrong track as a special case.
*
* Input: d7 Shift factor
* a0 Sector structure, SE_
* a2 Trackdisk trackbuffer structure, TB_
* a5 SalveBuffer structure, SB_
*
* Return: d0 Header, -1 on wrong track, 0 on other errors.
* a0 Ea of SE_Label
*
GetHeader addq.l #SE_Header,a0
moveq.l #HE_SIZE/2+TD_LABELSIZE/2,d0 Size of checksum area (longs)
bsr CheckSum Calculate checksum
move.l d0,-(a7) Keep checksum
bsr DecodeLong Decode it
cmp.l (a7)+,d0 The same?
bne.s GH_NotGood No..
add.w #(SE_Header-SE_SumD),a0 Lea header again
bsr DecodeLong
move.l d0,(a5) Make header available
cmp.b #DISKFORMAT,(a5) Our format?
bne.s GH_NotGood No..
move.w TB_TrkNo(a2),d1 Track number under head
cmp.b HE_TrkNo(a5),d1 Same as in header?
bne.s GH_WrongTrack No..
addq.w #1,SB_CorrectTrk(a5) Yes, one for us
rts
GH_WrongTrack addq.w #1,SB_WrongTrk(a5) One for them
moveq.l #-1,d0 Error (restore?)
rts
GH_NotGood moveq.l #0,d0 Error
rts
*-------------------------------------------------------*
*
* DecodeLong
*
* Get two longwords from shifted memory and decode them into one longword
*
* Input: d7 Shift factor
* a0 Data source
*
* Return: d0 Decoded longword
* a0 Proper aligned for next access
*
DecodeLong movem.l d2/d3,-(a7)
moveq.l #16,d3 Shift modulus
sub.l d7,d3 Complementary shift number
move.l (a0)+,d0 Get 48 bits (long + max shift)
move.w (a0),d2
lsl.l d7,d0 Shift first 32 bits left
lsr.w d3,d2 Shift last 16 bits right
or.w d2,d0 Put them together into one longword
move.l (a0)+,d1 Get 48 bits (long + max shift)
move.w (a0),d2
lsl.l d7,d1 Shift first 32 bits left
lsr.w d3,d2 Shift last 16 bits right
or.w d2,d1 Put them together into one longword
and.l #$55555555,d0 Remove MFM bits
and.l #$55555555,d1
lsl.l #1,d0 Line up
or.l d1,d0 Melt
movem.l (a7)+,d2/d3
rts
*-------------------------------------------------------*
*
* CheckSum
*
* Calculate checksum over shifted memory
*
* Input: d0 Length in longs
* d7 Shift factor
* a0 Begin of block
*
* Return: d0 Checksum
* a0 Aligned to begin of next block
*
CheckSum movem.l d2/d3,-(a7)
moveq.l #-1,d1 Build mask for first access
lsr.l d7,d1 Shift mask
move.l (a0)+,d2 Get part of first long
and.l d1,d2 Mask non-involved bits
subq.l #2,d0
10$ move.l (a0)+,d3 Get longs
eor.l d3,d2 Checksum algorithm
dbra d0,10$ Loop
move.l (a0),d3 Get last part of last long
not.l d1 Flip mask
and.l d1,d3 Mask non-involved bits
eor.l d3,d2 Checksum algorithm
rol.l d7,d2 Unshift
and.l #$55555555,d2 Select relevant bits
move.l d2,d0 Checksum
movem.l (a7)+,d2/d3
rts
*-------------------------------------------------------*
*
* SearchSync
*
* Search for a Sync. If found, return its address on word boundary and
* how many bits it is shifted to the right. (max 15)
*
* Input: d0.w Number of words to check
* a0 Start address to search
*
* Returns: d0 Words left
* d7 Bitshift
* a0 Sync
*
SearchSync move.w (a0)+,d1
cmp.w #SYNCSYNC>>0,d1
beq.s SS_Found0
cmp.w #SYNCSYNC>>1,d1
beq.s SS_Found1
cmp.w #SYNCSYNC>>2,d1
beq.s SS_Found2
cmp.w #SYNCSYNC>>3,d1
beq.s SS_Found3
cmp.w #SYNCSYNC>>4,d1
beq.s SS_Found4
cmp.w #SYNCSYNC>>5,d1
beq.s SS_Found5
cmp.w #SYNCSYNC>>6,d1
beq.s SS_Found6
cmp.w #SYNCSYNC>>7,d1
beq.s SS_Found7
cmp.w #SYNCSYNC>>8,d1
beq.s SS_Found8
cmp.w #SYNCSYNC>>9,d1
beq.s SS_Found9
cmp.w #SYNCSYNC>>10,d1
beq.s SS_Found10
cmp.w #SYNCSYNC>>11,d1
beq.s SS_Found11
cmp.w #SYNCSYNC>>12,d1
beq.s SS_Found12
cmp.w #SYNCSYNC>>13,d1
beq.s SS_Found13
cmp.w #SYNCSYNC>>14,d1
beq.s SS_Found14
cmp.w #SYNCSYNC>>15,d1
beq.s SS_Found15
dbra d0,SearchSync Loop d0 words
moveq.l #-1,d7 Set not found
SS_Rtn subq.l #2,a0
SS_Rtn10 rts
SS_Found0 moveq.l #0,d7
bra.s SS_Rtn10
SS_Found1 moveq.l #1,d7
bra.s SS_Rtn
SS_Found2 moveq.l #2,d7
bra.s SS_Rtn
SS_Found3 moveq.l #3,d7
bra.s SS_Rtn
SS_Found4 moveq.l #4,d7
bra.s SS_Rtn
SS_Found5 moveq.l #5,d7
bra.s SS_Rtn
SS_Found6 moveq.l #6,d7
bra.s SS_Rtn
SS_Found7 moveq.l #7,d7
bra.s SS_Rtn
SS_Found8 moveq.l #8,d7
bra.s SS_Rtn
SS_Found9 moveq.l #9,d7
bra.s SS_Rtn
SS_Found10 moveq.l #10,d7
bra.s SS_Rtn
SS_Found11 moveq.l #11,d7
bra.s SS_Rtn
SS_Found12 moveq.l #12,d7
bra.s SS_Rtn
SS_Found13 moveq.l #13,d7
bra.s SS_Rtn
SS_Found14 moveq.l #14,d7
bra.s SS_Rtn
SS_Found15 moveq.l #15,d7
bra.s SS_Rtn
*-------------------------------------------------------*
*
* BlitMove
*
* Move a block of data from source to destination and shift it left by some bits.
*
* Input: d0.w Blitsize ready to pass to the blitter
* d2.w Bytesize of block to move
* d7.w Shift factor: number of bits that memory IS shifted to the right
* a0 Source
* a1 Destination
*
* In linear mode the blitter can move at most 2^10 (1024) words. Therefore we use its
* rectancular mode. We can set the horizontal size to 1 to 128 words, thus limiting our
* blit to multiples of these.
BlitMove movem.l d3-d5,-(a7)
sub.w #TSBN_SIZE,a7 Extended blitnode on the stack
moveq.l #0,d4 First let's clear all unused and undefined
move.l d4,(a7) parts of the blinode as stated in
move.w d4,bn_stat(a7) I&A Introduction-5 Obey 3&4
move.l d4,bn_cleanup(a7)
* We use the blitter in ascending mode. Then the blitter performs shifts to the right.
* Therfore we translate our order to shift left into shift right. IF we shift, and we
* stick to our blitsize, we loose some bits. This is because we express in blitsize
* the size of the track in words instead of bits. If these bits do not begin on a
* word-boundary they do not end either. Because the blitter can move maximal 1024
* block of 1 to 128 words, and we do not determine the blocksize (the calling routine is),
* we take care of this word by hand (the cpu).
move.l d7,d4 Shiftfactor (to left)
neg.w d4 We want 16 minus shift results in requested shift to right, zero?
beq.s 10$ Yes, no shift..
subq.l #2,a1 Destination one word lower
move.w (a1),d3 Keep first word to restore after blit
move.l -2(a0,d2.w),d5 Get last two words of block (out of reach of the blitter)
lsl.l d7,d5 Do the shift of the last word here
swap.w d5 D5 holds now the last word
10$ move.w d0,bn_blitsize(a7) The calling routine has aready assembled the correct value
moveq.l #BSHIFTSHIFT,d0 Shift shift factor 12 bits left, thus clearing all other
lsl.w d0,d4 bits: no fill, ascending and area mode
move.w d4,TSBN_C1(a7) Prepared blitter command
move.l a0,TSBN_SceB(a7) Source
move.l a1,TSBN_Dest(a7) Destination
move.l a3,TSBN_Unit(a7) TD-Unit structure
lea.l QF_Shift(pc),a0 Lea blitter function
move.l a0,bn_function(a7) Function into blitnode
move.l a7,a1 Pointer to our blitnode
move.l a6,-(a7)
move.l TDD_GfxBase(a6),a6 The graphics library coordinates blitter usage
LibCall QBlit Control is returned immedately so we must wait here
move.l (a7)+,a6
bsr TD_WaitTDPort A70A Wait for a message we sent to ourself from within Gfx
tst.w TSBN_C1(a7) Shift not zero?: Did we modify the destination pointer?
beq.s 20$ No, blit fitted in word boundary..
move.l TSBN_Dest(a7),a0 Yes, get destination (pointing one word earlier)
move.w d3,(a0) Restore original value of word before desired destination
move.w d5,0(a0,d2.w) Last word which was out of reach of the blitter
20$ add.w #TSBN_SIZE,a7 Free blitnode
movem.l (a7)+,d3-d5
rts
*-------------------------------------------------------*
*
* QBlit function. Parameters are passed via the blitnode structure. We have exclusive control
* over the blitter here.
* NB! This code is executed under control of other regimes. Behave well.
* We tell the blitter to move and shift our block.
*
* Input: a0 Pointer to blitter
* a1 Pointer to blitnode
*
* Returns: d0 -1, meaning not ready
*
QF_Shift moveq.l #0,d0
move.w d0,bltbmod(a0) No modulus for B
move.w d0,bltdmod(a0) No modulus for D
BLITLF set ABC+ABNC+NABC+NABNC D=B
BLITUSE set SRCB+DEST B is source and D destination
move.w #BLITLF+BLITUSE,bltcon0(a0)
move.w TSBN_C1(a1),bltcon1(a0) Shift factor into BSH (B-shift) ascending
move.l TSBN_SceB(a1),bltbpt(a0) Source into B
move.l TSBN_Dest(a1),bltdpt(a0) Destination into D
move.w bn_blitsize(a1),bltsize(a0) Start blit by writing size
lea.l QF_End(pc),a0 Lea terminating function
move.l a0,bn_function(a1) Function into blit node
moveq.l #-1,d0
rts
*-------------------------------------------------------*
*
* QBlit function. Parameters are passed via the blitnode structure. We have exclusive control
* over the blitter here.
* NB! This code is executed under control of other regimes. Behave well.
* We signal the td task that the blit is done. (Here we are NOT the TD task)
*
* Input: a0 Pointer to blitter
* a1 Pointer to blitnode
*
* Returns: d0 0, meaning ready
*
QF_End move.l TSBN_Unit(a1),a1 TD unit pointer
bsr TD_Reply
moveq.l #0,d0 Return 0 to stop QBlit
rts
*********************************************************
*
* Read extensions.
*
* Adapt reads (and writes) to error handling based on error flags for each sector apart.
* Trackdisk sets the tracknumber in its trackbuffer to -1, meaning no valid track in the
* buffer. TD does this if it finds a TB_FirstSec larger than possible. We prevent TD doing
* so. Instead we check TD_FirstSec each time TD_TrkNo would have been checked. This enables
* us to access a faulty trackbuffer when we use the salve function.
*
TDE_Read cmp.b #SPT,TB_FirstSec(a0) Error in this track?
bmi TD_CmdRead A890 No..
btst.b #B_SALVE,UNIT_pad(a3) Yes, but is the track salved?
bne.s 10$ Yes..
move.b TB_FirstSec(a0),IO_ERROR(a2) No, set error in IORequest
bra TD_EndRW A920 Return error..
10$
*-- Here we have a read command on a salved track. Always copy data, but if this data is bad, set IO_ERROR
move.l TDU_TCB+TC_Userdata(a3),a1 Lea UnitData structure
move.l UD_SavedL(a1),d1 Get pattern with bad sectors and labels
moveq.l #0,d0
move.b TDU_IOSector(a3),d0 Current sector number
btst d0,d1 Faulting sector?
bne.s 20$ Yes, set error..
btst.b #0,TDU_Flags(a3) No, label transfer?
beq TD_CmdRead10 A8A0 No, no error, continue..
swap.w d1 Yes, label transfer, get label log
btst d0,d1 A8A0 Faulting label?
beq TD_CmdRead10 No..
20$ move.b TB_FirstSec(a0),IO_ERROR(a2) Set error
bra TD_CmdRead10 A8A0
*********************************************************
*
* ObtainBuffer - ReleaseBuffer
*
* Handling of permission to use the buffer
*
* Input: a3 TD unit structure
*
* Returns: a0 buffer
*
ObtainBuffer move.l a2,-(a7)
move.l TDU_TCB+TC_Userdata(a3),a2 Lea UnitData structure
move.l UD_TSControl(a2),a2 Lea TSControl structure
lea.l TSC_OwnBuffer(a2),a0 Lea Semaphore for salvage system usage
move.l a6,-(a7)
move.l TDD_SysBase(a6),a6 Trackdisk's SysBase
LibCall AttemptSemaphore Try to lock Salve system
move.l (a7)+,a6
tst.l d0 Locked?
bne.s 10$ Yes..
moveq.l #0,d0 No, motor off
bsr TD_SwitchMotor
lea.l TSC_OwnBuffer(a2),a0 Lea Semaphore for salvage system usage
move.l a6,-(a7)
move.l TDD_SysBase(a6),a6 Trackdisk's SysBase
LibCall ObtainSemaphore Wait for permission to use it
move.l (a7)+,a6
10$ move.l TSC_Buffer(a2),a0 The buffer itself
move.l (a7)+,a2
rts
ReleaseBuffer move.l TDU_TCB+TC_Userdata(a3),a0 Lea UnitData structure
move.l UD_TSControl(a0),a0 Lea TSControl structure
lea.l TSC_OwnBuffer(a0),a0 Lea Semaphore for salvage system usage
move.l a6,-(a7)
move.l TDD_SysBase(a6),a6 Trackdisk's SysBase
LibCall ReleaseSemaphore
move.l (a7)+,a6
rts
*********************************************************
*
* At one point in TD_NormTrack all data has been moved to their definitive position. After this point
* all sectorheaders are recalculated. If we are verifying we do not want any changes, just the move.
* So at this position we want to leave TD_NormTrack. TD_NormTrack calls some subroutine at that point
* and we are there to check whether we are verifying or not.
*
TDE_NormTrack tst.l 24(a7) The original caller of TD_NormTrack had zero saved here
beq.w TD_CorrectEdge Zero, proceed normal..
;addq.l #4,a7 Non-zero: TD_NormTrack was called by the verify routine
bra.w TD_NormTrackRtn Skip header revision..
*********************************************************
*
* Write extensions.
*
* Write Trackdisks buffer to disk and check whether verify is enabled. Do not verify if the
* TD_WriteTrack returned an error. Get the verify buffer and read the just written track into
* it. Tidy the buffer up and compare it with the just written. In case of some error, display
* a requester and rewrite if asked for.
*
* Input: a3 Trackdisk Unit structure
* a6 Trackdisk device base
*
* Returns: d0 Write error
*
* Usage d2 Error
* a2 Verify buffer
* a4 Trackdisk buffer written to disk
*
TDR_WriteTrackF clr.b TB_FirstSec(a0) Format does not use and set this field
TDR_WriteTrack bsr TD_WriteTrack Normal write track
btst.b #B_VERIFY,UNIT_pad(a3) Is write-verify enabled?
bne.s 20$ Yes..
10$ rts
20$ tst.l d0 Did TD_WriteTrack had an error?
bne.s 10$ Yes, we do not verify..
movem.l d2/a2/a4,-(a7)
bsr ObtainBuffer Get buffer to read into from disk
move.l a0,a2
move.l TDU_DiskBuf(a3),a4 The buffer which was written to disk
move.l a2,TDU_DiskBuf(a3) The buffer into we will read from disk
move.w (a4),(a2) Tracknumber
moveq.l #1,d0 Motor on
bsr TD_SwitchMotor
moveq.l #0,d0
move.w (a2),d0 Tracknumber
bsr TD_Seek A3DA Seek to it
lea.l TB_Data+4(a2),a0 Position in buffer to begin to read
move.w #(SPT+1)*SE_SIZE+GAPSIZE,d0 Size of read
bsr TD_ReadDisk Read from disk
tst.l d0 DiskChange?
bne.s 30$ Yes, that is a verify error..
move.w TDU_XTrack(a3),d2 Keep current value
move.w (a4),TDU_XTrack(a3) TD_NormTrack uses this value as the current track
moveq.l #-1,d0 Tell (modified) TD_NormTrack to skip header revision
bsr TD_NormTrack Tidy the track up
move.w d2,TDU_XTrack(a3) Restore original value
move.l a4,TDU_DiskBuf(a3) TD's write buffer back into TD's global
cmp.b #SPT,d0 Error?
bcc.s 30$ Yes..
move.b d0,TB_FirstSec(a2) First sector in the verify buffer
move.l a2,a0 Verify buffer
move.l a4,a1 Original written buffer
bsr CompareTracks Compare both buffers (they are not exactly the same)
beq.s VT_Rtn No error..
*-- Let's request. TD has a 512 byte stack. Not enough to call Intuition.. But we have here a buffer of 26k!
30$ moveq.l #0,d0 Motor off during request
bsr TD_SwitchMotor
add.w #10000,a2 Make a little room for stack
exg a2,a7 Set a7 to the buffer
move.w TB_TrkNo(a4),d0 Tracknumber
bsr VerifyAlert Display the requester
move.l a2,a7 TD's stack again
VT_Rtn move.l d0,d2 Answer of user: zero is ignore
bsr ReleaseBuffer We do not need the verify buffer anymore
move.l d2,d0 Rewrite?
movem.l (a7)+,d2/a2/a4
bne TDR_WriteTrack The user wanted a rewrite..
rts
*-------------------------------------------------------*
*
* CompareTracks
*
* Compare data in two trackbuffers. A simple compare is not possible. The data should be
* the same but may be arranged differently.
*
*
* Input: a0 Trackbuffer
* a1 Trackbuffer
*
* Returns: d0 Zero if buffers are the same, -1 in case of error
*
CompareTracks moveq.l #SPT,d0 Total number of sectors
add.b TB_FirstSec(a0),d0 Add first sector of the first buffer
sub.b TB_FirstSec(a1),d0 Subtract first sector of the other buffer
divu #SPT,d0 Subtract SPT if larger than SPT
swap.w d0 Remainder is sector shift between both buffers
mulu #SE_SIZE,d0 Byte size of first part
move.w #SPT*SE_SIZE,d1 Total size
sub.w d0,d1 Size of second part
lea.l TB_Data(a0),a0 Begin of compare in first buffer
lea.l TB_Data(a1),a1 Begin of sectors in second buffer
add.w d0,a1 Add to find first sector to compare in second buffer
lsr.w #2,d0 Cnv to long counter
lsr.w #2,d1 Cnv to long counter
cmp.w d0,d0 Preset equal condition
bra.s CT_Loop01 Enter loop
CT_Loop0 cmp.l (a0)+,(a1)+
CT_Loop01 dbne d1,CT_Loop0 Terminates on not equal or d1==-1
bne.s CT_Error Buffers are not the same..
subq.w #1,d0 We do not compare the first long
bmi.s CT_OK Nothing to compare anymore
addq.l #4,a0 Skip SectStart
lea.l -SPT*SE_SIZE+4(a1),a1 Compare buffer to one long past begin
cmp.w d0,d0 Preset equal condition
bra.s CT_Loop11 Enter loop
CT_Loop1 cmp.l (a0)+,(a1)+
CT_Loop11 dbne d0,CT_Loop1 Terminates on not equal or d1==-1
beq.s CT_OK Buffers are the same..
CT_Error moveq.l #-1,d0 I'm so sorry
bra.s CT_Rtn
CT_OK moveq.l #0,d0 No error
CT_Rtn rts
*-------------------------------------------------------*
*
* VerifyAlert - Notify user of the verity error and ask him what to do.
*
* To do so, we use a requester with the choise to ignore the event (inherent in TD) or to
* rewrite the track. This is more complicated as it looks at first sight. It would be
* nice if an AutoRequest could be used (simple & small), but the idea behind write verify
* requires an airtight approach. If there is not enough memory to build the AutoRequest,
* Intuition defaults to an Alert. But if there is not enough memory to build the Alert,
* Intuition simply returns FALSE. As if the user selected "Ignore". Useless for our
* purposes. So we have to build our own requester. We have no window open, so we open a
* window for just one use: to show the requester. A requester has the fe. ff feature to
* block all input to the window. Intuition permits all kinds of events to penetrate to
* the SysRequest. I do not know an easy way (we are patching TD, remember?) to get the same
* result. The other approach is to build the gadgets directly in the window. Then we
* receive all kind of events, including Left-Amiga-V and Left-Amiga-N. Pity that DMouse
* cannot see that we are requesting. But otherwise we have no shortcuts. So?
*
* Input: d0 Tracknumber
* a3 TD Unit structure
* a6 TD device pointer
*
* Returns: d0 TRUE for rewrite, FALSE for ignore
*
VerifyAlert movem.l d2-d4/a2/a4/a5,-(a7)
*-- Insert head number in requester string
moveq.l #'0'>>1,d1 Prepare for asci conversion
lsr.b #1,d0 Get head number in X-bit
roxl.b #1,d1 Make asci zero or one
lea.l TXT_HeadNr(pc),a0 Destination
move.b d1,(a0) Store into requester string
*-- D0 now contains the cylinder number. Convert via BCD to asci and store into string
move.l a7,a2 Predecrement pointer to local word
clr.w -(a7) One word local
moveq.l #7,d1 Binary 2 nibbles to 2 bcd nibbles conversion
10$ move.l a2,a0 Destination
move.l a2,a1 Destination
lsl.b #1,d0 Binary shift left
abcd.b -(a0),-(a1) Bcd shift left
dbra d1,10$ Loop for eigth bits
move.w (a7)+,d1 Get bcd word
lea.l TXT_TrackNr(pc),a0 Destination
move.b d1,d0 Bcd value
lsr.b #4,d1 Next nibble
or.b #'0',d1 Convert to asci
move.b d1,(a0)+ Store in alert string
and.b #$0f,d0 Mask nibble
or.b #'0',d0 Convert to asci
move.b d0,(a0) Store in alert string
*-- Unit number in string
moveq.l #'0',d0 Asci first unit
add.b TDU_UnitNr(a3),d0 Unit number
lea.l TXT_UnitNr(pc),a0 Position in requester string
move.b d0,(a0) Store unit number
*-- Open a window on the Workbench screen and show a requester in it.
moveq.l #-1,d2 Set flag to requester failed
move.l TDU_TCB+TC_Userdata(a3),a0 Lea UnitData structure
move.l UD_TSControl(a0),a0 TSControl structure
move.l a6,-(a7) Trackdisk device base
move.l TDD_SysBase(a6),a5 ExecBase
move.l TSC_IntuBase(a0),a6 Our starter got IntuitionBase already for us
LibCall WBenchToFront
move.l ib_FirstScreen(a6),a0
move.w sc_DetailPen(a0),d0 Negative
lea.l TSCodeBegin(pc),a0
move.w d0,IT_Body0-TSCodeBegin(a0)
move.w d0,IT_Body1-TSCodeBegin(a0)
move.b d0,IMG_ReqOnOff-TSCodeBegin(a0)
rol.w #8,d0 Positive
move.w d0,IT_Positive-TSCodeBegin(a0)
move.w d0,IT_Negative-TSCodeBegin(a0)
move.b d0,IMG_GadOnOff-TSCodeBegin(a0)
lea.l NEW_Requester(pc),a0 NewWindow structure
LibCall OpenWindow
move.l d0,a4 Window structure, success?
beq.s NoReqWindow No..
*-- Wait for an answer of the user
exg.l a5,a6 SysBase in a6
IDCMP_Loop move.l wd_UserPort(a4),a0 IDCMP message port
LibCall WaitPort Wait for a message from Intuition
move.l wd_UserPort(a4),a0 IDCMP message port
LibCall GetMsg Remove message from queue
move.l d0,a1
move.l im_Class(a1),d3 Keep Class
move.l im_IAddress(a1),d2 Keep message initiator
move.l im_Code(a1),d4 Keep Code AND Qualifier
LibCall ReplyMsg Message back to Intuition
*-- Perhaps the user clicked one of the gadgets
cmp.l #GADGETUP,d3 Gadget clicked?
bne.s VA_ChkRawkey No, check keyboard shortcut
lea.l GAD_Negative(pc),a0 Get one of both message inititors
sub.l a0,d2 Set return value to zero if this gadget was clicked
beq.s CloseReqWindow "Ignore" was clicked..
moveq.l #1,d2 Not equal, other gadget must have been clicked, return positive
bra.s CloseReqWindow
*-- Perhaps the user pressed a 'B' or 'V'
VA_ChkRawkey cmp.l #RAWKEY,d3 Keyboard event?
bne.s IDCMP_Loop No, ignore message..
and.w #IEQUALIFIER_LCOMMAND,d4 Left-Amiga pressed?
beq.s IDCMP_Loop No, ignore..
swap.w d4 Select code field
moveq.l #0,d2 Returnvalue for "Ignore"
cmp.w #$0035,d4 Keycode for 'B'
beq.s CloseReqWindow Same, return ignore..
moveq.l #1,d2 Returnvalue for "Rewrite"
cmp.w #$0034,d4 Keycode for 'V'
bne.s IDCMP_Loop Not what we want, ignore message..
*-- Get present position of the window and close it
CloseReqWindow exg.l a5,a6 IntuitionBase again
lea.l NEW_Requester(pc),a0 NewWindow structure
move.l wd_LeftEdge(a4),(a0) Install present window position into new window
move.l a4,a0 Window structure
LibCall CloseWindow
NoReqWindow move.l a6,a5 IntuitionBase
move.l (a7)+,a6 TD base
move.l d2,d0 Result
bpl.s VA_Rtn Positive, user replied on requester..
*-- For some reason there was no requester, so bleep screens and blink drive led, return rewrite
exg a5,a6 Negative, no requester, get IntuBase
sub.l a0,a0 All screens
LibCall DisplayBeep Bleep
exg a5,a6 TD Base
moveq.l #6,d2 Blink drive led 3 times
10$ move.l d2,d0 Get counter
and.l #1,d0 Select LSB (toggles)
bsr.w TD_SwitchMotor Motor on and off
move.l #200000,d0 Sleep for a while
bsr.w TD_Sleep
dbra d2,10$ Loop
moveq.l #-1,d0 Set rewrite as result
VA_Rtn movem.l (a7)+,d2-d4/a2/a4/a5
rts
*-------------------------------------------------------*
*
* Requester data structures.
*
* These structures have pointers to each other. Therefore we cannot move them without making
* adaptions. We can do two things. Normal relocation followed by an adaption after the move,
* or not relocate at loadtime and perform complete relocation later. We choose the latter
* because this saves relocation info in the exe and the relocation routine is not
* larger/smaller/easyer/harder.
* Because the relocation table is not to be included in the resident structure, it is
* physically placed somewhere at the end of this file.
* The "Body text" is tied to the "positve text". This saves us Intuprinting the requester text.
* Because code is outgrowing already the pan, the font is fixed to topaz 8. All calculations
* regarding window size, gadget positions, text postitions are done by hand and here and now.
*
NEW_Requester dc.w 0,0
dc.w 242,55
dc.b -1,-1
dc.l GADGETUP+RAWKEY
dc.l WINDOWDEPTH+WINDOWDRAG+SIMPLE_REFRESH+NOCAREREFRESH+ACTIVATE
NEW_ReqGadget dc.l GAD_Positive-TSCodeBegin
dc.l 0
NEW_ReqTitle dc.l TXT_VerTitle-TSCodeBegin
dc.l 0,0
dc.w 0,0,0,0
dc.w WBENCHSCREEN
GAD_Positive dc.l GAD_Negative-TSCodeBegin
dc.w 26,35
dc.w 82,16
dc.w GADGIMAGE+GADGHCOMP
dc.w RELVERIFY+ENDGADGET
dc.w BOOLGADGET+REQGADGET
GAD_PosRender dc.l IMG_Gadgets-TSCodeBegin
dc.l 0
GAD_PosIText dc.l IT_Positive-TSCodeBegin
dc.l 0
dc.l 0
dc.w 0
dc.l 0
GAD_Negative dc.l 0
dc.w 134,35
dc.w 82,16
dc.w GADGIMAGE+GADGHCOMP
dc.w RELVERIFY+ENDGADGET
dc.w BOOLGADGET+REQGADGET
GAD_NegRender dc.l IMG_Request-TSCodeBegin
dc.l 0
GAD_NegIText dc.l IT_Negative-TSCodeBegin
dc.l 0
dc.l 0
dc.w 0
dc.l 0
IMG_Request dc.w -130,-23
dc.w 234,41,0
dc.l 0
dc.b 0
IMG_ReqOnOff dc.b 0
IMG_ReqNext dc.l IMG_Gadgets-TSCodeBegin
IMG_Gadgets dc.w 0,0
dc.w 82,16,0
dc.l 0
dc.b 0
IMG_GadOnOff dc.b 0
dc.l 0
IT_Positive dc.b 0,0,RP_JAM2,0
dc.w 13,4
IT_PosFont dc.l TA_Topaz8-TSCodeBegin
IT_PosText dc.l TXT_Positive-TSCodeBegin
IT_PosNext dc.l IT_Body0-TSCodeBegin
IT_Negative dc.b 0,0,RP_JAM2,0
dc.w 17,4
IT_NegFont dc.l TA_Topaz8-TSCodeBegin
IT_NegText dc.l TXT_Negative-TSCodeBegin
dc.l 0
IT_Body0 dc.b 0,0,RP_JAM2,0
dc.w -14,-20 Relative to the positive gadget
IT_B0Font dc.l TA_Topaz8-TSCodeBegin
IT_B0Text dc.l TXT_Body0-TSCodeBegin
IT_B0Next dc.l IT_Body1-TSCodeBegin
IT_Body1 dc.b 0,0,RP_JAM2,0
dc.w -14,-11 Relative to the positive gadget
IT_B1Font dc.l TA_Topaz8-TSCodeBegin
IT_B1Text dc.l TXT_Body1-TSCodeBegin
dc.l 0
TA_Topaz8 dc.l TXT_FontName-TSCodeBegin
dc.w 8
dc.b FS_NORMAL,0
TXT_VerTitle dc.b ' TrackSalve 1.0 ',0
TXT_FontName dc.b 'topaz.font',0
TXT_Body0 dc.b 'Write verify error detected',0
TXT_Body1 dc.b 'on unit '
TXT_UnitNr dc.b 'x, track '
TXT_TrackNr dc.b 'xx, head '
TXT_HeadNr dc.b 'x',0
TXT_Positive dc.b 'Rewrite',0
TXT_Negative dc.b 'Ignore',0
cnop 0,2
*********************************************************
*
* End of code to be copied to the allocated space. Would this be the allocted space,
* then the TD-copy would begin here.
* From here it is allowed again to make the location counter external available.
*
TSCodeEnd
TD
TD_NoDisk equ TD+$00DE 99C2
TD_Seek equ TD+$0AF6 A3DA
TD_SwitchMotor equ TD+$0B7E A462
TD_ReadDisk equ TD+$0C40 A524
TD_WaitTDPort equ TD+$0E26 A70A
TD_ReadTrkRetry equ TD+$1106 A9Ea
TD_ReadTrkRtn equ TD+$1114 A9F8
TD_TaskLoop equ TD+$1580 AE64
TD_Reply equ TD+$0E0E A6F2
TD_CmdWrite equ TD+$0F34 A818
TD_CmdRead equ TD+$0FAC A890
TD_CmdRead10 equ TD+$0FBC A8A0
TD_EndRW equ TD+$103C A920
TD_P101b equ TD+$0F04 A7E8
TD_WriteTrack equ TD+$1074 A958
TD_NormTrack equ TD+$16FE AFE2
TD_NormTrackRtn equ TD+$18F0 B1D4
TD_CorrectEdge equ TD+$14DA ADBE
TD_Sleep equ TD+$0C0C A4F0
*********************************************************
*
* This table contains data which will be put into the trackdisk code we copied from ROM. Its location must
* directly follow TSCodeEnd for offset calculations. So do not reposition this table without an adaption of
* the Patch macro.
* The format of the table is a stucture of this form:
*
* WORD OffsetInTD Offset relative to rt_MatchTag
* UWORD PatchSize Size of patch in words
* STRUCT Patch,PatchSize*2 The patch itself
*
* The Patch table consists of a series of patch structures following each other. The end of the table
* is reached when a patch is met with a PatchSize of zero.
*
Patch MACRO <Offset in TD>,<Patchsize in bytes>
dc.w \1
dc.w (\2)/2
TS set *-TD-\1
ENDM
Func TSPatchTable,_TSPatchTable
*-- Bug patches
Patch $1A38,P000e-P000b B31C Bug in td_RawWrite
P000b cmp.l #$8000,d0
P000e
Patch $00E6,P001e-P001b AAAAAAAAARRRRRRRGGGHHHH...
P001b dc.w $0016 GetUnit before GiveUnit patch
P001e
*-- Let toplevel task loop flow through our code
Patch $1592,P100e-P100b AE76 Toplevel task loop
P100b bra.w TS+TDE_TaskLoop
P100e
*-- Check first with us befire clicking
Patch $0104,P200e-P200b 99E8 Presence test
P200b bsr.w TS+TDE_NoClick
nop
P200e
*-- Check readonly simutation before writes or returning td_ProtStatus
Patch $0D22,P300e-P300b A606 Write routine
P300b bsr.w TS+TDE_WriteProt
nop
nop
P300e
Patch $1194,P301e-P301b AA78 Tab-test for td_ProtStatus
P301b bsr.w TS+TDE_WriteProt1
P301e
* Patch $0162,P302e-P302b 9A46 Disk login, firt detection disk presence
*P302b bsr.w TS+TDE_WriteProt1
*P302e
*-- Read (write) adaptions to the salve function
Patch $10F8,P400e-P400b A9DC Read error after normalisation
P400b bra.w TS+TDE_ReadError
P400e
Patch $0EC8,P401e-P401b A7AC
P401b bne.s TS+TD_P101b A7E8 The track we want is in the buffer..
P401e
Patch $0F04,P402e-P402b A7E8
P402b move.l TDU_IOReq(a3),a2 Get IORequest
move.l TDU_DiskBuf(a3),a0 Track buffer
cmp.b #CMD_WRITE,IO_COMMAND+1(a2) Write?
bne TS+TDE_Read No, read..
cmp.b #SPT,TB_FirstSec(a0) Yes, write. No error in track?
bcs.s TS+TD_CmdWrite A818 No, go write
move.b TB_FirstSec(a0),IO_ERROR(a2)
bra TS+TD_EndRW A920 Bad return
P402e
Patch $102A,P403e-P403b A90E
P403b blt TS+TD+$0F04 A7E8
P403e
*-- Verify adaptions to write routines
Patch $07C4,P500e-P500b A0A8
P500b bsr TS+TDR_WriteTrack
P500e
Patch $0EDC,P502e-P502b A7C0
P502b bsr TS+TDR_WriteTrack
P502e
Patch $11D6,P503e-P503b AABA
P503b bsr TS+TDR_WriteTrack
P503e
Patch $15D2,P504e-P504b AEB6
P504b bsr TS+TDR_WriteTrack
P504e
Patch $16FE,P505e-P505b AFE2
P505b movem.l d0/d2-d6/a2,-(a7) D0 added to list, has become an argument
P505e
Patch $18FA,P506e-P506b
P506b movem.l (a7)+,d1/d2-d6/a2 D1 added to list as a dummy pull to compensate above
P506e
Patch $180E,P507e-P507b B0F2
P507b bsr.w TS+TDE_NormTrack
P507e
*-- Verify adaption to Format routine
Patch $0864,P551e-P551b A148
P551b move.w d2,TB_TrkNo(a0)
move.l a0,TDU_DiskBuf(a3)
bsr.w TS+TDR_WriteTrackF
P551e
Patch 0,0
*********************************************************
*
* The relocation table of the code between TSCodeBegin and TSCodeEnd.
*
Func TSCodeRelocTable
dc.w NEW_ReqGadget-TSCodeBegin
dc.w NEW_ReqTitle-TSCodeBegin
dc.w IMG_ReqNext-TSCodeBegin
dc.w GAD_Positive-TSCodeBegin
dc.w GAD_PosRender-TSCodeBegin
dc.w GAD_PosIText-TSCodeBegin
dc.w GAD_NegRender-TSCodeBegin
dc.w GAD_NegIText-TSCodeBegin
dc.w IT_B0Font-TSCodeBegin
dc.w IT_B0Text-TSCodeBegin
dc.w IT_B0Next-TSCodeBegin
dc.w IT_B1Font-TSCodeBegin
dc.w IT_B1Text-TSCodeBegin
dc.w IT_PosFont-TSCodeBegin
dc.w IT_PosText-TSCodeBegin
dc.w IT_PosNext-TSCodeBegin
dc.w IT_NegFont-TSCodeBegin
dc.w IT_NegText-TSCodeBegin
dc.w TA_Topaz8-TSCodeBegin
dc.w 0
*********************************************************
*
* The size of the code to be copied is EndTSCode-_TSCode. The size of the buffer is
* also assembler laid down.
* How do we pass these values to a C-module?
* For now with globals, but constants would be more appropriate..
*
SECTION __MERGED,data
gc_l _TSCodeSize,TSCodeEnd-TSCodeBegin
gc_l _BufferSize,SB_SIZE
*********************************************************
END