; extern void __asm AsmRenderWorld(register __a0 long,register __a1 long);
; extern void __asm AsmClearFrame(register __a0 long *,register __d0 long,register __d1 long);
; extern void __asm AsmChunky2Planar(register __a0 long,register __a1 long);

	XDEF	_AsmRenderWorld
	XDEF	_AsmClearFrame
	XDEF	_AsmChunky2Planar
	
;--------------------------------------------------------------------
;PARAMETERS
;
; a0 = xBUFFER
; a1 = fBUFFER

ViewRight	EQU	256
ViewBottom	EQU	128
ViewCenterY	EQU	64 ; ViewBottom/2

fBUFF_SIZE	EQU	32768
half_fBUFF	EQU 	fBUFF_SIZE/2

X		EQUR	d0
yinc		EQUR	d1
yrinc		equr	d2
HC		EQUR	d3
temp1		EQUR	d4
endY		EQUR	d5
errY		EQUR	d6
VIEWR		EQUR	d7

xBUFF		EQUR	a0
fBUFF		EQUR	a1
fBUFF2		equr	a2
LHC		EQUR	a3
BMP		EQUR	a4
LBMP		EQUR	a5
wall1		EQUR	a3
wall2		EQUR	a5
VIEWC		EQUR	a6


	section renderworld,code


_AsmRenderWorld:

INIT:	movem.l	d2-d7/a2-a6,-(sp)
	moveq	#0,X			; X <- ViewLeft
	move.l	X,LHC
	move.l	X,LBMP
	move.l	#ViewRight,VIEWR
	
	movea.l	#ViewCenterY,VIEWC
	
	; ---------------------------------------------------------------------
xLoop:	move.l	(xBUFF)+,HC		; Fetch height, column from xBUFFER
	movea.l	(xBUFF)+,BMP		; Fetch bitmap from xBUFFER
	
	cmp.l	LHC,HC			; Is Height = LastHeight & Column = LastColumn?
	bne.b	ScaleColumn		; No
	cmp.l	LBMP,BMP		; Is Bitmap = LastBitmap?
	bne.b	ScaleColumn		; No
	; -------------------------------
	
CopyColumn:
	move.l	fBUFF,-(sp)		; make a backup of fBUFF
	adda.l	X,fBUFF			; startY = fBUFF = X
	adda.l	#half_fBUFF,fBUFF
	move.l	fBUFF,fBUFF2

	cmp.w	VIEWC,HC		; Is height > ViewCenterY+1?
	ble.b	copySmall		; no
	; -------------------------------
copyBig:	
	move.l	VIEWC,temp1
	bra.b	PreCpy
copySmall:
	move.l	HC,temp1

PreCpy: subq.l	#1,temp1

COPY:	suba.l	VIEWR,fBUFF2
	move.b	-1(fBUFF),(fBUFF)
	adda.l	VIEWR,fBUFF
	move.b	-1(fBUFF2),(fBUFF2)	
	dbra	temp1,COPY

EndCpy:	move.l	(sp)+,fBUFF		; restore fBUFF
	bra.b	NextX	

	; -------------------------------

ScaleColumn:
	; if any future unexplained problems occur, try checking for HC > 0
	tst.w	HC
	beq.b	NextX
		
	move.l	fBUFF,-(sp)
	adda.l	X,fBUFF			; startY = fBUFF = X
	add.l	#half_fBUFF,fBUFF
	movea.l fBUFF,fBUFF2
	
	move.l	HC,temp1		; Initialize the wall bitmap ptrs
	swap	temp1
	ext.l	temp1			; temp1 = column
	lsl.w	#6,temp1		; temp1 = column * 64
	move.l	BMP,wall1
	adda.l	temp1,wall1		; bitmap+column*64
	lea	31(wall1),wall1
	move.l	wall1,wall2		; wall2 = bitmap+column*64+63-scrY
	addq.l	#1,wall1		; wall1 = bitmap+column*64+scrY

	moveq	#32,yrinc		; do scaling division
	moveq	#0,yinc
	cmp.w	yrinc,HC
	bgt.b	SetErr


DoDiv:	divs.w	HC,yrinc		; 
	move.w	yrinc,yinc		; yinc = 32 / height
	swap	yrinc			; yrinc = 32 % height
	
SetErr:	move.w	HC,errY			; errY = -height
	neg.w	errY
	
	cmp.w	VIEWC,HC		; Is height > ViewCenterY+1 ?
	ble.b	scaleSmall		; no

scaleBig:
	move.l	VIEWC,endY
	bra.b	MoreScaleInit

	; -------------------------------

NextX:	addq.w	#1,X
	cmp.w	VIEWR,X
	bne.b	xLoop
FIN:	movem.l	(sp)+,d2-d7/a2-a6
	rts

	; -------------------------------

scaleSmall:
	move.l	HC,endY

	; -------------------------------

MoreScaleInit:	
	subq.l	#1,endY
	tst.w	yinc
	beq.b	SCALE2

	; -------------------------------
	
SCALE1:	suba.l	VIEWR,fBUFF2
	move.b	(wall1),(fBUFF)
	adda.l	yinc,wall1
	move.b	(wall2),(fBUFF2)
	suba.l	yinc,wall2

	add.w	yrinc,errY
	blt.b	Check1ScaleFin
	sub.w	HC,errY
	addq.l	#1,wall1
	subq.l	#1,wall2
	
Check1ScaleFin:
	adda.l	VIEWR,fBUFF
	dbra	endY,SCALE1

	move.l	HC,LHC
	move.l	BMP,LBMP
	move.l	(sp)+,fBUFF
	bra.b	NextX

	; -------------------------------
	
SCALE2:	suba.l	VIEWR,fBUFF2
	move.b	(wall1),(fBUFF)
	move.b	(wall2),(fBUFF2)

	add.w	yrinc,errY
	blt.b	Check2ScaleFin
	sub.w	HC,errY
	addq.l	#1,wall1
	subq.l	#1,wall2
	
Check2ScaleFin:
	adda.l	VIEWR,fBUFF
	dbra	endY,SCALE2

	move.l	(sp)+,fBUFF
	move.l	HC,LHC
	move.l	BMP,LBMP	
	bra.b	NextX	
; ---------------------------------------------------------------------

_AsmClearFrame
	move.l	d2,-(sp)

	move.l	#half_fBUFF/4-1,d2	
ClearTop:
	move.l	d0,(a0)+
	dbra	d2,ClearTop

	move.l	#half_fBUFF/4-1,d2	
ClearBottom:
	move.l	d1,(a0)+
	dbra	d2,ClearBottom
	
	move.l	(sp)+,d2
	rts

; ----------------------------------------------------------------------------
; peterm/chunky4.s

; Basically the same as peterm/chunky3.s, except use Chris Hames' idea
; of temporary FAST buffers to allow longword writes to CHIP RAM.

;-----------------------------------------------------------------------------
; chunky2planar:	(new Motorola syntax)
;  a0 -> chunky pixels
;  a1 -> plane0 (assume other 7 planes are allocated contiguously)


PlaneStartOffset equ	404	; bytes
PlaneSize	 equ	8000 	; bytes
PlaneLineOffset  equ	8 	; bytes

ViewBottom	 equ	128
LongsPerLine	 equ	8

fbuffer		equr	a0
plane0		equr	a1
plane1		equr	a2
plane2		equr	a3
plane3		equr	a4

		section chunks,code

_AsmChunky2Planar:

		movem.l	d2-d7/a2-a4,-(sp)
		
; set up register constants

;		move.l	#$0f0f0f0f,d5	; d5 = constant $0f0f0f0f
; previous not used for 4 bit only colours

		move.l	#$55555555,d6	; d6 = constant $55555555
		move.l	#$3333cccc,d7	; d7 = constant $3333cccc

		lea	PlaneStartOffset(plane0),plane0

		move.w	#PlaneSize,d5
		
		movea.l	plane0,plane1
		adda.l	d5,plane1
		movea.l	plane1,plane2
		adda.l	d5,plane2
		movea.l	plane2,plane3
		adda.l	d5,plane3
		
		move.w	#ViewBottom,d5

; main loop (starts here) processes 8 chunky pixels at a time
		
PreMain:	moveq	#32,d0
mainloop:

; d2 = a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
		move.l	(a0)+,d2	; 12 get next 4 chunky pixels in d0

; d3 = e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0 g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
		move.l	(a0)+,d3	; 12 get next 4 chunky pixels in d1

; d2 = d2 & 0f0f0f0f
; d2 = ........a3a2a1a0 ........b3b2b1b0 ........c3c2c1c0 ........d3d2d1d0
;		and.l	d5,d2		;  8 d5=$0f0f0f0f
; previous line not necessary for 4 bit only graphics

; d3 = d3 & 0f0f0f0f
; d3 = ........e3e2e1e0 ........f3f2f1f0 ........g3g2g1g0 ........h3h2h1h0
;		and.l	d5,d3		;  8 d5=$0f0f0f0f
; previous line not necessary for 4 bit only graphics

; d2 = (d2 << 4) | d3
; d2 = a3a2a1a0e3e2e1e0 b3b2b1b0f3f2f1f0 c3c2c1c0g3g2g1g0 d3d2d1d0h3h2h1h0
		lsl.l	#4,d2		; 16
		or.l	d3,d2		;  8


; d3 = ((d2 & 33330000) << 2) | (swap(d2) & 3333cccc) | ((d2 & 0000cccc) >> 2)
; d3 = a1a0c1c0e1e0g1g0 b1b0d1d0f1f0h1h0 a3a2c3c2e3e2g3g2 b3b2d3d2f3f2h3h2
		move.l	d2,d3		;  4
		and.l	d7,d3		;  8 d7=$3333cccc
		move.w	d3,d1		;  4
		clr.w	d3		;  4
		lsl.l	#2,d3		; 12
		lsr.w	#2,d1		; 10
		or.w	d1,d3		;  4
		swap	d2		;  4
		and.l	d7,d2		;  8 d7=$3333cccc
		or.l	d2,d3		;  8

; d2 = d3 >> 7
; d2 = ..............a1 a0c1c0e1e0g1g0b1 b0d1d0f1f0h1h0a3 a2c3c2e3e2g3g2..
		move.l	d3,d2		;  4
		lsr.l	#7,d2		; 22
		
; d1 = d3 & 55555555
; d1 = ..a0..c0..e0..g0 ..b0..d0..f0..h0 ..a2..c2..e2..g2 ..b2..d2..f2..h2
		move.l	d3,d1		;  4
		and.l	d6,d1		;  8 d6=$55555555

; d3 ^= d1
; d3 = a1..c1..e1..g1.. b1..d1..f1..h1.. a3..c3..e3..g3.. b3..d3..f3..h3..
		eor.l	d1,d3		;  8

; d4 = d2 & 55555555
; d4 = ..............a1 ..c1..e1..g1..b1 ..d1..f1..h1..a3 ..c3..e3..g3....
		move.l	d2,d4		;  4
		and.l	d6,d4		;  8 d6=$55555555

; d2 ^= d4
; d2 = ................ a0..c0..e0..g0.. b0..d0..f0..h0.. a2..c2..e2..g2..
		eor.l	d4,d2		;  8

; d3 = (d3 | d4) >> 1
; d3 = ................ a1b1c1d1e1f1g1h1 ................ a3b3c3d3e3f3g3h3
		or.l	d4,d3		;  8
		lsr.l	#1,d3		; 10

; d2 = d2 | d1
; d2 = ................ a0b0c0d0e0f0g0h0 ................ a2b2c2d2e2f2g2h2
		or.l	d1,d2		;  8
					; inner loop thus far is 220

		move.b	d3,(plane3)+
		swap	d3
		move.b	d3,(plane1)+

		move.b	d2,(plane2)+
		swap	d2
		move.b	d2,(plane0)+
				
		subq.w	#1,d0		;   check if end of line is reached
		bne.b	mainloop	;   no continue as usual
; ---------------------------------------


		
		addq.l	#PlaneLineOffset,plane0
		addq.l	#PlaneLineOffset,plane1
		addq.l	#PlaneLineOffset,plane2
		addq.l	#PlaneLineOffset,plane3
		
		subq.w	#1,d5
;		tst.w	a5		; 68020+ instruction change to cmpa.w #0,a5
					; if you want 68000 compatibility
		bne.b	PreMain
		
; -------------------------------------------------------------------------

FINC2P:		movem.l	(sp)+,d2-d7/a2-a4

		rts
;-----------------------------------------------------------------------------

	end
