
*  Small Disk Cache program.
*
*	By Moshe Braner,    870101.
*
*  Caches FAT and root directory only.
*
*  Pure AL version - for a-Seka.  870103.

* install the cache into the rwabs() vector
    pea     poke_it
    move.w  #$26,-(a7)		;   Supexec()
    trap    #14
    addq.l  #6,a7

* Cconws("\r\n\n\tDisk Cache installed\r\n\n")
    pea     msg
    move.w  #9,-(a7)
    trap    #1
    addq.l  #6,a7
    
* delay
    clr.l   d0
delay:
    addq.l  #1,d0
    cmp.l   #200000,d0
    blt     delay

* terminate, but keep $3300 bytes
    clr.w   -(a7)
    move.l  #$00003300,-(a7)
    move.w  #$31,-(a7)
    trap    #1

*  Subroutine to copy a sector (512 bytes)
*	from one RAM area (pointed to by A0) to another (A1).
*
*	D0 is junked.
*	A0,A1 are returned incremented by 512.

copy:
    move.l  a0,d0
    btst    #0,d0
    bne.s   ocopy
    move.l  a1,d0
    btst    #0,d0
    bne.s   ocopy
    move.w  #31,d0
eloop:
    move.l  (a0)+,(a1)+
    move.l  (a0)+,(a1)+
    move.l  (a0)+,(a1)+
    move.l  (a0)+,(a1)+
    dbf     d0,eloop
    rts
ocopy:
    move.w  #511,d0
oloop:
    move.b  (a0)+,(a1)+
    dbf     d0,oloop
    rts

*  Our resident-utility-protocol stuff:

    dc.b  "CACH"		; magic number
old:
    dc.l  0			; space for old vector

*  Cache code:

*	chache logical sectors 6-17 for drives A and B
*	check for media change before using cached data
*	read from cached data when possible
*	refresh chache after writing or real reading

scache:
    move.w  14(a7),d7		; drive	
    cmp.w   #2,d7		; drive A or B ?
    blt.s   doit		;  then cache	
usual:
    move.l  old,a0		; old vector	
    jmp     (a0)
doit:
    move.l  $47e,a3		; mediach() vector
    move.w  d7,-(a7)		; drive no.	
    jsr     (a3)
    addq.l  #2,a7
    lea     mark,a3		; cache validity table
    move.w  12(a7),d6		; sector no.	
    beq.s   junk		; junk if reading BPB
    tst.l   d0			; mediach() result
    beq.s   noch		; no media change
junk:
    move.l  a3,a0
    tst.w   d7			; drive	
    beq.s   ja
    adda.w  #12,a0
ja:
    clr.l   (a0)+		; junk all sectors
    clr.l   (a0)+
    clr.l   (a0)+
noch:
    subi.w  #6,d6		; we start at sector 6
    bmi.s   usual
    move.w  10(a7),d5		; count of sectors
    add.w   d6,d5		; last sector	
    cmpi.w  #11,d5
    bgt.s   usual
    tst.w   d7			; drive	
    beq.s   ra
    add.w   #12,d5		; offset for drive B
    add.w   #12,d6
ra:
    tst.w   4(a7)		; rwflag
    bne.s   write
    lea     space,a0		; source	
    move.w  d6,d0
    asl.w   #8,d0		; add 512*sec	
    asl.w   #1,d0
    adda.w  d0,a0		; real source	
    move.l  6(a7),a1		; destination	
rloop:
    tst.b   0(a3,d6)		; sector cache valid?
    beq.s   write
    bsr     copy
    addq.w  #1,d6
    cmp.w   d5,d6		; any more sectors?
    blt.s   rloop
    clr.l   d0			; no errors	
    rts
write:
    move.w  d5,d7
    sub.w   d6,d7		; what's left	
    move.w  10(a7),d0		; old sec count
    move.w  d7,10(a7)		; new count	
    sub.w   d7,d0		; the part done
    add.w   d0,12(a7)		; new first sector
    move.w  d6,d0
jloop:
    clr.b   0(a3,d0)		; sector cache invalid
    addq.w  #1,d0
    cmp.w   d5,d0		; any more sectors?
    bne.s   jloop
    lea     retsav,a0
    move.l  (a7)+,(a0)		; save return address
    pea     comeback		; our return address
    bra     usual		; do usual but return
comeback:
    move.l  retsav,-(a7)	; restore return addr
    tst.l   d0			; any errors?	
    bne.s   exit		; then return it
    move.w  12(a7),d6		; sec no.
    subi.w  #6,d6
    move.w  10(a7),d5		; count of sectors
    add.w   d6,d5		; last sector	
    move.w  14(a7),d7		; drive	
    beq.s   mb
    add.w   #12,d5		; offset for drive B
    add.w   #12,d6
mb:
    lea     mark,a3		; cache validity table
    move.l  6(a7),a0		; source	
    lea     space,a1		; destination	
    move.w  d6,d0
    asl.w   #8,d0		; add 512*sec	
    asl.w   #1,d0
    adda.w  d0,a1		; real destination
wloop:
    lea     0(a3,d6),a4
    bset    #0,(a4)		; mark sector cache
    bsr     copy
    addq.w  #1,d6
    cmp.w   d5,d6		; any more sectors?
    blt.s   wloop
    clr.l   d0			; no errors	
exit:
    rts
retsav:
    dc.l    0
mark:
    dc.l    0,0,0		; 12 bytes for drive A
    dc.l    0,0,0		; 12 bytes for drive B

space:				; cache buffer here

poke_it:
    move.l  #$476,a1		; rwabs() vector
    move.l  (a1),a0		; old vector	
    move.l  -8(a0),d0		; magic there?	
    cmpi.l  #$43414348,d0		
    beq.s   dont		; then skip	
    lea     scache,a0
    move.l  (a1),-4(a0)		; save old vector
    move.l  a0,(a1)		; put new vector
dont:
    rts

msg:
    dc.b    13,10,10,9
    dc.b    "Disk Cache installed"
    dc.b    13,10,10,0
    even

    end
