;*---------------------------------------------------------------------------
;  :Program.	formats.s
;  :Contents.	informations and routines regarding special formats
;  :Author.	Bert Jahn
;  :EMail.	wepl@whdload.org
;  :Address.	Feodorstrasse 8, Zwickau, 08058, Germany
;  :Version	$Id: formats.s 1.6 2001/09/18 20:47:07 wepl Exp $
;  :History.	18.03.01 created
;		23.07.01 rob format added
;  :Requires.	OS V37+, MC68020+
;  :Copyright.	©1998-2001 Bert Jahn, All Rights Reserved
;  :Language.	68020 Assembler
;  :Translator.	Barfly V2.9
;  :To Do.
;---------------------------------------------------------------------------*

_format_unknown	dc.l	0		;succ
		dc.l	0		;decode
		dc.l	0		;decode force
		dc.l	0		;encode
		dc.l	_name_unknown	;name
		dc.w	0		;datalen
		dc.w	0		;rawlen
		dc.w	-1		;type

_format_raw	dc.l	_formats	;succ
		dc.l	0		;decode
		dc.l	0		;decode force
		dc.l	0		;encode
		dc.l	_name_raw	;name
		dc.w	DEFREADLEN	;datalen
		dc.w	0		;rawlen
		dc.w	TT_RAW		;type

_formats

.dos		dc.l	.grem		;succ
		dc.l	_decode_dos	;decode
		dc.l	_decodefrc_dos	;decode force
		dc.l	0		;encode
		dc.l	_name_dos	;name
		dc.w	$1600		;datalen
		dc.w	0		;rawlen
		dc.w	TT_STD		;type

.grem		dc.l	.rob		;succ
		dc.l	_decode_grem	;decode
		dc.l	_decode_grem	;decode force
		dc.l	_encode_grem	;encode
		dc.l	_name_grem
		dc.w	$1800		;datalen
		dc.w	$3000+20+2	;rawlen
		dc.w	TT_GREM		;type

.rob		dc.l	0		;succ
		dc.l	_decode_rob	;decode
		dc.l	_decode_rob	;decode force
		dc.l	_encode_rob	;encode
		dc.l	_name_rob
		dc.w	$1804		;datalen diskkey.l + $1800 data
		dc.w	2+(12*$40c)	;rawlen (that is minimum length, often a long track)
		dc.w	TT_ROB		;type

		;		       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
_syncrob	dc.l	0,0,0,$14484891
		dc.l	0,0,0,$ffffffff
_synccalc	dc.l	0,0,0,$448a448a
		dc.l	0,0,0,$ffffffff

_name_unknown	dc.b	"unknown",0
_name_raw	dc.b	"raw",0
_name_dos	dc.b	"dos",0
_name_grem	dc.b	"gremlin",0
_name_rob	dc.b	"robnorthen",0
	EVEN

;----------------------------------------
; decode standard amigados track
; IN:	D0 = ULONG length of raw mfm-data in bits
;	D1 = UWORD track number
;	_fastbuf mfm data
; OUT:	D0 = BOOL true on success
;	_fastbuf contains decoded data

	NSTRUCTURE	locals_decodedos,0
		NWORD	lc1_trknum
		NALIGNLONG
		NLABEL	lc1_SIZEOF

_decode_dos	movem.l	d2-d7,-(a7)
		link	LOC,#lc1_SIZEOF
		
		or.w	#$ff00,d1
		move.w	d1,(lc1_trknum,LOC)

		move.l	d0,d5			;D5 = mfm-length
		moveq	#-1,d4			;D4 = last sync offset

	;search inter sector gap
.search		move.l	d4,d0
		addq.l	#1,d0			;offset
		move.l	d5,d1			;buffer length
		move.l	(gl_fastbuf,GL),a0
		lea	(_syncstd),a1		;44894489...
		bsr	_searchsync
		tst.l	d0
		bmi	.no

		tst.l	d4
		bmi	.sd4
		move.l	d0,d1
		sub.l	d4,d1
		cmp.l	#$440*8,d1		;$440 is standard sector length
		bne	.gap
.sd4		move.l	d0,d4
		bra	.search

.gap
	;d4 = last sector before gap
	;d0 = first sector after gap
		move.l	d0,d6			;D6 = first sector
	
	;check that inter sector gap is set to zeros
		sub.l	d4,d0
		sub.l	#($440-4)*8+33,d0	;length of gap in bits to check
		bmi	.no
		move.l	#$aaaaaaaa,d3
		move.l	(gl_fastbuf,GL),a0
		bra	.cmpin
.cmp		bfextu	(a0){d6:32},d1
		cmp.l	d1,d3
		bne	.no
.cmpin		subq.l	#4,a0
		sub.l	#32,d0
		bcc	.cmp
		bfextu	(a0){d6:32},d1
		neg.l	d0
		lsl.l	d0,d1
		lsl.l	d0,d3
		cmp.l	d1,d3
		bne	.no

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

	;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
		bclr	#31,d0
		cmp.l	#$2aaaaaaa,d0
		bne	.no
		bsr	_getlw
		cmp.l	#$44894489,d0
		bne	.no
		
		moveq	#0,d3			;D3 = chksum

		bsr	_getlwd			;sector header
		
		subq.b	#1,d0			;num sectors before gap
		cmp.b	d7,d0
		bne	.no
		
		lsr.l	#8,d0			;sector number 0..10
		cmp.b	#10,d0
		bhi	.no
		bclr	d0,d4
		beq	.no			;same sector again
	;	move.b	d0,($1600+gl_tmpbuf.w,GL,d7.w)
		moveq	#0,d1
		move.b	d0,d1
		mulu	#$200,d1
		lea	(gl_tmpbuf.w,GL,d1.l),a1
		
		lsr.l	#8,d0			;track number
		cmp.w	(lc1_trknum,LOC),d0
		bne	.no

		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
		
		moveq	#-1,d0
		bra	.quit

.no		moveq	#0,d0

.quit		unlk	LOC
		movem.l	(a7)+,d2-d7
		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

;----------------------------------------
; force decode standard amigados track
; IN:	D0 = ULONG length of raw mfm-data in bits
;	D1 = UWORD track number
;	_fastbuf mfm data
; OUT:	D0 = BOOL true on success
;	_fastbuf contains decoded data

_decodefrc_dos	movem.l	d2-d7,-(a7)

		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	.no

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

	;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

		moveq	#-1,d0

.quit		movem.l	(a7)+,d2-d7
		rts

.no		moveq	#0,d0
		bra	.quit

;----------------------------------------
; decode gremlin track (lotus)
; IN:	D0 = ULONG length of raw mfm-data in bits
;	D1 = UWORD track number
;	_fastbuf mfm data
; OUT:	D0 = BOOL true on success
;	_fastbuf contains decoded data

_decode_grem	movem.l	d2-d7,-(a7)

		move.l	d0,d5			;D5 = mfm-length
		move.w	d1,d4			;D4 = track number

	;search sync
		moveq	#0,d0			;offset
		move.l	d5,d1			;buffer length
		move.l	(gl_fastbuf,GL),a0
		lea	(_syncgrem),a1
		bsr	_searchsync
		tst.l	d0
		bmi	.no

	;skip sync(448944894489) and unknown word(5555)
		add.l	#4*16,d0
		move.l	d0,d6			;offset
		
	;check that remaining mfm data is sufficent
		sub.l	d6,d5			;in bits
		cmp.l	#(2*$1800+4)*8,d5
		blo	.no

	;decode track
		move.l	(gl_fastbuf,GL),a0	;A0 = mfm buffer
		lea	(gl_tmpbuf,GL),a1	;A1 = decoded
		move.w	#$bff,d7
		move.l	#$55555555,d2
		moveq	#0,d3

.loop		bsr	.get
		move.w	d1,(a1)+
		add.w	d1,d3
		dbf	d7,.loop
		
		bsr	.get
		cmp.w	d1,d3
		bne	.no

		bsr	.get
		bchg	#0,d1
		cmp.w	d1,d4
		bne	.no

	;copy buffer
		move.w	#$1800/4-1,d0
		lea	(gl_tmpbuf,GL),a0
		move.l	(gl_fastbuf,GL),a1
.copy		move.l	(a0)+,(a1)+
		dbf	d0,.copy
		
		moveq	#-1,d0
		bra	.quit

.no		moveq	#0,d0

.quit		movem.l	(a7)+,d2-d7
		rts

.get		bfextu	(a0){d6:32},d0
		addq.l	#4,a0
		and.l	d2,d0
		move.w	d0,d1
		swap	d0
		add.w	d1,d1
		add.w	d0,d1
		rts

;----------------------------------------
; encode gremlin track
; IN:	D0 = UWORD track number
;	_tmpbuf  data to encode
; OUT:	_chipbuf encoded data

_encode_grem	movem.l	d2-d7,-(a7)

		move.l	(gl_chipbuf,GL),a0
		move.l	#$55555555,d3
		move.l	(gl_writelen,GL),d0
		sub.w	#$3000+20,d0
		lsr.w	#1,d0
		subq.w	#1,d0
.gap		move.w	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
		
		movem.l	(a7)+,_MOVEMREGS
		rts

; d2=long d3=55555555 a0=dest
; d0/d1 scratch

	QUAD
_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

;----------------------------------------
; rob northen disk format:
; (AlienBreed2,BodyBlows,MortalKombat,ProjectXSE,ArcadePool,SuperFrog)
;	0	1448		track header sync
;	now following 12 sectors:
;	0	4891		sync word
;	2	xxxxxxxx	mfm odd  bits \ eor.l with diskkey|$80000000
;	6	xxxxxxxx	mfm even bits / sector-number.b track-number.b sector-chksum.w
;	$a	$200 byte	mfm odd  bit data
;	$20a	$200 byte	mfm even bit data
;	$40a	xxxx		mfm encoded byte which is the length of the inter sector gap

;----------------------------------------
; decode rob track
; IN:	D0 = ULONG length of raw mfm-data in bits
;	D1 = UWORD track number
;	_fastbuf mfm data
; OUT:	D0 = BOOL true on success
;	_fastbuf contains decoded data

	NSTRUCTURE	locals_decoderob,0
		NLONG	lcdr_bitsleft		;remaining bits in mfm buffer
		NWORD	lcdr_chksum		;sector chksum
		NWORD	lcdr_trknum		;track number
		NALIGNLONG
		NLABEL	lcdr_SIZEOF

_decode_rob	movem.l	d2-d7,-(a7)
		link	LOC,#lcdr_SIZEOF

		move.l	d0,(lcdr_bitsleft,LOC)
		move.w	d1,(lcdr_trknum,LOC)

	;search sync
		move.l	d0,d1			;buffer length
		moveq	#0,d0			;offset
		move.l	(gl_fastbuf,GL),a0
		lea	(_syncrob),a1
		bsr	_searchsync
		move.l	d0,d6			;D6 = offset
		bmi	.no

	;check that remaining mfm data is sufficent
		sub.l	d6,(lcdr_bitsleft,LOC)
		cmp.l	#(2+(12*$40c))*8,(lcdr_bitsleft,LOC)	;minimum length!
		blo	.no

	;skip sync 1448
		add.l	#16,d6
		sub.l	#16,(lcdr_bitsleft,LOC)

	;calculate disk key
		move.l	(gl_fastbuf,GL),a0	;A0 = mfm buffer
		add.w	#10,a0			;skip sector header
		moveq	#0,d1
		move.w	#1024/4-1,d7
.chksum		bfextu	(a0){d6:32},d0
		addq.l	#4,a0
		eor.l	d0,d1
		dbf	d7,.chksum
		move.l	#$55555555,d2		;D2 = 55555555
		and.l	d2,d1
		move.l	d1,d5
		swap	d5
		add.w	d5,d5
		or.w	d1,d5
		swap	d5
		move.w	(lcdr_trknum,LOC),d5	;sector=0
		swap	d5
		move.l	(gl_fastbuf,GL),a0	;A0 = mfm buffer
		bfextu	(2,a0){d6:32},d0
		bfextu	(6,a0){d6:32},d1
		and.l	d2,d0
		and.l	d2,d1
		add.l	d0,d0
		or.l	d1,d0
		eor.l	d0,d5			;D5 = diskkey|$80000000

		lea	(gl_tmpbuf,GL),a1	;A1 = decoded
		move.l	d5,(a1)+

	;decode 12 sectors
		moveq	#0,d7			;D7 = actual sector

.sector		cmp.l	#$40c*8,(lcdr_bitsleft,LOC)
		blo	.no
		bfextu	(a0){d6:16},d0
		cmp.w	#$4891,d0
		bne	.no
		addq.w	#2,a0
		bfextu	(a0){d6:32},d0
		addq.w	#4,a0
		bfextu	(a0){d6:32},d1
		addq.w	#4,a0
		and.l	d2,d0
		and.l	d2,d1
		add.l	d0,d0
		or.l	d1,d0
		eor.l	d5,d0
		move.w	d0,(lcdr_chksum,LOC)
		swap	d0
		cmp.b	(lcdr_trknum+1,LOC),d0
		bne	.no
		lsr.w	#8,d0
		cmp.b	d7,d0			;sector number
		bne	.no

		moveq	#512/4-1,d3
		moveq	#0,d4

		bclr	#31,d5
		
.dec		bfextu	(a0){d6:32},d0
		bfextu	($200,a0){d6:32},d1
		eor.l	d0,d4
		and.l	d2,d0
		eor.l	d1,d4
		and.l	d2,d1
		add.l	d0,d0
		addq.w	#4,a0
		or.l	d1,d0
		eor.l	d5,d0
		move.l	d0,(a1)+
		dbf	d3,.dec

		bset	#31,d5
		
		and.l	d2,d4
		move.l	d4,d0
		swap	d4
		add.w	d4,d4
		or.w	d4,d0
		cmp.w	(lcdr_chksum,LOC),d0
		bne	.no

		add.w	#$200,a0
		
		bfextu	(a0){d6:16},d0
		moveq	#0,d1
		moveq	#7,d3
.gap		roxl.w	#2,d0
		roxl.b	#1,d1
		dbf	d3,.gap

		lea	(2,a0,d1.w*2),a0	;sector gap

		lsl.l	#4,d1
		add.l	#$40c*8,d1
		sub.l	d1,(lcdr_bitsleft,LOC)
		bcs	.no
		
		addq.w	#1,d7
		cmp.w	#12,d7
		bne	.sector
		
	;copy buffer
		move.w	#$1804/4-1,d0
		lea	(gl_tmpbuf,GL),a0
		move.l	(gl_fastbuf,GL),a1
.copy		move.l	(a0)+,(a1)+
		dbf	d0,.copy
		
		moveq	#-1,d0
		bra	.quit

.no		moveq	#0,d0

.quit		unlk	LOC
		movem.l	(a7)+,d2-d7
		rts

;----------------------------------------
; encode rob track
; IN:	D0 = UWORD track number
;	_tmpbuf  data to encode
; OUT:	_chipbuf encoded data

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

		move.w	d0,a3			;A3 = track number
		move.l	(gl_chipbuf,GL),a0
		lea	(gl_tmpbuf,GL),a1
		move.l	(a1)+,d6		;D6 = diskkey
		move.l	#$55555555,d3

		move.l	(gl_writelen,GL),d0
		sub.w	#2+(12*$40c)+4,d0
		lsr.w	#1,d0
		subq.w	#1,d0
.gap		move.w	d3,(a0)+
		dbf	d0,.gap

		move.w	#$1448,(a0)+		;2

		moveq	#0,d7			;D7 = sector

.sector		move.w	#$4891,(a0)+		;2

		move.l	a1,a2
		moveq	#512/4-1,d2
		moveq	#0,d4
.chksum		move.l	(a2)+,d0
		eor.l	d0,d4
		dbf	d2,.chksum
		
		move.l	d4,d0
		lsr.l	#1,d0
		eor.l	d0,d4
		and.l	d3,d4
		move.l	d4,d0
		swap	d0
		add.w	d0,d0
		or.w	d0,d4			;chksum
		
		move.b	d7,d2			;sector
		lsl.w	#8,d2
		add.l	a3,d2			;track
		swap	d2
		move.w	d4,d2			;chksum
		eor.l	d6,d2			;diskkey
		
		move.l	d2,d4
		lsr.l	#1,d2
		bsr	_encode_long		;4
		move.l	d4,d2
		bsr	_encode_long		;4

		bclr	#31,d6

		move.l	a1,a2
		moveq	#512/4-1,d4
.odd		move.l	(a2)+,d2
		eor.l	d6,d2
		lsr.l	#1,d2
		bsr	_encode_long		;$200
		dbf	d4,.odd

		moveq	#512/4-1,d4
.even		move.l	(a1)+,d2
		eor.l	d6,d2
		bsr	_encode_long		;$200
		dbf	d4,.even
		
		bset	#31,d6
		
		move.w	#$aaaa,d0
		btst	#0,-1(a0)
		beq	.ok
		bclr	#15,d0
.ok		move.w	d0,(a0)+		;2

		addq.w	#1,d7
		cmp.w	#12,d7
		bne	.sector
		
		moveq	#0,d2
		bsr	_encode_long		;4
		
		movem.l	(a7)+,_MOVEMREGS
		rts

