**MFM TRACK LOADER (V1.6)
**EARLY VERSIONS CODED BY NEGATIVE ACTION OF KILLERS !
**NOW ++OMICRON++ OF WIZZCAT !
** ASSEMBLED USING DEVPAC2.14

**PUT ONTO BOOTBLOCK USING UTIL. SUCH AS BOOTWRITER

**CALL PARAMETERS :-	(TRAP #1 TO ACTIVATE !)

** D0=START CYLINDER
** D1=NUMBER OF CYLINDERS
** D2=MFM BUFFER (RESERVE $5000 BYTES !)
** A0=DESTINATION ADDRESS

** INITIAL PARAMETERS :-
** MFMD=INITAL MFM BUFFER ADDRESS
** SYSBASE=LOADER BASE ADDRESS/STACK ADDRESS (SUGGESTED =<$1000)
** INITIALLOAD=ADDRESS TO LOAD INITIAL DATA + INITIAL JUMP
** STARTCYL/NUMCYL=START CYLINDER+NUMBER TO LOAD
** ISR=INITAL STATUS REGISTER

	section	loader2,code_c
	opt	c-,d-

time=2148				a bit more than 3 milliseconds !
mfmd=$7b000				Set buffer to $7b000
sysbase=$400				$400 for stack+loader code (+TRAP1)
initialload=$1000			Initial load+jump address
startcyl=62				Start cylinder
numcyl=8				Number of cylinders to load
ISR=$2000				Supervisor + Enable all Ints.


intreqr	EQU	$01E
dskpt	EQU	$020
dsklen	EQU	$024
dsksync	EQU	$07E
dmacon	EQU	$096
intena	EQU	$09A
intreq	EQU	$09C
adkcon	EQU	$09E
bplcon0	EQU	$100
color	EQU	$180

**BOOT STUFF !!
	dc.b	"DOS",0
	ds.l	1
	dc.l	$370

bootstart
	lea	bootem(pc),a0
	move.l	a0,$20.w
bootem	move.w	#ISR,sr
	bsr	loadreg
	move.w	#$7fff,d0
	move.w	d0,intena-$24(a5)
	move.w	d0,dmacon-$24(a5) 	no ints. or dma
	move.w	d0,adkcon-$24(a5)	clear disk control !!
	move.b	#$08,$e00(a3)		one-shot mode
	move.w	#$9500,adkcon-$24(a5)	set prefs for disk
	move.w	#$4489,dsksync-$24(a5)	standard sync
	bset	#1,(a3)			set LED

	bsr	activatedrive
.loop1	btst	#4,(a3)			track 0 ?
	beq.s	setupdma
	bsr	headsout		step heads out
	bra.s	.loop1
setupdma
	moveq	#0,d1
	move.w	d1,bplcon0-$24(a5)	no colors !!
	lea	$140-$24(a5),a0
	moveq	#16,d0
.nosprt	move.l	d1,(a0)+
	dbra	d0,.nosprt		clear sprites & color0 !!

	lea	mainloader(pc),a0
	lea	sysbase,a1		loader base address
	move.l	a1,$84.w
	move.l	a1,a7
	moveq	#(loaderend-mainloader)/4,d0
.copydown
	move.l	(a0)+,(a1)+		copy
	dbra	d0,.copydown

	lea	startloader(pc),a0
	move.l	a1,a2
	moveq	#mainloader-startloader-1,d0 not to overwrite !
.copyinit
	move.b	(a0)+,(a1)+
	dbra	d0,.copyinit
	jmp	(a2)

startloader
	lea	initialload,a0		load address
	moveq	#startcyl,d0		start cylinder
	moveq	#numcyl,d1		number of cylinders
	move.l	#mfmd,d2		mfm address !
	trap	#1			load tracks
	jmp	(a0)			into progy !!

mainloader
	movem.l	d0-d7/a0-a6,-(sp)	save all regs.
	bsr	loadreg			load my regs.
	movem.l	d2/a0,mfm(a4)		mfm maddress + dest address !

	bsr.s	activatedrive

	bsr	step			step heads to cylinder
	bsr.s	readendecode		read cylinders + decode 'em
	bsr.s	drivesoff

	movem.l	(sp)+,d0-d7/a0-a6
	rte				return

drivesoff
	move.b	#$f9,(a6)
	move.b	#$f1,(a6)
	rts

activatedrive
	move.b	#$79,(a6)		all drive bits on high !!
	move.b	#$71,(a6)
	bsr	waitdrive
	rts

readendecode
	bset	#2,(a6)		read head 0 !
	bsr.s	loaderror
.error1	bsr.s	checkerror
	bsr.s	read
	bsr.s	decode
	bne.s	.error1
	bclr	#2,(a6)		read head 1 !
	bsr.s	loaderror
.error2	bsr.s	checkerror
	bsr.s	read
	bsr.s	decode
	bne.s	.error2

	cmp.w	#79,(a4)	are we on track 79 !!
	beq.s	exitl		yes then exit !!
	addq.w	#1,(a4)		add 1 to track !

	bsr	headin
	subq.w	#1,d0		tracks to read
	bne.s	readendecode
exitl	rts
loaderror
	move.w	#11,error(a4)
	rts

checkerror
	subq.w	#1,error(a4)
	bne.s	exitl
	bsr.s	drivesoff
	moveq	#-1,d0
.loop	move.w	d0,$180-$24(a5)
	dbra	d0,.loop
.hold	bra.s	.hold

read
	move.w	#$8210,dmacon-$24(a5)	enable disk dma
	move.l	mfm(a4),dskpt-$24(a5)	destination
	move.w	#$4000,d6
	move.w	d6,(a5)
	move.w	#$9900,d3
	move.w	d3,(a5)
	move.w	d3,(a5)			read 7000 mfm words
	moveq	#$2,d7
	move.w	d7,intreq-$24(a5) clear DISK BLOCK DONE interupt request
.waitblock
	move.w	intreqr-$24(a5),d1
	and.w	d7,d1
	beq.s	.waitblock		test for DISK BLOCK DONE,wait till read
	move.w	d6,(a5)			no more dma
	move.w	#$10,dmacon-$24(a5)
	rts

decode
	move.l	#$55555555,d3	mask off in d3
	move.l	mfm(a4),a0
	lea	$4f00(a0),a1	store track table address !
	move.l	a1,-(sp)
	move.w	#$4489,d6	standard sync !!
	moveq	#10,d7		11 sectors

.loop0	cmp.w	(a0)+,d6
	bne.s	.loop0
	cmp.w	(a0),d6		2nd sync ?
	beq.s	.loop0		found branch
.loop2	move.l	a0,a2
	movem.l	(a0),d1-d2	info part
	and.l	d3,D1
	and.l	d3,d2
	add.l	d1,d1
	or.l	d2,d1		decode block info
	lsr.w	#8,d1
	move.w	d1,(a1)+	save sector
	lea	44(a0),a0	block checksum
	move.l	(a0)+,d5	block checksum in d5

	moveq	#9,d1		byte count
.bc	move.l	(a2)+,d4
	eor.l	d4,d5		eor with checksum
	dbra	d1,.bc		calculate header checksum
	and.l	d3,d5		mask clock bits
	bne.s	loadreg		return on error

	addq.l	#4,a0		align for data checksum
	move.l	(a0)+,(a1)+	data checksum !!
	move.l	a0,(a1)+	and address of data
	lea	1024(a0),a0	next sector
	dbra	d7,.loop0	for all tracks

	move.l	current(a4),a1	address of decoded data
	move.l	(sp)+,a0	restore track table !
	moveq	#$A,d7		11 sectors
.loop3	move.w	(a0)+,d1	sector
	moveq	#9,d2
	lsl.w	d2,d1		multiply by 512
	lea	0(a1,d1.w),a3	multiply by 1 sector and save address

	movem.l	(a0)+,d2/a2	checksum + start of data
	lea	512(a2),a5	next set of datas
	moveq	#512/4-1,d4
.dcode	move.l	(a2)+,d5	data
	move.l	(a5)+,d6	data
	eor.l	d6,d2
	eor.l	d5,d2		fix data checksum !!

	and.l	d3,d5
	and.l	d3,d6
	add.l	d5,d5
	or.l	d6,d5
	move.l	d5,(a3)+	save data
	dbra	d4,.dcode	continue
	and.l	d3,d2		mask checksum
	bne.s	loadreg		if sum is ok then branch
.sumok	dbra	d7,.loop3
	add.l	#512*11,current(a4)
	bsr.s	loadreg
	moveq	#0,d7		clear error
	rts

loadreg
	lea	$bfe001.l,a3
	lea	data(pc),a4
	lea	-$f01(a3),a6
	lea	$dff024.l,a5
	rts


step	move.w	(a4),d2		current track
	exg	d0,d1		swap !
	move.w	d1,(a4)		start track
	sub.w	d2,d1		subtract to get number of tracks to skip
	bmi.s	headout		step heads out if difference is negative
	beq.s	.ret1		0, then there already
.loop0	bsr.s	headin		step heads in
	subq.w	#1,d1
	bne.s	.loop0
.ret1	rts

headout
.loop0	bsr.s	headsout
	addq.w	#1,d1		for loop
	bne.s	.loop0
	rts

waitdrive
.loop0	btst	#5,(a3)
	bne.s	.loop0		drive ready ?, no wait
	rts

headin
	bclr	#1,(a6)
	bra.s	stepit
headsout
	bset	#1,(a6)
stepit
	moveq	#0,d6
	bclr	d6,(a6)
	bset	d6,(a6)
	move.b	#$7f,$d00(a3)
	move.b	#time&$ff,$400(a3)
	move.b	#time>>8,$500(a3)	set timer lo/hi & start timer
.busy	btst	d6,$d00(a3)		wait for timer interupt
	beq.s	.busy			busy then back !
	rts

	rsreset
track	rs.w	1
mfm	rs.l	1
current	rs.l	1
error	rs.w	1

data	ds.w	1
loaderend
	end
