rapid1337.com

Agile File Loader

2007-06-22 · [ code ] · by staff

; Disk routine (pinched from Agile – sorry guys)

<-- Spiv’s File Loader | [ Code ]

[ read in diskmag ]


; Disk routine (pinched from Agile – sorry guys)
CIAAPRA	EQU	$bfe001		Cia A port register A
CIABPRB	EQU	$bfd100		Cia B port register B
CIABICR	EQU	$bfdd00		Cia B interrupt control register
CUSTOM	EQU	$dff000		Custom hardware
INTREQR	EQU	$1e		Read interrupt request
DSKPTH	EQU	$20		Disk buffer pointer
DSKLEN	EQU	$24		Disk access length
DSKSYNC	EQU	$7e		Disk sync word
DMACON	EQU	$96		Write DMA control
INTREQ	EQU	$9c		Write interrupt request
ADKCON	EQU	$9e		Write audio and disk controller
StepDel	EQU	$bb7		Step delay (dbf, naughty!)
; a0 is address to load file at, d0 is no. of file
FileRead
    movem.l	d0-d7/a0-a6,-(sp)	Store registers
    move.l	a0,a1			Copy addr. to load into a1
    lea	Filename(pc),a0		Get filename in a0
    bsr	MkName			Put d0 (hex) into filename string
    lea	Variables(pc),a6	a6 = Variables base
    lea	CIABPRB,a5		a5 = CIA base (CIABPRB)
    lea	CUSTOM,a4		a4 = custom hardware base
    move.l	a1,20(a6)		Store addr. to load in vars
    clr.w	10(a6)			Set ‘no track in buffer’
    move.b	#%11111111,(a5)		All CIABPRB high
    move.b	#%10000111,(a5)		SEL0-3 low (all motors now off)
    move.b	#%01111111,(a5)		Ready for motors on again
    bclr	#3,(a5)			Select drive 0, motor on
    tst.w	0(a6)			}
    nop				}	blowed if I know why
    not.w	0(a6)			}
    clr.l	2(a6)			Clear current track and ?
    clr.l	6(a6)			Clear sec. to load, sec.no on track
    btst	#4,CIABICR-CIABPRB(a5)	Test index (pointlessly)
.wtindx	btst	#4,CIABICR-CIABPRB(a5)	Test index
    beq.s	.wtindx			Repeat until one occurs
    bset	#1,(a5)			Dir = out towards edge
.gttk0	btst	#4,CIAAPRA-CIABPRB(A5)	Are we at track 0?
    beq.s	.gottk0
.wtrdy	BTST	#5,CIAAPRA-CIABPRB(A5)	Drive ready?
    bne.s	.wtrdy			Wait until it is
    bclr	#0,(a5)			Set step
    nop
    nop
    nop				Wait a few cycles
    bset	#0,(a5)			Clear step
    move.w	#StepDel,D0	NAUGHTY – should use CIAs!
.stpdel	dbf	d0,.stpdel		Step delay
    bra.s	.gttk0			Repeat until we get to track 0
.gottk0	bsr	GetHash			Calculate filename’s hash value
    move.w	#880,d0			Root block no. in d0
    bsr	ReadSec
    tst.l	d7			Was there an error?
    bne	DoneAll			Clear up and return if so
    move.w	18(a6),d0		Filename’s hash offset into d0
    move.l	(a3,d0.w),d0		Get no. of file header block
    beq	DoneAll			If no file, clear up and return
.hshchn	bsr	ReadSec			Read sector
    tst.l	d7			Was there an error?
    bne.s	DoneAll			If so clear up, return
    lea	$1B0(a3),a2		a2 = pointer to filename in block
    moveq	#0,d0			Byte -> word
    move.b	(a2)+,d0		Get name length byte
    cmp.w	16(a6),d0		Compare with wanted filename length
    beq.s	.sameln			Go on if same lengths
.wrongF	move.l	$1F0(A3),d0		Get next hash chain
    beq.s	DoneAll			If none, file not found – return
    bra.s	.hshchn			Otherwise follow down the hash chain
.sameln	subq.w	#1,d0			Length -1 for dbf
    move.l	12(a6),a1		Required filename ptr. in a1
.letlop	move.b	(a2)+,d1		Get byte from current file’s name
    cmp.b	#”a”-1,d1		Test case (badly)
    ble.s	.isupr			Go on if upper case
    sub.b	#32,d1			Else convert to upper case
.isupr	cmp.b	(a1)+,d1		Compare with required filename
    bne.s	.wrongF			If different, wrong file
    dbf	d0,.letlop		Repeat to compare all letters
.loadlp	move.l	$10(a3),d0	Get first/next data block
    beq.s	DoneAll		If none, clean up and return
    cmp.w	#1759,d0	Above valid range?
    bgt.s	DoneAll		If so, clean up and return
    bsr.s	ReadSec		Otherwise load it
    tst.l	d7		If there was an error
    bne.s	DoneAll		then clear up and return
    lea	$200(a3),a0	Get end-of-block pointer in a0
    move.l	$14(a3),d1	Get checksum long
    clr.l	$14(a3)		Clear same long in block
    move.l	a3,a1		Copy block pointer to a1
    moveq	#0,d0		Clear sum
.sumlop	add.l	(a1)+,d0	Add long to sum
    cmp.l	a0,a1		At end of block
    blt.s	.sumlop		Sum all longs
    neg.l	d0		Negate sum
    eor.l	d0,d1		Compare with stored sum
    bne.s	DoneAll		If checksum fails, clean up and return
    move.l	$c(a3),d0	Get no. of bytes in this block in d0
    subq.w	#1,d0		Prepare for dbf
    lea	$18(a3),a1	Get pointer to data in a1
    move.l	20(a6),a0	Get address to load at in a0
.cpbyte	move.b	(a1)+,(a0)+	Copy data as bytes
    dbf	d0,.cpbyte	Repeat
    move.l	a0,20(a6)	Store new load address
    bra.s	.loadlp		Carry on loading
; Routine to switch off motors and return
DoneAll	move.b	#%11111111,(a5)		Select everything
    move.b	#%10000111,(a5)		All motors off
    move.b	#%11111111,(a5)		Left off
    movem.l	(sp)+,d0-d7/a0-a6	Restore registers
    rte				Return
; Routine to read a sector (in d0) from the disk
; Pointer to the loaded sector is returned in a3
ReadSec	tst.w	10(a6)			Check buffer status
    bmi.s	L701E6			Leave alone if negative
    move.w	#1,10(A6)		Otherwise set to 1 (pointless)
L701E6	moveq	#0,d7			d7 is error flag, none yet
    move.w	d0,6(a6)		Store sector to load in vars
    ext.l	d0			word -> long
    divu	#11,d0			sector number…
    swap	d0			…mod 11
    move.w	d0,8(a6)		gives sector on track, store in vars
    swap	d0			recover division result
    move.l	d0,d1			Copy to d1
    lsr.w	#1,d1			Get cylinder no. in d1.w
    tst.w	10(a6)			Is there a track in the buffer?
    bpl.s	.nedred			If not, will have to read one
    cmp.w	2(a6),d1		Is it the right cylinder?
    bne.s	.nedred			If not, will have to read one
    move.w	d0,d2			Copy track no. to d2
    and.w	#1,d2			Mask to get side
    cmp.w	4(a6),d2		Is the right side in the buffer?
    beq	L7036E			If so, buffer is prepared
.nedred	bset	#2,(a5)			Select side 0
    clr.w	4(a6)			Flag side 0 in vars
    btst	#0,d0			See which side is required
    beq.s	.sideok			Go on if 0; side is correct
    move.w	#1,4(a6)		Flag side 1 in vars
    bclr	#2,(a5)			Select side 1
.sideok	move.w	d1,d0			Copy d0 to d1
    bsr	GetTkd0			Go to that track
    move.w	#$7F00,ADKCON(a4)	Clear top byte of ADKCON
    move.w	#$9500,ADKCON(a4)	MFM, no precomp, wordsync, FAST(MFM)
    move.w	#$4489,DSKSYNC(a4)	Standard sync
    move.l	#$23600,a3		Get buffer pointer
    move.l	#$55555555,d6		Get clock value in d6
.fndlst	move.l	a3,a1			Copy buffer pointer to a1
    move.w	#2,INTREQ(a4)		Clear disk interrupt request
    move.l	a3,DSKPTH(a4)		Set disk buffer
.watrdy	btst	#5,CIAAPRA-CIABPRB(a5)	Disk ready?
    bne.s	.watrdy			Wait until it is
    move.w	#$8210,DMACON(a4)	Disk DMA on
    move.w	#$8008,DSKLEN(a4)
    move.w	#$8008,DSKLEN(a4)	Read len = sector info only
.wtdkdn	btst	#1,INTREQR+1(a4)	Disk DMA done interrupt?
    beq.s	.wtdkdn			Wait until one occurs
.skpsnc	cmp.w	#$4489,(a1)+		Compare syncs at (buffer+)
    beq.s	.skpsnc			Keep going until past
    subq.l	#2,a1			a1 points to last sync
    move.l	(a1),d0
    move.l	4(a1),d1		Get longs of sector info
    and.l	d6,d0
    and.l	d6,d1			Mask with clock
    add.l	d0,d0			Shift first one left
    or.l	d0,d1			Recombine
    cmp.b	#1,d1			Just before track gap?
    bne.s	.fndlst			If not keep looking for last sector
    move.l	a3,DSKPTH(a4)		Set buffer pointer again
    move.w	#$8210,DMACON(a4)	Ensure disk DMA is still on
    move.w	#$9770,DSKLEN(a4)
    move.w	#$9770,DSKLEN(a4)	Now read whole track
    move.w	#2,INTREQ(a4)		Clear disk DMA done int. request
    move.l	#$186A0,d1		d1 = quite a long time
.wtdmad	subq.l	#1,d1			Count down
    bne.s	.notstk			Go on if not end of count
    not.l	d7			Else flag an error
    move.w	#$4000,DSKLEN(a4)	Stop disk DMA
    rts				Return
.notstk	btst	#1,INTREQR+1(A4)	Disk DMA done interrupt?
    beq.s	.wtdmad			If not, keep counting
    move.w	#$4000,DSKLEN(a4)	Stop disk DMA
    moveq	#10,d5		11 sectors to decode
    move.l	a3,a2		Put them back over the buffer
    move.l	a3,a1		Save buffer pointer for later
.seclop	move.w	#$3ff,d0	Amount of space to look for sync in
.fndsnc	cmp.w	#$4489,(a3)+	Look for sync
    beq.s	.gotsc		Go on if found it
    dbf	d0,.fndsnc	Keep trying
    not.l	d7		If sync missing, flag error
    rts			and return
.gotsc	cmp.w	#$4489,(a3)	Looking at sync?
    bne.s	.skpsnk		If not, have passed it
    addq.l	#2,a3		Otherwise skip over it
.skpsnk	movem.l	(a3)+,d0-d1	Get two longs
    and.l	d6,d0
    and.l	d6,d1		And them with clock
    add.l	d0,d0		Shift first one left
    or.l	d1,d0		Recombine
    lsr.w	#8,d0		Shift right for sector number
    move.w	d0,(a2)+	Store sector number over buffer
    lea	$30(a3),a3	Skip sector info; a3 points to data
    moveq	#$7f,d2		128 longs of data to decode
.decdat	move.l	$200(a3),d1	Get second long of data
    move.l	(a3)+,d0	Get first long of data
    and.l	d6,d0
    and.l	d6,d1		And them with clock
    add.l	d0,d0		Shift first one left
    or.l	d1,d0		Recombine
    move.l	d0,(a2)+	Store over buffer again
    dbf	d2,.decdat	Repeat for all data
    dbf	d5,.seclop	Repeat for all sectors
; Track is now decoded as sectorno.w, data.b repeated 11 times
; Now bubblesort the sectors into order
.bubble	move.l	a1,a2		Get buffer pointer again
    moveq	#9,d0		10 (sector and next sector)s to compare
    moveq	#0,d1		d1 is count of sectors swapped
.cmpsec	move.w	(a2),d2		Get no. of current sector in d2
    cmp.w	$202(a2),d2	Compare with no. of next sector
    blt.s	.sortok		If less, go on
    move.l	a2,a3		Copy current sec. pointer to a3
    move.w	#$100,d2	One sector + sector no. words to swap
.swpwrd	move.w	$202(a3),d3
    move.w	(a3),$202(a3)
    move.w	d3,(a3)+	Swap a word of sector data
    dbf	d2,.swpwrd	Repeat
    addq.w	#1,d1		Inc. no. of sectors swapped
.sortok	lea	$202(a2),a2	Get next sector
    dbf	d0,.cmpsec	Repeat for 10 (sector and next sector)s
    tst.w	d1		Did we have to swap anything?
    bne.s	.bubble		If so, try again
    lea	2(a1),a2	a2 is pointer to first sector data
    moveq	#10,d0		11 sectors to shift back
.seccpy	moveq	#$7f,d1		128 longs of data in each sector
.cpydat	move.l	(a2)+,(a1)+	Copy longs of data back down buffer
    dbf	d1,.cpydat	Repeat for all data
    addq.l	#2,a2		Skip sector no., no longer needed
    dbf	d0,.seccpy	Copy other sectors directly after
; At this point, the track is prepared in the buffer, so we just need
; to return a pointer to the sector in a3
L7036E	move.l	#$23600,a3	Get buffer pointer
    moveq	#9,d0		Constant for shift
    moveq	#0,d1		word -> long
    move.w	8(a6),d1	Sector no. on track .w into d1
    asl.l	d0,d1		d1 $xx ones
; stores result in variables
GetHash	move.l	a0,12(a6)	Store filename in vars
    move.l	a0,a1		Copy to a1
    moveq	#0,d0		Clear length counter
.getlen	tst.b	(a1)+		End of filename?
    beq.s	.gotlen		Go on if so
    addq.w	#1,d0		Else increase length counter,
    bra.s	.getlen		repeat
.gotlen	move.w	d0,d1		Copy filename length to d1
    move.w	d0,16(a6)	Store filename length in vars
    subq.w	#1,d1		Prepare d1 (filename len) for dbf
.hshlop	mulu	#13,d0		d0 = filename length * 13
    moveq	#0,d2		Clear d2 for byte -> word
    move.b	(a0),d2		Get letter of filename
    cmp.b	#”a”-1,d2	Test case (badly)
    ble.s	.letok		If less or equal, is upper case
    sub.b	#32,d2		Otherwise sub 32 to make it upper case
.letok	move.b	d2,(a0)+	Store back in filename
    add.w	d2,d0		Add to hash total in d0
    and.w	#$7ff,d0	Keep d0 in range
    dbf	d1,.hshlop	Repeat for all bytes of filename
    divu	#72,D0		Hash total…
    swap	d0		…mod 72…
    addq.w	#6,d0		…plus 6…
    asl.w	#2,D0		…times 4
    move.w	d0,18(a6)	store in variables
    rts
; Routine to put the number in d0 into the filename at a0 (“$xx”)
MkName	move.w	d0,d1		Copy fileno. to d1
    move.w	d1,d2		and d2
    lsr.w	#4,d2		d2 is upper nibble
    bsr.s	D2toHex		convert to hex ascii
    move.b	d2,1(a0)	store as first digit of filename
    move.w	d1,d2		move lower nibble into d2
    bsr.s	D2toHex		convert to hex
    move.b	d2,2(a0)	store as second nibble
    rts			return
; Routine to convert d2 into hex ascii
D2toHex	and.w	#$f,d2		Only numbers from 0-15
    add.w	#”0″,d2		Convert to ascii
    cmp.w	#”9″,D2		letter or number?
    ble.s	.digit		return if number
    addq.w	#7,d2		else add 7 to convert to letter
.digit	rts			return
Variables:	dc.w	0		 0 = .w
        dc.w	0		 2 = Current track .w
        dc.w	0		 4 = Side in buffer (0/1) .w
        dc.w	0		 6 = sector to load .w
        dc.w	0		 8 = sector no. on track .w
        dc.w	0		10 = Valid track in buffer .w
        dc.l	0		12 = Pointer to filename .l
        dc.w	0		16 = Length of filename in bytes .w
        dc.w	0		18 = filename’s hash offset .w
        dc.l	0		20 = Address to load at .l
Filename	dc.b	“$00″,0		Filename to load

#amiga #cracking #loaders


<-- Spiv’s File Loader | [ Code ] | Alpha One’s Track loader -->