; NOTE: Only works on 68020+, because of MULU.L and DIVUL
;       instructions. Pretty lame, huh :)

; *****************************************************************************
; Scale
; -----------------------------------------------------------------------------
; Inputs     : a0   = SourcePtr
;  	       a1   = BufferPtr
;              d0.l = SourceW
;              d1.l = SourceH
;              d2.l = BufferX
;              d3.l = BufferY
;              d4.l = DestW
;              d5.l = DestH
; Output     : -
; Description: Scales a (byte-per-pixel) chunky image.
; 	       o Performs clipping
;              o Does not perform mirroring
;              o Destination coordinates are allowed to be negative
;              o No transparent colours !!!
; History    : 05 Dec 1996, Matthijs Hollemans, C version.
;              26 Dec 1996, Motorola 68020+ version. VERY UNOPTIMIZED !!!
; *****************************************************************************

ClipT	=	20		
ClipB	=	120		
ClipL	=	20
ClipR	=	159

BufferW	=	160

Scale
	; Test if bitmap is at least partially visible ------------------------

	cmp.l	#2,d4			; DestW < 2 ?
	blt	.Done
	cmp.l	#2,d5			; DestH < 2 ?
	blt	.Done
	cmp.l	#ClipR,d2		; BufferX > ClipR ?
	bgt	.Done
	cmp.l	#ClipB,d3		; BufferY > ClipB ?
	bgt	.Done
	move.l	d2,d6			; (BufferX + DestW) < ClipL ?
	add.l	d4,d6
	cmp.l	#ClipL,d6
	blt	.Done
	move.l	d3,d6			; (BufferY + DestH) < ClipT ?
	add.l	d5,d6
	cmp.l	#ClipT,d6
	blt	.Done

	move.w	d0,SourceW		
	
	; Determine step size -------------------------------------------------

	swap	d0			; XStep = SourceW << 16
	divul	d4,d0			; XStep = (SourceW << 16) / DestW
	swap	d1			; YStep = SourceH << 16
	divul	d5,d1			; YStep = (SourceH << 16) / DestH
	moveq	#0,d6			; SY = 0

	; Clipping ------------------------------------------------------------

.Top
	cmp.l	#ClipT,d3		; IF BufferY < ClipT
	bge	.Bottom			;
	move.l	#ClipT,d6		;   d6 = ClipT
	sub.l	d3,d6			;   d6 = ClipT - BufferY
	sub.l	d6,d5			;   d5 -= ClipT - BufferY
	mulu.l	d1,d6			;   d6 = (ClipT - BufferY) * YStep
	move.l	#ClipT,d3		;   d3 = ClipT
.Bottom					; ENDIF
	move.l	d3,d7			; d7 = BufferY
	add.l	d5,d7			; d7 = BufferY + ClipH
	cmp.l	#ClipB,d7		; IF (BufferY + ClipH) > ClipB
	ble	.Left			;
	move.l	#ClipB,d5		;   d5 = ClipB
	sub.l	d3,d5			;   d5 = ClipB - BufferY
	addq.l	#1,d5			;   d5 = ClipB - BufferY + 1
.Left					; ENDIF
	mulu	#BufferW,d3		; d3 = BufferY * BufferW
	add.l	d3,a1			; a1 += BufferY * BufferW
	moveq	#0,d3			; StartSX = 0

	cmp.l	#ClipL,d2		; IF BufferX < ClipL
	bge	.Right			;
	move.l	#ClipL,d3		;   d3 = ClipL
	sub.l	d2,d3			;   d3 = ClipL - BufferX
	sub.l	d3,d4			;   d4 -= (ClipL - BufferX)
	mulu.l	d0,d3			;   d3 = (ClipL - BufferX) * XStep
	move.l	#ClipL,d2		;   d2 = ClipL
.Right					; ENDIF
	move.l	d2,d7			; d7 = BufferX
	add.l	d4,d7			; d7 = BufferX + ClipW
	cmp.l	#ClipR,d7		; IF (BufferX + ClipW) > ClipR
	ble	.Scale			;
	move.l	#ClipR,d4		;   d4 = ClipR
	sub.l	d2,d4			;   d4 = ClipR - BufferX
	addq.l	#1,d4			;   d4 = ClipR - BufferX + 1
.Scale					; ENDIF
	add.l	d2,a1			; a1 += BufferX
	move.l	#BufferW,a3		; a3 = BufferW
	sub.l	d4,a3			; a3 = BufferW - ClipW
	subq.l	#1,d4			; ClipW-1
	bmi	.Done			; IF ClipW < 0 THEN Done
	subq.l	#1,d5			; ClipH-1
	bmi	.Done			; IF ClipH < 0 THEN Done
	
	; Scaling -------------------------------------------------------------

	; a0 = SourcePtr, a1 = BufferPtr, a2 = SourceLoop, a3 = BufferStep
	; d0 = XStep, d1 = YStep, d2 = SX (only in ColLoop)
	; d3 = StartSX, d4 = ColLoop counter backup
	; d5 = RowLoop counter, d6 = SY, d7 = ColLoop counter

.RowLoop				; FOR (i=0; i < ClipH; i++)
	move.l	d6,d2			;   d2 = SY
	move.l	a0,a2			;   a2 = SourcePtr

	swap	d2			;   d2 = SY >> 16
	mulu.w	SourceW,d2		;   d2 = (SY >> 16) * SourceW
	
	add.l	d2,a2			;   a2 = SourcePtr + (SY>>16)*SourceW

	move.l	d3,d2			;   d2 = StartSX
	move.l	d4,d7			;   FOR (j=0; j < ClipW; j++)
.ColLoop
	swap	d2			;     d2 = SX >> 16
	move.b	(a2,d2.w),(a1)+		;     *BufferPtr++ = *(SourceLoop + (SX>>16))
	swap	d2			;     d2 = SX
	add.l	d0,d2			;     d2 += XStep
	dbf	d7,.ColLoop		;   ENDFOR

	add.l	a3,a1			;   a1 += BufferStep
	add.l	d1,d6			;   d6 += YStep
	dbf	d5,.RowLoop		; ENDFOR

	; Finished.
	
.Done
	rts


SourceW	dc.w	0
