;*======================================================================*
;*                TITLE:       SORT.GAS                                 *
;*                Function:    Sort Turtles into Painter's Order        *
;*                                                                      *
;*                Project #:              RAPIER                        *
;*                Programmer:             Rob Zdybel                    *
;*                                                                      *
;*            COPYRIGHT 1993 Atari Computer Corporation                 *
;*          UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION,         *
;*          PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR          *
;*        THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED.       *
;*                            ALL RIGHTS RESERVED.                      *
;*                                                                      *
;*======================================================================*

;
;	DATA ORGANIZATION
;

;
;   	        +-------------------+	 +---------------+
;   	        |  Xrite  |  Yrite  |<---|  PTR to ARG1  | INPUT1
;   	        +-------------------+	 +---------------+
;   	        |  Zrite  |  Xdown  |
;   	        +-------------------+	ViewPoint Turtle Record
;   	        |  Ydown  |  Zdown  |
;   	        +-------------------+
;   	        |  Xhead  |  Yhead  |
;   	        +-------------------+
;   	        |  Zhead  |  Xposn  |
;   	        +-------------------+
;   	        |  Yposn  |  Zposn  |
;   	        +-------------------+
;                        ...         
;   	                  +---------+	 +---------------+
;   	                  | Drawers |<---|  (DrawList)   | INPUT2
;   	                  +---------+	 +---------------+
;   	                  +---------+	 +---------------+
;   	                  | Scrubs  |<---|  (ScrubList)  | INPUT3
;   	                  +---------+	 +---------------+
;   	        +-------------------+	 +---------------+
;   	        |     Turtle[1]     |<---|  (TURTLE[1])  | INPUT4
;   	        +-------------------+	 +---------------+
;   	        +-------------------+
;   	        |  No. of Turtles   |   INPUT5
;   	        +-------------------+
;   	        |  Turtle Rcd Size  |   INPUT6
;   	        +-------------------+
;

;
;	COMMON EQUATES
;

	.data
	.gpu
	.nojpad

DEBUG_ON	.equ	0
	.nolist
	.include "jaguar.inc"
	.include "blit.inc"
	.include "gpu.inc"
	.include "macros.inc"
	.list

SORT::
	.dc.l	G_RAM
	.dc.l	EndGPU-StartGPU

PTRSIZE		.equ	(1*4)		; 1 LONG
INPUT6		.equ	G_ENDRAM-PTRSIZE
INPUT5		.equ	INPUT6-PTRSIZE
INPUT4		.equ	INPUT5-PTRSIZE
INPUT3		.equ	INPUT4-PTRSIZE
INPUT2		.equ	INPUT3-PTRSIZE
INPUT1		.equ	INPUT2-PTRSIZE

	.org	G_RAM
StartGPU:

;
;	GLOBAL REGISTER EQUATES
;
temp		.equr	r0
temp2		.equr	r1
lomask		.equr	r2
himask		.equr	r3

ptr		.equr	r4
matptr		.equr	r5
mtxa		.equr	r6

jumpr		.equr	r10
gpuptr		.equr	r11
inptr		.equr	r12
step		.equr	r13
ndx		.equr	r14

this		.equr	r15	; * Caution Multiply Defined*
now		.equr	r16	; * Caution Multiply Defined*
last		.equr	r17	; * Caution Multiply Defined*
thisrec		.equr	r18	; * Caution Multiply Defined*
thisptr		.equr	r19	; * Caution Multiply Defined*

link		.equr	r15
xtemp		.equr	r16
ytemp		.equr	r17
ztemp		.equr	r18
xviewr		.equr	r19
yviewr		.equr	r20
zviewr		.equr	r21
zposn		.equr	r22

scrublist	.equr	r23
oldlist		.equr	r24

turtlsiz	.equr	r25
nturtles	.equr	r26
turtle68k	.equr	r27
draw68k		.equr	r28
scrub68k	.equr	r29

rsort		.equr	r30
return		.equr	r31

;
;	ALTERNATE REGISTER EQUATES
;
left1		.equr	r11
left2		.equr	r12

;
;	LOCAL MACROS
;

;	NOTE: Dedicated Subroutine calls expect the proper
;	      registers to be pre-set. No Nesting!

	.macro	JSR_SORT
	move	PC,return
	jump	T,(rsort)
	addq	#6,return	; Determine Return Address
	.endm

	.macro	SORT_RTS
	jump	T,(return)
	.endm

;
;	CODE SEGMENT
;

;
;	System Initialization
;
	
	DEBUG_INIT

	moveq	#1,himask
	neg	himask
	move	himask,lomask
	shlq	#16,himask		; HIMASK = $ffff0000
	shrq	#16,lomask		; LOMASK = $0000ffff
	movei	#sort,rsort

	movei	#INPUT1,ptr
	load	(ptr),temp2		; TEMP2 = 68000 ptr to Viewpt Turtle
	addq	#4,ptr
	load	(ptr),draw68k		; DRAW68K = Ptr to 68000 Drawlist 
	addq	#4,ptr
	load	(ptr),scrub68k		; SCRUB68K = Ptr to 68000 Scrublist 
	addq	#4,ptr
	load	(ptr),turtle68k		; TURTLE68K = Ptr to 68000 Turtles
	addq	#4,ptr
	load	(ptr),nturtles		; NTURTLES = Number of Active Turtles
	addq	#4,ptr
	load	(ptr),turtlsiz		; TURTLSIZ = Size of a Turtle Record (Bytes)
	or	turtlsiz,turtlsiz	; *KLUDGE* BUG 21 FIX

	movei	#G_MTXC,ptr
	movei	#(GPUM3x1|GPUMROW),temp	; Righthand matrix is [3x1] - COLUMN major
	store	temp,(ptr)		; Since we wish to multiply by the TRANSPOSE of the Viewer's Matrix
	movei	#G_MTXA,mtxa		; Prepare GPU for ROW MAJOR multiply
	movei	#matrix,matptr

	addq	#12,temp2
	move	matptr,gpuptr
	moveq	#5,ndx
.10:	loadw	(temp2),temp		; FOR (X,Y and Z Head and Posn) DO
	addq	#2,temp2
	shlq	#16,temp
	sharq	#16,temp
	subq	#1,ndx
	store	temp,(gpuptr)		; Matrix[i] = Head/Posn Element Sign-extended
	jr	PL,.10
	addq	#4,gpuptr

	nop				; << WHY IS THIS NOP REQUIRED? >> **KLUDGE**

	move	matptr,gpuptr		; Extract Posn values into registers
	addq	#12,gpuptr
	load	(gpuptr),xviewr
	addq	#4,gpuptr
	load	(gpuptr),yviewr
	addq	#4,gpuptr
	load	(gpuptr),zviewr
;
;	Find Final Zpos for all Turtles
;	NOTE: This code assumes ALL Turtles are active and displayed
;
	movei	#zloop,jumpr
	movei	#(gpuram+4),gpuptr
	move	turtle68k,inptr
	addq	#18,inptr		; INPTR = Ptr to Turtle[1].Xposn
	move	turtlsiz,step
	subq	#6,step			; STEP = Offset to same .Xposn of next turtle
	move	nturtles,ndx
zloop:					; FOR (All Turtles) DO
	loadw	(inptr),xtemp		; Fetch this Turtle
	addq	#2,inptr
	loadw	(inptr),ytemp
	addq	#2,inptr
	shlq	#16,xtemp
	shlq	#16,ytemp
	sharq	#16,xtemp		; XTEMP = 32-bit Xpos
	sharq	#16,ytemp		; YTEMP = 32-bit Ypos
	loadw	(inptr),ztemp
	addq	#2,inptr
	loadw	(inptr),link
	add	step,inptr
	shlq	#16,ztemp
	shlq	#2,link			; LINK = GPU Internal Index
	sharq	#16,ztemp		; ZTEMP = 32-bit Zpos

	sub	xviewr,xtemp		; XTEMP = DeltaX
	sub	yviewr,ytemp		; YTEMP = DeltaY
	sub	zviewr,ztemp		; ZTEMP = DeltaZ

	and	lomask,xtemp
	shlq	#16,ytemp
	or	ytemp,xtemp		; XTEMP = DeltaY | DeltaX
	store	matptr,(mtxa)
	moveta	xtemp,left1
	moveta	ztemp,left2
	nop
	mmult	left1,zposn		; ZPOSN = Final Z in Viewer Space

	sharq	#14,zposn
	shlq	#16,zposn
	or	zposn,link		; LINK = ZPosn | LinkIndex
	subq	#1,ndx
	store	link,(gpuptr)		; Save this result in local memory
	jump	NE,(jumpr)
	addq	#4,gpuptr
;
;	Sort Internal Records by Zpos
;

	loadw	(draw68k),oldlist	; OLDLIST = 68000 DrawList Root
	movei	#gpuram,gpuptr
	shlq	#2,oldlist		; OLDLIST = Internalized Drawlist Root
	moveq	#0,scrublist		; SCRUBLIST = Nil
	store	scrublist,(gpuptr)	; DRAWLIST = Nil
	JSR_SORT

	loadw	(scrub68k),oldlist	; OLDLIST = 68000 ScrubList Root
	shlq	#2,oldlist		; OLDLIST = Internalized Drawlist Root
	JSR_SORT
;
;	Write-Back Results to 68000 RAM
;
	shrq	#2,scrublist
	load	(gpuptr),temp
	storew	scrublist,(scrub68k)	; New ScrubList Root
	shrq	#2,temp
	storew	temp,(draw68k)		; New DrawList Root

	addq	#4,gpuptr
	addq	#24,turtle68k		; TURTLE68K = Turtle[1].Turtlnk
writlp:	load	(gpuptr),temp
	addq	#4,gpuptr
	and	lomask,temp
	shrq	#2,temp			; Divide Index back down for 68000 land
	subq	#1,nturtles
	storew	temp,(turtle68k)
	jr	NE,writlp
	add	turtlsiz,turtle68k

;
;	GPU RTS
;
gpuend:
	movei	#G_CTRL,temp2		; GPU control/status register
	load	(temp2),temp
	bclr	#0,temp			; clear GPUGO bit
	store	temp,(temp2)		; stop the GPU

endloop:
	jr	T,endloop			; infinite loop
	nop


;
;	SUBROUTINE AREA
;

;
;	sort   Sort Turtles by Zposn
;
;	GIVEN:
;		OLDLIST = Index of First Turtle in list
;		SCRUBLIST = Index of First Turtle in ScrubList
;		GPUPTR = Address of TurtleRecord[0]
;		TURTLE[0] = Drawlist Root
;
;	RETURNS:
;		SCRUBLIST = New Turtles Scrubbed as needed
;		TURTLE[0] = New Drawlist Root
;		Turtle Records Re-Linked
;
;	REGISTER USAGE:
;		temp, ptr, lomask, himask, rsort
;		this, now, last, thisptr, thisrec
;

sort:

	cmpq	#0,oldlist		; WHILE (Oldlist <> Nil) DO
	move	oldlist,thisptr
	jr	NE,.10
	nop
	SORT_RTS			; NOTE: Exit from the side
.10:
	move	oldlist,this		; THIS = Current Record Index
	add	gpuptr,thisptr		; THISPTR = Address of This Record
	load	(thisptr),oldlist
	move	oldlist,thisrec		; THISREC = Current Record
	and	lomask,oldlist		; OLDLIST = This.Next
	cmpq	#0,thisrec
	jr	PL,.33			; IF (Zpos < 0) THEN Scrub this Turtle
;
;	Add this record to the Scrublist
;
	and	himask,thisrec
	or	scrublist,thisrec	; This.Next = Scrublist
	move	this,scrublist		; Scrublist = This
	jump	T,(rsort)
	store	thisrec,(thisptr)
.33:					; ELSE (Zpos >= 0)
;
;	Insert this record into the Drawlist
;
	or	lomask,thisrec		; New guy wins ties
	moveq	#0,last			; LAST = Index to Root
	load	(gpuptr),now		; NOW = Last.Next
.40:	and	lomask,now		; WHILE ((Now <> Nil) ..
	move	now,ptr
	jr	EQ,.49
	add	gpuptr,ptr
	load	(ptr),temp
	cmp	thisrec,temp		; .. AND (Now.Z > This.Z)) DO
	jr	MI,.49
	nop
	move	now,last		; LAST = Now
	jr	T,.40
	move	temp,now		; NOW = Now.Next
.49:					; Drawlist Insertion Point found
	and	himask,thisrec
	add	gpuptr,last
	or	now,thisrec		; This.Next = Now
	load	(last),temp
	store	thisrec,(thisptr)	; Save 'This' record
	and	himask,temp
	or	this,temp		; Last.Next = This
	jump	T,(rsort)
	store	temp,(last)		; Save 'Last' record


;
;	CONSTANT DATA
;

;
;	VARIABLE STORAGE
;
	.phrase

matrix:					; HEAD portion of Viewpt
	.dcb.l	3,0

gpuram:					; Array of Turtle Zpos|Link Records
					; .. All the rest of memory
	.phrase				; this is VERY IMPORTANT TO HAVE HERE IF YOU USE THE
					; LINKER to include a *.BIN file via -iFILENAME LABELNAME 

EndGPU:
	.end

;*======================================================================*
;*                                 EOF                                  *
;*======================================================================*
