; extern void __asm AsmRenderMaze(register __a0 long *,register __a1 long *);
; extern void __asm AsmClearBackground(register __a0 long *,register __d0 long,register __d1 long);
; extern void __asm AsmChunky2Planar(register __a0 long *,register __a1 long *);

	XDEF	_AsmRenderMaze
	XDEF	_AsmClearBackground
	XDEF	_AsmChunky2Planar
	
	section AsmGfxRoutines,code
	
; ------------------  G L O B A L   D E F I N E S  ------------------

DISPLAY_DEPTH	equ	4	; These define the physical display
DISPLAY_WIDTH	equ	320
DISPLAY_HEIGHT	equ	200 

				; These define the maze viewing area
VIEW_WIDTH	equ	128	; size in pixels of wolf maze view (must be divisible by 8)
VIEW_HEIGHT	equ	64	; size in rows of wolf maze view
VIEW_LEFT	equ	100	; Column with in the framebuffer where the wolf view starts
VIEW_TOP	equ	68	; First row to draw into
VIEW_RIGHT	equ	((VIEW_WIDTH+VIEW_LEFT)-1)
VIEW_BOTTOM	equ	((VIEW_HEIGHT+VIEW_TOP)-1)

VIEW_CENTER_ROW equ	((VIEW_HEIGHT)/2)
VIEW_CENTER_COL equ	((VIEW_LEFT+VIEW_RIGHT)/2)

PlaneSize	equ	(DISPLAY_WIDTH*DISPLAY_HEIGHT)/8  ; 
BufferSize	equ	(DISPLAY_WIDTH*DISPLAY_HEIGHT)	  ;
VIEW_MIDDLE	equ	(DISPLAY_WIDTH*(VIEW_HEIGHT/2))

;--------------------------------------------------------------------
;AsmChunky2Planar
;
;FUNCTION:
;   Convert a chunky graphics bitmap into 4 planar bitmap planes
;
;PARAMETERS:
;   a0 -> chunky pixel buffer
;   a1 -> plane0 (assume other 3 planes are allocated contiguously)
;
;RETURNS:
;   none
;
;NOTE:
;   This is a modified version of the c2p routine: peterm/chunky4.s
;   by Peter McGavin (peterm@ker
;--------------------------------------------------------------------

; ------------------------  D E F I N E S  --------------------------

buffer		equr	a0
plane0		equr	a1
plane1		equr	a2
plane2		equr	a3
plane3		equr	a4
count		equr	d0
const1		equr	d5
const2		equr	d6

; ----------------------------  M A I N  ----------------------------

;	adda.l	#(VIEW_TOP*DISPLAY_WIDTH),buffer
;	adda.l	#((DISPLAY_WIDTH/8)*VIEW_TOP),plane0
Psize	equ	(DISPLAY_WIDTH*VIEW_HEIGHT)/8


_AsmChunky2Planar:
	movem.l	d2-d6/a2-a4,-(sp)
	
	adda.l	#(VIEW_TOP*DISPLAY_WIDTH),buffer
	adda.l	#((DISPLAY_WIDTH/8)*VIEW_TOP),plane0	

	moveq	#0,d0
	
	move.l	#$55555555,const1 ; d6 = constant $55555555
	move.l	#$3333cccc,const2 ; d5 = constant $3333cccc
	
	move.w	#PlaneSize,d0
	movea.l	plane0,plane1
	adda.l	d0,plane1
	movea.l	plane1,plane2
	adda.l	d0,plane2
	movea.l	plane2,plane3
	adda.l	d0,plane3
		
	move.w	#Psize,count ; Working on 4 planes at a time

				; processes 8 chunky pixels at a time
C2Pmain	move.l	(a0)+,d2	; 12 get next 4 chunky pixels in d0
	move.l	(a0)+,d3	; 12 get next 4 chunky pixels in d1

	lsl.l	#4,d2		; 16
	or.l	d3,d2		;  8
	move.l	d2,d3		;  4
	and.l	const2,d3	;  8
	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	const2,d2	;  8
	or.l	d2,d3		;  8
	move.l	d3,d2		;  4
	lsr.l	#7,d2		; 22
	move.l	d3,d1		;  4
	and.l	const1,d1	;  8
	eor.l	d1,d3		;  8
	move.l	d2,d4		;  4
	and.l	const1,d4	;  8
	eor.l	d4,d2		;  8
	or.l	d4,d3		;  8
	lsr.l	#1,d3		; 10
	or.l	d1,d2		;  8  inner loop thus far is 220

	move.b	d3,(plane3)+	; Write 8 pixels to the 4 bitplanes
	swap	d3
	move.b	d3,(plane1)+
	move.b	d2,(plane2)+
	swap	d2
	move.b	d2,(plane0)+
				
	subq.w	#1,count	;   check if end of buffer is reached
	bne.b	C2Pmain		;   no continue as usual
FINC2P:	movem.l	(sp)+,d2-d6/a2-a4
	rts
;--------------------------------------------------------------------
;--------------------------------------------------------------------


;--------------------------------------------------------------------
;AsmClearBackground
;
;FUNCTION:
;   Clears the upper and lower region of the wolf background
;   with two colours. The upper region's colour is found in d0,
;   and the lower region's colour is found in d1.
;
;PARAMETERS:
;   a0 -> chunky pixel buffer
;   d0 -> colour 1
;   d1 -> colour 2
;
;RETURNS:
;   none
;
;NOTE:
;   this routine requires the view area to be longword aligned
;   and for the width to be evenly divisible by 4
;--------------------------------------------------------------------


; -------------------------  D E F I N E S  -------------------------

CLR_ADDROFFSET	equ	((VIEW_TOP*DISPLAY_WIDTH)+VIEW_LEFT)
CLR_HALFSIZE	equ	(((VIEW_WIDTH*VIEW_HEIGHT)/8)/(VIEW_WIDTH/4))


; ----------------------------  M A I N  ----------------------------
_AsmClearBackground
	movem.l	d2-d3/a0-a1,-(sp)
	moveq	#0,d2
	
	adda.l	#CLR_ADDROFFSET,a0
	movea.l	a0,a1
					; PASS 1 - clear the upper region
CLR_PASS1:				; with the colours found in D0
	move.l	#CLR_HALFSIZE-1,d3
ClearTop:
	move.w	#VIEW_WIDTH/4-1,d2	; Used for clearing a single row
ClearRow1:
	move.l	d0,(a0)+
	dbra	d2,ClearRow1
	
	adda.w	#DISPLAY_WIDTH,a1
	movea.l	a1,a0
	dbra	d3,ClearTop

					; PASS 2 - clear the lower region
CLR_PASS2:				; with the colours found in D0
	move.l	#CLR_HALFSIZE-1,d3
ClearBottom:
	move.w	#VIEW_WIDTH/4-1,d2	; Used for clearing a single row
ClearRow2:
	move.l	d1,(a0)+
	dbra	d2,ClearRow2
	
	adda.w	#DISPLAY_WIDTH,a1
	movea.l	a1,a0
	dbra	d3,ClearBottom

CLRFIN:	movem.l	(sp)+,d2-d3/a0-a1
	rts
;--------------------------------------------------------------------
;--------------------------------------------------------------------



;--------------------------------------------------------------------
;AsmRenderMaze
;
;FUNCTION:
;   Render the visible maze walls into the frame buffer.
;
;PARAMETERS:
;   a0 -> &xBUFFER[VIEW_LEFT]
;   a1 -> frame buffer
;
;RETURNS:
;   none
;
;--------------------------------------------------------------------

; -------------------------  D E F I N E S  -------------------------

half_fBUFF	EQU 	VIEW_MIDDLE ; BufferSize/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


;+-------+	+-------+
;|walls	| ---\	|Create	|
;|doors	| ----|	|xBuffer|
;|objects| ---/	|	|
;+-------+	+-------+



; ----------------------------  M A I N  ----------------------------

_AsmRenderMaze:

INIT:	movem.l	d2-d7/a2-a6,-(sp)
	move.l	#VIEW_LEFT,X	
	move.l	X,LHC
	move.l	X,LBMP
	move.l	#DISPLAY_WIDTH,VIEWR
	move.l	#VIEW_TOP,d3
	muls.w	VIEWR,d3
	adda.l	d3,fBUFF
	
	movea.l	#VIEW_CENTER_ROW,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			; Empty column?
	beq.b	NextX			; Yup, skip this column
		
	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	#VIEW_RIGHT+1,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	
;--------------------------------------------------------------------
;--------------------------------------------------------------------
	end
