;*---------------------------------------------------------------------------
;  :Program.	WWarp.asm
;  :Contents.	Disk-Warper
;  :Author.	Bert Jahn
;  :EMail.	wepl@whdload.org
;  :Address.	Franz-Liszt-Straße 16, Rudolstadt, 07404, Germany
;  :Version	$Id: WWarp.asm 1.20 2000/08/06 13:13:01 jah Exp jah $
;  :History.	29.08.98 started
;		20.09.98 reading of std tracks added, and major rework
;		22.09.98 tracksize calculation added
;		08.10.98 def-tracklen changed from $7c00 to $6c00 (harry)
;		07.11.99 major rework started
;		24.12.99 varios stuff enhanced
;		28.05.00 gremlin format added, movehead fixed
;		21.06.00 writing std/gremlin added
;		28.06.00 remove fixed, _cmdwork improved
;		06.08.00 FORCE now skips all tracks which cannot be decoded
;  :Requires.	OS V37+, MC68020+
;  :Copyright.	©1998-2000 Bert Jahn, All Rights Reserved
;  :Language.	68020 Assembler
;  :Translator.	Barfly V2.9
;  :To Do.
;---------------------------------------------------------------------------*
;##########################################################################

	INCDIR	Includes:
	INCLUDE	lvo/exec.i
	INCLUDE	exec/execbase.i
	INCLUDE	exec/io.i
	INCLUDE	exec/memory.i
	INCLUDE	lvo/dos.i
	INCLUDE	dos/datetime.i
	INCLUDE	dos/dos.i
	INCLUDE	devices/trackdisk.i
	
	INCLUDE	macros/ntypes.i

;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

DEFTRACKS	= 160		;default amount tracks to process
MAXTRACKS	= 160		;amount tracks which can be procecced (currently)

;length for mfm raw reads
MINTRACKLEN	= $3000		;minimal track length (limited physical)
DEFTRACKLEN	= $6c00		;default track length
MAXTRACKLEN	= $7ffe		;maximal track length (limited by trackdisk.device)
DEFREADRETRY	= 6

FILEID		= "WWRP"
FILEVER		= 1
CREATORLEN	= 42

	STRUCTURE	WWarpFileHeader,0
		ULONG	wfh_id			;FILEID
		UWORD	wfh_ver			;structure format version
		STRUCT	wfh_creator,CREATORLEN	;creator of wwarp file
		STRUCT	wfh_ctime,ds_SIZEOF	;date of creation
		STRUCT	wfh_mtime,ds_SIZEOF	;date of last modification
		LABEL	wfh_SIZEOF

TABLEID		= "TABL"
TABLEVER	= 1

	STRUCTURE	WWarpTrackTable,0
		ULONG	wtt_id			;TABLEID
		UWORD	wtt_ver			;structure format version
		UWORD	wtt_first		;first track in list
		UWORD	wtt_last		;last track in list
		LABEL	wtt_tab			;track table, one bit for each track 

TRACKID		= "TRCK"
TRACKVER	= 1
SYNCLEN		= 16

	STRUCTURE	WWarpTrackHeader,0
		ULONG	wth_id			;TRACKID
		UWORD	wth_ver			;structure format version
		UWORD	wth_num			;track number
		UWORD	wth_type		;track data format type
		UWORD	wth_flags		;flags
		ULONG	wth_len			;length of data contained in wwp in bits!
		ULONG	wth_wlen		;lengtn of data to write back in bytes!
		STRUCT	wth_sync,SYNCLEN	;sync
		STRUCT	wth_mask,SYNCLEN	;sync mask (used bits in wth_sync)
		LABEL	wth_data		;track data

;track types

 ENUM 0
 EITEM TT_RAW		;raw mfm data
 EITEM TT_STD		;standard dos format ($1600 bytes)
 EITEM TT_GREM		;gremlin format ($1800 bytes)

;track flags

 BITDEF TF,INDEX,0	;track data starts with index signal (only TT_RAW)
 BITDEF TF,BZIP2,1	;copressed wih bzip2
 BITDEF TF,RAWSINGLE,2	;raw mfm data is saved in exact bit length
 BITDEF TF,LEQ,3	;all longs equal
 BITDEF TF,SLINC,4	;sector longs incremented

FILENAMELEN	= 1024

	STRUCTURE	Globals,0
		APTR	gl_execbase
		APTR	gl_dosbase
		APTR	gl_rdargs
		LABEL	gl_rdarray
		ULONG	gl_rd_file		;name of the wwarp file
		ULONG	gl_rd_cmd		;operation to perform
		ULONG	gl_rd_tracks		;affected tracks
		ULONG	gl_rd_arg		;further argument depending on operation
		ULONG	gl_rd_bpt		;bytes per track
		ULONG	gl_rd_unit		;drive unit
		ULONG	gl_rd_nostd		;dont try to read std format
		ULONG	gl_rd_retry		;how many read retries
		ULONG	gl_rc			;programs return code
		APTR	gl_chipbuf
		APTR	gl_fastbuf
		ALIGNLONG
		STRUCT	gl_DateTime,dat_SIZEOF
		STRUCT	gl_date,LEN_DATSTRING
		STRUCT	gl_time,LEN_DATSTRING
		STRUCT	gl_headin,wfh_SIZEOF	;file header input
		STRUCT	gl_headout,wfh_SIZEOF	;file header output
		STRUCT	gl_tabarg,wtt_tab+MAXTRACKS/8	;tracks specified via command line
							;default = argument || tabin
		STRUCT	gl_tabin,wtt_tab+MAXTRACKS/8	;tracks contained in input file
		STRUCT	gl_tabread,wtt_tab+MAXTRACKS/8	;tracks to read from the input file
							;default = 0
		STRUCT	gl_tabout,wtt_tab+MAXTRACKS/8	;tracks to write to the output file
							;default = tabin
		STRUCT	gl_tabdo,wtt_tab+MAXTRACKS/8	;tracks on which user func will called
							;default = tabarg
		STRUCT	gl_trk,wth_data
		STRUCT	gl_filename,FILENAMELEN
		STRUCT	gl_filename2,FILENAMELEN
		STRUCT	gl_io,8			;normal iorequest,msgport
		STRUCT	gl_ioi,8		;indexsync iorequest,msgport
		STRUCT	gl_sync,SYNCLEN*2
		STRUCT	gl_tmpbuf,$1800
		BYTE	gl_break
		ALIGNLONG
		LABEL	gl_SIZEOF

;##########################################################################

GL	EQUR	A4		;a4 ptr to Globals
LOC	EQUR	A5		;a5 for local vars
CPU	=	68020

	OUTPUT	C:WWarp
	BOPT	O+		;enable optimizing
	;BOPT	OG+		;enable optimizing
	BOPT	ODd-		;disable mul optimizing
	BOPT	ODe-		;disable mul optimizing
	BOPT	wo-		;no optimize warnings

	IFND	.passchk
	DOSCMD	"WBuild >T:build"
	DOSCMD	"WDate  >T:date"
.passchk
	ENDC

Version		= 1
Revision	= 6

	SECTION a,CODE

		bra	_Start

		dc.b	"$VER: "
_txt_creator	sprintx	"WWarp %ld.%ld [build ",Version,Revision
		INCBIN	"T:build"
		dc.b	"] "
		INCBIN	"T:date"
		dc.b	0
		dc.b	"$Id: WWarp.asm 1.20 2000/08/06 13:13:01 jah Exp jah $",0
	EVEN

;##########################################################################

	INCDIR	Sources:
	INCLUDE	dosio.i
		PrintLn
		PrintArgs
		CheckBreak
		FlushOutput
		GetKey
	INCLUDE	strings.i
		atoi
		etoi
		AppendString
		StrNCaseCmp
		CopyString
		StrLen
	INCLUDE	error.i
		PrintErrorDOS
		PrintErrorTD

;##########################################################################

_StartErr	moveq	#33,d0			;kick 1.2
		lea	(_dosname),a1
		jsr	(_LVOOpenLibrary,a6)
		tst.l	d0
		beq	.q
		move.l	d0,a6
		jsr	(_LVOOutput,a6)
		move.l	d0,d1			;file handle
		move.l	(a7)+,d2
		move.l	d2,a0
		moveq	#-1,d3
.c		addq.l	#1,d3
		tst.b	(a0)+
		bne	.c
		jsr	(_LVOWrite,a6)
		move.l	a6,a1
		move.l	(gl_execbase,GL),a6
		jsr	(_LVOCloseLibrary,a6)
.q		move.l	(gl_rc,GL),d0
		rts

	;program start
_Start		lea	(_Globals),GL
		move.l	#RETURN_FAIL,(gl_rc,GL)
		move.l	(4).w,a6
		move.l	a6,(gl_execbase,GL)

	;check cpu
		btst	#AFB_68020,(AttnFlags+1,a6)
		bne	.cpuok
		pea	(_badcpu)
		bra	_StartErr
.cpuok
	MC68020
	;open dos.library
		move.l	#37,d0
		lea	(_dosname),a1
		move.l	(gl_execbase,GL),a6
		jsr	_LVOOpenLibrary(a6)
		move.l	d0,(gl_dosbase,GL)
		bne	.dosok
		pea	(_badkick)
		bra	_StartErr
.dosok
	;read arguments
		lea	(_template),a0
		move.l	a0,d1
		lea	(gl_rdarray,GL),a0
		move.l	a0,d2
		moveq	#0,d3
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOReadArgs,a6)
		move.l	d0,(gl_rdargs,GL)
		bne	.argsok
		lea	(_readargs),a0
		bsr	_PrintErrorDOS
		bsr	_help
		bra	.noargs
.argsok
	;check filename
		move.l	(gl_rd_file,GL),a0
		lea	(gl_filename,GL),a1
		move.l	#FILENAMELEN,d0
		bsr	_CopyString
		lea	(gl_filename,GL),a0
		bsr	_StrLen
		cmp.l	#4,d0
		bls	.cs_1
		lea	(gl_filename-4.w,GL,d0.l),a0
		lea	(_extension),a1
		moveq	#4,d0
		bsr	_StrNCaseCmp
		tst.l	d0
		beq	.cs_end
.cs_1		lea	(gl_filename,GL),a0
		move.l	a0,d1
		move.l	#ACCESS_READ,d2
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOLock,a6)
		move.l	d0,d1
		beq	.cs_2
		jsr	(_LVOUnLock,a6)
		bra	.cs_end
.cs_2		lea	(_extension),a0
		lea	(gl_filename,GL),a1
		move.l	#FILENAMELEN,d0
		bsr	_AppendString
.cs_end

	;parse tracks
		move	#0,(gl_tabarg+wtt_first,GL)
		move	#MAXTRACKS-1,(gl_tabarg+wtt_last,GL)
		move.l	(gl_rd_tracks,GL),a0
		move.l	a0,d0
		beq	.pt_def
		cmp.w	#"*"<<8,(a0)
		bne	.pt_loop
		clr.l	(gl_rd_tracks,GL)
.pt_def		move.l	#DEFTRACKS-1,d0
.pt_1		bfset	(gl_tabarg+wtt_tab,GL){d0:1}
		dbf	d0,.pt_1
		bra	.pt_end

.pt_loop	bsr	.pt_getnum
		move.b	(a0)+,d1
		beq	.pt_single
		cmp.b	#",",d1
		beq	.pt_single
		cmp.b	#"-",d1
		beq	.pt_area
		cmp.b	#"*",d1
		beq	.pt_step
		bra	.pt_err

.pt_single	bfset	(gl_tabarg+wtt_tab,GL){d0:1}
.pt_check	tst.b	d1
		beq	.pt_end
		cmp.b	#",",d1
		beq	.pt_loop
		bra	.pt_err
		
.pt_step	move.l	d0,d2			;D2 = start
		move.l	#DEFTRACKS-1,d3		;D3 = last
.pt_step0	bsr	.pt_getnum		;D0 = skip
		tst.l	d0
		ble	.pt_err
.pt_step1	cmp.l	d2,d3
		blo	.pt_err
.pt_step_l	bfset	(gl_tabarg+wtt_tab,GL){d2:1}
		add.l	d0,d2
		cmp.l	d2,d3
		bhs	.pt_step_l
		move.b	(a0)+,d1
		bra	.pt_check

.pt_area	move.l	d0,d2			;D2 = start
		bsr	.pt_getnum
		move.l	d0,d3			;D3 = last
		moveq	#1,d0			;D0 = skip
		cmp.b	#"*",(a0)
		bne	.pt_step1
		addq.l	#1,a0
		bra	.pt_step0

.pt_getnum	move.l	(a7)+,a1
		move.l	a0,a3
		bsr	_atoi
		cmp.l	a0,a3
		beq	.pt_err
		cmp.l	#MAXTRACKS,d0
		bhs	.pt_err
		jmp	(a1)

.pt_err		lea	(_txt_badtracks),a0
		bsr	_PrintBold
		bsr	_help
		bra	.badargs

.pt_end
		move.l	#MAXTRACKLEN,d2		;D2 = maximal rawreadlen
		move.l	#DEFTRACKLEN,d0		;default tracklength
		move.l	(gl_rd_bpt,GL),d1
		beq	.bptok
		move.l	d1,a0
		bsr	_atoi
		addq.l	#1,d0
		bclr	#0,d0			;word aligned
		cmp.l	d2,d0
		blt	.bptok
		move.l	d2,d0
.bptok		move.l	d0,(gl_rd_bpt,GL)

		move.l	(gl_rd_unit,GL),d0
		beq	.unitok
		move.l	d0,a0
		move.l	(a0),d0
.unitok		move.l	d0,(gl_rd_unit,GL)

		move.l	#DEFREADRETRY,d1
		move.l	(gl_rd_retry,GL),d0
		beq	.retryok
		move.l	d0,a0
		move.l	(a0),d1
.retryok	move.l	d1,(gl_rd_retry,GL)

	;init globals
		lea	(_chipbuf),a0
		move.l	a0,(gl_chipbuf,GL)
		move.l	#MAXTRACKLEN,d0
		move.l	#MEMF_FAST,d1
		move.l	(gl_execbase,GL),a6
		jsr	(_LVOAllocVec,a6)
		move.l	d0,(gl_fastbuf,GL)
		bne	.memok
		move.l	(gl_chipbuf,GL),(gl_fastbuf,GL)
.memok
		pea	(.return)
		move.l	(gl_rd_cmd,GL),d0
		beq	_cmd_create
		move.l	d0,a0
		move.b	(a0)+,d0
		tst.b	(a0)
		bne	_cmd_bad
		UPPER	d0
		cmp.b	#"C",d0
		beq	_cmd_create
		cmp.b	#"D",d0
		beq	_cmd_dump
		cmp.b	#"F",d0
		beq	_cmd_force
		cmp.b	#"I",d0
		beq	_cmd_info
		cmp.b	#"L",d0
		beq	_cmd_length
		cmp.b	#"M",d0
		beq	_cmd_merge
		cmp.b	#"P",d0
		beq	_cmd_pack
		cmp.b	#"R",d0
		beq	_cmd_remove
		cmp.b	#"S",d0
		beq	_cmd_save
		cmp.b	#"Y",d0
		beq	_cmd_sync
		cmp.b	#"W",d0
		beq	_cmd_write
		bra	_cmd_bad
.return
	;free globals
		move.l	(gl_fastbuf,GL),a1
		cmp.l	(gl_chipbuf,GL),a1
		beq	.fgle
		move.l	(gl_execbase,GL),a6
		jsr	(_LVOFreeVec,a6)
.fgle
.badargs
		move.l	(gl_rdargs,GL),d1
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOFreeArgs,a6)
.noargs
		move.l	(gl_dosbase,GL),a1
		move.l	(gl_execbase,GL),a6
		jsr	(_LVOCloseLibrary,a6)
.nodoslib
		move.l	(gl_rc,GL),d7
_rts		rts

;##########################################################################

_cmd_bad	lea	(_txt_badcmd),a0
		bsr	_PrintBold

_help		lea	(_txt_help),a0
		bra	_Print

;##########################################################################
;##########################################################################

	INCLUDE	cmdc.s

;##########################################################################
;##########################################################################

_cmd_dump	moveq	#0,d4			;D4 = sync specified
		moveq	#1,d5			;D5 = sync num
		moveq	#0,d6			;D6 = length
		moveq	#0,d7			;D7 = offset

	;parse argument
		move.l	(gl_rd_arg,GL),d0
		beq	.argend
		move.l	d0,a2			;A2 = arg
	;sync
		cmp.b	#",",(a2)
		beq	.send
		move.l	a2,a0
.sl		move.b	(a0)+,d0
		beq	.se
		cmp.b	#",",d0
		bne	.sl
.se		move.b	-(a0),d2
		clr.b	(a0)
		exg.l	a0,a2
		bsr	_parsesync
		tst.l	d0
		beq	_rts
		moveq	#-1,d4
		move.b	d2,(a2)
	;sync num
.send		cmp.b	#",",(a2)+
		bne	.arglast
		cmp.b	#",",(a2)
		beq	.snend
		move.l	a2,a0
		bsr	_atoi
		cmp.l	a0,a2
		beq	.argerr
		move.l	a0,a2
		move.l	d0,d5
		ble	.argerr
	;length
.snend		cmp.b	#",",(a2)+
		bne	.arglast
		cmp.b	#",",(a2)
		beq	.lend
		move.l	a2,a0
		bsr	_etoi
		cmp.l	a0,a2
		beq	.argerr
		move.l	a0,a2
		move.l	d0,d6
		ble	.argerr
	;offset
.lend		cmp.b	#",",(a2)+
		bne	.arglast
		move.l	a2,a0
		bsr	_etoi
		cmp.l	a0,a2
		beq	.argerr
		move.l	d0,d7
		lea	(1,a0),a2
.arglast	tst.b	-(a2)
		bne	.argerr
.argend
		move.l	#CMDF_IN,d0		;flags
		movem.l	d4-d7,-(a7)
		move.l	a7,a0			;cbdata
		lea	.tracktable,a1		;cbtt
		lea	.tracks,a2		;cbt
		bsr	_cmdwork
		add.w	#16,a7
		rts

.argerr		lea	(_badarg),a0
		bra	_Print

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

.tracks		movem.l	d2-d7/a2-a3,-(a7)
		move.l	a0,a3			;a3 = cbdata

	;display track info
		move.l	(gl_trk+wth_wlen,GL),-(a7)
		move.l	(gl_trk+wth_len,GL),d0
		move.l	d0,d1
		and.l	#7,d1
		lsr.l	#3,d0
		movem.l	d0-d1,-(a7)
		moveq	#" ",d0
		btst	#TFB_INDEX,(gl_trk+wth_flags+1,GL)
		beq	.fi
		moveq	#"I",d0
.fi		move.l	d0,-(a7)
		bsr	_gettt
		pea	(a0)
		move.l	d5,-(a7)
		lea	(_dump1),a0
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#6*4,a7
		lea	(gl_trk+wth_sync,GL),a0
		bsr	_printsync
		bsr	_PrintLn

	;search syncs
		moveq	#0,d7				;d7 = bitoffset in buffer to display
		cmp.w	#TT_RAW,(gl_trk+wth_type,GL)
		bne	.dsend
		lea	(gl_sync,GL),a2			;a2 = sync (via arg)
		tst.l	(a3)
		bne	.syncarg
		lea	(gl_trk+wth_sync,GL),a2		;a2 = sync (from track header)
.syncarg	move.l	a2,a0
		bsr	_testsync
		tst.l	d0
		beq	.dsend
		moveq	#0,d2				;d2 = bitoffset in buffer
		move.l	(gl_trk+wth_len,GL),d3		;d3 = bitlength buffer
		move.l	(gl_trk+wth_flags,GL),d0
		btst	#TFF_RAWSINGLE,d0
		bne	.dsraws
.dsraw		sub.l	#SYNCLEN*8-1,d3
		move.l	#DEFTRACKLEN/2*8,d0
		cmp.l	d0,d3
		bls	.dsgo
		move.l	d0,d3
		bra	.dsgo
.dsraws		bsr	_doubleraws
.dsgo		moveq	#0,d4				;d4 = num of sync found
.dsloop		move.l	d2,d0
		move.l	d3,d1
		move.l	(gl_fastbuf,GL),a0
		move.l	a2,a1
		bsr	_searchsync
		move.l	d0,d2
		bmi	.dsprint
		addq.l	#1,d4
		cmp.l	(4,a3),d4
		bhi	.ds1
		move.l	d2,d7
.ds1		addq.l	#1,d2
		cmp.l	d3,d2
		blo	.dsloop
.dsprint	lea	(_syncfound1),a0
		bsr	_Print
		move.l	a2,a0
		bsr	_printsync
		lea	(_syncfound2),a0
		move.l	d4,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#4,a7
		move.l	d7,d0
		bsr	_printbitlen
		bsr	_PrintLn
.dsend
	;dump
		move.l	(gl_trk+wth_len,GL),d4		;d4 = buffersize in bits
	;offset
		move.l	(12,a3),d6			;d6 = offset in bytes
		move.l	d6,d0
		asl.l	#3,d0				;in bits
		add.l	d0,d7				;d7 = shift + offset
		bmi	.offerr
		beq	.endshift
		cmp.l	d7,d4
		ble	.offerr
		move.w	(gl_trk+wth_flags,GL),d0
		btst	#TFF_RAWSINGLE,d0
		beq	.single
		sub.l	d7,d4
.single		move.l	d7,d0
		move.l	d4,d1				;bitlen new buffer
		move.l	(gl_fastbuf,GL),a0		;buffer
		bsr	_shiftmfm
.endshift	addq.l	#7,d4
		lsr.l	#3,d4				;d4 = buffersize in bytes
	;length
		move.l	(8,a3),d0			;length
		bne	.len1
		move.l	(gl_trk+wth_wlen,GL),d0
		beq	.lenok
.len1		cmp.l	d0,d4
		bls	.lenok
		move.l	d0,d4
.lenok
	;dump
		move.l	d4,d0				;length
		move.l	d6,d1				;delta
		move.l	(gl_fastbuf,GL),a0		;memory
		bsr	_DumpMemory

	;return
		moveq	#-1,d0				;success
.end		movem.l	(a7)+,d2-d7/a2-a3
		rts

.offerr		lea	(_offerr),a0
		bsr	_Print
		moveq	#0,d0
		bra	.end

;----------------------------------------
; dump memory
; IN:	d0 = ULONG len
;	d1 = ULONG delta
;	a0 = APTR  memory
; OUT:	d0 = BOOL success

_DumpMemory	movem.l	d1/d5-d6/a2-a3,-(a7)
		move.l	a0,a2			;A2 = actual address
		lea	(a2,d0.l),a3		;A3 = end address
		clr.w	(a7)

.line		bsr	_CheckBreak		;check for CTRL-C
		tst.l	d0
		bne	.break

		lea	(.adr),a0
		lea	(2,a7),a1
		bsr	_PrintArgs
		
		moveq	#7,d6
		
.mem		lea	(.space),a0
		bsr	_Print
		
		moveq	#3,d5

.long		lea	(.byte),a0
		move.b	(a2)+,(1,a7)
		move.l	a7,a1
		bsr	_PrintArgs
		addq.w	#1,(2,a7)
		cmp.l	a2,a3
		bls	.ok
		
		dbf	d5,.long

		dbf	d6,.mem

.ok		bsr	_PrintLn

		cmp.l	a2,a3
		bhi	.line
		
.break		movem.l	(a7)+,_MOVEMREGS
		rts

.adr		dc.b	"$%04x",0
.space		dc.b	" ",0
.byte		dc.b	"%02x",0
	EVEN

;##########################################################################
;##########################################################################

_cmd_force	move.l	#CMDF_OUT|CMDF_IN,d0	;flags
		sub.l	a0,a0			;cbdata
		lea	.tracktable,a1		;cbtt
		lea	.tracks,a2		;cbt
		bra	_cmdwork

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

.tracks
	;check type
		cmp.w	#TT_RAW,(gl_trk+wth_type,GL)
		bne	.badtype

	;if single -> double
		bsr	_doubleraws
		move.l	d0,d5			;D5 = mfm length

	;search start
		moveq	#0,d0
		move.l	d5,d1
		move.l	(gl_fastbuf,GL),a0
		lea	(_syncstd2),a1
		bsr	_searchsync
		move.l	d0,d6			;D6 = offset
		bmi	.nosync

	;check that remaining mfm data is sufficent
		sub.l	d6,d5			;in bits
		cmp.l	#11*$440*8,d5
		blo	.shortmfm

	;decode track
		move.l	#%11111111111,d4	;D4 = sectors
		move.l	#$55555555,d5		;D5 = mfm decode
		moveq	#11-1,d7		;D7 = sector loop count
		move.l	(gl_fastbuf,GL),a0	;A0 = mfm buffer
		subq.l	#4,a0			;first $aaaaaaaa

.sector		bsr	.getlw			;$2aaaaaaa
		bsr	.getlw			;$44894489
		cmp.l	#$44894489,d0
		bne	.no
		
		moveq	#0,d3			;D3 = chksum

		bsr	.getlwd			;sector header
		
		lsr.l	#8,d0			;sector number 0..10
		cmp.b	#10,d0
		bhi	.no
		bclr	d0,d4
		beq	.no			;same sector again
		moveq	#0,d1
		move.b	d0,d1
		mulu	#$200,d1
		lea	(gl_tmpbuf.w,GL,d1.l),a1
		
		moveq	#3,d2
.label		bfextu	(a0){d6:32},d0
		bfextu	(16,a0){d6:32},d1
		eor.l	d0,d3
		eor.l	d1,d3
		and.l	d5,d0
		bne	.no
		and.l	d5,d1
		bne	.no
		addq.l	#4,a0
		dbf	d2,.label
		add.w	#16,a0

		move.l	d3,d2
		and.l	d5,d2
		bsr	.getlwd			;header chksum
		cmp.l	d2,d0
		bne	.no
		
		bsr	.getlwd			;data chksum
		move.l	d0,d3

		moveq	#$200/4-1,d2
.data		bfextu	(a0){d6:32},d0
		bfextu	($200,a0){d6:32},d1
		eor.l	d0,d3
		and.l	d5,d0
		eor.l	d1,d3
		and.l	d5,d1
		add.l	d0,d0
		addq.l	#4,a0
		or.l	d0,d1
		move.l	d1,(a1)+
		dbf	d2,.data
		add.w	#$200,a0
		
		and.l	d5,d3
		bne	.no
		
		dbf	d7,.sector
		
	;copy buffer
		move.w	#$1600/4-1,d0
		lea	(gl_tmpbuf,GL),a0
		move.l	(gl_fastbuf,GL),a1
.copy		move.l	(a0)+,(a1)+
		dbf	d0,.copy

	;set track header
		move.w	#TT_STD,(gl_trk+wth_type,GL)
		move.w	#0,(gl_trk+wth_flags,GL)
		move.l	#$1600*8,(gl_trk+wth_len,GL)

		moveq	#-1,d0
		rts

.getlw		bfextu	(a0){d6:32},d0
		addq.l	#4,a0
		eor.l	d0,d3
		rts

.getlwd		bsr	.getlw
		move.l	d0,d1
		bsr	.getlw
		and.l	d5,d1
		and.l	d5,d0
		add.l	d1,d1
		or.l	d1,d0
		rts

.badtype	lea	(_forcebadtype),a0
		bra	.print
.nosync		lea	(_forcenosync),a0
		bra	.print
.shortmfm	lea	(_forceshortmfm),a0
		bra	.print
.no		lea	(_forcebad),a0
.print		lea	(gl_trk+wth_num,GL),a1
		bsr	_PrintArgs
		moveq	#1,d0
		rts

;##########################################################################
;##########################################################################

_cmd_info	move.l	#CMDF_NOTTC|CMDF_IN,d0	;flags
		lea	.tracktable,a1		;cbtt
		lea	.tracks,a2		;cbt
		bra	_cmdwork

	;display for file
.tracktable	lea	(_txt_infohead1),a0
		bsr	_Print
		lea	(gl_headin+wfh_creator,GL),a0
		bsr	_Print

		lea	(gl_headin+wfh_ctime,GL),a0
		bsr	_GetDate
		lea	(_txt_infohead2),a0
		pea	(gl_time,GL)
		pea	(gl_date,GL)
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#8,a7
		
		lea	(gl_headin+wfh_mtime,GL),a0
		bsr	_GetDate
		lea	(_txt_infohead3),a0
		pea	(gl_time,GL)
		pea	(gl_date,GL)
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#8,a7

		moveq	#0,d0
		move.l	#MAXTRACKS-1,d1
.c0		bftst	(gl_tabin+wtt_tab,GL){d1:1}
		beq	.c1
		addq.l	#1,d0
.c1		dbf	d1,.c0
		
		lea	(_txt_infohead4),a0
		move.l	d0,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#4,a7

		moveq	#-1,d0
		rts

	;display for each track
.tracks		bsr	_gettt
		subq.l	#8,a7
		move.l	a7,a1
		pea	(a1)
		moveq	#3,d0
.fs1		move.b	(a0)+,(a1)+
		dbeq	d0,.fs1
		bne	.fs3
		subq.l	#1,a1
.fs2		move.b	#" ",(a1)+
		dbf	d0,.fs2
.fs3		clr.b	(a1)
		lea	(_txt_infotrack),a0
		move.l	d5,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#16,a7

		moveq	#" ",d2
		btst	#TFB_SLINC,(gl_trk+wth_flags+1,GL)
		beq	.fc
		moveq	#"C",d2
.fc		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOOutput,a6)
		move.l	d0,d1
		jsr	(_LVOFPutC,a6)

		moveq	#" ",d2
		btst	#TFB_LEQ,(gl_trk+wth_flags+1,GL)
		beq	.fq
		moveq	#"Q",d2
.fq		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOOutput,a6)
		move.l	d0,d1
		jsr	(_LVOFPutC,a6)

		moveq	#" ",d2
		btst	#TFB_RAWSINGLE,(gl_trk+wth_flags+1,GL)
		beq	.fs
		moveq	#"S",d2
.fs		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOOutput,a6)
		move.l	d0,d1
		jsr	(_LVOFPutC,a6)

		moveq	#" ",d2
		btst	#TFB_INDEX,(gl_trk+wth_flags+1,GL)
		beq	.fi
		moveq	#"I",d2
.fi		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOOutput,a6)
		move.l	d0,d1
		jsr	(_LVOFPutC,a6)

		lea	(_length),a0
		move.l	(gl_trk+wth_len,GL),d0
		move.l	d0,d1
		and.l	#7,d1
		lsr.l	#3,d0
		move.l	(gl_trk+wth_wlen,GL),d2
		movem.l	d0-d2,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#12,a7
		
	;print sync
		lea	(gl_trk+wth_sync,GL),a0
		bsr	_printsync
		
		bsr	_PrintLn

	;return
.ret		moveq	#-1,d0				;success
		rts

;##########################################################################
;##########################################################################

_cmd_length	move.l	(gl_rd_arg,GL),d0
		bne	.1
		lea	(_needlength),a0
		bra	_Print

.wronglength	lea	(_wronglength),a0
		bra	_Print

.1		move.l	d0,a0
		bsr	_atoi
		tst.l	d0
		bmi	.wronglength
		btst	#0,d0
		bne	.wronglength
		
		move.l	d0,-(a7)
		move.l	#CMDF_OUT|CMDF_IN,d0	;flags
		move.l	a7,a0			;cbdata
		lea	.tracktable,a1		;cbtt
		lea	.tracks,a2		;cbt
		bsr	_cmdwork
		add.w	#4,a7
		rts

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

.tracks		cmp.w	#TT_RAW,(gl_trk+wth_type,GL)
		bne	.badtype
		move.l	(gl_trk+wth_len,GL),d0
		lsr.l	#3,d0
		cmp.l	(a0),d0
		blo	.tobig
		move.l	(a0),(gl_trk+wth_wlen,GL)
		moveq	#-1,d0
		rts

.badtype	lea	(_lenbadtype),a0
		bra	.print
.tobig		lea	(_lentobig),a0
.print		lea	(gl_trk+wth_num,GL),a1
		bsr	_PrintArgs
		moveq	#0,d0
		rts

;##########################################################################
;##########################################################################

_cmd_merge	lea	.sorry,a0
		bra	_Print
.sorry		dc.b	"Sorry, this command is currently not implemented.",10,0,0

;##########################################################################
;##########################################################################

_cmd_pack	bra	_cmd_merge

;##########################################################################
;##########################################################################

_cmd_remove
		tst.l	(gl_rd_tracks,GL)
		bne	.1
		lea	(_notracks),a0
		bra	_Print

.1		move.l	#CMDF_OUT|CMDF_IN,d0	;flags
		lea	.tracktable,a1		;cbtt
		sub.l	a2,a2			;cbt
		bra	_cmdwork

.tracktable
	;remove all selected tracks from output
		move.l	#MAXTRACKS-1,d0
.loop		bftst	(gl_tabarg+wtt_tab,GL){d0:1}
		beq	.next
		bfclr	(gl_tabout+wtt_tab,GL){d0:1}
.next		dbf	d0,.loop
	;skip removed tracks
		lea	(gl_tabout,GL),a0
		lea	(gl_tabread,GL),a1
		bsr	_copytt
	;return
		moveq	#-1,d0
		rts

;##########################################################################
;##########################################################################

_cmd_save	bra	_cmd_merge

;##########################################################################
;##########################################################################

_cmd_sync	move.l	(gl_rd_arg,GL),d0
		bne	.1
		lea	(_needsync),a0
		bra	_Print

.1		move.l	d0,a0
		bsr	_parsesync
		tst.l	d0
		beq	_rts

.go		move.l	#CMDF_OUT|CMDF_IN,d0	;flags
		lea	.tracktable,a1		;cbtt
		lea	.tracks,a2		;cbt
		bra	_cmdwork

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

.tracks		cmp.w	#TT_RAW,(gl_trk+wth_type,GL)
		bne	.badtype
		lea	(gl_sync,GL),a0
		lea	(gl_trk+wth_sync,GL),a1
		move.w	#SYNCLEN-1,d0
.cp		move.w	(a0)+,(a1)+
		dbf	d0,.cp
		moveq	#-1,d0
		rts

.badtype	lea	(_lenbadtype),a0
		move.l	d5,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#4,a7
		moveq	#0,d0
		rts

;----------------------------------------
; translate arg into sync
; sync will be stored in gl_sync
; IN:	A0 = CPTR arg
; OUT:	D0 = BOOL true if sync has been translated

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

		move.l	a0,a2		;A2 = string
		bsr	_StrLen
		move.l	d0,d2
		beq	.badsync
		subq.w	#1,d2		;D2 = last char (mask)
		
		move.l	d2,d3		;D3 = amparsent
.samp		cmp.b	#"&",(a2,d3.l)
		beq	.mfound
		dbf	d3,.samp
.mfound
		tst.w	d3		;empty data?
		beq	.badsync
		cmp.w	d2,d3		;empty mask?
		beq	.badsync
		
		move.w	d2,d4		;D4 = last char data
		tst.w	d3
		bmi	.nomask
		move.w	d3,d4
		subq.w	#1,d4
.nomask
	;decode sync data
		cmp.w	#31,d4		;to many chars?
		bhi	.badsync
		lea	(gl_sync+SYNCLEN,GL),a3
.dloop		move.l	(gl_fastbuf,GL),a1
		move.b	#"$",(a1)+
		moveq	#7,d5
		cmp.w	d5,d4
		bhs	.2
		move.w	d4,d5
.2		move.w	d5,d0
		lea	(a2,d4.w),a0
		sub.w	d0,a0
.c1		move.b	(a0)+,(a1)+
		dbf	d0,.c1
		clr.b	(a1)
		move.l	a1,d7
		move.l	(gl_fastbuf,GL),a0
		bsr	_atoi
		cmp.l	a0,d7
		bne	.badsync
		move.l	d0,-(a3)
		sub.w	d5,d4
		subq.w	#1,d4
		bpl	.dloop

		tst.w	d3
		bpl	.mask

	;calculate default mask
		moveq	#SYNCLEN-1,d0
		sf	d1
		lea	(gl_sync,GL),a0
		lea	(SYNCLEN,a0),a1
.dmloop		tst.b	(a0)+
		beq	.dm1
		st	d1
.dm1		move.b	d1,(a1)+
		dbf	d0,.dmloop
		bra	.success

	;decode sync mask
.mask		lea	(1,a2,d3.w),a2
		move.w	d2,d4
		sub.w	d3,d4
		sub.w	#1,d4
		cmp.w	#31,d4		;to many chars?
		bhi	.badsync
		lea	(gl_sync+SYNCLEN+SYNCLEN,GL),a3
.mloop		move.l	(gl_fastbuf,GL),a1
		move.b	#"$",(a1)+
		moveq	#7,d5
		cmp.w	d5,d4
		bhs	.m2
		move.w	d4,d5
.m2		move.w	d5,d0
		lea	(a2,d4.w),a0
		sub.w	d0,a0
.mc1		move.b	(a0)+,(a1)+
		dbf	d0,.mc1
		clr.b	(a1)
		move.l	a1,d7
		move.l	(gl_fastbuf,GL),a0
		bsr	_atoi
		cmp.l	a0,d7
		bne	.badsync
		move.l	d0,-(a3)
		sub.w	d5,d4
		subq.w	#1,d4
		bpl	.mloop
	;apply mask on the sync
		lea	(gl_sync,GL),a0
		lea	(SYNCLEN,a0),a1
		moveq	#SYNCLEN/4-1,d1
.m		move.l	(a1)+,d0
		and.l	d0,(a0)+
		dbf	d1,.m

.success	moveq	#-1,d0
.end		movem.l	(a7)+,_MOVEMREGS
		rts

.badsync	lea	(_badsync),a0
		bsr	_Print
		moveq	#0,d0
		bra	.end

;##########################################################################
;##########################################################################

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

	;main
		move.l	#CMDF_IN,d0		;flags
		lea	.tracktable,a1		;cbtt
		lea	.tracks,a2		;cbt
		bsr	_cmdwork

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

	;copy tabarg to tabout so that the trackdata for all tracks
	;to write will read
.tracktable	lea	(gl_tabarg,GL),a0
		lea	(gl_tabread,GL),a1
		bsr	_copytt
		moveq	#-1,d0
		rts

.tracks		cmp.w	#TT_RAW,(gl_trk+wth_type,GL)
		beq	_cmdw_raw
		cmp.w	#TT_STD,(gl_trk+wth_type,GL)
		beq	_cmdw_std
		cmp.w	#TT_GREM,(gl_trk+wth_type,GL)
		beq	_cmdw_grem
		lea	(_unknowntt),a0
		bsr	_Print
		moveq	#0,d0
		rts

_cmdw_std	move.w	(gl_trk+wth_flags,GL),d0
		move.l	(gl_trk+wth_len,GL),d7	;D7 = length
		btst	#TFB_LEQ,d0
		bne	.leq
		btst	#TFB_SLINC,d0
		bne	.slinc
		
		cmp.l	#$1600*8,d7
		bne	_cmdw_corrupt

.go
	;get length, print info
		bsr	_gettt
		move.l	d0,d7
		ble	_cmdw_corrupt
		move.l	a0,-(a7)
		move.w	(gl_trk+wth_num,GL),-(a7)
		clr.w	-(a7)
		lea	(_wtrack),a0
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#8,a7

	;write track
		move.l	(gl_io,GL),a1
		move.l	(gl_fastbuf,GL),(IO_DATA,a1)
		move.w	(gl_trk+wth_num,GL),d0
		mulu	d7,d0
		move.l	d0,(IO_OFFSET,a1)
		move.l	d7,(IO_LENGTH,a1)
		move.w	#ETD_WRITE,(IO_COMMAND,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

		moveq	#-1,d0
		rts

.err		lea	(_readdisk),a0
		bsr	_PrintErrorTD
		moveq	#0,d0
		rts

.leq		cmp.l	#4*8,d7
		bne	_cmdw_corrupt
		move.l	(gl_fastbuf,GL),a0
		move.w	#$1600/4-2,d0
		move.l	(a0)+,d1
.leq1		move.l	d1,(a0)+
		dbf	d0,.leq1
		bra	.go

.slinc		cmp.l	#11*4*8,d7
		bne	_cmdw_corrupt
		move.l	(gl_fastbuf,GL),a0
		lea	($1600,a0),a1
		movem.l	(a0),d0-d7/a2-a3/a6
		movem.l	_MOVEMREGS,(a1)
		moveq	#11-1,d5
.slinc2		moveq	#$200/4-1,d6
		move.l	(a1)+,d7
.slinc1		move.l	d7,(a0)+
		addq.l	#1,d7
		dbf	d6,.slinc1
		dbf	d5,.slinc2
		bra	.go

_cmdw_grem

	;get length, print info
		bsr	_gettt
		lsl.l	#3,d0
		cmp.l	(gl_trk+wth_len,GL),d0
		bne	_cmdw_corrupt
		move.l	a0,-(a7)
		move.w	(gl_trk+wth_num,GL),-(a7)
		clr.w	-(a7)
		lea	(_wtrack),a0
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#8,a7

	;copy to tmp
		move.l	(gl_fastbuf,GL),a0
		lea	(gl_tmpbuf,GL),a1
		move.w	#$1800/4-1,d0
.cpy		move.l	(a0)+,(a1)+
		dbf	d0,.cpy

	;build mfm
		move.l	(gl_chipbuf,GL),a0
		move.l	#$55555555,d3
		move.w	#($3200-$3000-20)/4-1,d0
.gap		move.l	d3,(a0)+
		dbf	d0,.gap
		move.l	#$44894489,(a0)+	;4
		move.l	#$44895555,(a0)+	;4
		lea	(gl_tmpbuf,GL),a1
		moveq	#0,d5
		move.w	#$1800/2-1,d6
.data		move.w	(a1)+,d2		;$3000
		add.w	d2,d5
		move.w	d2,d0
		swap	d2
		lsr.w	#1,d0
		move.w	d0,d2
		bsr	_encode_long
		dbf	d6,.data
		move.w	d5,d2
		swap	d2
		lsr.w	#1,d5
		move.w	d5,d2
		bsr	_encode_long		;4
		move.w	(gl_trk+wth_num,GL),d2
		bchg	#0,d2
		move.w	d2,d0
		swap	d2
		lsr.w	#1,d0
		move.w	d0,d2
		bsr	_encode_long		;4
		moveq	#0,d2
		bsr	_encode_long		;4

	;write track
		move.l	(gl_io,GL),a1
		move.l	(gl_chipbuf,GL),(IO_DATA,a1)
		move.w	(gl_trk+wth_num,GL),d0
		ext.l	d0
		move.l	d0,(IO_OFFSET,a1)
		move.l	#$3200,(IO_LENGTH,a1)
		move.w	#ETD_RAWWRITE,(IO_COMMAND,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

		moveq	#-1,d0
		rts

.err		lea	(_readdisk),a0
		bsr	_PrintErrorTD
		moveq	#0,d0
		rts

_cmdw_raw	bsr	_cmd_merge
		moveq	#0,d0
		rts

_cmdw_corrupt	lea	(_corrupt),a0
		bsr	_Print
		moveq	#0,d0
		rts

; d2=long d3=55555555 a0=dest

_encode_long	and.l	d3,d2
		move.l	d2,d0
		eor.l	d3,d0
		move.l	d0,d1
		add.l	d0,d0
		lsr.l	#1,d1
		bset	#31,d1
		and.l	d0,d1
		or.l	d1,d2
		btst	#0,-1(a0)
		beq	.ok
		bclr	#31,d2
.ok		move.l	d2,(a0)+
		rts

;##########################################################################
;##########################################################################
; read wwarp file,
; call given function after tracktable has been read,
; call given function on each track in the input file which is marked in gl_tabdo,
; optionally copy all tracks marked in tabout to new wwarp file (which will
; be created and renamed to the original on success)
; IN:	D0 = ULONG flags
;	A0 = APTR  data area for routines, provided in a0 on calling
;	A1 = FPTR  routine for tracktable (a0 = data)
;	A2 = FPTR  routine for tracks (d0 = trknum, a0 = data)
; OUT:	D0 = BOOL  success

	NSTRUCTURE cmdwork_locals,0
		NULONG	wl_flags
		NBYTE	wl_tmpfile
		NSTRUCT	wl_pad,3
		NULONG	wl_cbdata
		NULONG	wl_cbtt
		NULONG	wl_cbt
		NULONG	wl_lt
		NLABEL	wl_SIZEOF

 BITDEF CMD,IN,0	;read input (obsolete)
 BITDEF CMD,OUT,1	;write output
 BITDEF CMD,NOTTC,2	;dont check tabarg against tabin

_cmdwork	link	LOC,#wl_SIZEOF
		move.l	d0,(wl_flags,LOC)
		move.l	a0,(wl_cbdata,LOC)
		move.l	a1,(wl_cbtt,LOC)
		move.l	a2,(wl_cbt,LOC)
		sf	(wl_tmpfile,LOC)
		moveq	#0,d6				;d6 = fh input
		moveq	#0,d7				;d7 = fh output

		btst	#CMDB_IN,(wl_flags+3,LOC)
		beq	.noin1
	;open input file
		lea	(gl_filename,GL),a0
		move.l	a0,d1
		move.l	#MODE_OLDFILE,d2
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOOpen,a6)
		move.l	d0,d6				;d6 = fh input
		bne	.fhinok
.openerr	lea	(_openfile),a0
		bsr	_PrintErrorDOS
		bra	.error
.fhinok
	;read input file header
		bsr	_readfilehead
		beq	.error
	;read input track table
		bsr	_readtt
		beq	.error
	;copy original stamp to output file header
		lea	(gl_headin+wfh_ctime,GL),a0
		lea	(gl_headout+wfh_ctime,GL),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
	;if no track specification given copy gl_tabin to gl_tabarg
		tst.l	(gl_rd_tracks,GL)
		bne	.aftersetarg
		lea	(gl_tabin,GL),a0
		lea	(gl_tabarg,GL),a1
		bsr	_copytt
.aftersetarg
	;compare tabarg against tabin and print a warning for all tracks
	;delete also these tracks
	;which are in tabarg but not in tabin
		btst	#CMDB_NOTTC,(wl_flags+3,LOC)
		bne	.nif2
		sf	d4
		move.l	#-1,d5
.loop		addq.l	#1,d5
		bftst	(gl_tabarg+wtt_tab,GL){d5:1}
		beq	.next
		bftst	(gl_tabin+wtt_tab,GL){d5:1}
		bne	.next
		bfclr	(gl_tabarg+wtt_tab,GL){d5:1}
		lea	(_notinfile1),a0
		tst.b	d4
		beq	.nif1
		lea	(_notinfile2),a0
.nif1		st	d4
		move.l	d5,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#4,a7
.next		cmp.l	#MAXTRACKS-1,d5
		bne	.loop
		tst.b	d4
		beq	.nif2
		lea	(_notinfile3),a0
		bsr	_Print
.nif2
	;copy gl_tabin to gl_tabout
		lea	(gl_tabin,GL),a0
		lea	(gl_tabout,GL),a1
		bsr	_copytt
.noin1

		btst	#CMDB_OUT,(wl_flags+3,LOC)
		beq	.noout1
	;check if creating new or modifying existing
		btst	#CMDB_IN,(wl_flags+3,LOC)
		sne	(wl_tmpfile,LOC)
		bne	.tmpout
	
.newout
	;check file exists
		lea	(gl_filename,GL),a0
		move.l	a0,d1
		move.l	#ACCESS_READ,d2
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOLock,a6)
		move.l	d0,d1
		beq	.noold
		jsr	(_LVOUnLock,a6)
		lea	(_txt_exists),a0
		pea	(gl_filename,GL)
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#4,a7
		bsr	_FlushOutput
		bsr	_GetKey
		move.b	d0,d2
		bsr	_PrintLn
		UPPER	d2
		cmp.b	#"Y",d2
		bne	.error
	;open new output file
.noold		lea	(gl_filename,GL),a0
		move.l	a0,d1
		move.l	#MODE_NEWFILE,d2
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOOpen,a6)
		move.l	d0,d7				;d7 = fh output
		bne	.fhoutok
		bra	.openerr

	;open temp output file
.tmpout		lea	(gl_filename,GL),a0
		lea	(gl_filename2,GL),a1
		move.l	#FILENAMELEN,d0
		bsr	_CopyString
		move.l	#"!"<<24,-(a7)
		move.l	a7,a0
		lea	(gl_filename2,GL),a1
		move.l	#FILENAMELEN,d0
		bsr	_AppendString
		add.w	#4,a7
		lea	(gl_filename2,GL),a0
		move.l	a0,d1
		move.l	#MODE_NEWFILE,d2
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOOpen,a6)
		move.l	d0,d7				;d7 = fh output
		beq	.openerr
.fhoutok
	;write output file header
		bsr	_writefilehead
		beq	.error

.noout1

	;copy gl_tabarg to gl_tabdo
		lea	(gl_tabarg,GL),a0
		lea	(gl_tabdo,GL),a1
		bsr	_copytt
		
	;callback tracktable
		move.l	(wl_cbtt,LOC),d0
		beq	.s1
		move.l	(wl_cbdata,LOC),a0
		movem.l	d2-d7/a2-a6,-(a7)
		jsr	(d0.l)
		movem.l	(a7)+,_MOVEMREGS
		tst.l	d0
		beq	.error
.s1
	;write output track table
		btst	#CMDB_OUT,(wl_flags+3,LOC)
		beq	.skipout2
		bsr	_writett
		beq	.error
.skipout2

	;count last track to process
		lea	(gl_tabdo+wtt_tab,GL),a0
		btst	#CMDB_OUT,(wl_flags+3,LOC)
		beq	.clt1
		lea	(gl_tabout+wtt_tab,GL),a0
.clt1		move.l	#MAXTRACKS-1,d0
.clt2		bftst	(a0){d0:1}
		dbne	d0,.clt2
		beq	.finish
		move.l	d0,(wl_lt,LOC)
		
	;***
	;do for each input track upto wl_lt
	;
		move.l	#-1,d5				;d5 = actual track
.trkloop	addq.l	#1,d5
		cmp.l	(wl_lt,LOC),d5
		bhi	.finish

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

	;input
		btst	#CMDB_IN,(wl_flags+3,LOC)
		beq	.noin2
		bftst	(gl_tabin+wtt_tab,GL){d5:1}
		beq	.noin2
	;read input track header
		bsr	_readth
		beq	.error
	;if track in gl_tabread read track data else skip it
		lea	(_skiptd),a0
		bftst	(gl_tabread+wtt_tab,GL){d5:1}
		beq	.indo
		lea	(_readtd),a0
.indo		jsr	(a0)
		beq	.error

.noin2

	;callback track if in tabdo
		bftst	(gl_tabdo+wtt_tab,GL){d5:1}
		beq	.nodo
		move.l	(wl_cbt,LOC),d1
		beq	.nodo
		move.l	d5,d0
		move.l	(wl_cbdata,LOC),a0
		movem.l	d2-d7/a2-a6,-(a7)
		jsr	(d1.l)
		movem.l	(a7)+,_MOVEMREGS
		tst.l	d0
		beq	.error
.nodo

	;write
		btst	#CMDB_OUT,(wl_flags+3,LOC)
		beq	.trkloop
		bftst	(gl_tabout+wtt_tab,GL){d5:1}
		beq	.trkloop
	;write track
		bsr	_writet
		beq	.error
		bra	.trkloop

	;success, all tracks
.finish		move.l	#0,(gl_rc,GL)
.break
.error
	;close output file
		move.l	d7,d1
		beq	.noout
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOClose,a6)
.noout
	;close input file
		move.l	d6,d1
		beq	.noin
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOClose,a6)
.noin
	;success or fail
		tst.l	(gl_rc,GL)
		bne	.fail

.success
	;if tmpfile rename
		tst.b	(wl_tmpfile,LOC)
		beq	.end
		lea	(gl_filename,GL),a0
		move.l	a0,d1
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVODeleteFile,a6)
		lea	(gl_filename2,GL),a0
		move.l	a0,d1
		lea	(gl_filename,GL),a0
		move.l	a0,d2
		jsr	(_LVORename,a6)
		bra	.end

.fail
		tst.l	d7
		beq	.end
	;delete output file
		lea	(gl_filename,GL),a0
		tst.b	(wl_tmpfile,LOC)
		beq	.del
		lea	(gl_filename2,GL),a0
.del		move.l	a0,d1
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVODeleteFile,a6)

.end		unlk	LOC
		rts

;##########################################################################
;##########################################################################
;----------------------------------------
; open device
; IN:	D0 = UBYTE flags for OpenDevice
;	A0 = APTR  io structure (iorequest,msgport)
; OUT:	D0 = BOOL  success

_OpenDevice	movem.l	d7/a2/a6,-(a7)
		move.l	d0,d7				;D7 = flags
		move.l	a0,a2				;A2 = struct

		move.l	(gl_execbase,GL),a6
		jsr	(_LVOCreateMsgPort,a6)
		move.l	d0,(4,a2)
		bne	.portok
		moveq	#0,d0
		lea	(_noport),a0
		sub.l	a1,a1
		bsr	_PrintError
		bra	.noport
.portok		
		move.l	d0,a0
		move.l	#IOTD_SIZE,d0
		jsr	(_LVOCreateIORequest,a6)
		move.l	d0,(a2)
		bne	.ioreqok
		moveq	#0,d0
		lea	(_noioreq),a0
		sub.l	a1,a1
		bsr	_PrintError
		bra	.noioreq
.ioreqok
		lea	(_trackdisk),a0
		move.l	(gl_rd_unit,GL),d0		;unit
		move.l	(a2),a1				;ioreq
		move.l	d7,d1				;flags
		jsr	(_LVOOpenDevice,a6)
		tst.l	d0
		beq	.deviceok
		move.l	(a2),a1
		move.b	(IO_ERROR,a1),d0
		lea	(_opendevice),a0
		bsr	_PrintErrorTD
		bra	.nodevice
.deviceok
		move.l	(a2),a1
		move.w	#TD_CHANGENUM,(IO_COMMAND,a1)
		jsr	(_LVODoIO,a6)
		move.l	(a2),a1
		move.l	(IO_ACTUAL,a1),(IOTD_COUNT,a1)	;the diskchanges

		moveq	#-1,d0				;success

.end		movem.l	(a7)+,_MOVEMREGS
		rts

.nodevice	move.l	(a2),a0
		jsr	(_LVODeleteIORequest,a6)
.noioreq	move.l	(4,a2),a0
		jsr	(_LVODeleteMsgPort,a6)
.noport		moveq	#0,d0
		bra	.end

;----------------------------------------
; close device
; IN:	A0 = APTR  io structure (iorequest,msgport)
; OUT:	-

_CloseDevice	movem.l	a2/a6,-(a7)
		move.l	a0,a2				;A2 = struct

		move.l	(a2),a1
		move.l	#0,(IO_LENGTH,a1)
		move.w	#ETD_MOTOR,(IO_COMMAND,a1)
		move.l	(gl_execbase,GL),a6
		jsr	(_LVODoIO,a6)
		
		move.l	(a2),a1
		jsr	(_LVOCloseDevice,a6)

		move.l	(a2),a0
		jsr	(_LVODeleteIORequest,a6)

		move.l	(4,a2),a0
		jsr	(_LVODeleteMsgPort,a6)

		movem.l	(a7)+,_MOVEMREGS
		rts

;##########################################################################
;----------------------------------------
; write to file
; IN:	D3 = ULONG length
;	D7 = BPTR  filehandle
;	A0 = APTR  data
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	A6 = destroyed

_write		move.l	d7,d1
		move.l	a0,d2
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOWrite,a6)
		cmp.l	d0,d3
		beq	_success
		lea	(_txt_writing),a0
		bsr	_PrintErrorDOS
_writeerr	moveq	#0,d0
		rts
		
;----------------------------------------
; write fileheader
; IN:	D7 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_writefilehead	move.l	#FILEID,(gl_headout+wfh_id,GL)
		move	#FILEVER,(gl_headout+wfh_ver,GL)
		lea	(gl_headout+wfh_creator,GL),a0
		move	#CREATORLEN-1,d0
.cc		clr.b	(a0)+
		dbf	d0,.cc
		lea	(_txt_creator),a0
		lea	(gl_headout+wfh_creator,GL),a1
		move.l	#CREATORLEN,d0
		bsr	_CopyString
		lea	(gl_headout+wfh_mtime,GL),a0
		move.l	a0,d1
		jsr	(_LVODateStamp,a6)
		move.l	#wfh_SIZEOF,d3
		lea	(gl_headout,GL),a0
		bra	_write

;----------------------------------------
; write track table
; IN:	D7 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_writett	lea	(gl_tabout,GL),a0
		move.l	#TABLEID,(wtt_id,a0)
		move	#TABLEVER,(wtt_ver,a0)
		move.l	#wtt_tab+MAXTRACKS/8,d3
		bra	_write

;----------------------------------------
; write track
; IN:	D7 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_writet		move.l	#TRACKID,(gl_trk+wth_id,GL)
		move	#TRACKVER,(gl_trk+wth_ver,GL)
		move.l	#wth_data,d3
		lea	(gl_trk,GL),a0
		bsr	_write
		beq	_writeerr
		move.l	(gl_trk+wth_len,GL),d3
		addq.l	#7,d3
		lsr.l	#3,d3
		move.l	(gl_fastbuf,GL),a0
		bra	_write

;----------------------------------------
; read from file
; IN:	D3 = ULONG length
;	D6 = BPTR  filehandle
;	A0 = APTR  data
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	A6 = destroyed

_read		move.l	d6,d1
		move.l	a0,d2
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVORead,a6)
		cmp.l	d0,d3
		beq	_success
		lea	(_txt_reading),a0
		bsr	_PrintErrorDOS
		moveq	#0,d0
		rts

;----------------------------------------
; read fileheader
; IN:	D6 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_readfilehead	move.l	#wfh_SIZEOF,d3
		lea	(gl_headin,GL),a0
		bsr	_read
		beq	_readerr
		
		cmp.l	#FILEID,(gl_headin+wfh_id,GL)
		bne	.badfile
		cmp.w	#FILEVER,(gl_headin+wfh_ver,GL)
		bne	_badstruct
		
		moveq	#-1,d0
		rts

.badfile	lea	(_txt_badfile),a0
		bsr	_Print
		bra	_readerr
_badstruct	lea	(_txt_badstruct),a0
		bsr	_Print
_readerr	moveq	#0,d0
		rts

;----------------------------------------
; read track table
; IN:	D6 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_readtt		move.l	#wfh_SIZEOF,d3
		move.l	#wtt_tab,d3
		lea	(gl_tabin,GL),a0
		bsr	_read
		beq	_readerr
		
		cmp.l	#TABLEID,(gl_tabin+wtt_id,GL)
		bne	_badstruct
		cmp.w	#TABLEVER,(gl_tabin+wtt_ver,GL)
		bne	_badstruct
		
		moveq	#0,d3
		move	(gl_tabin+wtt_last,GL),d3
		sub	(gl_tabin+wtt_first,GL),d3
		bcs	_badstruct
		addq.l	#8,d3
		lsr.l	#3,d3
		lea	(gl_tabin+wtt_tab,GL),a0
		bsr	_read
		beq	_readerr

		lea	(gl_tabin,GL),a0
		bsr	_expandtt
		
		moveq	#-1,d0
		rts

;----------------------------------------
; read track header
; IN:	D6 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_readth		move.l	#wth_data,d3
		lea	(gl_trk,GL),a0
		bsr	_read
		beq	_readerr

		cmp.l	#TRACKID,(gl_trk+wth_id,GL)
		bne	_badstruct
		cmp	#TRACKVER,(gl_trk+wth_ver,GL)
		bne	_badstruct

_success	moveq	#-1,d0
		rts

;----------------------------------------
; read track data
; IN:	D6 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_readtd		move.l	(gl_trk+wth_len,GL),d3
		addq.l	#7,d3
		lsr.l	#3,d3
		move.l	(gl_fastbuf,GL),a0
		bra	_read
		
;----------------------------------------
; skip track data
; IN:	D6 = BPTR  filehandle
; OUT:	D0 = BOOL  success
;	D2 = destroyed
;	D3 = destroyed
;	A6 = destroyed

_skiptd		move.l	d6,d1
		move.l	(gl_trk+wth_len,GL),d2
		addq.l	#7,d2
		lsr.l	#3,d2
		move.l	#OFFSET_CURRENT,d3
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVOSeek,a6)
		jsr	(_LVOIoErr,a6)
		tst.l	d0
		beq	_success
		lea	(_seeking),a0
		bsr	_PrintErrorDOS
		bra	_readerr
		
;----------------------------------------
; convert given datestamp to strings
; IN:	A0 = APTR  stamp
; OUT:	-

_GetDate	move.l	a6,-(a7)

		move.b	#FORMAT_DOS,(gl_DateTime+dat_Format,GL)
		lea	(gl_time,GL),a1
		move.l	a1,(gl_DateTime+dat_StrTime,GL)
		lea	(gl_date,GL),a1
		move.l	a1,(gl_DateTime+dat_StrDate,GL)
		
		lea	(gl_DateTime+dat_Stamp,GL),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+

		lea	(gl_DateTime,GL),a0
		move.l	a0,d1
		move.l	(gl_dosbase,GL),a6
		jsr	(_LVODateToStr,a6)

	;fix that on some formats there is a trailing space
		lea	(gl_date,GL),a0
.l		tst.b	(a0)+
		bne	.l
		subq.l	#2,a0
		cmp.b	#" ",(a0)
		bne	.q
		clr.b	(a0)
.q
		move.l	(a7)+,a6
		rts

;----------------------------------------
; copy track table
; IN:	A0 = APTR  wtt source
;	A1 = APTR  wtt destination
; OUT:	-

_copytt		move.w	#wtt_tab+MAXTRACKS/8-1,d0
.1		move.b	(a0)+,(a1)+
		dbf	d0,.1
		rts

;----------------------------------------
; expand given track table
; IN:	A0 = APTR  wtt
; OUT:	-

_expandtt	move.l	#MAXTRACKS-1,d0
.loop		cmp	(wtt_last,a0),d0
		bhi	.clear
		cmp	(wtt_first,a0),d0
		blo	.clear
		move.l	d0,d1
		add	(wtt_first,a0),d1
		bftst	(wtt_tab,a0){d1:1}
		bne	.set

.clear		bfclr	(wtt_tab,a0){d0:1}
.dbf		dbf	d0,.loop
		clr.w	(wtt_first,a0)
		move	#MAXTRACKS-1,(wtt_last,a0)
		rts

.set		bfset	(wtt_tab,a0){d0:1}
		bra	.dbf

;----------------------------------------
; check if there is a sync set in trkin
; IN:	A0 = sync
; OUT:	D0 = BOOL

_testsync	moveq	#-1,d0
		add.w	#SYNCLEN,a0
		tst.l	(a0)+
		bne	.true
		tst.l	(a0)+
		bne	.true
		tst.l	(a0)+
		bne	.true
		tst.l	(a0)+
		bne	.true
		moveq	#0,d0
.true		rts

;##########################################################################
;----------------------------------------
; expand rawsinge track to double size
; IN:	-
; OUT:	d0 = ULONG track length in bits

_doubleraws	move.l	(gl_trk+wth_len,GL),d0
		btst	#TFB_RAWSINGLE,(gl_trk+wth_flags+1,GL)
		bne	.single
		rts

.single		move.l	d0,-(a7)
		add.l	d0,(a7)
		move.l	d2,a1
		move.l	d0,d1
		lsr.l	#5,d1
		move.l	(gl_fastbuf,GL),a0
		sub.l	#32,d0
.loop		move.l	(a0)+,d2
		bfins	d2,(a0){d0:32}
		dbf	d1,.loop
		move.l	a1,d2
		move.l	(a7)+,d0
		rts

;----------------------------------------
; get track type
; IN:	-
; OUT:	D0 = ULONG standard length of track
;	A0 = CPTR  name/description

_gettt		move.w	(gl_trk+wth_type,GL),d0
		cmp.w	#TT_RAW,d0
		beq	.raw
		cmp.w	#TT_STD,d0
		beq	.std
		cmp.w	#TT_GREM,d0
		beq	.grem
		moveq	#0,d0
		lea	(.tunknown),a0
		rts

.raw		move.l	#DEFTRACKLEN,d0
		lea	(.traw),a0
		rts
.std		move.l	#$1600,d0
		lea	(.tstd),a0
		rts
.grem		move.l	#$1800,d0
		lea	(.tgrem),a0
		rts

.tunknown	dc.b	"unknown",0
.traw		dc.b	"raw",0
.tstd		dc.b	"dos",0
.tgrem		dc.b	"gremlin",0
	EVEN

;----------------------------------------
; shift mfm buffer
; IN:	D0 = ULONG  bitoffset in buffer which make the new start
;	D1 = ULONG  bitlength for new mfm-buffer
;	A0 = APTR   mfm-buffer
; OUT:	-

_shiftmfm	move.l	d2,a1
		lsr.l	#5,d1
.loop		bfextu	(a0){d0:32},d2
		move.l	d2,(a0)+
		dbf	d1,.loop
		move.l	a1,d2
		rts

;----------------------------------------
; search sync in mfm buffer
; IN:	D0 = ULONG  bitoffset in buffer to start search
;	D1 = ULONG  bitlength of mfm-buffer
;	A0 = APTR   mfm-buffer
;	A1 = STRUCT sync to search (16 byte sync + 16 byte mask)
; OUT:	D0 = ULONG  bitoffset in buffer where sync has been found, -1 on error

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

	;count bits to compare
		move.l	#SYNCLEN*8-1,d2
		moveq	#-1,d3
.cs		addq.l	#1,d3
		bftst	(SYNCLEN,a1){d3:1}
		dbne	d2,.cs
		addq.l	#1,d2			;D2 = bits to compare (synclen)
		beq	.err

	;search for sync
		subq.l	#1,d0			;because loop starts with increment
		move.l	d2,a2			;A2 = bits to compare (synclen)

	;outer loop (128 bit - full size)
.lo		move.l	a2,d2			;D2 = actual bits to compare (synclen)
		moveq	#32,d6
		cmp.l	d6,d2
		bhs	.s1
		move.l	d2,d6			;D6 = actual synclen
.s1
		move.l	#SYNCLEN*8,d5
		sub.l	d2,d5			;D5 = actual syncoffset
		bfextu	(SYNCLEN,a1){d5:d6},d3	;D3 = mask
		bfextu	(a1){d5:d6},d4		;D4 = sync
		and.l	d3,d4

	;inner loop (32 bit)
.li		addq.l	#1,d0
		cmp.l	d1,d0
		bhs	.err
		bfextu	(a0){d0:d6},d7
		and.l	d3,d7
		cmp.l	d4,d7
		bne	.li
		
		sub.l	d6,d2
		beq	.end

		moveq	#32,d6
		cmp.l	d6,d2
		bhs	.s2
		move.l	d2,d6			;D6 = actual synclen
.s2		move.l	#SYNCLEN*8,d5
		sub.l	d2,d5			;D5 = actual syncoffset
		bfextu	(SYNCLEN,a1){d5:d6},d3	;D3 = mask
		bfextu	(a1){d5:d6},d4		;D4 = sync
		and.l	d3,d4
		bfextu	(4,a0){d0:d6},d7
		and.l	d3,d7
		cmp.l	d4,d7
		bne	.lo
		
		sub.l	d6,d2
		beq	.end

		moveq	#32,d6
		cmp.l	d6,d2
		bhs	.s3
		move.l	d2,d6			;D6 = actual synclen
.s3		move.l	#SYNCLEN*8,d5
		sub.l	d2,d5			;D5 = actual syncoffset
		bfextu	(SYNCLEN,a1){d5:d6},d3	;D3 = mask
		bfextu	(a1){d5:d6},d4		;D4 = sync
		and.l	d3,d4
		bfextu	(8,a0){d0:d6},d7
		and.l	d3,d7
		cmp.l	d4,d7
		bne	.lo
		
		sub.l	d6,d2
		beq	.end

		move.l	#SYNCLEN*8,d5
		sub.l	d2,d5			;D5 = actual syncoffset
		bfextu	(SYNCLEN,a1){d5:d2},d3	;D3 = mask
		bfextu	(a1){d5:d2},d4		;D4 = sync
		and.l	d3,d4
		bfextu	(12,a0){d0:d2},d7
		and.l	d3,d7
		cmp.l	d4,d7
		bne	.lo
		
.end		movem.l	(a7)+,_MOVEMREGS
		rts

.err		moveq	#-1,d0
		bra	.end

;##########################################################################
;----------------------------------------
; print sync
; IN:	A0 = APTR   sync
; OUT:	-

_printsync	movem.l	d2-d3/a2-a3,-(a7)
		move.l	a0,a3			;a3 = sync
		lea	(SYNCLEN,a3),a0
		moveq	#SYNCLEN-1,d3
.cnt		tst.b	(a0)+
		dbne	d3,.cnt
		cmp.w	#1,d3
		bge	.ndef
		moveq	#1,d3
.ndef		lea	(SYNCLEN-1,a3),a2
		move.w	d3,d2
		bsr	.ps
		lea	(_amp),a0
		bsr	_Print
		lea	(2*SYNCLEN-1,a3),a2
		move.w	d3,d2
		bsr	.ps
		movem.l	(a7)+,_MOVEMREGS
		rts

.ps		sub.w	d2,a2
.p		lea	(_lx),a0
		moveq	#0,d0
		move.b	(a2)+,d0
		move.l	d0,-(a7)
		move.l	a7,a1
		bsr	_PrintArgs
		add.w	#4,a7
		dbf	d2,.p
		rts
		
;----------------------------------------
; print value as bit count in hex
; IN:	D0 = ULONG value to print
; OUT:	-

_printbitlen	move.l	d0,d1
		lsr.l	#3,d0
		and.l	#7,d1
		movem.l	d0-d1,-(a7)
		lea	(_bitlen),a0
		move.l	a7,a1
		bsr	_PrintArgs
		addq.l	#8,a7
		rts

_TxtBold	lea	(_txt_bold),a0
		bra	_Print

_TxtReset	lea	(_txt_reset),a0
		bra	_Print

_PrintBold	pea	(a0)
		bsr	_TxtBold
		move.l	(a7)+,a0
		bsr	_Print
		bra	_TxtReset

;##########################################################################

	CNOP 0,4
		;		       even	 odd
		;	   --sync--  ffTTSSGG  ffTTSSGG
_syncstd	dc.l	0,$44894489,$55000000,$55000000		;finds one sector
		dc.l	0,$ffffffff,$ff000000,$ff000000
_syncstd2	dc.l	0,$44894489,$55000005,$55000001		;finds first sector after gap
		dc.l	0,$ffffffff,$ff000055,$ff000055
_syncgrem	dc.l	0,0,$44894489,$44895555
		dc.l	0,0,$ffffffff,$ffffffff

_txt_help	dc.b	"Synopsis:",10
		dc.b	"	WWarp filename[.wwp] [command] [tracks] [args] [options...]",10
		dc.b	"valid commands are:",10
		dc.b	"	C - create wwarp file (default)",10
		dc.b	"	F - force tracks to std format",10
		dc.b	"	D - dump tracks",10
		dc.b	"	    args = [sync[&mask]][,[syncno][,[len][,off]]]",10
		dc.b	"	I - print informations about wwarp file",10
		dc.b	"	L - set track length",10
		dc.b	"	    args = length",10
		dc.b	"	M - merge two wwarp files together",10
		dc.b	"	    args = wwarp-to-add",10
		dc.b	"	P - pack wwarp file",10
		dc.b	"	R - remove tracks from a wwarp file",10
		dc.b	"	S - save tracks",10
		dc.b	"	W - write wwarp file back to disk",10
		dc.b	"	Y - set sync",10
		dc.b	"	    args = sync[&mask]",10
		dc.b	0
_txt_nl		dc.b	10,0
_txt_bold	dc.b	155,"1m",0
_txt_reset	dc.b	155,"22m",0
_txt_badtracks	dc.b	"Invalid [tracks] specification",10,0
_txt_badcmd	dc.b	"Invalid [command]",10,0
_extension	dc.b	".wwp",0
_txt_create	dc.b	'creating new wwarp file "%s" from DF%ld: %ld tracks',10,0
_txt_exists	dc.b	'file "%s" already exists, overwrite ? (yN) ',0
_trackdisk	dc.b	"trackdisk.device",0
_diskprogress	dc.b	"reading track %ld",0
_openfile	dc.b	"open file",0
_txt_writing	dc.b	"writing file",0
_txt_reading	dc.b	"reading file",0
_seeking	dc.b	"seeking",0
_trklens	dc.b	" single"
_trklen		dc.b	" raw trklen=$%lx.%ld",10,0
_txt_badfile	dc.b	"file is not a WWarp file.",10,0
_txt_badstruct	dc.b	"structure of WWarp file is corrupt.",10,0
_txt_infohead1	dc.b	"created by: ",0
_txt_infohead2	dc.b	10,"created at: %s %s",10,0
_txt_infohead3	dc.b	"last modified at: %s %s",10,0
_txt_infohead4	dc.b	"total tracks in file: %ld",10
		dc.b	"trk type flags length  wlen  sync",10,0
_txt_infotrack	dc.b	"%3ld %s  ",0
_lx		dc.b	"%02lx",0
_amp		dc.b	"&",0
_length		dc.b	" $%4lx.%ld $%04lx ",0
_bitlen		dc.b	"$%lx.%ld",0
_needlength	dc.b	"length must be specified",10,0
_wronglength	dc.b	"invalid length",10,0
_notinfile1	dc.b	"warning, tracks %ld",0
_notinfile2	dc.b	",%ld",0
_notinfile3	dc.b	" aren't contained in wwarp file!",10,0
_lenbadtype	dc.b	"error track %d, type must be raw!",10,0
_lentobig	dc.b	"error track %d, length cannot be larger than stored track size!",10,0
_forcebadtype	dc.b	"skipping track %d, no raw mfm-data!",10,0
_forcenosync	dc.b	"skipping track %d, sync not found",10,0
_forceshortmfm	dc.b	"skipping track %d, insufficient mfm-data",10,0
_forcebad	dc.b	"skipping track %d, could not decode",10,0
_needsync	dc.b	"sync must be specified",10,0
_badsync	dc.b	"invalid sync",10,0
_dump1		dc.b	"track=%ld type=%s flags=%lc len=$%4lx.%ld wlen=$%04lx sync=",0
_badarg		dc.b	"Invalid [arg]",10,0
_offerr		dc.b	"error, offset out of range",10,0
_syncfound1	dc.b	"sync ",0
_syncfound2	dc.b	" found %ld times, using offset ",0
_unknowntt	dc.b	"unknown track type",10,0
_corrupt	dc.b	"wwarp file is corrupt",0
_wtrack		dc.b	"writing track %ld fmt %s",10,0
_notracks	dc.b	"error, tracks must be specified",10,0

_decoded	dc.b	" format %s ($%lx bytes)",10,0
_nosync		dc.b	"no sync found",10,0
_noport		dc.b	"can't create MessagePort",0
_noioreq	dc.b	"can't create IO-Request",0
_readdisk	dc.b	"read disk",0
_opendevice	dc.b	"open device",0
_badkick	dc.b	"Sorry, WWarp requires Kickstart 2.0 or better.",10,0
_badcpu		dc.b	"Sorry, WWarp requires a 68020 or better.",10,0
_readargs	dc.b	"read arguments",0

;subsystems
_dosname	DOSNAME

_template	dc.b	"Filename/A"		;file to create
		dc.b	",Command"		;operation to perform
		dc.b	",Tracks"		;tracks affected
		dc.b	",Argument"		;depending on operation
		dc.b	",BPT=BytesPerTrack/K"	;
		dc.b	",Unit/N/K"		;drive unit to read from/write to
		dc.b	",NoStd/S"		;dont try to read std format
		dc.b	",RetryCnt/N/K"		;how many retries
		dc.b	0

;##########################################################################

	SECTION c,BSS,CHIP

_chipbuf	dsb	MAXTRACKLEN

;##########################################################################

	SECTION g,BSS

_Globals	dsb	gl_SIZEOF

;##########################################################################

	END

