;*---------------------------------------------------------------------------
;  :Program.	cmdc.s
;  :Contents.	command c - create
;  :Author.	Bert Jahn
;  :EMail.	wepl@whdload.org
;  :Address.	Franz-Liszt-Straße 16, Rudolstadt, 07404, Germany
;  :Version	$Id: cmdc.s 1.9 2001/09/20 16:55:46 wepl Exp $
;  :History.	12.06.00 separated from wwarp.asm
;		28.06.00 adapted for _cmdwork
;		06.08.00 inter sector gap check improved
;		24.07.01 trackdisk Update and Clear added before doing a Read
;  :Requires.	OS V37+, MC68020+
;  :Copyright.	©1998-2000 Bert Jahn, All Rights Reserved
;  :Language.	68020 Assembler
;  :Translator.	Barfly V2.9
;  :To Do.
;---------------------------------------------------------------------------*

_cmd_create

	;print announcement
		move.l	#MAXTRACKS-1,d0
		moveq	#0,d1
.pa_0		bftst	(gl_tabarg+wtt_tab,GL){d0:1}
		beq	.pa_1
		addq.l	#1,d1
.pa_1		dbf	d0,.pa_0
		move.l	d1,-(a7)
		move.l	(gl_rd_unit,GL),-(a7)
		pea	(gl_filename,GL)
		lea	(_txt_create),a0
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#12,a7

	;open the device
		move.l	#0,d0
		lea	(gl_io,GL),a0
		bsr	_OpenDevice
		tst.l	d0
		beq	.nodevice

	;set file header
		lea	(gl_headout+wfh_ctime,GL),a0
		move.l	a0,d1
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVODateStamp,a6)
		
	;main loop
		move.l	#CMDF_OUT,d0		;flags
		sub.l	a0,a0			;cbdata
		lea	.tracktable,a1		;cbtt
		lea	.tracks,a2		;cbt
		bsr	_cmdwork

	;close device
		lea	(gl_io,GL),a0
		bsr	_CloseDevice
.nodevice
		rts

.tracktable	lea	(gl_tabarg,GL),a0
		lea	(gl_tabout,GL),a1
		bsr	_copytt
		moveq	#-1,d0
		rts

.tracks		move.l	d0,d6				;D6 = actual track

	;progress output
		lea	(_diskprogress),a0		;output progress
		move.l	d6,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#4,a7
		bsr	_FlushOutput

	;read track
		move.l	(gl_rd_retry,GL),d7		;D7 = read retries

.retryloop

	;check CTRL-C pressed
		bsr	_CheckBreak			;check for CTRL-C
		tst.l	d0
		bne	.error

	;read track
		move.l	d6,d0
		bsr	_cmdc_read
		beq	.error
		
		tst.l	(gl_rd_nostd,GL)
		bne	.nonstd
	;try to decode
		move.l	(gl_rd_bpt,GL),d0
		lsl.l	#3,d0
		move.l	d6,d1
		sf	d2				;no force mode
		bsr	_cmdc_decode
		move.w	d0,d4				;D4 = type
		beq	.nonstd
		move.l	d1,d5				;D5 = length
		move.w	d2,d3				;D3 = flags
	;progress output decoded
		move.w	d4,(gl_trk+wth_type,GL)
		bsr	_gettt
		move.w	(wwf_datalen,a0),-(a7)
		clr.w	-(a7)
		move.l	(wwf_name,a0),-(a7)
		lea	(_decoded),a0
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#8,a7
	;write
		bra	.write

.nonstd
	;try to calculate track length
		move.l	(gl_rd_bpt,GL),d0
		bsr	_cmdc_CalcTrackSize
		move.l	d0,d5				;D5 = length
		beq	.nolen
	;progress output raw single
		lea	(_trklens),a0
		move.l	d5,d3
		lsr.l	#3,d3				;bytes
		move.l	d5,d4
		and.l	#7,d4				;bits
		movem.l	d3-d4,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#8,a7
	;write
		bfclr	([gl_fastbuf,GL]){d5:7}		;alignment
		move.w	#TT_RAW,d4			;D4 = type
		move.w	#TFF_INDEX|TFF_RAWSINGLE,d3	;D3 = flags
		bra	.write

.nolen		subq	#1,d7
		bmi	.writefull
		bsr	_cmdc_movehead
		bra	.retryloop

.writefull
	;progress output raw
		lea	(_trklen),a0
		clr.l	-(a7)
		move.l	(gl_rd_bpt,GL),d5
		move.l	d5,-(a7)
		lsl.l	#3,d5				;D5 = length
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#8,a7
	;write
		move.w	#TT_RAW,d4			;D4 = type
		move.w	#TFF_INDEX,d3			;D3 = flags

	;write track
.write		move	d6,(gl_trk+wth_num,GL)
		move	d4,(gl_trk+wth_type,GL)
		move	d3,(gl_trk+wth_flags,GL)
		move.l	d5,(gl_trk+wth_len,GL)
		clr.l	(gl_trk+wth_wlen,GL)
		lea	(gl_trk+wth_sync,GL),a0
		lea	(gl_trk+wth_mask,GL),a1
		move.b	#SYNCLEN-1,d0
.hc		clr.b	(a0)+
		clr.b	(a1)+
		dbf	d0,.hc
		clr.w	(gl_trk+wth_syncnum,GL)
		
		moveq	#-1,d0
		rts

.error		moveq	#0,d0
		rts

;----------------------------------------
; read raw mfm track
; IN:	D0 = UWORD track number
; OUT:	D0 = BOOL true on success
;	_fastbuf contains mfm data

_cmdc_read	move.w	d0,-(a7)
		clr.w	-(a7)
	;flush trackdisk buffers
		move.l	(gl_io,GL),a1
		move.w	#ETD_UPDATE,(IO_COMMAND,a1)
		clr.b	(IO_FLAGS,a1)
		clr.b	(IO_ERROR,a1)
		move.l	(gl_execbase,GL),a6
		jsr	(_LVODoIO,a6)
		move.l	(gl_io,GL),a1
		move.b	(IO_ERROR,a1),d0
		bne	.err
		move.l	(gl_io,GL),a1
		move.w	#ETD_CLEAR,(IO_COMMAND,a1)
		clr.b	(IO_FLAGS,a1)
		clr.b	(IO_ERROR,a1)
		jsr	(_LVODoIO,a6)
		move.l	(gl_io,GL),a1
		move.b	(IO_ERROR,a1),d0
		bne	.err
	;read mfm
		move.l	(gl_io,GL),a1
		move.l	(a7),d0
		move.l	d0,(IO_OFFSET,a1)
		bsr	_tdenable81
		move.l	(gl_chipbuf,GL),(IO_DATA,a1)
		move.l	(gl_rd_bpt,GL),(IO_LENGTH,a1)
		move.w	#ETD_RAWREAD,(IO_COMMAND,a1)
		move.b	#IOTDF_INDEXSYNC|IOF_QUICK,(IO_FLAGS,a1)
		clr.b	(IO_ERROR,a1)
		move.l	(IO_DEVICE,a1),a6
		jsr	(-$1e,a6)
		move.l	(gl_io,GL),a1
		move.l	(gl_execbase,GL),a6
		jsr	(_LVOWaitIO,a6)
		move.l	(gl_io,GL),a1
		bsr	_tddisable81
		move.b	(IO_ERROR,a1),d0
		bne	.err
	;copy mfm data to fast mem for better performance
		move.l	(gl_rd_bpt,GL),d0
		bsr	_copy_c2f

		moveq	#-1,d0
		addq.l	#4,a7
		rts

.err		lea	(_readdisk),a0
		bsr	_PrintErrorTD
		moveq	#0,d0
		addq.l	#4,a7
		rts

;----------------------------------------
; copy _chipbuf to _fastbuf
; IN:	D0 = ULONG bytes to copy
;	_chipbuf
; OUT:	_fastbuf contains mfm data

_copy_c2f	move.l	(gl_chipbuf,GL),a0
		move.l	(gl_fastbuf,GL),a1
		cmp.l	a0,a1
		beq	.ok
		addq.l	#3,d0
		lsr.l	#2,d0
		subq.w	#1,d0
.cp		move.l	(a0)+,(a1)+
		dbf	d0,.cp
.ok		rts

;----------------------------------------
; try to decode track as known format
; IN:	D0 = ULONG length of raw mfm-data in bits
;	D1 = UWORD track number
;	D2 = BOOL  force decoding
;	gl_fastbuf mfm data
; OUT:	D0 = ULONG track type identified
;	D1 = ULONG decoded data length in bits!
;	D2 = ULONG track flags
;	gl_fastbuf contains decoded data

_cmdc_decode	movem.l	d4-d7/a2,-(a7)

		move.l	d0,d7
		move.l	d1,d6
		move.w	#wwf_decode,d4
		tst.b	d2
		beq	.nof
		move.w	#wwf_decodefrc,d4
.nof
		lea	(_formats),a2
.next
		move.l	d7,d0
		move.l	d6,d1
		jsr	([a2,d4.w])
		tst.l	d0
		bne	.found
		
		move.l	(wwf_succ,a2),d0
		beq	.no
		move.l	d0,a2
		bra	.next

.found		moveq	#0,d0
		move.w	(wwf_type,a2),d0	;type
		moveq	#0,d1
		move.w	(wwf_datalen,a2),d1	;length
		moveq	#0,d2			;flags

	;all lw's equal
		move.l	(gl_fastbuf,GL),a0
		move.l	d1,d6
		lsr.l	#2,d6
		subq.w	#2,d6
		move.l	(a0)+,d7
.eq		cmp.l	(a0)+,d7
		dbne	d6,.eq
		bne	.neq
		move.l	#4,d1
		or.w	#TFF_LEQ,d2
		bra	.end
.neq

	;each sector with lw's incremented
		cmp.l	#$1600,d1
		bne	.ninc
		move.l	(gl_fastbuf,GL),a0
		lea	($1600,a0),a1
		moveq	#11-1,d5
.inc2		moveq	#$200/4-2,d6
		move.l	(a0)+,d7
		move.l	d7,(a1)+
.inc		addq.l	#1,d7
		cmp.l	(a0)+,d7
		dbne	d6,.inc
		dbne	d5,.inc2
		bne	.ninc
		moveq	#11-1,d5
.inc3		move.l	-(a1),(-$1600,a1)
		dbf	d5,.inc3
		move.l	#4*11,d1
		or.w	#TFF_SLINC,d2		;sector long incremented
		bra	.end
.ninc

.end		lsl.l	#3,d1			;length in bits
		movem.l	(a7)+,d4-d7/a2
		rts

.no		moveq	#0,d0
		bra	.end

;----------------------------------------
; calculate track length if possible
; IN:	D0 = ULONG length of raw mfm-data in bytes
;	_fastbuf mfm data
; OUT:	D0 = ULONG size in bits if successful, otherwise 0

_cmdc_CalcTrackSize
		movem.l	d2-d7/a2,-(a7)

		move.l	d0,d5			;D5 = mfm-length
		move.l	(gl_fastbuf,GL),a0	;A0 = buffer start
		move.l	#MINTRACKLEN*8,d0	;D0 = actual offset (track size)

.s		move.l	a0,a1			;A1 = actual p1
		move.l	d0,d1
		lsr.l	#5,d1			;/32
		lsl.l	#2,d1			;*4
		lea	(a1,d1.l),a2
		
.n		bfextu	(a1){d0:32},d7
		cmp.l	(a1)+,d7
		bne	.ne
		cmp.l	a1,a2
		bhi	.n
		move.l	d0,d1
		and.w	#31,d1			;how many bits are left to compare ?
		beq	.eq
		bfextu	(a1){d0:d1},d7
		bfextu	(a1){0:d1},d6
		cmp.l	d6,d7
		bne	.ne
.eq		movem.l	(a7)+,_MOVEMREGS
		rts

.ne		addq.l	#1,d0
		move.l	d0,d1
		add.l	d1,d1			;track must fit two times in the raw buffer
		add.l	#7,d1			;round up
		lsr.l	#3,d1			;in bytes
		cmp.l	d5,d1
		bls	.s

		moveq	#0,d0
		movem.l	(a7)+,_MOVEMREGS
		rts

;----------------------------------------
; move head
; IN:	D6 = ULONG actual track
; OUT:	-

_cmdc_movehead
		move.l	d6,d0
		lsr.l	#1,d0			;cylinder

		lea	(.data),a0
		cmp.w	(a0),d6
		beq	.calc
.init
		move.w	d6,(a0)			;set new track
		clr.w	(2,a0)			;offset
.calc
		move.w	(2,a0),d1		;offset
		addq.w	#2,(2,a0)
		cmp.w	#.liste-.list,d1
		beq	.init
		
		add.w	(4,a0,d1.w),d0
		bpl	.1
		moveq	#1,d0
.1		cmp.w	#MAXTRACKS/2,d0
		blo	.2
		move.w	#MAXTRACKS/2-2,d0
.2

		move.l	d0,-(a7)
	IFD DEBUG
		lea	.s,a0
		move.l	a7,a1
		bsr	_PrintArgs
		bra	.ss
.s		dc.b	"»%ld",0
	EVEN
.ss
	ELSE
		move.l	#"."<<24,-(a7)
		move.l	a7,a0
		bsr	_Print
		addq.l	#4,a7
	ENDC
		bsr	_FlushOutput
		move.l	(a7)+,d0

		mulu	#2*$1600,d0
		add.l	#$1600,d0

		move.l	(gl_io,GL),a1
		move.l	d0,(IO_OFFSET,a1)
		divu.l	#$1600,d0
		bsr	_tdenable81
		move.w	#ETD_SEEK,(IO_COMMAND,a1)
		clr.b	(IO_ERROR,a1)
		move.l	(gl_execbase,GL),a6
		jsr	(_LVODoIO,a6)
		move.l	(gl_io,GL),a1
		bsr	_tddisable81
		move.b	(IO_ERROR,a1),d0
		bne	.err

		rts

.err		lea	(_movehead),a0
		bra	_PrintErrorTD

.data		dc.w	-1		;actual cylinder
		dc.w	0		;offset in list
.list		dc.w	0,0,1,0,0,0,-1,0
.liste

