
	section	ddp,code_c

	opt	d+
	
headspeed	= 3
time	= 716*headspeed	; ? miliseconds - head step rate
				
load	= 14		; trap number to nondos load

	; this loader is a byte loader not a track loader
	; as so the data loaded may not be in the place you 
	; requested but slightly higher up, the address the
	; data was loaded into is returned in A0.
	; NOTE: the loader loads 2 more tracks then requried to
	; allow for sector offsets, so make sure your buffer is
	; big enough!

	; the id for the disk is located at the 14,15,16,17 bytes
	; of the bootblock. (see bootblock.s for info)

	; the address to load data into doesn't need to be in chipmem
	; but "workspace" does!!


	lea	loadtracks(pc),a0
	move.l	a0,$80+(4*load)
	move.w	#-1,current_track

	move.l	disk1name,d0	; id of disk 2 search for
	bsr	search_for_disk	; find the disk
				; routine will not return
				; until disk has been inserted
	

	move.l	#space,a0		; load address
	move.l	#120*11*512,d0	; disk address (as trackdisk.device)
	move.l	#5*11*512,d1	; length
	move.l	#0,d7		; mfm load
	trap	#load

	cmp.b	#120,3(a0)
	bne	Error

	move.l	#space,a0		; load address
	move.l	#102*11*512,d0	; disk address (as trackdisk.device)
	move.l	#5*11*512,d1	; length
	move.l	#0,d7		; mfm load
	trap	#load

	cmp.b	#102,3(a0)
	bne	Error

	move.l	#space,a0		; load address
	move.l	#140*11*512,d0	; disk address (as trackdisk.device)
	move.l	#5*11*512,d1	; length
	move.l	#0,d7		; mfm load
	trap	#load

	cmp.b	#140,3(a0)
	bne	Error

	clr.l	d0
	rts

Error:	move.l	#-1,d0
	rts

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

show_insert_pic:
	move.w	#$ffff,d0
.loop	move.w	$dff006,$dff180
	dbf	d0,.loop
	rts

************************* MFM loader by Shagratt/LSD ***************************

header_checksum:
	movem.l	d0-d7/a0-a6,-(a7)

	lea	workspace,a4
	lea	12664(a4),a5

	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	bsr	checksums
	cmp.l	#0,d5
	
	movem.l	(a7)+,d0-d7/a0-a6
	clr.l	d5
	rts
	
.bad_read	movem.l	(a7)+,d0-d7/a0-a6
	move.l	#-1,d5
	rts	

********************************************************************************	
	
checksums:	cmp.w	#$4489,2(a4)
	bne	.not_header	

	move.w	#$28,d1		; calc block checksum
	lea	4(a4),a0
	bsr	calc_checksum

	move.l	48(a4),d3		; orig block checksum
	and.l	#$55555555,d3

	cmp.l	d0,d3
	bne	_bad
	
	lea	60(a4),a0		; calc data checksum
	move.w	#$400,d1
	bsr	calc_checksum

	move.l	56(a4),d3		; orig data checksum
	and.l	#$55555555,d3

	cmp.l	d0,d3
	bne	_bad

	clr.l	d5
	add.l	#1088,a4
.loop1	cmp.w	#$4489,(a4)
	beq	.not_gap_mark1
	add.l	#2,a4
	bra	.loop1
	
.not_gap_mark1
	rts

.not_header
	move.w	#$28,d1		; calc block checksum
	lea	2(a4),a0
	bsr	calc_checksum

	move.l	46(a4),d3		; orig block checksum
	and.l	#$55555555,d3

	cmp.l	d0,d3
	bne	_bad

	lea	58(a4),a0		; calc data checksum
	move.w	#$400,d1
	bsr	calc_checksum

	move.l	54(a4),d3		; orig data checksum
	and.l	#$55555555,d3

	cmp.l	d0,d3
	bne	_bad

.ok	move.l	#0,d5
	add.l	#1086,a4
.loop2	cmp.w	#$4489,(a4)
	beq	.not_gap_mark2
	add.l	#2,a4
	bra	.loop2
	
.not_gap_mark2
	rts

_bad	move.l	#-1,d5
	rts
	
calc_checksum:
	lsr.w	#2,d1
	subq.w	#1,d1
	moveq	#0,d0
.loop	move.l	(a0)+,d2
	eor.l	d2,d0
	dbf	d1,.loop
	and.l	#$55555555,d0
	rts

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

search_for_disk:
	move.l	d0,looklabel

sfd_loop:
	move.b	#0,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	move.b	#1,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	move.b	#2,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	move.b	#3,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	bsr	show_insert_pic
	
	bra	sfd_loop	

found_disk:	clr.l	d0
	rts

get_volume_name:
	move.l	#0,label
	lea	$bfd000,a5
	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mini_pause
	bclr	#7,$100(a5)		; motor on
	bsr	mini_pause
	move.b	drive,d6
	add.b	#3,d6
	bclr	d6,$100(a5)		; select drive
	bsr	mini_pause
	
	move.w	#900/headspeed,d7

.volloop	bsr	mspause
	btst	#5,$1001(a5)	; drive ready 
	beq	.is_ready
	dbf	d7,.volloop

.not_ready	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mini_pause

	move.b	#$ff,d0
	move.b	drive,d6
	add.b	#3,d6
	bchg	d6,d0
	move.b	d0,$100(a5)		; select drive
	bsr	mini_pause

	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mini_pause
	
	move.l	#-1,d0
	rte

.is_ready	move.b	#-1,current_track

	move.l	#volumespace,a0	; load address
	move.l	#$000000,d0		; disk address (as trackdisk.device)
	move.l	#$400,d1		; length
	move.l	#0,d7		; mfm load
	trap	#load
	move.l	14(a0),label
	move.l	14(a0),d0
	rte

mini_pause:	rts

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

loadtracks:	cmp.l	#1,d7
	beq	get_volume_name

	movem.l	d0-d7/a1-a6,-(sp)

	move.l	a0,loadaddress
	move.l	d0,diskaddress
	move.l	d1,loadlength
	
	lsr.l	#7,d1
	lsr.l	#2,d1		; div by 512

	divu	#11,d1		; number of tracks
	and.l	#$ffff,d1
	add.w	#1,d1
	cmp.l	#$2c00,loadlength
	blt	.short_load
	add.w	#1,d1
.short_load
	
	lsr.l	#7,d0		
	lsr.l	#2,d0		; div by 512	
	divu	#11,d0
	and.l	#$ffff,d0

	move.w	d0,temp
	
				; d0=track
				; d1=number of tracks
	lea	workspace,a4	; workspace
	lea	$bfd000,a5		; base address of cia
	lea	$dff000,a6		; base address of hardware
	move.l	#$55555555,d7	; data mask - for mfm decoding

	move.b	$1f01(a5),d6
	and.b	#%11000000,d6
	or.b	#%00001000,d6
	move.b	d6,$1f01(a5)
	move.b	#%00000010,$1d01(a5)
	move.b	#(time&$ff),$1601(a5)
	move.b	#(time>>8),$1701(a5)

	move.w	#$4489,a1		; disk sync
	bsr	load2
	
	clr.l	d2
	move.w	temp,d2		; track number
	move.l	loadaddress,a0
	move.l	diskaddress,d0
	move.l	loadlength,d1
	
	mulu	#11,d2
	asl.l	#7,d2
	asl.l	#2,d2
	
	sub.l	d2,d0
	add.l	d0,a0		; a0 = data start address

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

load2:	subq.w	#1,d1
	bpl	.ok
	rts

.ok	bsr	find_track
	
read_tracks:

	bsr	readdata
	cmp.l	#0,d5
	bne	skip
	
	move.l	a4,a2
	moveq	#10,d6

find_sync:	cmp.w	(a2)+,a1
	bne.b	find_sync

	cmp.w	(a2),a1
	bne.b	double_sync

	add.l	#2,a2

double_sync
	move.l	0(a2),d3
	move.l	4(a2),d4
	and.w	d7,d3
	and.w	d7,d4
	lsl.w	#1,d3
	or.w	d4,d3
	asr.w	#8,d3
	
	move.l	a0,a3
	lsl.w	#8,d3
	lsl.w	#1,d3
	add.w	d3,a3
	
	lea	56(a2),a2

	moveq	#127,d2

decode_mfm	
	move.l	$200(a2),d3
	move.l	(a2)+,d4
	and.l	d7,d3
	and.l	d7,d4
	lsl.l	#1,d4
	or.l	d3,d4
	move.l	d4,(a3)+
	dbf	d2,decode_mfm
	dbf	d6,find_sync

skip	lea	$1600(a0),a0
	add.b	#1,d0

	bsr	flip_side

	dbf	d1,read_tracks

finished_blocks:

	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mspause	

	move.b	#$ff,d0
	move.b	drive,d6
	add.b	#3,d6
	bchg	d6,d0
	move.b	d0,$100(a5)		; select drive
	bsr	mspause
	
	move.b	#$ff,$100(a5)	; deselect all drives
	rts	

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

drive_ready:
	btst	#5,$1001(a5)	; drive ready 
	bne.b	drive_ready
	rts

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

readdata:	move.w	#3,retries

load_again:	move.w	#$8500,$9e(a6)	; set bits 8,10 = disk data clock rate 1=fast 
				; word sync to sync ($4489)	
	move.w	a1,$7e(a6)		; set sync to $4489
	bsr	drive_ready

	move.w	#$4000,$24(a6)	; disk length (write disk to ram)
	move.l	a4,$20(a6)		; disk pointer
	move.w	#$98d0,$24(a6)	; disk length($18d0 + set)
	move.w	#$98d0,$24(a6)	; disk length again - must be twice(!!)

	move.w	#2,$9c(a6)		; int req - clear disk blk finished

waitblk:	move.w	$1e(a6),d2		; irq bits read - 
	btst	#1,d2		; disk blk finished
	beq	waitblk

	bsr	header_checksum
	cmp.l	#0,d5
	beq	.ok
	
	sub.w	#1,retries
	bpl	load_again

	move.w	#$ffff,d5
.loop	move.w	$dff006,$dff180
	dbf	d5,.loop
	
	move.l	#-1,d5
.ok	rts

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

mspause:	lea	$bfd000,a5		; base address of cia

	move.b	$1f01(a5),d6
	and.b	#%11000000,d6
	or.b	#%00001000,d6
	move.b	d6,$1f01(a5)
	move.b	#%00000010,$1d01(a5)
	move.b	#(time&$ff),$1601(a5)
	move.b	#(time>>8),$1701(a5)

busy_wait:	btst.b	#1,$1d01(a5)
	beq	busy_wait

	rts

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

flip_side:	add.b	#1,current_track
	bchg	#2,$100(a5)		; change side
	
	btst.b	#0,current_track
	bne	.skip

	bclr	#1,$100(a5)		; direction towards outside

	bclr	#0,$100(a5)		; pulse step low
	bsr	.skip
	bset	#0,$100(a5)		; pulse step high	
	bsr	mspause		; milisecond pause
.skip	rts

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

flip_side_b:
	sub.b	#1,current_track
	bchg	#2,$100(a5)		; change side

	btst.b	#0,current_track
	beq	.skip

	bset	#1,$100(a5)		; direction towards center

	bclr	#0,$100(a5)		; pulse step low
	bsr	.skip
	bset	#0,$100(a5)		; pulse step high	
	bsr	mspause		; milisecond pause
.skip	rts

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

find_track:	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mspause
	
	bclr	#7,$100(a5)		; motor on
	bsr	mspause	
	
	move.b	drive,d6
	add.b	#3,d6
	bclr	d6,$100(a5)		; select drive 0
	bsr	mspause
	bsr	drive_ready

	cmp.b	#-1,current_track
	bne	.seek_rel

	bset	#1,$100(a5)		; direction towards centre

	; look for track 0

.zero	btst	#4,$1001(a5)	; check for track 0	
	beq	.found
	bclr	#0,$100(a5)		; pulse step low
	bsr	.skip
	bset	#0,$100(a5)		; pulse step high	
	bsr	mspause		
	bra	.zero

.found	move.w	#0,current_track

	move.w	d0,d2
	sub.w	#1,d2
	bmi	.skip

	bset	#2,$100(a5)		; select side 0

.track	bsr	flip_side
	dbf	d2,.track

.skip	rts

.seek_rel	and.b	#$fe,current_track	; force to side 0
	bset	#2,$100(a5)		; force to side 0

	moveq	#0,d2
	move.b	current_track,d2
	cmp.w	d2,d0
	blt	.backward
	bgt	.forward
	bra	.zero

.backward	sub.w	d0,d2		; find relitive track
	sub.w	#1,d2		; -1 coz of dbf loop
	
.track_b	bsr	flip_side_b
	dbf	d2,.track_b

	rts

.forward	sub.w	d0,d2		; find relitive track
	not.w	d2		; make pos

.track_f	bsr	flip_side
	dbf	d2,.track_f

	rts

********************************************************************************	
		
	section	stuff_c,data_c

workspace:		ds.b	$3200	; dma buffer for td loader (chipmem)

	section	volspc,data

current_track:	dc.b	-1,0

counter:		dc.l	0
drive:		dc.w	0
temp:		dc.l	0
label:		dc.l	0
looklabel:		dc.l	0
loadaddress:	dc.l	0
diskaddress:	dc.l	0
loadlength:		dc.l	0
retries:		dc.l	0
volumespace:	ds.l	$600	; space for search_for_disk routine

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



       ************** stuff used by demo not loader itself! ***************

	section	stuff_p,data

space:		ds.l	7*11*128

disk1name:		dc.b	"K",0,"TR"

	end
	
