
* Kwikcopy 2.5 - (c) Phil Ruston 27/6/94.

	section kwikcopy,code

********
* Init *
********

	movem.l d0-d7/a0-a6,-(a7)
	
	move.l $4,a6
	jsr -$84(a6)	;Forbid Multitask

	Move.l $4,a6
	move.l #gfxlib.txt,a1
	moveq #0,d0
	jsr -$228(a6)
	move.l d0,a3

	move.l #vars,a2
	move.l $26(a3),orig_copper(a2)

	Move.l $4,a6
	move.l d0,a1
	moveq #0,d0
	jsr -$19e(a6)
	
	move.w #$4000,$dff09a

	move.l #$dff000,a0
	move.l #$bfd000,a1
	move.l #vars,a2
	move.w $1c(a0),orig_inten(a2)
	move.w $1e(a0),orig_intreq(a2)
	move.w $10(a0),orig_adkcon(a2)
	move.w $2(a0),orig_dmacon(a2)
	move.l $68,orig_lev2(a2)
	move.l $6c,orig_lev3(a2)
	move.b $100(a1),orig_bfd100(a2)
	move.b $1001(a1),orig_bfe001(a2)
	move.b $1f01(a1),orig_cr1(a2)
	move.b #$10,$1f01(a1)
	move.b $1601(a1),orig_tl1(a2)
	move.b $1701(a1),orig_th1(a2)
	move.b $f00(a1),orig_cr2(a2)
	move.b #$10,$f00(a1)
	move.b $600(a1),orig_tl2(a2)
	move.b $700(a1),orig_th2(a2)
	move.l $0,orig_zero(a2)
	clr.l $0
		
	move.w #$7fff,$9a(a0)
	move.w #$8400,$96(a0)
	move.l #trap,$80
	trap #0
wait	bra wait

trap	move.l USP,a6
	move.l a6,orig_usp(a2)
	move.l a7,orig_a7(a2)
	move.l #stack2,a6
	move.l a6,USP
	move.l #stack3,a7
	eori.w #$2000,SR

	moveq #0,d7	;Set up screen from character map.
	move.l #charmap,a6
nxt_line	moveq #0,d6	
	bsr display_sentence4
	addq.w #1,d7
	cmpi.w #22,d7
	bne.s nxt_line

	move.l #screen,d0
	move.l #copper2,a1
	addq.l #2,d0
	move.w d0,$a(a1)
	swap d0
	move.w d0,$6(a1)
	swap d0
	add.l #44,d0
	move.w d0,$12(a1)
	swap d0
	move.w d0,$e(a1)
	swap d0
	add.l #44,d0
	move.w d0,$1a(a1)
	swap d0
	move.w d0,$16(a1)
	swap d0
	add.l #44,d0
	move.w d0,$22(a1)
	swap d0
	move.w d0,$1e(a1)

	move.l #pointersprite,d0
	move.w d0,$4e(a1)
	swap d0
	move.w d0,$4a(a1)

	move.l #trackstartsprite,d0
	move.w d0,$5e(a1)
	swap d0
	move.w d0,$5a(a1)

	move.l #trackendsprite,d0
	move.w d0,$6e(a1)
	swap d0
	move.w d0,$6a(a1)

	move.l #vars,a2
	move.b #$80,keypressed(a2)
	bsr go_default
	bsr show_settings

	move.l #$bfd000,a1
	move.b #$ff,$100(a1)
	move.b #$87,$100(a1)
	bsr shortwait
	move.b #$ff,$100(a1)
	bsr shortwait

	move.l #copper1,$80(a0)
	move.l #irq,$6c
	move.l #keyirq,$68
	move.w #$c028,$9a(a0)

	move.b #$7f,$100(a1)	;is df1: connected?
	bclr #4,$100(a1)		
	move.w #500,d7
	bsr cia_wait
	move.b #$ff,$100(a1)		
	bclr #4,$100(a1)
	moveq #$1f,d7
	moveq #0,d0
df1idloop	lsl.l #1,d0
	bclr #4,$100(a1)
	bsr vshrtwait
	btst #5,$1001(a1)
	beq.s nxtbit
	ori.w #1,d0
nxtbit	bset #4,$100(a1)
	dbf d7,df1idloop
	not.l d0
	cmpi.l #-1,d0
	beq.s df1_avail
	move.l #nodf1,a6
	bsr showmessage
	bsr init_error_sound
	move.w #2000,d7
	bsr cia_wait
	bra rs_df1

df1_avail	move.l #welcome,a6
	bsr showmessage
	bsr init_ok_sound
	bsr shortwait
	bsr reset_heads
	move.w d4,orig_df0(a2)
	move.w d5,orig_df1(a2)
	move.b #$ff,$100(a1)
	move.b #$87,$100(a1)
	bsr vshrtwait
	move.b #$ff,$100(a1)


*************
* Main loop *
*************

wait_irq	move.l #$dff000,a0
	move.l #$bfd000,a1
	move.l #vars,a2
	tst.w irq_occured(a2)
	beq.s wait_irq
	bsr adjust_range
	clr.w irq_occured(a2)
	move.w clicked_box(a2),d0
	beq.s wait_irq

	clr.w clicked_box(a2)
	clr.w dont_check(a2)
	cmpi.w #$a,d0
	beq return_to_dos
	cmpi.w #$b,d0
	bne.s no_namef
	bsr fetch_name
	bra ncheckd1

no_namef	cmpi.w #4,d0
	bhi altersettings
	bne.s notformat
	bsr format_disk
	cmpi.w #$2,check_mode(a2)
	bne.s notformat
	tst.w dont_check(a2)
	bne ncheckd1
	bsr check_disk
	bra ncheckd1

notformat	cmpi.w #1,d0
	bne.s ncopyd1
	bsr copy_disk
	cmpi.w #$2,check_mode(a2)
	bne.s ncopyd1
	tst.w dont_check(a2)
	bne ncheckd1
	bsr check_disk
	bra ncheckd1

ncopyd1	cmpi.w #2,d0
	bne.s ncheckd1
	bsr check_disk

ncheckd1	clr.w irq_occured(a2)
	clr.w clicked_box(a2)
	bra wait_irq

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

Return_to_DOS

	move.w #$7fff,$9a(a0)
	move.l #goodbye,a6
	bsr showmessage

	bsr reset_heads		;put heads back to original
	move.b #$ff,$100(a1)	;positions.
	bsr vshrtwait
	move.b #$f7,$100(a1)
	bclr #1,$100(a1)
rslpdf0	subq.w #1,orig_df0(a2)
	bmi.s rs_df0
	bsr step_pulse
	bra.s rslpdf0

rs_df0	bsr shortwait
	move.b #$ff,$100(a1)
	bsr vshrtwait
	move.b #$ef,$100(a1)
	bclr #1,$100(a1)
rslpdf1	subq.w #1,orig_df1(a2)
	bmi.s rs_df1
	bsr step_pulse
	bra.s rslpdf1

rs_df1	move.b #$ff,$100(a1)		;reset drive hardware
	bsr shortwait
	move.b orig_bfd100(a2),$100(a1)
	move.b orig_bfe001(a2),$1001(a1)

	move.l orig_lev2(a2),$68	;reset int vectors
	move.l orig_lev3(a2),$6c

	move.b orig_tl1(a2),$1601(a1)	;reset cia timers
	move.b orig_th1(a2),$1701(a1)
	move.b orig_cr1(a2),$1f01(a1)
	move.b orig_tl2(a2),$600(a1)
	move.b orig_th2(a2),$700(a1)
	move.b orig_cr2(a2),$f00(a1)

	move.l #trap2,$80
	trap #0
wait2	bra wait2

trap2	move.l orig_usp(a2),a6	;reset stack pointers
	move.l a6,USP
	move.l orig_a7(a2),a7
	eori.w #$2000,SR

	move.l orig_zero(a2),$0

	move.w orig_adkcon(a2),d0
	ori.w #$8000,d0
	move.w #$7fff,$9e(a0)
	move.w d0,$9e(a0)

	move.w orig_intreq(a2),d0	;reset int req
	ori.w #$8000,d0
	move.w #$7fff,$9c(a0)
	move.w d0,$9c(a0)

	move.w orig_dmacon(a2),d0	;reset dma control
	ori.w #$8000,d0
	move.w #$7fff,$96(a0)
	move.w d0,$96(a0)
	
	move.l orig_copper(a2),$dff080
	clr.w $dff088

	move.w orig_inten(a2),d0	;reset int enable
	ori.w #$c000,d0
	move.w #$7fff,$9a(a0)
	move.w d0,$9a(a0)

	move.l $4,a6
	jsr -$8a(a6)		;Permit Multitask
	movem.l (a7)+,d0-d7/a0-a6
	clr.w d0
	rts

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

Fetch_name:
	
	bsr clear_track_status	
	bsr reset_heads
	
	move.w destination(a2),d0
	eori.w #1,d0
	add.w #3,d0
	move.b #$7f,$100(a1)
	bclr d0,$100(a1)	
	bsr wait_motor
	moveq #40,d0
	bsr moveheads
	move.b #$40,track_bcd(a2)
	cmpi.w #$10,disk_error(a2)
	bne.s name_go
dskgonnam	tst.w destination(a2)
	bne nodisk0
	bra nodisk1

name_go	move.w #1,side_sel(a2)
	move.w #3,re_read(a2)
rereadnam	cmpi.w #3,clicked_box(a2)
	beq terminated
	bsr read_mfm
	tst.w disk_error(a2)
	beq.s trkok_nam
	subq.w #1,re_read(a2)
	bne.s rereadnam
	cmpi.w #$10,disk_error(a2)
	beq dskgonnam

trkok_nam	bsr show_track_status
	
	move.l #mfm_buffer,a3
	lea $18e0*2(a3),a5

fsync_nam	cmp.l a5,a3
	bhi cant_find_name
	cmpi.w #$4489,(a3)+
	bne.s fsync_nam
	cmpi.w #$4489,(a3)
	beq.s sync_nam
	subq.w #2,a3
	
sync_nam	lea $2(a3),a4
	bsr decode_long
	andi.w #$ff00,d5
	beq.s gsec0_nam
	add.w #$430,a3
	bra fsync_nam

gsec0_nam	swap d5
	cmpi.b #80,d5
	bne cant_find_name
	
	moveq #$7f,d4
	lea $3a(a3),a4
	move.l #$55555555,d7	
	move.l #decoded_rootblock,a5
dcblk_nam	move.l $200(a4),d6		
	move.l (a4)+,d5		
	and.l d7,d5	
	and.l d7,d6
	add.l d5,d5
	or.l d6,d5		
	move.l d5,(a5)+
	dbf d4,dcblk_nam

	move.l #decoded_rootblock,a5
	cmpi.l #$2,(a5)
	bne cant_find_name
	cmpi.l #$1,127*4(a5)
	bne cant_find_name
	lea 108*4(a5),a5
	moveq #0,d0
	move.b (a5),d0
	cmpi.b #31,d0
	bhi cant_find_name
	lea $1(a5),a6
	clr.b $00(a6,d0.w)	;null terminate string
	bsr showmessage
	bsr shutdown
	bsr init_ok_sound
	rts

cant_find_name

	move.l #no_name,a6
	bsr showmessage
	bsr shutdown
	bsr init_error_sound
	rts


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


Format_disk:
	
	bsr getdiskname		;format disk proceddure
	tst.w total_error(a2)
	bmi terminated
	bsr clear_track_status	
	bsr reset_heads
	clr.w total_error(a2)

	move.l #formting0,a6
	move.w destination(a2),d0
	beq.s drive0c
	move.l #formting1,a6
drive0c	add.w #3,d0
	move.b #$7f,$100(a1)
	bclr d0,$100(a1)	
	bsr showmessage
	bsr wait_motor
	bsr position_heads
	bsr get_strt_trk_bcd
	cmpi.w #$10,disk_error(a2)
	bne.s fdiskin
	tst.w destination(a2)
	beq nodisk0
	bra nodisk1
fdiskin	cmpi.w #$11,disk_error(a2)
	beq write_pro

	move.w use_sides(a2),side_sel(a2)
	andi.w #$1,side_sel(a2)

fmtlp	cmpi.w #3,clicked_box(a2)	;stop format?
	beq terminated
	
	tst.w side_sel(a2)
	beq.s f_upper
	bset #2,$100(a1)		
	bra fside_set
f_upper	bclr #2,$100(a1)		

fside_set	moveq #3,d7		
	bsr cia_wait
	bsr create_track

	move.w recopy_mode(a2),recopycount(a2)
format_lp	bsr write_mfm
	cmpi.w #1,check_mode(a2)
	bne F_trackok		;check this written track now?

	move.w #3,re_read(a2)	;check track just formatted
f_reread	cmpi.w #3,clicked_box(a2)
	beq terminated
	bsr read_mfm
	tst.w disk_error(a2)	;written track ok (now)?
	beq.s f_trackok
	subq.w #1,re_read(a2)	;nope - maybe just a read error?
	bne.s f_reread
	cmpi.w #$10,disk_error(a2)	
	beq diskgone1
	subq.w #1,recopycount(a2)	
	bpl format_lp
	
F_TrackOk	move.w disk_error(a2),d0
	or.w d0,total_error(a2)
	bsr show_dest_track_status

	cmpi.w #$2,use_sides(a2)
	bne.s nxttrack3
	eori.w #1,side_sel(a2)
	bne nostep3
nxttrack3	addq.w #1,track(a2)
	bsr stepin
	bsr next_track_bcd

nostep3	move.w endtrack(a2),d1
	add.w #1,d1
	cmp.w track(a2),d1
	bne fmtlp
	bsr ending
	rts


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

Copy_disk:

	bsr clear_track_status	;copy disk proceedure
	bsr reset_heads
	move.l #copying0,a6
	move.w destination(a2),d0
	bne.s drive0a
	move.l #copying1,a6
drive0a	bsr showmessage
	move.b #$7f,$100(a1)	;switch on both motors
	move.b #$67,$100(a1)
	bsr shortwait

	move.b #$77,$100(a1)	;wait motor 0
	bsr wait_motor
	tst.w destination(a2)
	bne.s din0
	cmpi.w #$11,disk_error(a2)
	beq write_pro
din0	cmpi.w #$10,disk_error(a2)
	beq nodisk0
	move.b #$6f,$100(a1)	;wait motor 1
	bsr wait_motor
	tst.w destination(a2)
	beq.s din1
	cmpi.w #$11,disk_error(a2)
	beq write_pro
din1	cmp.w #$10,disk_error(a2)
	beq nodisk1
	move.w use_sides(a2),side_sel(a2)
	andi.w #$1,side_sel(a2)
	clr.w total_error(a2)
	
	move.b #$67,$100(a1)
	bsr position_heads
	bsr get_strt_trk_bcd

copylp	move.w recopy_mode(a2),recopycount(a2)
recopylp1	move.w #3,re_read(a2)
reread2	cmpi.w #3,clicked_box(a2)
	beq terminated
	move.b #$7f,$100(a1)	;select source drive
	move.w destination(a2),d0
	eor.w #1,d0
	add.w #3,d0
	bclr d0,$100(a1)
	bsr read_mfm
	tst.w disk_error(a2)
	beq.s trackok2
	cmpi.w #$10,disk_error(a2)
	beq diskgone1
	subq.w #1,re_read(a2)	;try reading again..
	bne.s reread2
	bsr read_error_track	;this source track has errors so
	bra skipx2		;try to copy it 'manually'

trackok2	bsr double_mfm
	cmpi.w #1,check_mode(a2)	;dont show source status if
	beq noshsrc		;checkmode 1 (+ track = OK)
skipx2	bsr show_track_status
noshsrc	move.w disk_error(a2),sourcestatus(a2)

	ori.b #$78,$100(a1)		;select destination drive without
	move.w destination(a2),d0	;affecting disk side selection.
	add.w #3,d0
	bclr d0,$100(a1)
recopylp2	bsr write_mfm
	cmpi.w #$10,disk_error(a2)
	beq diskgone1

	cmpi.w #1,check_mode(a2)	;check this written track now?
	bne notduring
	tst.w sourcestatus(a2)	;if source had error - dont check!
	bne SrcErr
chklp2	move.w #3,re_read(a2)	;check track just copied
reread3	cmpi.w #3,clicked_box(a2)
	beq terminated
	bsr read_mfm
	tst.w disk_error(a2)	;written track ok (now)?
	beq.s trackok3

	subq.w #1,re_read(a2)	;nope - maybe just a read error?
	bne.s reread3
	cmpi.w #$10,disk_error(a2)	
	beq diskgone1
	subq.w #1,recopycount(a2)	
	bmi Trackok3
	bsr remove_track_mark	
	bra recopylp2

SrcErr	subq.w #1,recopycount(a2)	
	bmi notduring		
	bsr remove_track_mark	
	bra recopylp1

TrackOk3	bsr show_dest_track_status
	
notduring	move.w disk_error(a2),d0
	or.w d0,total_error(a2)
	
	cmpi.w #$2,use_sides(a2)
	bne.s nxttrack2
	eori.w #1,side_sel(a2)
	bne nostep2
nxttrack2	addq.w #1,track(a2)
	move.b #$67,$100(a1)
	bsr stepin
	bsr next_track_bcd

nostep2	move.w endtrack(a2),d1
	add.w #1,d1
	cmp.w track(a2),d1
	bne copylp
	bsr ending
	rts

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

Check_disk:

	bsr clear_track_status	;check disk proceedure
	bsr reset_heads
	move.l #checking0,a6
	move.w destination(a2),d0
	beq.s drive0b
	move.l #checking1,a6
drive0b	add.w #3,d0
	move.b #$7f,$100(a1)
	bclr d0,$100(a1)	
	bsr showmessage
	bsr wait_motor
	bsr position_heads
	bsr get_strt_trk_bcd
	
	cmpi.w #$10,disk_error(a2)
	bne.s chk_go
diskgone1	tst.w destination(a2)
	beq nodisk0
	bra nodisk1

chk_go	move.w use_sides(a2),side_sel(a2)
	andi.w #$1,side_sel(a2)
	clr.w total_error(a2)

chklp	move.w #3,re_read(a2)
reread1	cmpi.w #3,clicked_box(a2)
	beq terminated
	bsr read_mfm
	tst.w disk_error(a2)
	beq.s trackok1
	subq.w #1,re_read(a2)
	bne.s reread1
	cmpi.w #$10,disk_error(a2)
	beq diskgone1
trackok1	bsr show_track_status

	move.w disk_error(a2),d0
	or.w d0,total_error(a2)

	cmpi.w #$2,use_sides(a2)
	bne.s nxttrack1
	eori.w #1,side_sel(a2)
	bne nostep1
nxttrack1	addq.w #1,track(a2)
	bsr stepin
	bsr next_track_bcd

nostep1	move.w endtrack(a2),d1
	add.w #1,d1
	cmp.w track(a2),d1
	bne.s chklp
	bsr checked
	rts

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

Ending:	tst.w check_mode(a2)
	bne.s checked
	bsr init_ok_sound
	move.l #taskdone2,a6
	bsr showmessage
	bra finish

checked	tst.w total_error(a2)
	beq.s noerrs1
	bsr init_error_sound
	move.l #taskdone0,a6
	bsr showmessage
	bra finish
noerrs1	bsr init_ok_sound
	move.l #taskdone1,a6
	bsr showmessage
finish	bsr shutdown
	rts

terminated:

	move.w #1,dont_check(a2)
	move.l #terminate,a6
	bsr showmessage
	bsr shutdown
	bsr init_error_sound
	rts

nodisk0:	move.w #1,dont_check(a2)
	move.l #no_disk0,a6
	bsr showmessage
	bsr shutdown
	bsr init_error_sound
	rts

nodisk1:	move.w #1,dont_check(a2)
	move.l #no_disk1,a6
	bsr showmessage
	bsr shutdown
	bsr init_error_sound
	rts

write_pro	move.w #1,dont_check(a2)
	move.l #writepro,a6
	bsr showmessage
	bsr shutdown
	bsr init_error_sound
	rts

shutdown:	move.b #$ff,$100(a1)
	move.b #$e7,$100(a1)
	bsr vshrtwait
	move.b #$ff,$100(a1)
	clr.w irq_occured(a2)
	rts

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

Altersettings

	cmpi.w #9,d0
	beq.s ch_dest
	cmpi.w #5,d0
	bne.s notchangedest
ch_dest	eori.w #1,destination(a2)

notchangedest

	cmpi.w #6,d0		;change check mode?
	bne.s chksysok
	cmpi.w #1,check_mode(a2)
	bne.s no_chrc
	addq.w #1,recopy_mode(a2)
	cmpi.w #$9,recopy_mode(a2)
	bls.s chksysok
	clr.w recopy_mode(a2)
no_chrc	addi.w #1,check_mode(a2)
	cmpi.w #2,check_mode(a2)
	bls.s chksysok
	clr.w check_mode(a2)
chksysok

	cmpi.w #$7,d0		;change sides mode?
	bne.s notchangesides
	addq.w #1,use_sides(a2)
	cmpi.w #$3,use_sides(a2)
	bne.s notchangesides
	clr.w use_sides(a2)

notchangesides
	
	cmpi.w #$8,d0		;default?
	bne.s notdefault
	bsr go_default

notdefault

	bsr show_settings
	clr.w clicked_box(a2)
	bra wait_irq


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

*****************
* Key Interrupt *
*****************

keyirq	movem.l d0/a2,-(a7)
	move.l #$bfe001,a2
	btst #3,$d00(a2)
	beq nokey
	bset #6,$e00(a2)

	move.b #$08,$f00(a2)	
	move.b #53,$600(a2)		;set timer lo
	move.b #00,$700(a2)		;set timer hi (starts counter)
kciawlp2	btst #0,$f00(a2)		;wait for timeout
	bne.s kciawlp2
	
	bclr #6,$e00(a2)
	move.b $c00(a2),d0
	not.b d0
	ror.b #1,d0
	move.l #vars,a2
	move.b d0,keypressed(a2)
	cmpi.b #$45,d0
	bne.s not_esc
	move.w #3,clicked_box(a2)

not_esc	andi.b #$7c,d0		;shift held?
	cmpi.b #$60,d0
	bne.s nokey
	tst.b keypressed(a2)
	bpl.s shfton
	clr.w shift_on(a2)
	bra nokey
shfton	move.w #1,shift_on(a2)

nokey	move.w #8,$dff09c
	movem.l (a7)+,d0/a2
	rte
	
*****************
* VBL Interrupt *
*****************


Irq	movem.l a0-a6/d0-d7,-(a7)
	move.w #$20,$dff09c
	bsr irq_routines
	movem.l (a7)+,a0-a6/d0-d7
	rte
	
********************************************************************************

irq_routines	

	move.l #$dff000,a0		;move pointer
	move.l #vars,a2

	tst.w rmb_latch(a2)
	beq.s latch_off
	btst #2,$16(a0)
	beq.s rmbpress
	clr.w rmb_latch(a2)
	bra rmbpress

latch_off	btst #2,$16(a0)
	bne.s rmbpress
	eori.w #1,mouse_lock(a2)
	move.w #1,rmb_latch(a2)
	move.b $a(a0),oldmousex(a2)
	move.b $b(a0),oldmousey(a2)
rmbpress		
	tst.w mouse_lock(a2)	
	bne skipxy

	move.b $a(a0),d0
	move.b $b(a0),d1
	move.b d0,d2
	move.b d1,d3
	sub.b oldmousex(a2),d0
	sub.b oldmousey(a2),d1
	ext.w d0
	ext.w d1
	tst.w adjrng_mode(a2)
	bne.s skp_y
	add.w d0,pointery(a2)
skp_y	add.w d1,pointerx(a2)
	cmpi.w #$13c,pointerx(a2)
	blt.s xinrr
	move.w #$13c,pointerx(a2)
xinrr	tst.w pointerx(a2)
	bpl.s xinrl
	clr.w pointerx(a2)
xinrl	cmpi.w #$a0,pointery(a2)
	blt.s yinrb
	move.w #$a0,pointery(a2)
yinrb	tst.w pointery(a2)
	bpl.s yinrt
	clr.w pointery(a2)
yinrt	move.b d2,oldmousex(a2)
	move.b d3,oldmousey(a2)

	move.l #pointersprite,a3	;put new coords in sprite
	tst.w adjrng_mode(a2)
	beq.s sprnormal
	clr.l (a3)
	bra skipxy
sprnormal	move.w pointerx(a2),d0
	move.w pointery(a2),d1
	add.w #$80,d0
	add.w #$4a,d1
	move.w d1,d2
	add.w #$f,d2
	move.b d1,(a3)
	move.b d2,$2(a3)
	clr.w d4
	lsr.w #1,d0
	bcc.s nocarry
	moveq #1,d4
nocarry	move.b d0,$1(a3)
	btst #8,d1
	beq.s novstrt
	ori.w #4,d4
novstrt	btst #8,d2
	beq.s novstop
	ori.w #4,d4
novstop	move.b d4,$3(a3)

skipxy	move.w #1,irq_occured(a2)
	tst.w button_latch(a2)	;test button on boxes?
	beq.s latchoff
	btst #6,$bfe001
	beq.s mouse_end
	clr.w button_latch(a2)
	bra.s mouse_end
latchoff	btst #6,$bfe001
	bne.s mouse_end
	bsr test_boxes
	bsr toggle_adjrange
	move.w #1,button_latch(a2)

mouse_end	tst.w volume(a2)
	beq.s soundend
	move.w volume(a2),$a8(a0)
	move.w volume(a2),$b8(a0)
	move.w volume(a2),$c8(a0)
	move.w volume(a2),$d8(a0)
	subq.w #2,volume(a2)
	bpl.s soundend
	move.w #$f,$96(a0)
	clr.w volume(a2)
soundend	rts


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

**********************
* Main disk routines *
**********************

*************
* Read data *
*************

read_mfm	move.l #$dff000,a0		;load in a track side into
	move.l #$bfd000,a1		;mfm buffer
	move.l #vars,a2
	tst.w side_sel(a2)
	beq.s upperside
	bset #2,$100(a1)		
	bra side_set
upperside	bclr #2,$100(a1)		

side_set	move.w #2,$9c(a0)
	clr.w disk_error(a2)
	moveq #2,d7		;let head settle.
	bsr cia_wait
	move.l #mfm_buffer,a3
	move.l a3,$20(a0)		;mfm buffer location
	move.w #$4000,$24(a0)	
	move.w #$8010,$96(a0)	
	move.w #$6800,$9e(a0)	
	move.w #$9500,$9e(a0)
	move.w #$4489,$7e(a0)	
	move.w #$98e0,$24(a0)	;no of words to load 
	move.w #$98e0,$24(a0)	
	bsr show_track_no_bcd
	move.w #2000,d3		
w_dma_end	moveq #1,d7		;wait 3 seconds for sync or
	bsr cia_wait		;time out.
	btst #1,$1f(a0)		
	bne.s dma_end
	dbf d3,w_dma_end
	move.w #1,re_read(a2)
	btst #2,$1001(a1)		
	bne.s no_sync
	move.w #$10,disk_error(a2)	;disk removed error.
	bra dma_end
no_sync	move.w #$2,disk_error(a2)	;no sync / time out (error 2)
dma_end	move.w #$4000,$24(a0)	
	move.w #$10,$96(a0)		

**************
* Check data *
**************


Check_Mfm	tst.w disk_error(a2)	
	bne errors
	move.l #mfm_buffer,a3	;check read mfm for errors
	cmpi.w #$4489,(a3)
	beq.s sync1
	cmpi.w #$4489,$2(a3)	;check for 1st sync
	beq.s sync1
	move.w #2,disk_error(a2)
	bra errors

sync1	moveq #$a,d1		;11 sectors to find
chek_loop	move.w #$4489,d2		;sync
	cmp.w $2(a3),d2
	bne.s one_sync
	addq.w #2,a3
one_sync	move.w d2,-$2(a3)		;tidy up pre-sync locations
	move.l #$aaaaaaaa,-$6(a3)
	btst #0,-$7(a3)
	beq.s clock_ok
	move.w #$2aaa,-$6(a3)
clock_ok
	lea $2a(a3),a4		;check header checksum
	bsr decode_long
	move.l d5,d2	
	lea $2(a3),a4		
	bsr decode_long
	cmp.l d4,d2
	beq hdrchksm_ok
	move.w #4,disk_error(a2)	;header checksum error 4
	bra errors
hdrchksm_ok
	move.l d5,d2		;track mark ok?
	swap d2
	move.w track(a2),d7
	lsl.w #1,d7
	or.w side_sel(a2),d7
	eori.w #1,d7
	cmp.b d7,d2
	beq header_ok
	move.w #5,disk_error(a2)	;track mark error 5
	bra errors
header_ok
	lsr.w #8,d2
	cmpi.b #$ff,d2
	beq header_ok2
	move.w #5,disk_error(a2)	;no $ff error 5
	bra errors
header_ok2
	lea $32(a3),a4		;check diskblock checksum
	bsr decode_long		
	bsr data_checksum		
	cmp.l d4,d5
	beq dbchksm_ok
	move.w #6,disk_error(a2)	;data block checksum_error
	bra errors
dbchksm_ok				
	move.w #$4489,d2		;find next sync
	add.w #$440,a3
	cmp.w (a3),d2
	beq.s next_sync
				
	add.w #$1c0,a3		;no sync so this is either the gap 
	move.l a3,d6		;or an error!
	subi.l #mfm_buffer,d6
	move.w #$31be,d7		;attempt to find sync after gap
	sub.w d6,d7		
	lsr.w #1,d7		;amount of words till end of mfm
find_sag	cmp.w (a3)+,d2
	dbeq d7,find_sag
	subq.w #2,a3
	move.l a3,firstsync(a2)	;store 1st sync after gap address
	tst.w d7
	bpl next_sync		
	move.w #3,disk_error(a2)	;no sync after gap error 3
	bra errors
next_sync	dbf d1,chek_loop
errors	rts

*****************************************
* Double MFM Length to make write track *
*****************************************

double_mfm
	move.w #$4489,d2
	move.l firstsync(a2),a3	;addr of 1st sync after original gap
	cmp.w $2(a3),d2		
	bne.s onesync
	addq.w #2,a3
onesync	move.w d2,-(a3)		;tidy up pre-sync locations
	move.l #$aaaaaaaa,d2	;(make sure theres 2 syncs and
	move.w #$7f,d6		;fill most of gap with $AAAA.)
loop...	move.l d2,-(a3)		
	dbf d6,loop...		;a3 = start of mfm for write.
	move.l a3,write_addr(a2)

	move.l #mfm_buffer,a4
	lea $31c0(a4),a5
	move.w #$4489,d2	
	cmp.w $2(a4),d2		;locate the sync before header at
	bne.s loopd		;start of mfm (1st sector read)
	addq.w #2,a4
loopd	cmp.w -(a5),d2		;locate last sync in mfm (2nd
	bne.s loopd		;occurance of that sector)
	
	move.l #$ffffffff,$44(a0)	;copy mfm data end to end,aligned
	clr.l $64(a0)		;on same sync using blitter
	move.l a4,$50(a0)		
	move.l a5,$54(a0)
	move.w #$09f0,$40(a0)
	move.w #$31e0,$58(a0)
	bsr wait_blit
	rts

*******************************
* Attempt to Copy error track *
*******************************

Read_Error_Track

	move.l #mfm_buffer,a3	;re-read 2 x track length
	move.l a3,$20(a0)		
	move.w #$1002,$9c(a0)	
	move.w #$8010,$96(a0)	
	move.w #$7f00,$9e(a0)	
	move.w #$9500,$9e(a0)	
	move.w #$4000,$24(a0)	
	move.w #$b2c0,$24(a0)	
	move.w #$b2c0,$24(a0)	
	
	move.w #3000,d3		
w_dma2	moveq #1,d7		;wait 3 seconds for sync or
	bsr cia_wait		;time out.
	btst #1,$1f(a0)		
	bne.s dma_end2
	dbf d3,w_dma2
	move.w #1,re_read(a2)
	move.w #$2,disk_error(a2)	;no sync - time out (error 2)
	move.w #$4000,$24(a0)	;special code for disk
	move.w #$10,$96(a0)		;disable disk dma
	bra no_copy

dma_end2	move.w #$4000,$24(a0)	;special code for disk
	move.w #$10,$96(a0)		;disable disk dma

	move.w #$4489,d2		;try to find the gap
	cmp.w $2(a3),d2
	bne.s et_sync1
	add.w #2,a3
et_sync1	move.w #$240,d7		;next sync should be within
et_loop	cmp.w (a3)+,d2		;about $440 bytes. If it isnt -
	beq.s et_sync		;call this the gap
	dbf d7,et_loop
	bra gotet_gap
et_sync	addq.w #2,a3		;skip possible 2nd sync
	bra et_sync1

gotet_gap	cmp.l #mfm_buffer+$6580,a3
	bls.s fetstart
	move.l #mfm_buffer,a3	;track is totally shot!
fetstart	move.l a3,write_addr(a2)

	move.w #$195f,d7		;try to locate and fix up sync
pusynclp	cmp.w (a3),d2		;and pre-sync words
	bne.s not_sync		
	addq.w #$2,a3
	cmp.w (a3),d2
	bne.s fasyncpos
	addq.w #$2,a3
fasyncpos	move.l #$44894489,-$4(a3)
	move.l #$aaaaaaaa,-$8(a3)
not_sync	addq.w #2,a3
	dbf d7,pusynclp	
no_copy	rts
	
***************
* Write track *
***************

Write_mfm	move.l write_addr(a2),$20(a0)	;mfm buffer location
	move.w #$1002,$9c(a0)	;clear disk irq flags
	move.w #$8010,$96(a0)	;enable dma
	move.w #$4000,$24(a0)	;special code for disk
	move.w #$7f00,$9e(a0)	;diskcontrol
	move.w #$9100,$9e(a0)
	move.w #$d940,$24(a0)	;no of words to write to disk
	move.w #$d940,$24(a0)	;from mfm buffer
	bsr show_track_no_bcd
waitdirq2	btst #1,$1f(a0)		
	beq.s waitdirq2		
	move.w #$4000,$24(a0)	;special code for disk
	move.w #$10,$96(a0)		;disable dma
	rts

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

*******************************************
* Small disk hardware/software procedures *
*******************************************

decode_long

	move.l #$55555555,d7	;returns decoded longword in
	move.l (a4),d5		;d5
	move.l $4(a4),d6		
	and.l d7,d5		;and checksum in d4
	and.l d7,d6
	move.l d5,d4
	eor.l d6,d4
	add.l d5,d5
	or.l d6,d5		
	rts

data_checksum

	move.l #checklong,a5
	clr.l (a5)
	move.l #$55555555,$44(a0)	;f/lwmask
	move.l a5,$54(a0)		;destination
	move.l a5,$4c(a0)		;source b
	lea $3a(a3),a4		
	move.l a4,$50(a0)		;source a
	move.w #$fffc,$62(a0)	;blit mod b
	move.l #$0000fffc,$64(a0)	;blit mod a,d
	move.l #$0d3c0000,$40(a0)	;use ab,d with 3c minterm
	move.w #$4002,$58(a0)	;100 * 4 bytes
	bsr wait_blit
	move.l (a5),d4
	rts

reset_heads

	move.b #$fd,$100(a1)	
	move.b #$e5,$100(a1)
	tst.w track(a2)		;if track is already 0, step
	bne.s skp_stp		;to track 1 first, to enusure
	bsr stepin		;disk_chng is reset.

skp_stp	move.b #$e7,d6		
	moveq #-1,d4
	moveq #-1,d5

seek0	btst #3,d6
	bne.s skipdf0
	move.b #$f7,$100(a1)	
	bsr vshrtwait
	btst #4,$1001(a1)
	bne.s stepdf0
	bset #3,d6
	bra skipdf0
stepdf0	addq.w #1,d4
	
skipdf0	btst #4,d6
	bne.s skipdf1
	move.b #$ef,$100(a1)
	bsr vshrtwait
	btst #4,$1001(a1)
	bne.s stepdf1
	bset #4,d6
	bra skipdf1
stepdf1	addq.w #1,d5

skipdf1	cmpi.b #$ff,d6
	beq.s zerod
	move.b d6,$100(a1)
	bsr vshrtwait
	bsr step_pulse
	bra.s seek0

zerod	moveq #12,d7
	bsr cia_wait
	clr.w track(a2)
	rts

position_heads

	move.w starttrack(a2),d0	;positions heads over selected track
moveheads	cmp.w track(a2),d0		;as defined by the range markers
	beq.s movedone
	bclr #1,$100(a1)
	bsr vshrtwait	
	bsr step_pulse
	addq.w #1,track(a2)
	bra moveheads
movedone	moveq #12,d7
	bsr cia_wait
	rts


Stepout	bset #1,$100(a1)		;for use if read follows
	bra.s step
Stepin	bclr #1,$100(a1)
step	bsr vshrtwait	
	bsr step_pulse
	moveq #14,d7
	bsr cia_wait
	rts

step_pulse

	bclr #0,$100(a1)
	bsr vshrtwait
	bset #0,$100(a1)
	moveq #4,d7
	bsr cia_wait
	rts

wait_motor
	clr.w disk_error(a2)
	move.w #1000,d1
wait_m	moveq #1,d7
	bsr cia_wait
	btst #5,$1001(a1)
	beq.s speed_ok
	dbf d1,wait_m
	move.w #$10,disk_error(a2)
	bra write_en
speed_ok	btst #3,$1001(a1)
	bne.s write_en
	move.w #$11,disk_error(a2)
write_en	rts


cia_wait	move.b #$08,$f00(a1)	
	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 timeout
	bne.s ciawlp2
	subq.w #1,d7
	bne.s cia_wait		;d7 = milliseconds to wait.
	rts


shortwait	moveq #1,d7
	bsr cia_wait
	rts


vshrtwait	nop
	nop	
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop	
	nop
	nop
	rts

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

****************************
* Kwikcopy system routines *
****************************

test_boxes

	move.l #box_areas,a3
	moveq #1,d3
boxloop	moveq #0,d4
	moveq #0,d5
	moveq #0,d6
	moveq #0,d7
	move.b (a3)+,d4
	move.b (a3)+,d5
	move.b (a3)+,d6
	move.b (a3)+,d7
	lsl.w #3,d4
	lsl.w #3,d5
	lsl.w #3,d6
	lsl.w #3,d7
	add.w #20+4,d4
	add.w #20+4,d6
	sub.w #24-4,d5
	sub.w #24-4,d7
	cmp.w pointery(a2),d4
	bhi.s missbox
	cmp.w pointery(a2),d6
	bls.s missbox
	cmp.w pointerx(a2),d5
	bhi.s missbox
	cmp.w pointerx(a2),d7
	bls.s missbox
	move.w d3,clicked_box(a2)
	rts
missbox	addq.w #1,d3
	cmpi.w #$10,d3
	bne.s boxloop
	rts


toggle_adjrange

	move.w adjrng_mode(a2),d0	;alter start/stop tracks.
	beq init_mark
	tst.w button_latch(a2)
	bne.s noadjesc
	clr.w adjrng_mode(a2)
noadjesc	rts

init_mark	move.w starttrack(a2),d0	;initiate move start/end markers.
	move.w endtrack(a2),d2
	lsl.w #2,d0
	lsl.w #2,d2
	subq.w #8,d0
	subq.w #2,d2
	move.w d0,d1
	move.w d2,d3
	add.w #16,d1
	add.w #16,d3
	move.w pointerx(a2),d4
	move.w pointery(a2),d5
	cmp.w d0,d4
	blt.s ncstartt
	cmp.w d1,d4
	bgt.s ncstartt
	cmp.w #14,d5
	blt.s ncstartt
	cmp.w #24,d5
	bgt.s ncstartt
	move.w #1,adjrng_mode(a2)	;adjust start track mode on 	
	rts

ncstartt	cmp.w d2,d4
	blt.s ncendt
	cmp.w d3,d4
	bgt.s ncendt
	cmp.w #44,d5
	blt.s ncendt
	cmp.w #54,d5
	bgt.s ncendt
	move.w #2,adjrng_mode(a2)	;adjust end track mode on 	
ncendt	rts
	

adjust_range

	move.w adjrng_mode(a2),d0	;alter start/stop tracks.
	beq notadj
	cmpi.w #2,d0
	beq.s alt_end
	
alt_strt	move.w pointerx(a2),d0
	lsr.w #2,d0
	cmp.w endtrack(a2),d0
	bls.s strackok
	move.w endtrack(a2),d0
strackok	move.w d0,starttrack(a2)
	bsr convert
	move.l #trackstartsprite+4,a3
	bsr trkdigits
	bra setmarkerpositions

alt_end	move.w pointerx(a2),d0
	lsr.w #2,d0
	cmp.w starttrack(a2),d0
	bhi.s etrackok
	move.w starttrack(a2),d0
etrackok	move.w d0,endtrack(a2)
	bsr convert
	move.l #trackendsprite+96,a3
	bsr trkdigits

setmarkerpositions

	move.w starttrack(a2),d0	;track marker x coords
	lsl.w #1,d0
	add.w #$3b,d0
	move.b d0,trackstartsprite+1
	move.w endtrack(a2),d0
	lsl.w #1,d0
	add.w #$3e,d0
	move.b d0,trackendsprite+1
notadj	rts


go_default
	
	move.w #$2,check_mode(a2)
	clr.w recopy_mode(a2)
	move.w #2,use_sides(a2)
	move.w #1,destination(a2)
	move.w #0,starttrack(a2)
	move.w #79,endtrack(a2)
	clr.w side_sel(a2)
	move.w starttrack(a2),d0
	bsr convert
	move.l #trackstartsprite+4,a3
	bsr trkdigits
	move.w endtrack(a2),d0
	bsr convert
	move.l #trackendsprite+96,a3
	bsr trkdigits
	bsr setmarkerpositions
	bsr clear_track_status
	bsr get_strt_trk_bcd
	bsr show_track_no_bcd
	rts


convert	clr.w d1
	andi.w #$ff,d0
	move.b d0,d1		;convert hex in d0 to BCD in
	andi.b #$f,d1		;d1
	cmpi.b #$9,d1
	bls.s sk1
	sub.b #$a,d1
	ori.b #$10,d1
sk1	move.w d0,d2
	lsr.w #4,d2
	subq.w #1,d2
	bmi.s sk2
	move.b #$16,d3
bcdlp1	move.b #4,ccr
	abcd d3,d1
	dbf d2,bcdlp1
sk2	rts

trkdigits	clr.w d2			;put figures in track sprites
	move.b d1,d2
	lsr.b #4,d1
	move.l #ONEplanefont+$10,a4
	add.w d1,a4
	move.b (a4),(a3)
	move.b 96*1(a4),$4(a3)
	move.b 96*2(a4),$8(a3)
	move.b 96*3(a4),$c(a3)
	move.b 96*4(a4),$10(a3)
	move.b 96*5(a4),$14(a3)
	andi.w #$f,d2
	move.l #ONEplanefont+$10,a4
	add.w d2,a4
	move.b (a4),$1(a3)
	move.b 96*1(a4),$5(a3)
	move.b 96*2(a4),$9(a3)
	move.b 96*3(a4),$d(a3)
	move.b 96*4(a4),$11(a3)
	move.b 96*5(a4),$15(a3)
	rts

show_settings

	move.l #$dff000,a0
	move.l #vars,a2
	move.l #$ffffffff,$44(a0)
	move.l #$09f00000,$40(a0)

	move.l #checktxt,a6		;show check mode
	move.w check_mode(a2),d1
	mulu #17,d1
	add.w d1,a6
	moveq #24,d6
	moveq #4,d7
	bsr display_sentence4

	move.l #sidestext,a6	;show sides mode
	move.w use_sides(a2),d1
	mulu #$6,d1
	add.l d1,a6
	moveq #10,d6
	moveq #15,d7
	bsr display_sentence4

	move.l #retrytxt,a6		;show retries figure
	cmpi.w #1,check_mode(a2)	;(if check mode 1)
	bne.s show_src
	move.w recopy_mode(a2),d1
	lsl.w #1,d1
	add.w d1,a6
	moveq #31,d6
	moveq #4,d7
	bsr display_sentence4

show_src	move.w destination(a2),d0	;show source/destination number
	eori.w #1,d0
	mulu #$5,d0
	move.l #sourcetxt,a6	
	add.w d0,a6
	moveq #23,d6
	moveq #8,d7
	bsr display_sentence4
show_dst	move.w destination(a2),d0	
	mulu #$5,d0
	move.l #sourcetxt,a6	
	add.w d0,a6
	moveq #23,d6
	moveq #11,d7
	bsr display_sentence4
	rts

blit_wait	btst #$6,$2(a0)
	bne.s blit_wait
	rts

showmessage

	move.l a6,-(a7)
	move.l #nullmsg,a6
	bsr message
	move.l (a7)+,a6
	bsr message
	rts

message	move.l #screen+(175*176)+3,a4
	clr.w d1			;set a6 = addr of null terminated
messagelp	clr.w d0			;string. Plot in ONE plane font.
	move.b (a6)+,d0	
	beq.s mess_end
	sub.b #$20,d0
	bsr printchar
	addq.w #1,d1
	bra messagelp
mess_end	rts


printchar	move.l a4,-(a7)
	move.l #ONEplanefont,a3	;d0 = font char number,d1=x pos
	add.w d0,a3		;set a4 to screen line address
	add.w d1,a4		
	move.b (a3),(a4)
	move.b 96*1(a3),176(a4)
	move.b 96*2(a3),352(a4)
	move.b 96*3(a3),528(a4)
	move.b 96*4(a3),704(a4)
	move.b 96*5(a3),880(a4)
	move.l (a7)+,a4
	rts

show_track_status

	move.l #errornos,a3		;fill track block status for this
	move.l #screen+(35*176)+1,a4	;disk side
	tst.w side_sel(a2)
	beq.s upper	
	add.w #176*6,a4
upper	move.w track(a2),d7
	clr.w d0
	btst #0,d7
	beq.s leftnyb
	moveq #4,d0
leftnyb	lsr.w #1,d7
	add.w d7,a4
	move.w disk_error(a2),d7
	beq.s noerror
	add.w #44,a4
noerror	add.w d7,a3

plotTmark	move.b (a3),d7
	lsr.b d0,d7
	or.b d7,(a4)
	move.b $8(a3),d7
	lsr.b d0,d7
	or.b d7,176(a4)
	move.b $10(a3),d7
	lsr.b d0,d7
	or.b d7,352(a4)
	move.b $18(a3),d7
	lsr.b d0,d7
	or.b d7,528(a4)
	move.b $20(a3),d7
	lsr.b d0,d7
	or.b d7,704(a4)
	rts

show_dest_track_status

	move.l #errornos,a3		;fill track block status for this
	move.l #screen+(35*176)+1,a4	;disk side
	tst.w side_sel(a2)
	beq.s upper2
	add.w #176*6,a4
upper2	move.w track(a2),d7
	clr.w d0
	btst #0,d7
	beq.s leftnyb2
	moveq #4,d0
leftnyb2	lsr.w #1,d7
	add.w d7,a4
	move.w disk_error(a2),d7
	beq.s noerror2
	add.w #88,a4
noerror2	add.w d7,a3
	bra plotTmark

remove_track_mark

	move.l #screen+(35*176)+1,a4	;erase track mark for this
	tst.w side_sel(a2)		;position only
	beq.s upper3
	add.w #176*6,a4
upper3	move.w track(a2),d7
	move.b #$f,d0
	btst #0,d7
	beq.s leftnyb3
	not.b d0
leftnyb3	lsr.w #1,d7
	add.w d7,a4
	
	moveq #2,d7
cltmlp	and.b d0,(a4)
	and.b d0,176(a4)
	and.b d0,352(a4)
	and.b d0,528(a4)
	and.b d0,704(a4)
	add.w #44,a4
	dbf d7,cltmlp
	rts

clear_track_status

	clr.l $64(a0)
	move.l #$ffffffff,$44(a0)
	move.l #screen+(176*35),$54(a0)
	move.l #$01000000,$40(a0)
	move.w #$0b16,$58(a0)
	bsr wait_blit
	rts

wait_blit	btst #$6,$2(a0)
	bne.s wait_blit
	rts	

display_sentence4

	movem.l a2-a5/d5-d7,-(a7)
	move.l #FOURplanefont,a3	;display a string of characters
	move.l #asciiconv,a5	;(terminated in $a) using the 4 plane
	mulu #176*8,d7		;font. A6 =charstring address
	add.w d6,d7		;d6 = x, d7 = y. All registers
	move.l #screen+(176*30),a4	;preserved EXCEPT A6
	add.w d7,a4
	moveq #0,d5
snt_loop1	move.b (a6)+,d5
	cmpi.b #$a,d5
	beq.s sent_done
	move.b $00(a5,d5.w),d5
	lea $00(a3,d5.w),a2
	moveq #7,d7
snt_loop2	move.b (a2),(a4)
	add.w #58,a2
	add.w #44,a4
	move.b (a2),(a4)
	add.w #58,a2
	add.w #44,a4
	move.b (a2),(a4)
	add.w #58,a2
	add.w #44,a4
	move.b (a2),(a4)
	add.w #58,a2
	add.w #44,a4
	dbf d7,snt_loop2
	sub.w #1407,a4
	bra snt_loop1
sent_done	movem.l (a7)+,a2-a5/d5-d7
	rts


get_strt_trk_bcd

	move.w starttrack(a2),d0	;gets the start track number as BCD
	bsr convert
	move.b d1,track_bcd(a2)
	rts

show_track_no_bcd

	movem.l d0/d1/d7/a4/a3,-(a7)
	clr.w d0
	move.b track_bcd(a2),d0
	move.w d0,d7
	lsr.w #4,d0
	andi.w #$f,d7
	add.w #$10,d0
	add.w #$10,d7
	move.l #screen+(63*176),a4
	moveq #9,d1
	bsr printchar
	move.w d7,d0
	moveq #10,d1
	bsr printchar
	moveq #$0e,d0
	moveq #11,d1
	bsr printchar
	move.w #"U"-$20,d0
	move.w side_sel(a2),d1
	mulu #9,d1
	sub.w d1,d0
	moveq #12,d1
	bsr printchar
	movem.l (a7)+,d0/d1/d7/a4/a3
	rts

next_track_bcd

	move.b track_bcd(a2),d0
	move.w #4,CCR
	moveq #1,d1
	abcd.b d1,d0
	move.b d0,track_bcd(a2)
	rts
				
init_ok_sound
	
	move.w #$d0,$a6(a0)
	move.w #$d2,$b6(a0)
	move.w #$d0,$c6(a0)
	move.w #$d2,$d6(a0)
sound	move.l #sounddata,$a0(a0)
	move.l #sounddata,$b0(a0)
	move.l #sounddata,$c0(a0)
	move.l #sounddata,$d0(a0)
	move.w #$10,$a4(a0)
	move.w #$10,$b4(a0)
	move.w #$10,$c4(a0)
	move.w #$10,$d4(a0)
	move.w #$3f,volume(a2)
	move.w #$800f,$96(a0)
	rts

init_error_sound
	
	move.w #$c00,$a6(a0)
	move.w #$c00,$b6(a0)
	move.w #$c00,$c6(a0)
	move.w #$c00,$d6(a0)
	bra sound

getdiskname

	clr.w total_error(a2)
	move.l #namereq,a6
	bsr showmessage
	clr.w charnumber(a2)
	move.l #diskname,a4
	moveq #30,d7
cdnlp	clr.b (a4)+
	dbf d7,cdnlp

	move.l #screen+(175*176)+3,a4
nxtchr	moveq #95,d0		;print cursor
	clr.w d1
	move.b charnumber+1(a2),d1
	addq.b #5,d1
	bsr printchar

keyup	btst #7,keypressed(a2)
	bne.s keyup	
	clr.w d0
	move.b keypressed(a2),d0
	move.b d0,oldkey(a2)

	cmpi.b #$45,d0
	beq cancel_frmt
	cmpi.b #$44,d0		;return?
	beq gotname
	cmpi.b #$41,d0		;delete?
	bne.s notdel
	
	move.l #diskname+1,a3
	move.w charnumber(a2),d1
	subq.b #1,d1
	bmi samekey		;cannot delete if pos 0	
	clr.b $00(a3,d1.w)
	moveq #0,d0
	clr.w d1
	move.b charnumber+1(a2),d1	;erase cursor character
	addq.w #5,d1
	bsr printchar
	subq.w #1,charnumber(a2)
	bra samekey

notdel	cmpi.w #30,charnumber(a2)
	beq samekey

	move.l #keycdconv,a6
	tst.w shift_on(a2)
	beq.s noshift
	add.w #$80,a6
noshift	move.b $00(a6,d0.w),d0	;ascii character
	beq samekey

	move.l #diskname+1,a3
	move.w charnumber(a2),d1
	move.b d0,$00(a3,d1.w)
	sub.b #32,d0	
	clr.w d1
	move.b charnumber+1(a2),d1
	addq.b #5,d1
	bsr printchar
	addq.w #1,charnumber(a2)
	
samekey	move.b keypressed(a2),d0
	cmp.b oldkey(a2),d0
	beq.s samekey
	bra nxtchr

gotname	move.w charnumber(a2),d0
	beq.s defname
	move.b d0,diskname
	bra namedone

defname	move.l #blankname,a3
	move.l #diskname,a4
	moveq #30,d7
cbnlp	move.b (a3)+,(a4)+
	dbf d7,cbnlp
	
namedone	move.l #rootsect,a5		;recalculate root block
	clr.l $14(a5)		;checksum
	moveq #0,d6
	moveq #$7f,d7
redocslp	add.l (a5)+,d6
	dbf d7,redocslp
	neg.l d6
	move.l d6,rootsect+$14
	clr.w trackmade(a2)
	rts

cancel_frmt

	move.w #$ffff,total_error(a2)
	move.w #1,dont_check(a2)
	rts

***********************
* Format support code *
***********************

* This code will create a MFM track in the format_buffer for the
* track and side specified in variable offsets TRACK and SIDE_SEL

Create_track

	tst.w track(a2)		;make boot trackside?
	bne.s not_bt
	tst.w side_sel(a2)
	beq.s not_bt
	bsr make_boot_track
	bra track_created

not_bt	cmpi.w #40,track(a2)	;make root trackside?
	bne.s not_rt
	tst.w side_sel(a2)
	beq.s not_rt
	bsr make_root_track
	bra track_created
not_rt
	tst.w trackmade(a2)		;normal track in buffer already?
	bne.s track_created
	bsr make_normal_track

track_created
	
	move.w #$ff00,d0		;make top word of header
	move.b track+1(a2),d0	;byte.
	lsl.b #1,d0
	or.b side_sel+1(a2),d0
	eori.b #1,d0
	swap d0

	move.l #format_buffer+$200,a4	;now fill in unclocked HEADER DATA
	moveq #0,d7		;in each sector.
nextsect	
	move.b d7,d0	
	lsl.w #8,d0		;sector number
	move.b #$b,d0
	sub.b d7,d0		;blocks before gap
	
	move.l d0,d1
	move.l d0,d2
	andi.l #$aaaaaaaa,d1
	andi.l #$55555555,d2
	lsr.l #1,d1
	move.l d1,$8(a4)		;put in unclocked header longwords
	move.l d2,$c(a4)		
	eor.l d1,d2		;header checksum longword.
			
	move.l d2,d1
	andi.l #$aaaaaaaa,d1
	andi.l #$55555555,d2
	lsr.l #1,d1
	move.l d1,$30(a4)		;put in unclocked header checksum
	move.l d2,$34(a4)		;longwords.

	lea $8(a4),a3		;now fill in the missing clocks
	moveq #1,d4		;prev data bit = 1 (from sync)
	moveq #3,d6		;longwords to do (part 1)
	bsr fill_clocks

	lea $30(a4),a3		
	moveq #0,d4		;prev data bit = 0 (from padding)
	moveq #5,d6		;longwords to do (part 2)
	bsr fill_clocks

	add.w #$440,a4
	addq.w #1,d7
	cmpi.w #$b,d7		;end sector loop?
	bne.s nextsect
	move.l #format_buffer,write_addr(a2)
	rts


Make_boot_track
	
	move.l #format_buffer,a6
	bsr makegap
	move.l #bootsect,a5
	bsr make_mfm_sector
	add.w #$440,a6
	move.l #bootsect+$200,a5
	bsr make_mfm_sector	
	add.w #$440,a6
	moveq #8,d7
othsect1	move.l #nullsect,a5
	bsr make_mfm_sector
	add.w #$440,a6
	dbf d7,othsect1	
	bsr makegap
	clr.w trackmade(a2)
	rts

Make_normal_track

	move.l #format_buffer,a6
	bsr makegap
	moveq #$a,d7
othsect2	move.l #nullsect,a5
	bsr make_mfm_sector
	add.w #$440,a6
	dbf d7,othsect2
	bsr makegap
	move.w #1,trackmade(a2)
	rts

Make_root_track

	move.l #format_buffer,a6
	bsr makegap
	move.l #rootsect,a5
	bsr make_mfm_sector
	add.w #$440,a6
	move.l #rootsect+$200,a5
	bsr make_mfm_sector	
	add.w #$440,a6
	moveq #8,d7
othsect3	move.l #nullsect,a5
	bsr make_mfm_sector
	add.w #$440,a6
	dbf d7,othsect3
	bsr makegap
	clr.w trackmade(a2)
	rts

makegap	move.w #$ff,d7
gaplp	move.w #$aaaa,(a6)+
	dbf d7,gaplp
	rts


* Make Amiga MFM sector from 512 byte data block.

* Set A5 to Address of Data block to convert.
* Set A6 to Address to place MFM sector.

Make_MFM_Sector

	movem.l a0-a6/d0-d7,-(a7)
	moveq #0,d6		;prev data bit

maketrack_lp	

	btst #0,-$1(a6)
	beq.s prev0
	move.w #$2aaa,(a6)
	bra.s prev1

prev0	move.w #$aaaa,(a6)		;padding
prev1	move.w #$aaaa,$2(a6)	
	move.l #$44894489,$4(a6)	;sync words
	
	move.l #$aaaaaaaa,$10(a6)	;more padding
	move.l #$aaaaaaaa,$14(a6)
	move.l #$aaaaaaaa,$18(a6)	
	move.l #$aaaaaaaa,$1c(a6)
	move.l #$aaaaaaaa,$20(a6)	
	move.l #$aaaaaaaa,$24(a6)
	move.l #$aaaaaaaa,$28(a6)
	move.l #$aaaaaaaa,$2c(a6)
	
* Separate odd / even bits for this data block *

	moveq #0,d0
	lea $40(a6),a3		;store start of block address
	moveq #$7f,d4		;split original block into odd/even
splitloop	move.l (a5)+,d7		;all clock bits low.
	move.l d7,d5
	move.l d7,d6
	andi.l #$aaaaaaaa,d5	;odd bits
	andi.l #$55555555,d6	;even bits
	lsr.l #1,d5
	eor.l d5,d0		;update data checksum
	eor.l d6,d0		;update data checksum
	move.l d5,(a3)
	move.l d6,$200(a3)
	addq.w #4,a3
	dbf d4,splitloop

	move.l d0,d5		;put in unclocked data checksum
	move.l d0,d6
	andi.l #$aaaaaaaa,d5	
	andi.l #$55555555,d6	
	lsr.l #1,d5
	move.l d5,$38(a6)
	move.l d6,$3c(a6)
	move.l d6,d4		;previous longword

* Fill in the data block clocks only *

	move.w #$ff,d6		;longwords to do
	lea $40(a6),a3
	bsr fill_clocks
	movem.l (a7)+,a0-a6/d0-d7
	rts

fill_clocks

	movem.l a3/d2-d4/d7,-(a7)
lw_loop	move.l (a3),d7		;get unclocked mfm longword
	andi.l #$55555555,d7	;remove any clocks just in case

	moveq #30,d2		;bit count
conv_lp	btst d2,d7
	bne.s notzero
	cmpi.w #30,d2		;first bit on right
	bne.s not1st
	
	btst #0,d4		;check last bit for previous
	bne notzero		;longword
	move.l d2,d3
	addq.w #1,d3
	bra zero
	
not1st	move.l d2,d3		;check bit before
	addq.w #2,d3
	btst d3,d7
	bne.s notzero
	subq.w #1,d3
zero	bset d3,d7		;set this clock bit.

notzero	subq.w #2,d2		;next bit in longword
	bpl.s conv_lp

	move.l d7,d4
	move.l d4,(a3)+		;replace the unclckd mfm lw 

	dbf d6,lw_loop		;next longword to do.
end
	movem.l (a7)+,a3/d2-d4/d7
	rts

*****************************************************************************
	
	section kcopydata,data

vars	dcb.w $40,$0

pointerx	   equ $0
pointery	   equ $2
oldmousex    equ $4
oldmousey    equ $5
button_latch equ $6
clicked_box  equ $8
destination  equ $a
check_mode   equ $c
recopy_mode  equ $e
starttrack   equ $10
endtrack     equ $12
irq_occured  equ $14
disk_error   equ $16
track        equ $18
firstsync    equ $1a
re_read      equ $1e
write_addr   equ $20
volume	   equ $24
not_used     equ $26
recopycount  equ $28
sourcestatus equ $2a
use_sides    equ $2c
side_sel     equ $2e
keypressed   equ $30
charnumber   equ $32
oldkey       equ $34
trackmade    equ $36
total_error  equ $38
mouse_lock   equ $3a
rmb_latch    equ $3c
dont_check   equ $3e
adjrng_mode  equ $40
track_bcd	   equ $42

orig_inten 	equ $44
orig_intreq	equ $46
orig_lev2		equ $48
orig_lev3		equ $4c
orig_usp		equ $50
orig_a7		equ $54
orig_dmacon	equ $58
orig_df0		equ $5a
orig_df1		equ $5c
orig_cr1		equ $5e
orig_tl1		equ $5f
orig_th1		equ $60
orig_cr2		equ $61
orig_tl2		equ $62
orig_th2		equ $63
orig_bfd100	equ $64
orig_bfe001	equ $65
orig_adkcon	equ $66
orig_copper	equ $68
shift_on		equ $6c
orig_zero		equ $6e

box_areas	dc.b 8,6,10,13		;1-copy (y,x to y,x)
	dc.b 11,6,13,13		;2-check
	dc.b 15,18,17,24		;3-stop
	dc.b 11,30,13,39		;4-format
	dc.b 11,15,13,28		;5-dest
	dc.b 4,16,6,42		;6-check sys/recopy
	dc.b 15,3,17,16		;7-sides
	dc.b 15,26,17,34		;8-default
	dc.b 8,15,10,28		;9-source
	dc.b 15,36,17,43		;a-quit to dos
	dc.b 8,30,10,39		;b-fetch disk name
	dc.b 0,0,0,0		;c-not used
	dc.b 0,0,0,0		;d-not used
	dc.b 0,0,0,0		;e-not used

bootsect	incbin kc2.5bootblocks

rootsect	incbin kc2.5rootblocks

nullsect	incbin kc2.5blankblock

diskname  equ rootsect+432

nullmsg   dc.b "                                    ",0
welcome   dc.b "WELCOME TO KWIKCOPY 2.5 BY PHIL!94",0
taskdone0	dc.b "TASK COMPLETE: ERRORS!!",0
taskdone1	dc.b "TASK COMPLETE: DISK OK!",0
taskdone2	dc.b "TASK COMPLETE!",0
formting0	dc.b "FORMATTING DISK IN DF0:",0
formting1	dc.b "FORMATTING DISK IN DF1:",0
checking0	dc.b "CHECKING DISK IN DF0:",0 
checking1	dc.b "CHECKING DISK IN DF1:",0
copying0	dc.b "COPYING DF0: TO DF1:",0
copying1	dc.b "COPYING DF1: TO DF0:",0
terminate dc.b "TASK TERMINATED!",0
no_disk0  dc.b "NO DISK IN DF0!",0
no_disk1  dc.b "NO DISK IN DF1!",0
writepro  dc.b "DISK IS WRITE PROTECTED!",0
namereq   dc.b "NAME:",0
nodf1     dc.b "DF1: NOT AVAILABLE!!",0
no_name	dc.b "DISK NAME IS INVALID!",0
goodbye	dc.b "BYE BYE!",0

sidestext	dc.b "UPPER",$a
	dc.b "LOWER",$a
	dc.b "BOTH ",$a

sourcetxt dc.b "DF0:",$a
	dc.b "DF1:",$a

checktxt  dc.b "OFF : NO CHECK! ",$a
	dc.b "DURING:0 RETRIES",$a
	dc.b "AFTER TASK      ",$a

retrytxt	dc.b "0",$a,"1",$a,"2",$a,"3",$a,"4",$a
	dc.b "5",$a,"6",$a,"7",$a,"8",$a,"9",$a

	 even

gfxlib.txt dc.b "graphics.library",$0

errornos	incbin errornumbers.raw

blankname dc.b 22,"Kwikcopy2.5-Blank-Disk",0,0,0,0,0,0,0,0

asciiconv incbin 4planefontsasciiconvtable

keycdconv	incbin Keycode-ascii.table

charmap	 incbin screencharmap

FOURplanefont incbin 4planecset.raw

ONEplanefont  incbin 1planecset.raw

	 even

stack1	dcb.l $80,$0

stack2	dcb.l $80,$0

stack3    dc.l $0

decoded_rootblock dcb.l $80,$0

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

	section chipstuff,data_c

copper1	dc.l $0101ff00,$01060000,$01fc0000
copper2	dc.l $0201ff00,$00e00000,$00e20000,$00e40000
	dc.l $00e60000,$00e80000,$00ea0000,$00ec0000
	dc.l $00ee0000,$01004200,$01020000,$0104003f
	dc.l $008e4480,$009003d0,$00920038,$009400d0
	dc.l $01080088,$010a0088,$01200000,$01220000
	dc.l $01240000,$01260000,$01280000,$012a0000
	dc.l $012c0000,$012e0000,$01300000,$01320000
	dc.l $01340000,$01360000,$01380000,$013a0000
	dc.l $013c0000,$013e0000,$01800000,$018203f1
	dc.l $01840f00,$01860820,$0188008f,$018a0639
	dc.l $018c0457,$018e08ab,$0190095e,$01920a6e
	dc.l $01940b8e,$01960cae,$01980dbf,$019a0edf
	dc.l $019c0eef,$019e0fff,$01a00000,$01a20fff
	dc.l $01a4000f,$01a60008,$01a80000,$01aa00f0
	dc.l $01ac00c0,$01ae0090,$01b00000,$01b20f00
	dc.l $01b40c00,$01b60900,$01b80000,$01ba0000
	dc.l $01bc0000,$01be0000

	dc.l $5a01ff00,$01080086,$010a0086,$01020077
	dc.l $5b01ff00,$008e4470,$009003d0,$00920030
	dc.l $009400d8,$01080084,$010a0084

	dc.l $7a01ff00,$0108ffd4,$010affd4

	dc.l $7e01ff00,$01080086,$010a0086
	dc.l $7f01ff00,$008e4480,$009003d0,$00920038
	dc.l $009400d0,$01020000,$01080088,$010a0088

	dc.l $fffffffe


pointersprite:
	dc.w	$70c0,$7f00
	dc.w	$0004,$FFFC
	dc.w	$7FFC,$800C
	dc.w	$4018,$BFF8
	dc.w	$4030,$BFF0
	dc.w	$4020,$BFE0
	dc.w	$4050,$BFB0
	dc.w	$4028,$BFD8
	dc.w	$4014,$BFEC
	dc.w	$400E,$BFFE
	dc.w	$481C,$BFFC
	dc.w	$5C38,$BFF8
	dc.w	$7670,$B7F0
	dc.w	$63E0,$E3E0
	dc.w	$C1C0,$C1C0
	dc.w	$0080,$0080
	dc.w	$0000,$0000
	dc.w	$0000,$0000

trackstartsprite:	
	dc.w	$5b3b,$7900
	dc.w	$7C7C,$0000
	dc.w	$C6C6,$0000
	dc.w	$C6C6,$0000
	dc.w	$C6C6,$0000
	dc.w	$C6C6,$0000
	dc.w	$7C7C,$0000
	dc.w	$0000,$0000
	dc.w	$0380,$0080
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0280,$0180
	dc.w	$0290,$0180
	dc.w	$02E8,$0190
	dc.w	$0204,$01F8
	dc.w	$03E8,$03F8
	dc.w	$0010,$0010
	dc.w	$0000,$0000
	dc.w	$0000,$0000

trackendsprite:

	dc.w	$62dd,$8001
	dc.w	$0800,$0000
	dc.w	$17C0,$0840
	dc.w	$2040,$1FC0
	dc.w	$1740,$1EC0
	dc.w	$0940,$08C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$0140,$00C0
	dc.w	$01C0,$01C0
	dc.w	$0000,$0000
	dc.w	$7C7C,$0000
	dc.w	$C6C6,$0000
	dc.w	$C6C6,$0000
	dc.w	$C6C6,$0000
	dc.w	$C6C6,$0000
	dc.w	$7C7C,$0000
	dc.w	$0000,$0000
	dc.w	$0000,$0000

checklong dc.l $00000000

padding	dc.l $0,$0,$0,$0,$0,$0,$0,$0

mfm_buffer 
	dcb.l $1c00,$0

format_buffer 

	dcb.l $d00,$0

sounddata	dc.l $7f7f7f7f,$7f7f7f7f,$7f7f7f7f,$7f7f7f7f
	dc.l $80808080,$80808080,$80808080,$80808080

screen	incbin Kwikcopylogo2.raw
	
	dcb.l 44*176,$0

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

