;;;;; Sample Compression Algorithms (Implementation in MC680x0 Assembly)
;;;;; ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
;;;;; The ADPCMx algorithms originally devised by Christian Nuchner, İ 1993
;;;;;
;;;;; These sources can be used as a basis for your own "ProTracker" module
;;;;; sample packing systems for high compression of sample data`s with good
;;;;; high/quality playback...
;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;
;;;;;  CF          Type       Alogrithm  CMode   Quality Rating
;;;;; -----------------------------------------------------------
;;;;;  4:1         Samples    ADPCM3       4     Good Quality tapes
;;;;;  7:1         Samples    ADPCM2       5     Poor Quality Tapes
;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

test
		lea	source+$506b,a0		;samples source
		lea	dest,a1			;packed samples dest
		move.l	#90437,d0		;samples length
		bsr.w	PackMode4		;**PACK EM!! **

;a0.l = packed start ptr
;d0.l = packed length (bytes)

		lea	source+$506b,a1		;samples dest
		bsr.w	UnpackMode4		**UNPACK EM!! **

;a0.l = unpacked start ptr
;d0.l = unpacked length (bytes)

gpc		rts

** Good Tape Recordings Quality (4:1 Ratio!!)

PackMode3	moveq	#0,d1
		moveq	#3,d5
		move.w	d1,d3			; d3=EstMax
		swap	d1
		move.w	d1,d2			; d2=Delta
		bne.s	c3loop
		moveq	#5,d2
c3loop		moveq	#0,d1			; d1=Shifter
		bsr.s	c3byte
		lsl.b	d5,d1
		bsr.s	c3byte
		lsl.w	d5,d1
		bsr.s	c3byte
		lsl.w	d5,d1
		bsr.s	c3byte
		lsl.w	d5,d1
		bsr.s	c3byte
		lsl.l	d5,d1
		bsr.s	c3byte
		lsl.l	d5,d1
		bsr.s	c3byte
		lsl.l	d5,d1
		bsr.s	c3byte
		swap	d1
		move.b	d1,(a1)+
		rol.l	#8,d1
		move.b	d1,(a1)+
		rol.l	#8,d1
		move.b	d1,(a1)+
		subq.l	#8,d0			; d0=Counter
		bhi.s	c3loop
		move.w	d2,d0			; -> d0=JoinCode
		swap	d0
		move.w	d3,d0
		move.l	a1,d0		;a0.l = packed data ptr
		sub.l	a0,d0		;d0.l = packed length in bytes
		rts
c3byte		move.b	(a0)+,d4
		ext.w	d4
		asl.w	#6,d4
		sub.w	d3,d4
		bpl.s	c3positive
		or.b	#%100,d1
		neg.w	d4
c3positive	sub.w	d2,d4
		bls.s	c300
		sub.w	d2,d4
		bls.s	c301
		sub.w	d2,d4
		bls.s	c310
c311		or.b	#%11,d1
		bra.s	c300
c310		or.b	#%10,d1
		bra.s	c300
c301		or.b	#%01,d1
c300		bsr.b	adaptive3
		rts

** Good Tape Recordings Quality (4:1 Ratio!!)

UnpackMode3	move.l	a1,-(sp)
		moveq	#0,d1
		moveq	#3,d5
		move.w	d1,d3			; d3=EstMax
		swap	d1
		move.w	d1,d2			; d2=Delta
		bne.s	d3loop
		moveq	#5,d2
d3loop		move.b	(a0)+,d1		; d1=Shifter
		rol.b	d5,d1
		bsr.s	d3byte
		rol.b	d5,d1
		bsr.s	d3byte
		lsl.w	#2,d1
		move.b	(a0)+,d1
		ror.w	#7,d1
		bsr.s	d3byte
		rol.w	d5,d1
		bsr.s	d3byte
		rol.w	d5,d1
		bsr.s	d3byte
		lsr.w	#7,d1
		move.b	(a0)+,d1
		ror.w	#6,d1
		bsr.s	d3byte
		rol.w	d5,d1
		bsr.s	d3byte
		rol.w	d5,d1
		bsr.s	d3byte
d3entry		sub.l	d5,d0			; d0=Counter
		bhi.s	d3loop
		move.w	d2,d0			; -> d0=JoinCode
		swap	d0
		move.w	d3,d0
		move.l	(sp)+,a0
		move.l	a1,d0		;a0.l = packed data ptr
		sub.l	a0,d0		;d0.l = packed length in bytes
		rts
d3byte		bsr.b	adaptive3
		move.w	d3,d4
		asr.w	#6,d4
		cmp.w	#127,d4
		bgt.s	d3high
		cmp.w	#-128,d4
		blt.s	d3low
		move.b	d4,(a1)+
		rts
d3high		move.b	#127,(a1)+
		rts
d3low		move.b	#-128,(a1)+
		rts
adaptive3	move.w	d2,d4		; d1 = SignBit + DataBit
		lsr.w	#1,d4
		btst	#1,d1
		beq.s	d30
d31		btst	#0,d1
		beq.s	d310
d311		add.w	d2,d4
		add.w	d2,d4
		add.w	d2,d4
		mulu	#$6607,d2
		bra.s	d3sign
d310		add.w	d2,d4
		add.w	d2,d4
		mulu	#$4D14,d2
		bra.s	d3sign
d30		btst	#0,d1
		beq.s	d300
d301		add.w	d2,d4
		mulu	#$3A9F,d2
		bra.s	d3sign
d300		mulu	#$399A,d2
d3sign		btst	#2,d1
		beq.s	d3add
		neg.w	d4
d3add		add.w	d4,d3
		add.l	#8192,d2
		moveq	#14,d4
		asr.l	d4,d2
		rts


** Poor Tape Recordings Quality (8:1 Ratio!!)

		cnop	0,4
PackMode4:	moveq	#0,d1
		moveq	#2,d5
		addq.l	#3,d0
		lsr.l	d5,d0
		move.w	d1,d3			; d3=EstMax
		swap	d1
		move.w	d1,d2			; d2=Delta
		bne.s	c2entry
		moveq	#5,d2
		bra.s	c2entry
c2loop		lsl.b	d5,d1			; d1=Shifter
		bsr.s	c2byte
		lsl.b	d5,d1
		bsr.s	c2byte
		lsl.b	d5,d1
		bsr.s	c2byte
		lsl.b	d5,d1
		bsr.s	c2byte
		move.b	d1,(a1)+
c2entry		dbra	d0,c2loop		; d0=Counter
		swap	d0
		subq.w	#1,d0
		bcs.s	c2finished
		swap	d0
		bra.s	c2loop
c2finished	move.w	d2,d0			; -> d0=JoinCode
		swap	d0
		move.w	d3,d0
		move.l	a1,d0		;a0.l = packed data ptr
		sub.l	a0,d0		;d0.l = packed length in bytes
		rts
		cnop	0,4
c2byte		move.b	(a0)+,d4
		ext.w	d4
		asl.w	#6,d4
		sub.w	d3,d4
		bpl.s	c2skip1
		bset	#1,d1
		neg.w	d4
c2skip1		cmp.w	d2,d4
		bls.s	c2skip2
		bset	#0,d1
c2skip2		bsr.s	adaptive4
		rts

** Poor Tape Recordings Quality (7:1 Ratio!!)

		cnop	0,4
UnpackMode4:	move.l	a1,-(sp)
		moveq	#0,d1
		moveq	#2,d5
		move.w	d1,d3			; d3=EstMax
		swap	d1
		move.w	d1,d2			; d2=Delta
		bne.s	d2entry
		moveq	#5,d2
		bra.s	d2entry
d2loop		move.b	(a0)+,d1		; d1=Shifter
		rol.b	d5,d1
		bsr.s	d2byte
		rol.b	d5,d1
		bsr.s	d2byte
		rol.b	d5,d1
		bsr.s	d2byte
		rol.b	d5,d1
		bsr.s	d2byte
d2entry		dbra	d0,d2loop		; d0=Counter
		swap	d0
		subq.w	#1,d0
		bcs.s	d2finished
		swap	d0
		bra.s	d2loop
d2finished	move.w	d2,d0			; -> d0=JoinCode
		swap	d0
		move.w	d3,d0
		move.l	(sp)+,a0
		move.l	a1,d0		;a0.l = packed data ptr
		sub.l	a0,d0		;d0.l = packed length in bytes
		rts
		cnop	0,4
d2byte		bsr.s	adaptive4
		move.w	d3,d4
		asr.w	#6,d4
		cmp.w	#127,d4
		bgt.s	d2high
		cmp.w	#-128,d4
		blt.s	d2low
		move.b	d4,(a1)+
		rts
		cnop	0,4
d2high		move.b	#127,(a1)+
		rts
		cnop	0,4
d2low		move.b	#-128,(a1)+
		rts

		cnop	0,4
adaptive4	move.w	d2,d4			; d1 = SignBit + DataBit
		lsr.w	#1,d4
		btst	#0,d1
		beq.s	d2skip1
		add.w	d2,d4
		mulu	#$5600,d2
		bra.s	d2sign
d2skip1		mulu	#$3800,d2
d2sign		btst	#1,d1
		beq.s	d2skip2
		neg.w	d4
d2skip2		add.w	d4,d3
		add.l	#8192,d2
		moveq	#14,d4
		asr.l	d4,d2
		rts

source		incbin	'st-00:modules/mod.tune'
sourceend
dest		ds.b	1024*100
destend
