***********************************************************
* й 1992 Epsilon
*
* This is just some crummy filled convex vectors.  This source is very
* slow, but it works.
*
* I'd like to thank Tip, of SpreadPoint, for writing and spreading what
* is quite possibly the fastest line drawing routine for the Amiga.  I
* modified it just a little bit so that it would work in multiple colors.
* The original version should also be found in this archive, if it isn't
* then contact me.
*
* I can be reached at:
*			Epsilon
*			P.O.B. 1914
*			Beaverton, OR  97075-1914
*			U.S.A.
* Or, you can e-mail me at:
*			idr@rigel.cs.pdx.edu
* Enjoy!
***********************************************************
* Macros
***********************************************************

WaitBlit	MACRO
		tst.b	(a6)
.\@		btst	#6,(a6)
		bne.s	.\@
		ENDM
		
WaitVert	MACRO
.\@		move.l	4(a5),d0
		andi.l	#$1ff00,d0
		cmpi.l	#$c400,d0
		bne.b	.\@
		ENDM

ClearBmap	MACRO
		move.l	ActiveBmap,a0
		adda.l	#6,a0
		WaitBlit
		move.l	a0,$54(a5)
		move.w	#12,$66(a5)
		move.l	#$01000000,$40(a5)
		move.w	#(600*64)+14,$58(a5)
		ENDM

*******************************************************************************

		bsr.w	TakeOverSystem
		move.w	#$0400,$96(a5)

		bra.b	DoCube
Wm:
		bsr.w	RestoreSystem
		rts

*******************************************************************************

DoCube:		move.l	#Cube,CurrentObject

		move.w	#600,Scale	
		move.w	#1,XInc
		move.w	#2,YInc
		move.w	#3,ZInc

sc:		WaitVert
		bsr.w	FlipBmaps
		ClearBmap
		bsr.w	Rotate
		btst.b	#6,$bfe001
		bne.b	sc
		bra	Wm
				
*******************************************************************************

Rotate:		lea	SineData,a2
		lea	CosineData,a3
		moveq	#0,d5
		move.w	XAngle,d5
		add.l	d5,d5			; d5 * 2 (byte offset)
		move.w	(a2,d5),SinX		; d3 = sin(xa)
		move.w	(a3,d5),CosX		; d4 = cos(xa)

		move.w	YAngle,d5
		add.l	d5,d5			; d5 * 2 (byte offset)
		move.w	(a2,d5),SinY		; d3 = sin(ya)
		move.w	(a3,d5),CosY		; d4 = cos(ya)

		move.w	ZAngle,d5
		add.l	d5,d5			; d5 * 2 (byte offset)
		move.w	(a2,d5),SinZ		; d3 = sin(za)
		move.w	(a3,d5),CosZ		; d4 = cos(za)
	
		move.l	CurrentObject,a0
		lea	OutputCoords,a1

		move.w	(a0)+,d7		; d7 = num of coords
		subq.w	#1,d7
		
CalcLoop:	movem.w	(a0)+,d0-d2		; x,y,z coord
		
		; X rotation
		movem.l	d1/d2,-(sp)		; save x,y,z
		muls	CosX,d1			; d1 = y * cos(xa)
		muls	SinX,d2			; d2 = z * sin(xa)
		add.l	d2,d1			; d1 = (y*cos(xa))+(z*sin(xa))
		move.l	d1,d5			; d5 = temporary y
		movem.l	(sp)+,d1/d2
		muls	CosX,d2			; d2 = z * cos(xa)
		muls	SinX,d1			; d1 = y * sin(xa)
		sub.l	d1,d2			; d2 = (z*cos(xa))-(y*sin(xa))
		move.l	d5,d1

		lsr.l	#8,d1
		lsr.l	#8,d2

		; Y rotation
		movem.l	d0/d2,-(sp)		; save x,y,z
		muls	CosY,d0			; d0 = x * cos(ya)
		muls	SinY,d2			; d2 = z * sin(ya)
		sub.l	d2,d0			; d0 = (x*cos(ya))-(z*sin(ya))
		move.l	d0,d5			; d5 = temporary x
		movem.l	(sp)+,d0/d2
		muls	CosY,d2			; d2 = z * cos(ya)
		muls	SinY,d0			; d0 = x * sin(ya)
		add.l	d0,d2			; d2 = (z*cos(ya))+(y*sin(ya))
		move.l	d5,d0

		lsr.l	#8,d0
		lsr.l	#8,d2	

		; Z rotation
		movem.l	d0/d1,-(sp)		; save x,y,z
		muls	CosZ,d0			; d0 = x * cos(za)
		muls	SinZ,d1			; d1 = y * sin(za)
		sub.l	d1,d0			; d0 = (x*cos(za))-(y*sin(za))
		move.l	d0,d5			; d5 = temporary x
		movem.l	(sp)+,d0/d1
		muls	SinZ,d0			; d0 = x * sin(za)
		muls	CosZ,d1			; d1 = y * cos(za)
		add.l	d0,d1			; d1 = (y*cos(za))+(x*sin(za))
		move.l	d5,d0

		add.w	Scale,d2		
		divs	d2,d0
		divs	d2,d1

		add.w	#160,d0
		add.w	#100,d1

		move.w	d0,(a1)+		; store output coordinates
		move.w	d1,(a1)+
		dbra	d7,CalcLoop

		move.w	XInc,d0
		add.w	d0,XAngle
		cmpi.w	#360,XAngle
		blt.b	NoXAngleReset
		clr.w	XAngle
NoXAngleReset:	
		move.w	YInc,d0
		add.w	d0,YAngle
		cmpi.w	#360,YAngle
		blt.b	NoYAngleReset
		clr.w	YAngle
NoYAngleReset:	
		move.w	ZInc,d0
		add.w	d0,ZAngle
		cmpi.w	#360,ZAngle
		blt.b	NoZAngleReset
		clr.w	ZAngle
NoZAngleReset:

***********************************************************

DrawPoly:
		moveq	#0,d0
		moveq	#0,d1
		moveq	#0,d2
 		moveq	#0,d3
		moveq	#0,d5	

		lea	OutputCoords,a1
		move.w	(a0)+,d7	; d7 = number of surfaces
		move.w	d7,num_faces
		
		bsr.w	DL_Init

SurfaceLoop:	move.w	(a0)+,d6	; d6 = number of points this surface
		move.w	(a0)+,color

		bsr.w	CheckFace	; check the visibility of the surface
		cmp.l	d0,d1		; can we see it?
		bge.b	face_ok		; yes.

		add.w	d6,d6
		add.w	d6,a0		
		bra.w	dont_do_it

face_ok:	subq.w	#2,d6
		
PointLoop:	move.w	(a0)+,d5	; d5 = point number
		subq.w	#1,d5
		lsl.w	#2,d5

		move.w	d5,-(sp)	; save for later...
		move.w	(a1,d5.w),d0
		move.w	2(a1,d5.w),d1	; d0,d1 are first coord
GetPoint:		
		move.w	(a0)+,d5
		subq.w	#1,d5
		lsl.w	#2,d5
		move.w	(a1,d5.w),d2
		move.w	2(a1,d5.w),d3	; d2,d3 are second coord
		bsr.w	DrawLine	; draw the line

		cmpi.w	#3,color
		bne.b	no_color_3
		move.w	#2,color
		bsr.w	DrawLine
		move.w	#3,color
no_color_3:	move.w	d2,d0
		move.w	d3,d1
		dbra	d6,GetPoint

		move.w	(sp)+,d5	; the first point
		move.w	(a1,d5.w),d2
		move.w	2(a1,d5.w),d3	; d2,d3 are second coord
do_line2:	bsr.w	DrawLine	; draw the line
		cmpi.w	#3,color
		bne.b	dont_do_it
		move.w	#2,color
		bra.b	do_line2

dont_do_it:	dbra	d7,SurfaceLoop

***********************************************************

FillSurface:	move.l	ActiveBmap,a2
		adda.l	#(24000-2-6),a2
		move.l	#$000c000c,d1
		move.w	#(600*64)+14,d4

		WaitBlit
		
		move.l	#$09f00012,$40(a5)
		move.l	d1,$64(a5)
		move.l	a2,$50(a5)
		move.l	a2,$54(a5)
		move.w	d4,$58(a5)
		rts
		
*******************************************************************************
x1		EQUR	d0
y1		EQUR	d1
x2		EQUR	d2
y2		EQUR	d3
x3		EQUR	d4
y3		EQUR	d5
dx1		EQUR	d1
dy1		EQUR	d7
dx2		EQUR	d0
dy2		EQUR	d6

CheckFace:	movem.l	d6-d7/a0,-(sp)
		move.w	(a0)+,d5	; d5 = point number
		subq.w	#1,d5
		lsl.w	#2,d5
		move.w	(a1,d5.w),x1
		move.w	2(a1,d5.w),y1	; d0,d1 are first coord

		move.w	(a0)+,d5
		subq.w	#1,d5
		lsl.w	#2,d5
		move.w	(a1,d5.w),x2
		move.w	2(a1,d5.w),y2	; d2,d3 are second coord

		move.w	(a0)+,d5
		subq.w	#1,d5
		lsl.w	#2,d5
		move.w	(a1,d5.w),x3
		move.w	2(a1,d5.w),y3	; d4,d5 are third coord

		move.w	y1,dy1
		sub.w	y2,dy1		; find delta y for first line
		move.w	y2,dy2
		sub.w	y3,dy2		; find delta y for second line
		move.w	x1,dx1
		sub.w	x2,dx1		; find delta x for first line
		move.w	x2,dx2
		sub.w	x3,dx2		; find delta x for second line

		muls	dy1,dx2		; here I just "cross multiply"
		muls	dy2,dx1		;   the two slopes
		movem.l	(sp)+,d6-d7/a0
		rts

*******************************************************************************
*			'DrawLine V1.01' By TIP/SPREADPOINT		      *
*******************************************************************************

DL_Width	=	40
DL_Fill		=	1		; 0=NOFILL / 1=FILL
	IFEQ	DL_Fill
DL_MInterns	=	$CA
	ELSE
DL_MInterns	=	$4A
	ENDC

;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
;	A0 = PlanePtr, A6 = $DFF002, D0/D1 = X0/Y0, D2/D3 = X1/Y1
;	D4 = PlaneWidth > Kills: D0-D4/A0-A1 (+D5 in Fill Mode)

DrawLine:	movem.l	d0-d5/a0-a1,-(sp)
		move.l	ActiveBmap,a0
		cmpi.w	#2,color	; if it's color 2 we don't draw in
		bne.b	no_plane_2
		adda.l	#8000,a0	;   bpl one or three.
no_plane_2:		
		cmpi.w	#4,color	; if it's color 4 we don't draw in
		bne.b	no_plane_3
		adda.l	#16000,a0	;   bpl one or two.
no_plane_3:
		cmp.w	d1,d3		; Drawing only from Top to Bottom is
		bge.s	.y1ly2		; necessary for:
		exg	d0,d2		; 1) Up-down Differences (same coords)
		exg	d1,d3		; 2) Blitter Invert Bit (only at top of
					;    line)
.y1ly2:		sub.w	d1,d3		; D3 = yd

; Here we could do an Optimization with Special Shifts
; depending on the DL_Width value... I know it, but please, let it be.

		mulu	#40,d1		; Use muls for neg Y-Vals

		add.l	d1,a0		; Please don't use add.w here !!!
		moveq	#0,d1		; D1 = Quant-Counter
		sub.w	d0,d2		; D2 = xd
		bge.s	.xdpos
		addq.w	#2,d1		; Set Bit 1 of Quant-Counter (here it
					; could be a moveq)
		neg.w	d2
.xdpos:		moveq	#$f,d4		; D4 full cleaned (for later oktants
					; move.b)
		and.w	d0,d4
	IFNE	DL_Fill
		move.b	d4,d5		; D5 = Special Fill Bit
		not.b	d5
	ENDC
		lsr.w	#3,d0		; Yeah, on byte (necessary for bchg)...
		add.w	d0,a0		; ...Blitter ands automagically
		ror.w	#4,d4		; D4 = Shift
		or.w	#$B00+DL_MInterns,d4	; BLTCON0-codes
		swap	d4
		cmp.w	d2,d3		; Which Delta is the Biggest ?
		bge.s	.dygdx
		addq.w	#1,d1		; Set Bit 0 of Quant-Counter
		exg	d2,d3		; Exchange xd with yd
.dygdx:		add.w	d2,d2		; D2 = xd*2
		move.w	d2,d0		; D0 = Save for $52(a6)
		sub.w	d3,d0		; D0 = xd*2-yd
		addx.w	d1,d1		; Bit0 = Sign-Bit
		move.b	Oktants(PC,d1.w),d4	; In Low Byte of d4
						; (upper byte cleaned above)
		swap	d2
		move.w	d0,d2
		sub.w	d3,d2		; D2 = 2*(xd-yd)
		moveq	#6,d1		; D1 = ShiftVal (not necessary) 
					; + TestVal for the Blitter
		lsl.w	d1,d3		; D3 = BLTSIZE
		add.w	#$42,d3
		lea	$52-2(a6),a1	; A1 = CUSTOM+$52
rept:
		WaitBlit
	IFNE	DL_Fill
		bchg	d5,(a0)		; Inverting the First Bit of Line
	ENDC
		move.l	d4,$40-2(a6)	; Writing to the Blitter Regs as fast
		move.l	d2,$62-2(a6)	; as possible
		move.l	a0,$48-2(a6)
		move.w	d0,(a1)+
		move.l	a0,(a1)+	; Shit-Word Buffer Ptr...
		move.w	d3,(a1)
		movem.l	(sp)+,d0-d5/a0-a1
		rts
;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
	IFNE	DL_Fill
SML		= 	2
	ELSE
SML		=	0
	ENDC

Oktants:	dc.b	SML+1,SML+1+$40
		dc.b	SML+17,SML+17+$40
		dc.b	SML+9,SML+9+$40
		dc.b	SML+21,SML+21+$40
;нннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннннн
;		Optimized Init Part... A6 = $DFF002 > Kills : D0-D2

DL_Init:	movem.l	d0-d2,-(sp)
		moveq	#-1,d1
	IFGT	DL_Width-127
		move.w	#DL_Width,d0
	ELSE
		moveq	#DL_Width,d0
	ENDC
		moveq	#6,d2
		WaitBlit
		move.w	d1,$44-2(a6)
		move.w	d1,$72-2(a6)
		move.w	#$8000,$74-2(a6)
		move.w	d0,$60-2(a6)
		move.w	d0,$66-2(a6)
		movem.l	(sp)+,d0-d2
		rts

*******************************************************************************

FlipBmaps:	move.l	ActiveBmap,d0
		move.l	VisualBmap,ActiveBmap
		move.l	d0,VisualBmap

InstallBmap:	lea	BmapPtrs+2,a0
		move.l	VisualBmap,d0
		move.w	d0,4(a0)
		swap	d0
		move.w	d0,(a0)
		swap	d0
		add.l	#8000,d0
		move.w	d0,12(a0)
		swap	d0
		move.w	d0,8(a0)
		swap	d0
		add.l	#8000,d0
		move.w	d0,20(a0)
		swap	d0
		move.w	d0,16(a0)
		rts

*******************************************************************************

InstallSprites:	lea	SprPtrs,a0
		move.l	#NullSprite,d0
		move.w	d0,6(a0)
		move.w	d0,14(a0)
		move.w	d0,22(a0)
		move.w	d0,30(a0)
		move.w	d0,38(a0)
		move.w	d0,46(a0)
		move.w	d0,54(a0)
		swap	d0
		move.w	d0,2(a0)
		move.w	d0,10(a0)
		move.w	d0,18(a0)
		move.w	d0,26(a0)
		move.w	d0,34(a0)
		move.w	d0,42(a0)
		move.w	d0,50(a0)
		move.w	d0,58(a0)
		rts
		
*******************************************************************************

TakeOverSystem:	bsr.w	InstallBmap
		bsr.w	InstallSprites

		move.l	#$dff000,a5		; base of custom chip regs
		lea	2(a5),a6

		move.w	2(a5),d0		; read dma bits
		move.w	$1c(a5),d1		; read interrupt bits
		or.w	#$8000,d0		; set the SET bit
		or.w	#$c000,d1		; set the SET bit
		move.w	d0,dmaconrSave		; keep old values for dma
		move.w	d1,intenarSave		; keep old interrupts
		move.w	#$7fff,$9a(a5)		; turn off all interrupts
		move.w	#$7fff,$96(a5)		; turn off all dma

		move.l	#Copper,$80(a5)		; install my copper
		move.w	#$87e0,$96(a5)		; activate certain DMAs
		rts

*******************************************************************************

RestoreSystem:	move.w	#$7fff,$96(a5)		; turn off all DMA
		move.w	#$7fff,$9a(a5)		; turn off all interrupts
		move.w	dmaconrSave,$96(a5)	; activate old DMA
		move.w	intenarSave,$9a(a5)	; activate old interrupts

		movea.l	4.w,a6			; execbase ptr
		lea	GraphicsName,a1		; "graphics.library"
		jsr	-$198(a6)		; open it
		move.l	d0,a1			; move ptr to gfxbase to a1
		move.l	$26(a1),$80(a5)		; install system copper
		jmp	-$19e(a6)		; close graphics library
		
*******************************************************************************

		section	TheData,DATA

GraphicsName:	dc.b	'graphics.library',0,0

SineData:
 dc.l $00000004,$0008000D,$00110016,$001A001F,$00230028,$002C0030,$00350039
 dc.l $003D0042,$0046004A,$004F0053,$0057005B,$005F0064,$0068006C,$00700074
 dc.l $0078007C,$00800083,$0087008B,$008F0092,$0096009A,$009D00A1,$00A400A7
 dc.l $00AB00AE,$00B100B5,$00B800BB,$00BE00C1,$00C400C6,$00C900CC,$00CF00D1
 dc.l $00D400D6,$00D900DB,$00DD00DF,$00E200E4,$00E600E8,$00E900EB,$00ED00EE
 dc.l $00F000F2,$00F300F4,$00F600F7,$00F800F9,$00FA00FB,$00FC00FC,$00FD00FE
 dc.l $00FE00FF,$00FF00FF,$00FF00FF
CosineData:
 dc.l $010000FF,$00FF00FF,$00FF00FF,$00FE00FE,$00FD00FC,$00FC00FB,$00FA00F9
 dc.l $00F800F7,$00F600F4,$00F300F2,$00F000EE,$00ED00EB,$00E900E8,$00E600E4
 dc.l $00E200DF,$00DD00DB,$00D900D6,$00D400D1,$00CF00CC,$00C900C6,$00C400C1
 dc.l $00BE00BB,$00B800B5,$00B100AE,$00AB00A7,$00A400A1,$009D009A,$00960092
 dc.l $008F008B,$00870083,$007F007C,$00780074,$0070006C,$00680064,$005F005B
 dc.l $00570053,$004F004A,$00460042,$003D0039,$00350030,$002C0028,$0023001F
 dc.l $001A0016,$0011000D,$00080004,$FFFFFFFB,$FFF7FFF2,$FFEEFFE9,$FFE5FFE0
 dc.l $FFDCFFD7,$FFD3FFCF,$FFCAFFC6,$FFC2FFBD,$FFB9FFB5,$FFB0FFAC,$FFA8FFA4
 dc.l $FFA0FF9B,$FF97FF93,$FF8FFF8B,$FF87FF83,$FF7FFF7C,$FF78FF74,$FF70FF6D
 dc.l $FF69FF65,$FF62FF5E,$FF5BFF58,$FF54FF51,$FF4EFF4A,$FF47FF44,$FF41FF3E
 dc.l $FF3BFF39,$FF36FF33,$FF30FF2E,$FF2BFF29,$FF26FF24,$FF22FF20,$FF1DFF1B
 dc.l $FF19FF17,$FF16FF14,$FF12FF11,$FF0FFF0D,$FF0CFF0B,$FF09FF08,$FF07FF06
 dc.l $FF05FF04,$FF03FF03,$FF02FF01,$FF01FF00,$FF00FF00,$FF00FF00,$FF00FF00
 dc.l $FF00FF00,$FF00FF00,$FF01FF01,$FF02FF03,$FF03FF04,$FF05FF06,$FF07FF08
 dc.l $FF09FF0B,$FF0CFF0D,$FF0FFF11,$FF12FF14,$FF16FF17,$FF19FF1B,$FF1DFF20
 dc.l $FF22FF24,$FF26FF29,$FF2BFF2E,$FF30FF33,$FF36FF39,$FF3BFF3E,$FF41FF44
 dc.l $FF47FF4A,$FF4EFF51,$FF54FF58,$FF5BFF5E,$FF62FF65,$FF69FF6D,$FF70FF74
 dc.l $FF78FF7C,$FF80FF83,$FF87FF8B,$FF8FFF93,$FF97FF9B,$FFA0FFA4,$FFA8FFAC
 dc.l $FFB0FFB5,$FFB9FFBD,$FFC2FFC6,$FFCAFFCF,$FFD3FFD7,$FFDCFFE0,$FFE5FFE9
 dc.l $FFEEFFF2,$FFF7FFFB,$00000004,$0008000D,$00110016,$001A001F,$00230028
 dc.l $002C0030,$00350039,$003D0042,$0046004A,$004F0053,$0057005B,$005F0064
 dc.l $0068006C,$00700074,$0078007C,$00800083,$0087008B,$008F0092,$0096009A
 dc.l $009D00A1,$00A400A7,$00AB00AE,$00B100B5,$00B800BB,$00BE00C1,$00C400C6
 dc.l $00C900CC,$00CF00D1,$00D400D6,$00D900DB,$00DD00DF,$00E200E4,$00E600E8
 dc.l $00E900EB,$00ED00EE,$00F000F2,$00F300F4,$00F600F7,$00F800F9,$00FA00FB
 dc.l $00FC00FC,$00FD00FE,$00FE00FF,$00FF00FF,$00FF00FF

ActiveBmap:	dc.l	Bmap2
VisualBmap: 	dc.l	Bmap1
CurrentObject:	dc.l	Cube
FaceList:	ds.l	20

Cube:		dc.w	8			; number of unique points
		dc.w	0100,0100,0100
		dc.w	0100,-100,0100
		dc.w	-100,-100,0100
		dc.w	-100,0100,0100
		dc.w	0100,0100,-100
		dc.w	0100,-100,-100
		dc.w	-100,-100,-100
		dc.w	-100,0100,-100
		dc.w	5			; number of surfaces - 1
		dc.w	4,1			; number of pts in surface 1
		dc.w	4,1,2,3			; pt numbers
		dc.w	4,1
		dc.w	5,8,7,6
		dc.w	4,2
		dc.w	5,6,2,1
		dc.w	4,3
		dc.w	4,8,5,1
		dc.w	4,2
		dc.w	4,3,7,8
		dc.w	4,3
		dc.w	2,6,7,3

**********************************************************
		section	TheChipData,DATA_C

Copper:		dc.l	$01003200,$01020000,$01040000,$01080000,$010a0000
		dc.l	$008e2cc1,$0090f4c1,$00920038,$009400d0
ColorTable:	dc.w	$0180,$0044
co1:		dc.w	$0182,$010d
co2:		dc.w	$0184,$0707
co3:		dc.w	$0186,$0d01
co4:		dc.w	$0188,$0c00
BmapPtrs:dc.l	$00e00000,$00e20000,$00e40000,$00e60000,$00e80000,$00ea0000
SprPtrs: dc.l	$01200000,$01220000,$01240000,$01260000,$01280000,$012a0000
	 dc.l	$012c0000,$012e0000,$01300000,$01320000,$01340000,$01360000
	 dc.l	$01380000,$013a0000,$013c0000,$013e0000
		dc.l	-2

*******************************************************************************

		section ChipBSS,BSS_c
NullSprite:	ds.l	3
		ds.l	1000
Bmap1:		ds.b	24000
Bmap2:		ds.b	24000
		ds.l	1000
				
*******************************************************************************

		section	TheBSS,BSS
		ds.l	200
SpitD7:		ds.w	1
SpitA0:		ds.l	1
color:		ds.w	1
num_faces:	ds.w	1
intenarSave:	ds.w	1
dmaconrSave:	ds.w	1
SinX:		ds.w	1
CosX:		ds.w	1
SinY:		ds.w	1
CosY:		ds.w	1
SinZ:		ds.w	1
CosZ:		ds.w	1
XAngle:		ds.w	1
YAngle:		ds.w	1
ZAngle:		ds.w	1
Scale:		ds.w	1
XInc:		ds.w	1
YInc:		ds.w	1
ZInc:		ds.w	1
OutputCoords:	ds.w	1
		ds.w	2*42

