	SECTION	Main,CODE
*03/05-89*********************************************************
*	ManyLinesProgram					 *
******************************************************************

******** Macros and nececarry definitions ************************

_custom		equ	$dff000

******** Screen info *********************************************

PicYOff		equ	10		; offset for picture
PicHeight	equ	260		; height of picture
PicWidth	equ	20		; width of picture
PicDepth	equ	1		; depth of picture

******** Line info ************************************************

LineSplit	equ	8		; # of words in line
LineLen		equ	LineSplit*16	; linelength
LineNum		equ	70		; # of lines drawn.

TriNum		equ	$400		; # of entries in tri. tables

******** Copperlist macros

** Move word commando

Mov	Macro				; Syntax: Mov Constant,Destination
	dc.w	(\2)&%111111110
	dc.w	(\1)
	EndM

** Move longword commando

MovL	Macro				; Syntax: Mov Constant,Destination
	dc.w	(\2)&%111111110		; Hi-word
	dc.w	(\1)>>16		; Shift 16 right left
	dc.w	(\2)&%111111110+2	; Lo-word
	dc.w	(\1)&$ffff
	EndM

WaitB	Macro
	dc.w	1			; wait for the blitter only
	dc.w	%0
	dc.w	1			; two waits because the blitter
	dc.w	%0			; is slower than the coppercomandos
	EndM

** Wait	commando

Wait	Macro
	dc.w	(((\1)&$ff)*%10)!(((\2)&$ff)*%100000000)!%1
	dc.w	%1111111111111110
	EndM

EndCop	Macro				; End of copperlist
	Wait	255,255
	EndM

***********************
******** Includes
***********************

	incdir	"include:"
	include	"graphics/graphics_lib.i"
	include	"graphics/gfxbase.i"
	include	"hardware/custom.i"
	include	"hardware/blit.i"
	include	"hardware/intbits.i"
	include	"hardware/dmabits.i"
	include	"math/mathffp_lib.i"
	include	"math/mathtrans_lib.i"
	include	"exec/exec_lib.i"

******************************************************************
******** Setup and main loop *************************************
******************************************************************

Main
	move.l	#GfxName,a1
	clr.l	d0
	move.l	_SysBase,a6
	jsr	_LVOOpenLibrary(a6)		; need this library to
;						; restore * to cop1lc
	move.l	d0,_GfxBase
	cmp.l	#0,d0				; NOTE! Z flag is NOT
;						; set above
	beq	Abort				; No such library found

	move.l	#MathName,a1
	clr.l	d0
	move.l	_SysBase,a6
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,_MathBase
	cmp.l	#0,d0				; NOTE! Z flag is NOT
;						; set above
	beq	Abort				; No such library found

	move.l	#MathTransName,a1
	clr.l	d0
	move.l	_SysBase,a6
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,_MathTransBase
	cmp.l	#0,d0				; NOTE! Z flag is NOT
;						; set above
	beq	Abort				; No such library found

** Clear chip memory

	move.l	#StopChip-StartChip,d0
	move.l	#StartChip,a0
.NB	clr.b	(a0)+
	subq.l	#1,d0
	bne	.NB

** Clear public memory

	move.l	#StopPublic-StartPublic,d0
	move.l	#StartPublic,a0
.NB1	clr.b	(a0)+
	subq.l	#1,d0
	bne	.NB1

** Setup math tables

	move.l	#0,d0
	move.l	_MathBase,a6
	jsr	_LVOSPFlt(a6)		; start angle
	move.l	d0,Angle

	move.l	#$7fff,d0
	move.l	_MathBase,a6
	jsr	_LVOSPFlt(a6)		; factor to use in table
	move.l	d0,Factor

	move.l	#31415927*2,d0		; 2pi*10^7
	jsr	_LVOSPFlt(a6)
	move.l	d0,-(sp)

	move.l	#10000000,d0		; 10^7
	jsr	_LVOSPFlt(a6)
	move.l	d0,d1
	move.l	(sp)+,d0
	jsr	_LVOSPDiv(a6)
	move.l	d0,-(sp)		; 2*pi

	move.l	#TriNum,d0
	jsr	_LVOSPFlt(a6)		; # of entries in table

	move.l	d0,d1
	move.l	(sp)+,d0
	jsr	_LVOSPDiv(a6)		; 2*pi/TriNum
	move.l	d0,Step

	move	#TriNum-1,d7
	lea	SinTable,a4
	lea	CosTable,a5

.MT01	move.l	Angle,d0
	move.l	_MathTransBase,a6
	jsr	_LVOSPCos(a6)

	move.l	d0,d2
	move.l	Factor,d1
	move.l	_MathBase,a6
	jsr	_LVOSPMul(a6)

	jsr	_LVOSPFix(a6)
	move	d0,(a4)+		; costable

	move.l	Angle,d0
	move.l	_MathTransBase,a6
	jsr	_LVOSPSin(a6)

	move.l	d0,d2
	move.l	Factor,d1
	move.l	_MathBase,a6
	jsr	_LVOSPMul(a6)

	jsr	_LVOSPFix(a6)
	move	d0,(a5)+		; sinetable

	move.l	Step,d0
	move.l	Angle,d1
	jsr	_LVOSPAdd(a6)
	move.l	d0,Angle

	dbra	d7,.MT01

** Setup Lines

	jsr	SetupCopperLine	; setup Linecopperlist
	jsr	LinePos
	jsr	LinePos
	jsr	LinePos	
	jsr	LinePos		; X4 to fill all the copperLine
				; double buffering *rs

** Main loop

	jsr	StartCopper
	jsr	StartInt

	jsr	MoveLines

	jsr	StopInt
	jsr	StopCopper


** unload non resident libraries

	move.l	_MathTransBase,a1
	move.l	_SysBase,a6
	jsr	_LVOCloseLibrary(a6)
	
** Abort routine

Abort	
	clr.l	d0
	rts


Angle	ds.l	1		; current angle
Step	ds.l	1		; step speed(dependent on TriNum)
Factor	ds.l	1		; factor to keep resolution of
;				; cos and sine

_MathBase	ds.l	1		; * to ffp base
_MathTransBase	ds.l	1		; * to ffp base
_GfxBase	ds.l	1		; * to gfx. base
MathTransName	MATHTRANSNAME
MathName	FFPNAME
GfxName		GRAFNAME
		even

*******************************************************
******** Setup the Linecopperlist **********************
*******************************************************


SetupCopperLine

** Copy copperlining commands

	move	#LineNum-1,d0		; # of line items.
	move.l	#SLine,a1
	move.l	#CoppLines,a3
	move.l	#LineSize-1,d2

.CL02	move	d2,d1
	move.l	a1,a0
.CL01	move.b	(a0)+,(a3)+		; make coppies of line draw
	dbra	d1,.CL01

	dbra	d0,.CL02

** Copy Copperlist

	move.l	#CopperList,a0
	move.l	#SecCopperList,a1
	move.l	#EndCopperList-CopperList-1,d0

.Loop5	move.b	(a0)+,(a1)+
	dbra	d0,.Loop5

** End of session

	rts

** One line "record"

SLine
L_cpt	MovL	0,bltcpt
L_dpt	MovL	0,bltdpt
L_apt	Mov	0,bltapt+2
L_amod	Mov	0,bltamod
L_bmod	Mov	0,bltbmod
	Mov	PicWidth*2,bltcmod
	Mov	PicWidth*2,bltdmod
L_con0	Mov	0,bltcon0
L_con1	Mov	0,bltcon1
	Mov	$8000,bltafwm
 	Mov	$8000,bltadat
L_TRep
	REPT	LineSplit
	Mov	0,bltbdat		; texture
	Mov	($10<<6)!2,bltsize	; size of this blit.
	WaitB				; just wait for the blitter.
	ENDR
L_ETRep
ELine

LineSize equ	ELine-SLine	; size of a blitterline
l_RSize	equ	(L_ETRep-L_TRep)/LineSplit ; size of a rep. line
l_TRep	equ	L_TRep-SLine

l_cpt	equ	L_cpt-SLine
l_dpt	equ	L_dpt-SLine
l_apt	equ	L_apt-SLine
l_amod	equ	L_amod-SLine
l_bmod	equ	L_bmod-SLine
l_con0	equ	L_con0-SLine
l_con1	equ	L_con1-SLine

lr_bsize equ	4	; actual offset l_TRep+N*l_RSize+lr_bsize
lr_bdat	equ	0	; ---""----

******************************************************************
************** Copper lists for Play *****************************
******************************************************************

	SECTION	CopperList,DATA_C
CopperList

** Clean old screen

	WaitB				; wait for the blitter.
CoppClear
	MovL	0,bltdpt
	Mov	DEST,bltcon0
	Mov	0,bltcon1
	Mov	0,bltdmod
	Mov	((PicHeight*PicDepth)<<6)!PicWidth,bltsize

** Pic window **

	Mov	0,spr+sd_dataa		; to avoid sprite flicker
	Mov	0,spr+sd_datab
	Mov	0,spr+sd_ctl
	Mov	0,spr+sd_pos

	Mov	$000,bplcon0  

** Set colors

	Mov	$000,color
	Mov	$f00,color+2

** Set window data fetch Pict and stop

	Mov	$38,ddfstrt			; 20words)
	Mov	$d0,ddfstop			; Maximum 

** Set Window size

	Mov	$2c50,diwstrt
	Mov	$30d0,diwstop

** Set modulo

	Mov	PicWidth*(PicDepth-1)*2,bpl1mod
	Mov	PicWidth*(PicDepth-1)*2,bpl2mod

	Mov	0,bplcon0
CoppPicP
	MovL	0,bplpt
	Wait	0,PicYOff
	Mov	%0001000000000000,bplcon0	; 4 bitplanes hires
	Mov	%0000000000000000,bplcon1	; Scroll codes (defined in program)
	Mov	%0000000000000000,bplcon2	; Priority set to default


*****************
** Line storing**
*****************

** Line copp. blit.

	WaitB
CoppLines
	ds.b	LineSize*LineNum
	Mov	INTF_SETCLR!INTF_COPER,intreq	; re update blitter info
	EndCop

** End of session

	EndCop
EndCopperList

SecCopperList	ds.b	EndCopperList-CopperList ; double buffering
;						; on coppperlist

******************************************************************
****** Start Copper **********************************************
******************************************************************

	Section	Copper,CODE

StartCopper
	move.l	#_custom,a5
	move	#$ffff,copcon(a5)		; enable blitter
;						; from copperlist
	move.l	#CopperList,cop1lc(a5)
	move	#DMAF_SPRITE,dmacon(a5)		; turn off sprites
	clr.l	d0
	rts

******************************************************************
******** End Copper **********************************************
******************************************************************

StopCopper	
	move.l	#_custom,a5
	move	#$0000,copcon(a5)		; no blitter from copperlist
	move	#DMAF_SETCLR!DMAF_SPRITE,dmacon(a5)
	move.l	_GfxBase,a0
	move.l	gb_copinit(a0),cop1lc(a5)	; reset copperlist
	rts


*********************** Constants ********************************

INTP		equ	$60
IntNum		equ	9

** Setup and Start Interrupt

*NOTE: this routine must be called before any action is taken of the Lines concerned

StartInt
	move.l	#_custom,a5
	move.w	intenar(a5),IntOnSave	; Save current ON/OFF state
	move.w	#$7fff,intena(a5)	; Turns off all interrupts

SeI03	btst	#DMAB_BLTDONE,dmaconr(a5)	; wait until Blitter is finished
	bne	SeI03

	move.l	#INTP,a0
	move.l	#SaveIntP,a1
	move.l	#IntLevelP,a2
	move.l	#IntNum-1,d0

SeI01	move.l	(a0),(a1)+
	move.l	(a2)+,d1
	bne	SeI02
	move.l	(a0),d1			; keep old int
SeI02	move.l	d1,(a0)+
	dbra	d0,SeI01

 move	#INTF_INTEN!INTF_SETCLR!INTF_COPER!INTF_VERTB!INTF_PORTS,intena(a5)

** End of session

	rts

** Pointer to all the levels

IntLevelP
	dc.l	Interrupt				; spurious
	dc.l	Interrupt				; 1 serial b.e,soft,dskblk
	dc.l	Interrupt				; 2 IO timers
	dc.l	IntVertBlit				; 3 copp. blit. vert.
	dc.l	Interrupt				; 4 audio
	dc.l	Interrupt				; 5 ser rec b. full,dsk
	dc.l	Interrupt				; 6 extern
	dc.l	Interrupt
	dc.l	Interrupt

** Close down interrupt and stop interrupt

StopInt
	move.l	#_custom,a5
	move.w	#INTF_INTEN!INTF_COPER!INTF_VERTB,intena(a5)

	move.l	#INTP,a0
	move.l	#SaveIntP,a1
	move.l	#IntNum-1,d0

RSeI01	move.l	(a1)+,(a0)+
	dbra	d0,RSeI01

	move	#DMAF_SETCLR!DMAF_BLITTER,dmacon(a5)
	move.w	IntOnSave,d0
	or.w	#INTF_SETCLR!INTF_INTEN,d0
	move.w	d0,intena(a5)		; reload old On/Off state
	rts			

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
** Interrupt Blitter, and vertb 
;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

IntVertBlit
	movem.l	a0-a6/d0-d7,-(sp)			; Save all register on stack

	move.l	#_custom,a5

	move.w	intreqr(a5),d0				; Read which interrupt that occured
	and.w	#$3fff,d0
	move.w	d0,intreq(a5)
	and.w	intenar(a5),d0

	btst	#INTB_COPER,d0
	beq	No02				; no copper interrupt
	move	d0,-(sp)
	bsr	CopperVTB	
	move	(sp)+,d0
No02

	btst	#INTB_VERTB,d0
	beq	No01				; no copper interrupt
	addq	#1,CountVTB	; start calcuclating pos.
No01

** End of Interrupt Main

EndOfVer
	movem.l	(sp)+,a0-a6/d0-d7			; Reload all register from stack
	rte

** Interrupt Main Routine

Interrupt
	movem.l	a0-a6/d0-d7,-(sp)			; Save all register on stack

	move.l	#_custom,a5

	move.w	intreqr(a5),d0				; Read which interrupt that occured
	and.w	#$3fff,d0
	and.w	intenar(a5),d0
	move.w	d0,intreq(a5)

	btst	#INTB_PORTS,d0
	beq	No2					; Key in interrupt					
	move	d0,-(sp)
	bsr	KeyUp					; Key in interrupt					
	move	(sp)+,d0
No2

** End of Interrupt Main

EndOfInt
	movem.l	(sp)+,a0-a6/d0-d7			; Reload all register from stack
	rte

** This routine catches up the keys, if you don't do it, the program
** will crash when you press a key.

KeyUp	
	clr.l	d0
	move.b	$bfed01,d0
	move.b	$bfec01,d0
	eor.b	#$ff,d0
	move	d0,KeyDown
	move.b	#$40,$bfee01
	move.b	#$00,$bfee01
	rts

*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
************ Copper VTB ******************************************
*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

CopperVTB
	jsr	LinePos		; update Line pos
	rts

** Variables

IntOnSave	ds.w	1			; Old interrupt ON/OFF state
SaveIntP	ds.l	IntNum			; Pointer to Old interrupt routine
CountVTB	ds	1			; Counter that are increased by one each Vertical Blank(must be decreased be the main program).
KeyDown		ds	1			; current key code


******************************************************************
******** Move lines **********************************************
******************************************************************

CentreX	equ	120
CentreY	equ	(PicHeight/2)-(LineNum/2)
RotateSpeed equ	5	; speed of movement

MoveLines
.ML01	move	CountVTB,d0
.ML02	cmp	CountVTB,d0
	beq	.ML02

	lea	CosTable,a2
	lea	SinTable,a3

	move.l	#LineXY,a0
	move	#LineNum-1,d0

	add	#RotateSpeed,Angle
	and	#$3ff,Angle
	move	Angle,d0
	asl	d0
	move	(a2,d0),d1
	move	(a3,d0),d2
	muls	#LineLen,d1
	muls	#LineLen,d2
	swap	d1
	swap	d2
	add	#CentreX,d1
	add	#CentreY,d2

	add	#$400,d0
	and	#$7ff,d0
	move	(a2,d0),d3
	move	(a3,d0),d4
	muls	#LineLen,d3
	muls	#LineLen,d4
	swap	d3
	swap	d4
	add	#CentreX,d3
	add	#CentreY,d4

	move	d1,.XY
	move	d2,.XY+4
	move	d3,.XY+8
	move	d4,.XY+12

	move.l	#LineXY,a0
	move	#LineNum-1,d7
.ML03
	move	.XY,d0
	move	.XY+4,d1
	move	.XY+8,d2
	move	.XY+12,d3
	move	d0,(a0)+
	move	d1,(a0)+
	move	d2,(a0)+
	move	d3,(a0)+

	addq	#1,.XY
	addq	#1,.XY+8
	addq	#1,.XY+4
	addq	#1,.XY+12

	dbra	d7,.ML03

	btst	#6,$bfe001
	bne	.ML01
	rts

.Angle	ds	1			; angle of movement.
.XY	ds.l	4			; current pos line
.DXY	ds.l	2			; delta XY for normal vector
;					; on default line.

******************************************************************
***************** Store Line pos **********************************
******************************************************************

LinePos
	eor	#$8000,FlipFlop		; double buffering change
;					; screens.

** Decide which of the double buffers to use.

	move.l	#CopperList,NextCopperList
	move.l	#SecCopperList,CurCopperList
	move.l	#RasterPic2,Screen
	move.l	#RasterPic,Screen2
	tst	FlipFlop
	bmi	BP04
	move.l	#RasterPic2,Screen2
	move.l	#RasterPic,Screen
	move.l	#CopperList,CurCopperList
	move.l	#SecCopperList,NextCopperList
BP04

** Update copperlists

	move.l	Screen,d0		; to be showed screen
	move	#PicDepth-1,d1
	move.l	#CoppPicP-CopperList,a0
	add.l	NextCopperList,a0
BP03	move	d0,6(a0)
	swap	d0
	move	d0,2(a0)
	swap	d0
	addq.l	#8,a0
	add.l	#PicWidth*2,d0
	dbra	d1,BP03

** Set clear screen

	move.l	#CoppClear-CopperList,a0
	add.l	NextCopperList,a0
	move.l	Screen2,d0
	move	d0,6(a0)
	swap	d0
	move	d0,2(a0)

** Store XY loop

	move	#LineNum-1,d0
	move.l	#CoppLines-CopperList,a0
	add.l	NextCopperList,a0
	move.l	#LineXY,a1		; XY pos of Lines		
	lea	Logon,a2

BP01
	move	d0,-(sp)		; hide counter on stack

	move	(a1)+,d0		; X1
	move	(a1)+,d1		; Y1
	move	(a1)+,d2		; X2
	move	(a1)+,d3		; Y2

; DrawLine setup
; d0 = x1
; d1 = y1
; d2 = x2
; d3 = y2

	move	#PicWidth*2,d4
	mulu	d1,d4
	move	d0,d5
	lsr	#4,d5
	asl	#1,d5
	add	d5,d4
	add.l	Screen2,d4		; startaddress of line

; find octant

	clr	d5
	sub	d1,d3			; DY
	roxl.b	d5			; X=1 if DY<0
	tst	d3
	bpl	.OC01
	neg	d3
.OC01
	sub	d0,d2
	roxl.b	d5			; X=1 if DX<0
	tst	d2
	bpl	.OC02
	neg	d2
.OC02
	move	d3,d1
	sub	d2,d1			; DX-DY
	bpl	.OC03
	exg	d2,d3			; swap DX and DY
.OC03	roxl.b	d5			; X=1 if (DY-DX)<0

	lea	Octant,a3
	move.b	(a3,d5),d5

	asl	d2
	move	d2,l_bmod+2(a0)	; bltbmod	2DY
	sub	d3,d2
	bpl	.SIGNALFLAG
	or.b	#SIGNFLAG,d5	; 2DY-DX<0
.SIGNALFLAG
	move	d2,l_apt+2(a0)	; bltapt+2(a5)	2DY-DX
	sub	d3,d2
	move	d2,l_amod+2(a0)	; bltamod(a5)	2DY-2DY

	and	#$000f,d0
	ror	#4,d0		; start of line(0..15)
	or	#DEST!SRCC!SRCA,d0 ; ACD dma lines on
	or	#$ca,d0		; minterm. AB+notAC
	move	d0,l_con0+2(a0)
	or	#$f<<12,d5	; start of texture
	move	d5,l_con1+2(a0)
	move.l	d4,-(sp)	; bltcpt(a5)&bltdpt(a5)

; BLTSIZE initialiseren en blitter starten

	lea	l_TRep(a0),a3	; start of this rep.
	move	#LineSplit-1,d0

.UCL01	move	(a2)+,lr_bdat+2(a3)	; texture
	add.l	#l_RSize,a3
	dbra	d0,.UCL01

	move.l	(sp)+,d0
	move	d0,l_cpt+2+4(a0)
	move	d0,l_dpt+2+4(a0)
	swap	d0
	move	d0,l_cpt+2(a0)
	move	d0,l_dpt+2(a0)

	movem	(sp)+,d0

	add.l	#LineSize,a0
	dbra	d0,BP01			; store next line

;					; next copperlist
	move.l	CurCopperList,cop1lc+_custom

** End of session

	rts

Octant	dc.b	OCTANT2!LINEMODE
	dc.b	OCTANT1!LINEMODE
	dc.b	OCTANT3!LINEMODE
	dc.b	OCTANT4!LINEMODE
	dc.b	OCTANT7!LINEMODE
	dc.b	OCTANT8!LINEMODE
	dc.b	OCTANT6!LINEMODE
	dc.b	OCTANT5!LINEMODE
	even

FlipFlop	ds	1	; flipflop double buffering flag
Screen		ds.l	1	; which screen that is on
Screen2		ds.l	1	; Screen to clear
CurCopperList	ds.l	1	; * to current copperlist
NextCopperList	ds.l	1	; the copper list to be used next

******** Allocations *********************************************

	Section	PublicMemory,BSS
StartPublic
LineXY	ds	LineNum*4		; Pos of lines
CosTable ds	TriNum			; cosinus table
SinTable ds	TriNum			; sinus table
StopPublic


	SECTION	ChipMemory,BSS_C
StartChip
RasterPic	ds	PicWidth*PicDepth*PicHeight	
RasterPic2	ds	PicWidth*PicDepth*PicHeight	
StopChip

	Section	LogonHeader,DATA_C

Logon	incbin	logon.lo1

	END

