
* EXAMPLE OF USE!

	move.w #$4000,$dff09a	;Disable Irqs....

	jsr INIT_DISK		;set up

	move.l #loadspace,a6	;Address of load
	move.l #$10000,d6		;Bytes to load
	move.w #880,d7		;Start block
	jsr Block_load

	tst.w d7			;check for failure
	beq.s fileok

	move.w #$7fff,d0		;red screen = error 
erlp	move.w #$f00,$dff180
	dbf d0,erlp

fileok	jsr motor_off
	move.w #$c000,$dff09a
	rts

loadspace dcb.l $8000,$00

*****************************************************************************

            *     System Independant Block Loader - V1.1 26/4/94   *
            *------------------------------------------------------*

                    * By PHIL RUSTON AKA:PHIL!94/LSD *

* Call "INIT_DISK" before loading for the 1st time!!

* To LOAD A FILE Set:-

* A6 - Destination Address.
* D6 - Bytes to load.
* D7 - Starting Block.

* Then call: "BLOCK_LOAD" - All registers preserved except D7

* D7 returns as 00 is load OK. Else one of the following errors:

* 01 = No speed signal from motor   (disk ejected whilst loading?)
* 02 = No DMA transfer time out     (bad disk / ''             '')
* 03 = No disk in drive.            (Obvious)
* 04 = Can't find that disk block   (disk corrupt)
* 05 = Wrong track marker ID        ('')
* 06 = Checksum error on disk block ('')
* 07 = Block number out of range    (>$6df)

* Call "MOTOR_OFF" when finished loading for a while!!

*******************************************************************************

	section loadcode,code

DRIVE equ 0


INIT_DISK	movem.l d7/a1/a2,-(a7)
	move.l #$bfd000,a1
	move.l #Variables,a2
	bsr motor_off
	bclr #drive+3,$100(a1)
	bsr initialize_drive
	bsr motor_off
	movem.l (a7)+,d7/a1/a2
	rts

BLOCK_LOAD
	movem.l d0-d6/a0-a6,-(a7)
	move.l #$dff000,a0
	move.l #$bfd000,a1
	move.l #Variables,a2
	moveq #0,d0
	move.w d7,d0
	subq.l #1,d6   
nxt_blk	bsr get_block
	tst.b error(a2)
	bne.s Load_done
	tst.l d6			;Byte countdown ended?
	bmi.s load_done
	addq.w #1,d0
	bra nxt_blk

load_done	tst.b error(a2)		;Disk removed handler.
	beq.s no_error
	bsr motor_off
	move.w #1000,d7		
	bsr cia_wait

no_error	moveq #0,d7
	move.b error(a2),d7
	movem.l (a7)+,d0-d6/a0-a6
	rts


MOTOR_OFF	movem.l d7/a1-a2,-(a7)
	move.l #$bfd000,a1
	move.l #variables,a2
	clr.b motor(a2)
	move.b #$ff,$100(a1)
	move.b #$87,$100(a1)
	bsr wait1msec
	move.b #$ff,$100(a1)
	movem.l (a7)+,d7/a1-a2
	rts

*****************************************************************************

*************
* Get Block *
*************

* D0 will equal block number required ($0 - $6df)

Get_block	cmp.w #$6df,d0		;check block is range
	bls.s blockinrange
	move.b #$7,error(a2)
	bra No_reload

Blockinrange

	move.w #$0503,attempts(a2)
	move.l d0,d1		
	divu #11,d1		;what cylinder is that on?
	tst.b motor(a2)
	beq.s reload

	cmp.b trackside(a2),d1	
	beq.s Trksde_in		;that track is already in.

Reload	bsr Fetch_trackside		;loads MFM track required
	tst.b error(a2)
	bne No_reload

Trksde_in	clr.b error(a2)		;find a sector
	swap d1			;get sector number lo.
	move.l #MFMbuffer,a3
	lea $31fe(a3),a5
find_sync	move.w #$4489,d7
fs_loop	cmp.w (a3)+,d7
	beq.s found_sync
	cmp.l a5,a3
	bls.s fs_loop
	move.b #4,error(a2)		;couldnt find that sector-error 4
	bra MFM_error

found_sync	

	cmp.w (a3),d7		;2 syncs?
	beq.s syncstart
	subq.w #2,a3

syncstart	lea $2a(a3),a4		;Check header checksum.
	bsr decode_lw		
	move.l $2(a3),d3
	move.l $6(a3),d4
	andi.l #$55555555,d3
	andi.l #$55555555,d4
	eor.l d4,d3
	cmp.l d3,d5
	bne.s Not_sector

	lea $2(a3),a4		;Track mark = Head position?
	bsr decode_lw
	move.l d5,d4		
	swap d4
	cmp.b trackside(a2),d4
	beq.s Track_mark_ok
	move.b #5,error(a2)		;wrong track mark - error 5
	bra MFM_error

Track_mark_ok

	lsr.w #8,d5		;Is this the sector required?
	cmp.b d5,d1
	beq.s Found_block
	
Not_sector

	add.w #$430,a3      	;loop until find correct sector
	bra.s find_sync

Found_Block
	
	moveq #0,d2		;Transfer converted MFM to dest.
	move.l #$55555555,d7
	lea $3a(a3),a4		
	lea $23a(a3),a5
	move.l d6,d1		;back up pointers in case of error.
	move.l a6,a3		
	moveq #$7f,d3

conv_lw	move.l (a4)+,d5
	move.l (a5)+,d4
	and.l d7,d5
	and.l d7,d4
	eor.l d5,d2		;update checksum
	eor.l d4,d2
	add.l d5,d5
	or.l d4,d5
	subq.l #4,d6
	bmi.s lst_bytes
	move.l d5,(a6)+
nxt_lw	dbf d3,conv_lw
	bra.s blk_done

Lst_bytes	move.w d6,d4
	addq.w #4,d4		;last bytes
	bmi.s nxt_lw

Lb_loop	rol.l #8,d5
	move.b d5,(a6)+
	dbf d4,Lb_loop
	bra.s nxt_lw
		
blk_done	sub.w #$208,a4		;get data checksum
	bsr decode_lw		
	cmp.l d5,d2
	beq.s no_reload
	move.b #6,error(a2)		;checksum error - error 6
	move.l a3,a6		;restore pointers
	move.l d1,d6

MFM_error	move.l d0,d1		
	divu #11,d1		
	subq.b #1,attempts(a2)
	bne Reload
	bsr initialize_Drive	;reset heads
	move.b #5,attempts(a2)
	subq.b #1,attempts+1(a2)
	bne Reload

No_reload	rts

*****************************************************************************

* MFM Track loader!
* D1 will equal trackside 0 - 159

Fetch_trackside
	
	clr.b error(a2)		
	tst.b motor(a2)
	bne.s motor_on
	move.b #$ff,$100(a1)
	bclr #drive+3,$100(a1)
	bsr wait1msec
	btst #2,$1001(a1)
	bne.s start_mot
	btst #1,trackside(a2)
	beq.s inchk
	bsr stepout
	bra.s stepchk
inchk	bsr stepin
stepchk	btst #2,$1001(a1)
	beq.s no_disk
	bsr initialize_drive
	
start_mot	move.b #$7f,$100(a1)	;drive selected / motor on.
	bclr #drive+3,$100(a1)
	move.b #1,motor(a2)
	move.w #200,d2		;wait for correct motor speed.
wdskrdy	moveq #10,d7
	bsr cia_wait		
	btst #5,$1001(a1)		
	dbeq d2,wdskrdy
	tst.w d2
	bpl motor_on
	move.b #1,error(a2)		;no speed signal - error 1
	bra trackload_end

motor_on	btst #2,$1001(a1)		;disk removed?		
	bne.s disk_in
no_disk	move.b #3,error(a2)
	bra trackload_end

disk_in	move.w d1,d3
	lsr.b #1,d3		;select disk side to load from.
	bcc.s head1
	bclr #2,$100(a1)
	bra.s checkhead
head1	bset #2,$100(a1)

checkhead	move.b trackside(a2),d2	;ensure head is over correct
	lsr.b #1,d2		;track
	cmp.b d2,d3
	beq.s headok
	bls.s seekout
	bsr stepin
	bra.s checkhead 
seekout	bsr stepout	
	bra.s checkhead

headok	move.b d1,trackside(a2)
	move.w #$2,$9c(a0)		;clear disk block irq
	moveq #18,d7		;settle wait.
	bsr cia_wait

	move.l #mfmbuffer,$20(a0)
	move.w #$4000,$24(a0)	
	move.w #$8010,$96(a0)	;enable dma
	move.w #$6800,$9e(a0)	
	move.w #$9500,$9e(a0)
	move.w #$4489,$7e(a0)	;sync
	move.w #$9900,$24(a0)	
	move.w #$9900,$24(a0)	

	move.w #200,d2
waitdirq	moveq #10,d7
	bsr cia_wait		
	btst #1,$1f(a0)		
	dbne d2,waitdirq
	tst.w d2
	bpl.s read_ok
	move.b #2,error(a2)		;No DMA finish-Time Out-error 2

read_ok	move.w #$4000,$24(a0)	
	move.w #$10,$96(a0)		;disable dma

Trackload_end

	rts

*******************************************************************************

decode_lw	move.l #$55555555,d7	;decode two consec mfm longwords
	move.l (a4),d5		;into d5
	move.l $4(a4),d4	
	and.l d7,d5	
	and.l d7,d4
	add.l d5,d5
	or.l d4,d5		
	rts

stepout	subq.b #2,trackside(a2)
	bset #1,$100(a1)
	bra.s step

stepin	addq.b #2,trackside(a2)
	bclr #1,$100(a1)
step	bsr.s shortwait
	bclr #0,$100(a1)
	bsr.s shortwait
	bset #0,$100(a1)
	moveq #4,d7
	bsr cia_wait
	rts

shortwait	nop
	nop
	nop	
	nop	
	rts

initialize_drive

	btst #$4,$1001(a1)		
	beq.s gottrack0
	bsr.s stepout
	bra.s initialize_drive

gottrack0	clr.b trackside(a2)	
	move.w #20,d7
	bsr cia_wait
	rts

wait1msec	moveq #1,d7
	
cia_wait	move.b #$08,$f00(a1)	;set one shot / stop timer.
	move.b #$cc,$600(a1)	;set timer lo
	move.b #$02,$700(a1)	;set timer hi (starts counter)
ciawlp2	btst #0,$f00(a1)		;wait for ciab timer b to timeout
	bne.s ciawlp2
	subq.w #1,d7
	bne.s cia_wait		;d7 = milliseconds to wait.
	rts

*******************************************************************************

attempts     equ $0
trackside    equ $2
error    	   equ $3
motor        equ $4

variables	dcb.w $3,$0

	section chipstuff,data_c

mfmbuffer	dcb.w $1910,$0000

*******************************************************************************

