************************************************************************* * * * * * Program Name: NoClick3.4 * * * * Version Date: 20 August 1989 * * * * Based on the prototype NoClick program posted by * * Dan Babcock to PLINK in May 1989 * * * * With thanks to Werner Guenther for showing the use of * * FindName to generate the trackdisk task list, and * * pointing out the possibility of changing the code's * * jump table. * * * * Copyright (c) 1989 - Norman Iscove iscove@utoroci (bitnet) * * * * * * USAGE: Place in c: directory. Type 'NoClickxx' from CLI, * * or include in Startup-sequence, preferably after FastMemFirst. * * Safer not to invoke it at a point where disks are concurrently * * active. * * * * FUNCTION: * * * * Intended to eliminate clicking of empty drives installed in * * Amiga 500, 1000 or 2x00 computers, provided the particular * * drive models respond quietly to negative stepping of the * * heads past track 0. The program checks for and sets * * additional floppy drives if also present. Aborts harmlessly * * if a second execution is attempted. Also repairs a known * * bug in the trackdisk.device code involving raw read and * * write calls. * * * * Works by copying the trackdisk.device code from rom into * * ram. A single byte is modified so that the drive heads * * will be stepped (silently) in a negative rather than * * positive direction during the regular system checks for a * * disk change. One word is also altered to repair the raw * * read/write bug. After creating the copy and fixing it, the * * program changes the system vectors in each drive's task * * structure to point to the ram copy. * * * * * * ENTRY REGISTERS: none assumed * * * * EXIT REGISTERS: d2-d7/a2-a6 preserved in entry condition * * d0 = 0 * * * * ASSUMPTIONS: * * * * Private structure of the trackdisk.device code in rom is * * not documented. The offsets of the pointers to start and * * end of the code, and the offsets of the bytes to be altered * * are all determined by inspection of the code in the 1.3 rom. * * * * CAVEAT: * * * * Has been tested and works on a B2000 running KS/WB 1.3 V34.2 * * with two internal floppy drives, 2 MB expansion memory (2058) * * and no hard drive. * * * ************************************************************************* INCLUDE 'execlib' *-----------------------------------------------------------------------* * Save the incoming registers * *-----------------------------------------------------------------------* main: movem.l d2-d7/a2-a6,-(sp) movea.l 4,a6 ;a6 = execbase *-----------------------------------------------------------------------* * Make a list of all the trackdisk tasks * *-----------------------------------------------------------------------* tasklist: moveq #1,d6 ;d6 = counter (search through two lists) lea tasks,a3 ;a3 = pointer to my list of td tasks lea tdname,a4 ;a4 = pointer to "trackdisk.device" jsr _LVODisable(a6) ;disable interrupts & task switching lea 406(a6),a0 ;a0 = start of taskready queue nexttask: move.l a4,a1 ;a1 = pointer to "trackdisk.device" jsr _LVOFindName(a6) ;find the next task with this name move.l d0,(a3)+ ;save task pointer in my list, sets cond. movea.l d0,a0 ;a0 = start for next FindName search bne.s nexttask ;check for next task if not zero waitqueue: lea -4(a3),a3 ;correct pointer lea 420(a6),a0 ;a0 = start of taskwait queue dbf d6,nexttask jsr _LVOEnable(a6) *-----------------------------------------------------------------------* * Abort if already installed * *-----------------------------------------------------------------------* check: lea tasks,a4 ;1st entry is the one that was ready bsr nextset move.l $46(a3),a0 ;a0 = finalPC, td code that task exits to cmp.l #$f80000,a0 ;exit if already pointing to ram bls exit *-----------------------------------------------------------------------* * Find trackdisk.device in rom, get start, end, size * *-----------------------------------------------------------------------* findcode: lea tdname,a0 moveq #0,d0 ;unit df0: moveq #0,d1 ;flags lea iorequest,a1 jsr _LVOOpenDevice(a6) ;open the trackdisk.device bne exit move.l iodevice,a3 ;a3 = trackdisk library base address C03AE4 lea iorequest,a1 jsr _LVOCloseDevice(a6) move.l $0A(a3),a1 ;ln_name(a3) (C03AEE) points to string ; 'trackdisk.device' at FE957E sub.w #$18,a1 ;a1 = FE9566 move.l (a1),d2 ;d2 = start of trackdisk routine in rom, ; FE9564. add.w #4,a1 ;a1 = FE956A move.l (a1),a0 ;a0 = end of trackdisk routine in rom, ; FEB05C suba d2,a0 ;a0 = signed length of trackdisk routine moveq #0,d3 move.w a0,d3 ;d3 = unsigned length (bytes) of td routine addq #3,d3 ;ensure all copied if not multiple of 4 *-----------------------------------------------------------------------* * Allocate some ram and copy to it * *-----------------------------------------------------------------------* copy: move.l d3,d0 ;d0 = number of bytes moveq #1,d1 ;d1 = MEMF_PUBLIC, fastmem if available jsr _LVOAllocMem(a6) move.l d0,a1 ;d0,a1 = location of reserved block in ram lsr.w #2,d3 ;d3 = number of longs to copy move.l d2,a0 ;a0 = start of rom routine cploop: move.l (a0)+,(a1)+ ;copy rom routine to ram dbra d3,cploop *-----------------------------------------------------------------------* * Fix the copy's jump table so that the code patched by fixbug * * (below) is actually used (thanks to W. Guenther) * *-----------------------------------------------------------------------* fixjumps: move.l d2,d3 ;d3 = start of rom routine sub.l d0,d3 ;- start of ram copy = offset movea.l d0,a0 ;a0 = start of ram copy lea $a1c(a0),a0 ;a0 = pointer to copy's jump table moveq #21,d4 ;d4 = 22 functions to patch fj1: sub.l d3,(a0)+ ;correct the address of each function dbf d4,fj1 *-----------------------------------------------------------------------* * Stop the clicks * *-----------------------------------------------------------------------* rmvclick: move.l d0,a5 ;a5 = location of copy bchg #7,$0105(a5) ;fix the critical byte *-----------------------------------------------------------------------* * Repair trackdisk read/write bug originally at $feaf9c (1.3) * *-----------------------------------------------------------------------* fixbug: move.w #$0C80,$1A38(a5) ;fix to cmp.l #$8000,d0 *-----------------------------------------------------------------------* * Fix each task's exit vector to point to ram version * *-----------------------------------------------------------------------* fixptrs: lea tasks,a4 ;a4 = address of task list bsr.s nextset move.l $46(a3),a2 ;a2 = finalPC, td code that task exits to sub.l d2,a2 ;a2 = offset of code from start (d2) in rom add.l a2,a5 ;a5 = corresponding address in ram copy jsr _LVODisable(a6) move.l a5,$46(a3) ;replace corrected finalPC pointer jsr _LVOEnable(a6) fixloop: bsr.s nextset beq.s exit jsr _LVODisable(a6) move.l a5,$46(a3) ;replace corrected finalPC pointer jsr _LVOEnable(a6) bra.s fixloop *-----------------------------------------------------------------------* * Done * *-----------------------------------------------------------------------* exit: movem.l (sp)+,d2-d7/a2-a6 ;restore the incoming registers moveq #0,d0 ;tell system no error rts ;*** subroutines *-----------------------------------------------------------------------* * Find task's exit pointer to trackdisk code * * * * Exit registers: a1 = address of task structure * * a3 = tc_SPReg * * d0 = a1 * * z flag = 0 if no more tasks * *-----------------------------------------------------------------------* nextset: move.l (a4)+,a1 ;a1 = address of this task structure move.l $36(a1),a3 ;a3 = tc_SPReg for this task move.l a1,d0 ;test for a1=0 rts ;*** data tdname: dc.b 'trackdisk.device',0 EVEN iorequest: dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 iodevice: dc.b 0,0,0,0 iounit: dc.b 0,0,0,0,0,0,0,0 EVEN tasks: ds.l 4 ;room for 4 drives dc.l 0 ;end of list marker END