;
; Some practical assembler utility routines. See sutils.h for corresponding C prototypes.
; These are mostly called from within video.c as most of them are kinda copy
; routines which handle cropping and adding together different-sized channels.
;
; Michael Rausch  15-2-94  23:05:00
;

	SECTION	text,CODE

	XREF	_clamp

; ***************************************************************

;void PMB2_reconstruct(char *dest, char *dest1, char *source, char *source1, int row_incr);

	XDEF	_PMB2_reconstruct
_PMB2_reconstruct:
	subq.l	#2,d0			; (int*)   correct row_size
	lsl.l	#2,d0
	moveq	#7,d1
pmb2_all_rows:
	move.l	(a2)+,(a0)+
	move.l	(a2)+,(a0)+
	move.l	(a3)+,(a1)+
	move.l	(a3)+,(a1)+
	add.l	d0,a0
	add.l	d0,a1
	add.l	d0,a2
	add.l	d0,a3
	dbra	d1,pmb2_all_rows
	rts

; ***************************************************************

;void PMB1_reconstruct(char *dest, char *source, int row_incr);

	XDEF	@PMB1_reconstruct
@PMB1_reconstruct:
	subq.l	#4,d0			; correct row_size
	lsl.l	#2,d0
	moveq	#15,d1
pmb1_all_rows:
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	add.l	d0,a0
	add.l	d0,a1
	dbra	d1,pmb1_all_rows
	rts

; ***************************************************************

; void PSB4_reconstruct(char *dest, char *dest1, char *source1, char *source2, char *source1a, char *source2a, int row_size);
;

	XDEF	_PSB4_reconstruct
_PSB4_reconstruct:
psb4reg REG	d2-d4
	movem.l	psb4reg,-(sp)

	subq.l	#8,d0			; correct row_size

	move.l	#$fefefefe,d3

	moveq	#7,d4
psb4_all_rows:

	REPT	2
	move.l	(a2)+,d1
	move.l	(a3)+,d2
	and.l	d3,d1
	and.l	d3,d2
	add.l	d1,d2
	roxr.l	#1,d2			; tricky! get bit no 32 from the previous addition
	move.l	d2,(a0)+		; this one kicks ass !!!
	ENDR

	REPT	2
	move.l	(a5)+,d1
	move.l	(a6)+,d2
	and.l	d3,d1
	and.l	d3,d2
	add.l	d1,d2
	roxr.l	#1,d2
	move.l	d2,(a1)+
	ENDR

	add.l	d0,a0
	add.l	d0,a1
	dbra	d4,psb4_all_rows

	movem.l	(sp)+,psb4reg
	rts


; ***************************************************************

; void PSB3_reconstruct(char *dest, char *source1, char *source2, int row_size);
;

	XDEF	_PSB3_reconstruct
_PSB3_reconstruct:
psb3reg REG	d2-d4
	movem.l	psb3reg,-(sp)

	sub.l	#16,d0			; correct row_size

	move.l	#$fefefefe,d3

	moveq	#15,d4
psb3_all_rows:

	REPT	4
	move.l	(a1)+,d1
	move.l	(a2)+,d2
	and.l	d3,d1
	and.l	d3,d2
	add.l	d1,d2
	roxr.l	#1,d2			; tricky! get bit no 32 from the previous addition
	move.l	d2,(a0)+		; this one kicks ass !!!
	ENDR

	add.l	d0,a0
	dbra	d4,psb3_all_rows

	movem.l	(sp)+,psb3reg
	rts

; ***************************************************************

;void PSB2_reconstruct(char *dest, char *dest1, char *source, char *source1, int row_incr);

	XDEF	_PSB2_reconstruct
_PSB2_reconstruct:
	subq.l	#2,d0			; (int*)   correct row_size
	lsl.l	#2,d0
	moveq	#7,d1
psb2_all_rows:
	move.l	(a2)+,(a0)+
	move.l	(a2)+,(a0)+
	move.l	(a3)+,(a1)+
	move.l	(a3)+,(a1)+
	add.l	d0,a0
	add.l	d0,a1
	dbra	d1,psb2_all_rows
	rts


; ***************************************************************

;void PSB1_reconstruct(char *dest, char *source, int row_incr);

	XDEF	@PSB1_reconstruct
@PSB1_reconstruct:
	subq.l	#4,d0			; (int*) correct row_size
	lsl.l	#2,d0
	moveq	#15,d1
psb1_all_rows:
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	add.l	d0,a0
	dbra	d1,psb1_all_rows
	rts

; ***************************************************************

; void RSB4_reconstruct(char *dest, char *source1, char *source2, int row_size);
;

	XDEF	_RSB4_reconstruct
_RSB4_reconstruct:
rsb4reg REG	d2-d4
	movem.l	rsb4reg,-(sp)

	subq.l	#8,d0			; correct row_size

	move.l	#$fefefefe,d3

	moveq	#7,d4
rsb4_all_rows:

	REPT	2
	move.l	(a1)+,d1
	move.l	(a2)+,d2
	and.l	d3,d1
	and.l	d3,d2
	add.l	d1,d2
	roxr.l	#1,d2			; tricky! get bit no 32 from the previous addition
	move.l	d2,(a0)+		; this one kicks ass !!!
	ENDR

	add.l	d0,a1
	add.l	d0,a2
	dbra	d4,rsb4_all_rows

	movem.l	(sp)+,rsb4reg
	rts


; ***************************************************************

;void RSB3_reconstruct(char *dest, char *source, int row_size);

	XDEF	@RSB3_reconstruct
@RSB3_reconstruct:
	subq.l	#8,d0			; correct row_size
	moveq	#3,d1
rsb3_all_rows:
	rept	2
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	add.l	d0,a1
	endr
	dbra	d1,rsb3_all_rows
	rts

; ***************************************************************

; void RSB2_reconstruct(char *dest, char *source1, char *source2, int row_size);
;

	XDEF	_RSB2_reconstruct
_RSB2_reconstruct:
rsb2reg REG	d2-d4
	movem.l	rsb2reg,-(sp)

	sub.l	#16,d0			; correct row_size

	move.l	#$fefefefe,d3

	moveq	#15,d4
rsb2_all_rows:

	REPT	4
	move.l	(a1)+,d1
	move.l	(a2)+,d2
	and.l	d3,d1
	and.l	d3,d2
	add.l	d1,d2
	roxr.l	#1,d2			; tricky! get bit no 32 from the previous addition
	move.l	d2,(a0)+		; this one kicks ass !!!
	ENDR

	add.l	d0,a1
	add.l	d0,a2
	dbra	d4,rsb2_all_rows

	movem.l	(sp)+,rsb2reg
	rts


; ***************************************************************

;void RSB1_reconstruct(char *dest, char *source, int row_size);

	XDEF	@RSB1_reconstruct
@RSB1_reconstruct:
	sub.l	#16,d0			; correct row_size
	moveq	#15,d1
rsb1_all_rows:
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	add.l	d0,a1
	dbra	d1,rsb1_all_rows
	rts

; ***************************************************************

;void BM_reconstruct(char *index, char *rindex1, int row_size);

	XDEF	@BM_reconstruct
@BM_reconstruct:
	subq.l	#8,d0			; correct row_size
	moveq	#3,d1
bm_all_rows:
	rept	2
	move.l	(a1)+,(a0)+
	move.l	(a1)+,(a0)+
	add.l	d0,a0
	add.l	d0,a1
	endr
	dbra	d1,bm_all_rows
	rts


; ***************************************************************

;void BMcm_reconstruct(char *index, char *rindex1, short *blockvals, int row_size);


	XDEF	_BMcm_reconstruct
_BMcm_reconstruct:
bmcmreg REG	d2-d5/a4
	movem.l	bmcmreg,-(sp)

	lea	_clamp,a4

	subq.l	#8,d0			; correct row_size

	moveq	#7,d5
bmcm_all_rows:


	REPT	2
	move.l	(a1)+,d3

	moveq	#0,d1
	move.b	d3,d1

	lsr.l	#8,d3
	moveq	#0,d4
	move.b	d3,d4

	lsr.w	#8,d3		; *grin evilly*  eadiz, peecee  *strut*
	add.l	(a2)+,d3
	move.w	d3,d2
	swap	d3

	move.w	(a4,d3.w*2),d3
	move.b	(a4,d2.w*2),d3
	swap	d3

	add.w	(a2)+,d4
	add.w	(a2)+,d1
	move.w	(a4,d4.w*2),d3
	move.b	(a4,d1.w*2),d3

	move.l	d3,(a0)+
	ENDR

	add.l	d0,a0
	add.l	d0,a1
	dbra	d5,bmcm_all_rows

	movem.l	(sp)+,bmcmreg
	rts


; ***************************************************************

;void BIMcm_reconstruct(char *index, char *rindex1, char *bindex1, short *blockvals, int row_size);


	XDEF	_BIMcm_reconstruct
_BIMcm_reconstruct:
bimcmreg REG	d2-d6/a4
	movem.l	bimcmreg,-(sp)

	lea	_clamp,a4

	subq.l	#8,d0			; correct row_size

	move.l	#$fefefefe,d4

	moveq	#7,d5
bimcm_all_rows:

	REPT	2

	move.l	(a1)+,d1
	move.l	(a2)+,d3
	and.l	d4,d1
	and.l	d4,d3
	add.l	d1,d3
	roxr.l	#1,d3		; tricky! get bit #32 from the previous addition

	moveq	#0,d1
	move.b	d3,d1

	lsr.l	#8,d3
	moveq	#0,d6
	move.b	d3,d6

	lsr.w	#8,d3		; *grin evilly*  eadiz, peecee  *strut*
	add.l	(a3)+,d3
	move.w	d3,d2
	swap	d3

	move.w	(a4,d3.w*2),d3
	move.b	(a4,d2.w*2),d3
	swap	d3


	add.w	(a3)+,d6
	add.w	(a3)+,d1
	move.w	(a4,d6.w*2),d3
	move.b	(a4,d1.w*2),d3

	move.l	d3,(a0)+
	ENDR

	add.l	d0,a0
	add.l	d0,a1
	add.l	d0,a2
	dbra	d5,bimcm_all_rows

	movem.l	(sp)+,bimcmreg
	rts


; ***************************************************************

;void BIM_reconstruct(char *index, char *rindex1, char *bindex1, int row_size);
;

	XDEF	_BIM_reconstruct
_BIM_reconstruct:
bimreg REG	d2-d4
	movem.l	bimreg,-(sp)

	subq.l	#8,d0			; correct row_size

	move.l	#$fefefefe,d3

	moveq	#7,d4
bim_all_rows:

	REPT	2
	move.l	(a1)+,d1
	move.l	(a2)+,d2
	and.l	d3,d1
	and.l	d3,d2
	add.l	d1,d2
	roxr.l	#1,d2			; tricky! get bit no 32 from the previous addition
	move.l	d2,(a0)+		; this one kicks ass !!!
	ENDR

	add.l	d0,a0
	add.l	d0,a1
	add.l	d0,a2
	dbra	d4,bim_all_rows

	movem.l	(sp)+,bimreg
	rts


; ***************************************************************

	XDEF	@IM_reconstruct
@IM_reconstruct:
cdctreg REG	d2-d3/a2
	movem.l	cdctreg,-(sp)

	lea	_clamp,a2

	subq.l	#8,d0			; correct row_size

	moveq	#7,d2
cdct_all_rows:

	REPT	2
	move.w	(a1)+,d1
	move.w	(a2,d1.w*2),d3
	move.w	(a1)+,d1
	move.b	(a2,d1.w*2),d3
	swap	d3
	move.w	(a1)+,d1
	move.w	(a2,d1.w*2),d3
	move.w	(a1)+,d1
	move.b	(a2,d1.w*2),d3
	move.l	d3,(a0)+
	ENDR

	add.l	d0,a0
	dbra	d2,cdct_all_rows

	movem.l	(sp)+,cdctreg
	rts

; ***************************************************************

	XDEF	@clear64words
@clear64words:
	moveq	#7,d0
c64i:	clr.l	(a0)+
	clr.l	(a0)+
	clr.l	(a0)+
	clr.l	(a0)+
	dbra	d0,c64i
	rts

; ***************************************************************

	END
