;3D STARFIELD 8
;--------------
;Same as the first starfield demo but runs in 8 colours.  Default is 500
;stars which runs fine on my A1200+Fast - but try 5000 stars or more for a
;real visual experience :-)

	opt	o+,c+

	INCLUDE	"exec/exec_lib.i"
	INCLUDE	"games/games_lib.i"
	INCLUDE	"games/games.i"

CALL	MACRO
	jsr	_LVO\1(a6)
	ENDM

NSTARS	=	500	;Number of stars

XSPEED	=	-4
YSPEED	=	6
ZSPEED	=	2

SCR_HEIGHT =	256
SCR_WIDTH =	320

	SECTION	"Stars",CODE

;==========================================================================;
;                             INITIALISE DEMO
;==========================================================================;

Start:	MOVEM.L	A0-A6/D1-D7,-(SP)
	move.l	($4).w,a6
	lea	GMS_Name(pc),a1
	moveq	#$00,d0
	CALL	OpenLibrary
	move.l	d0,GMS_Base
	beq.s	.Error_GMS

	move.l	GMS_Base(pc),a6
	sub.l	a0,a0
	CALL	SetUserPrefs

	lea	Screen(pc),a0
	CALL	Add_Screen
	tst.l	d0
	bne.s	.Error_Screen

	CALL	Show_Screen

	bsr.s	Main

.ReturnToDOS:
	move.l	GMS_Base(pc),a6
	lea	Screen(pc),a0
	CALL	Delete_Screen
.Error_Screen
	move.l	GMS_Base(pc),a1
	move.l	($4).w,a6
	CALL	CloseLibrary
.Error_GMS
	MOVEM.L	(SP)+,A0-A6/D1-D7
	moveq	#$00,d0
	rts

;==========================================================================;
;
;==========================================================================;

	;Randomize star coordinates

Main:	lea	StarCoords,a0	;a0 = Ptr to star co-ordinates.
	move.w	#NSTARS-1,d7
.loop1	move.w	#8192,d1
	CALL	SlowRandom
	move.w	d0,(a0)+
	CALL	SlowRandom
	move.w	d0,(a0)+
	CALL	SlowRandom
	move.w	d0,(a0)+
	dbra	d7,.loop1

	;Construct perspective table

	lea	PersTable,a0	;a0 = ptr to perspective table.
	moveq	#0,d1	;d1 = Starting at 0.
.loop2	move.l	#$95FFFF,d2	;d2 = $95FFFF
	move.l	d1,d3	;d3 = d1
	add.w	#300,d3	;d3 = ++300
	divu	d3,d2	;d2 = ($95ffff)/d3
	move.w	d2,(a0)+	;a0 = d2+
	addq.w	#1,d1	;d1 = ++1
	cmp.w	#8192,d1	;d1 = Equal to 8192?
	bne.s	.loop2

	;Construct plot tables for fast drawing.

	lea	PlotXTable,a0	;a0 = X table - byte positions.
	lea	PlotBTable,a1	;a1 = Bit table (X related).
	lea	PlotYTable,a2	;a2 = Y table - line position.
	moveq	#0,d0	;d0 = 00
.loop3	move.w	d0,d1	;d1 = d0
	lsr.w	#3,d1	;d1 = (d0)<<3
	move.w	d1,(a0)+	;a0 = d1+

	move.w	d0,d1	;d1 = d0
	eor.w	#$FFFF,d1	;d1 = (d0) eor $ffff
	and.w	#%00000111,d1	;d1 = &%00000111
	move.w	d1,(a1)+	;a1 = BitSet++

	cmp.w	#SCR_HEIGHT,d0	;Write out the Y values for the
	bge.s	.plot2	;table.
	move.w	d0,d1	;d1 = Line Number.
	mulu	#120,d1	;d1 = (LineNumber)*80
	move.w	d1,(a2)+	;a2 = (LineNumber*80)++

.plot2	addq.w	#1,d0
	cmp.w	#SCR_WIDTH,d0
	bne.s	.loop3

;==========================================================================;
;                                MAIN LOOP
;==========================================================================;

MainLoop:
	move.l	GMS_Base(pc),a6
	CALL	Wait_OSVBL

	lea	Screen(pc),a0
	CALL	SwapBuffers

;==========================================================================;
;                             STAR ANIMATION
;==========================================================================;

	movem.w	StarXPos(pc),d0/d1/d2	;MV = d0/d1/d2 = XPos/YPos/ZPos
	add.w	#XSPEED,d0	;d0 = (StarXPos)+XSPEED
	add.w	#YSPEED,d1	;d1 = (StarYPos)+YSPEED
	add.w	#ZSPEED,d2	;d2 = (StarZPos)+ZSPEED
	and.w	#%0000011111111111,d0
	and.w	#%0000011111111111,d1
	and.w	#%0000011111111111,d2
	movem.w	d0/d1/d2,StarXPos

	lea	Sinus(pc),a0	;a0 = Sinus table.
	movem.w	StarXAdd(pc),d3/d4/d5	;MV = d3/d4/d5 : X/Y/Z
	add.w	(a0,d0.w),d3
	add.w	(a0,d1.w),d4
	add.w	(a0,d2.w),d5
	movem.w	d3/d4/d5,StarXAdd

;===========================================================================;
;                              SCREEN CLEAR
;===========================================================================;
;Let the blitter clear our 3rd screen while the CPU draws the stars.

	move.l	GMS_Base(pc),a6
	lea	Screen(pc),a0
	moveq	#BUFFER3,d0
	CALL	ClrScreen

;==========================================================================;
;                               DRAW STARS
;==========================================================================;

	lea	StarCoords,a0	;Draw starfield
	lea	PersTable,a1	;a1 = Perspective table.
	lea	PlotXTable,a2	;a2 = X table.
	lea	PlotBTable,a3	;a3 = Bit table.
	lea	PlotYTable,a4	;a4 = Y table.

	move.l	Screen+GS_MemPtr2(pc),a6

	movem.w	StarXAdd(pc),d3/d4/d5	;MV = d3/d4/d5 : ?
	add.w	#4096,d3	;d3 = ++4096
	add.w	#4096,d4	;d4 = ++4096

	move.w	#NSTARS-1,d7

.draw	movem.w	(a0)+,d0/d1/d2	;MV = d0/d1/d2 : XPos/YPos/ZPos.
	add.w	d3,d0	;Increase XPos.
	and.w	#8191,d0	;d0 = And'd
	sub.w	#4096,d0	;d0 = --4096

	add.w	d4,d1	;Y-movement
	and.w	#8191,d1	;d1 = And'd
	sub.w	#4096,d1	;d1 = --4096

	add.w	d5,d2	;Z-movement
	and.w	#8191,d2
	add.w	d2,d2	;d2 = *2 [word]
	move.w	(a1,d2.w),d6	;d6 = Read from Perspective table.

	muls	d6,d0	;X-projection
	swap	d0
	add.w	#176,d0

	cmp.w	#SCR_WIDTH-1,d0
	bhi	.nodraw
	muls	d6,d1	;Y-projection
	swap	d1
	add.w	#136,d1
	cmp.w	#SCR_HEIGHT-1,d1
	bhi	.nodraw

	add.w	d0,d0	;d0 = *2 [word]
	add.w	d1,d1	;d1 = *2 [word]
	move.w	(a4,d1.w),d6	;d6 = Plot Y.
	add.w	(a2,d0.w),d6	;d6 = ++PlotX.
	move.w	(a3,d0.w),d0	;d0 = BitValue.

.draw1	cmp.w	#4000,d2	;Now draw the star according to
	bgt.s	.draw2	;its position in the Z axis.
	bset	d0,(a6,d6.w)
	dbra	d7,.draw
	bra.s	.done

.draw2	cmp.w	#6000,d2
	bgt.s	.draw3
	bset	d0,40(a6,d6.w)
	dbra	d7,.draw
	bra.s	.done

.draw3	cmp.w	#8000,d2
	bgt.s	.draw4
	bset	d0,(a6,d6.w)
	bset	d0,40(a6,d6.w)
	dbra	d7,.draw
	bra.s	.done

.draw4	cmp.w	#10000,d2
	bgt.s	.draw5
	bset	d0,80(a6,d6.w)
	dbra	d7,.draw
	bra.s	.done

.draw5	cmp.w	#12000,d2
	bgt.s	.draw6
	bset	d0,(a6,d6.w)
	bset	d0,80(a6,d6.w)
	dbra	d7,.draw
	bra.s	.done

.draw6	cmp.w	#14000,d2
	bgt.s	.draw7
	bset	d0,40(a6,d6.w)
	bset	d0,80(a6,d6.w)
	dbra	d7,.draw
	bra.s	.done

.draw7	bset	d0,(a6,d6.w)
	bset	d0,40(a6,d6.w)
	bset	d0,80(a6,d6.w)
.nodraw	dbra	d7,.draw

.done	move.l	GMS_Base(pc),a6
	moveq	#JPORT1,d0	;Read from port 1 (mouse).
	moveq	#JT_ZBXY,d1
	CALL	Read_JoyPort	;Go get joystick status.
	btst	#MB_LMB,d0
	beq	MainLoop
	rts

;===========================================================================;
;                                  DATA
;===========================================================================;

GMS_Name:
	dc.b	"games.library",0
	even
GMS_Base:
	dc.l	0

AMT_PLANES =	3

Screen:	dc.l	GSV1,0
	dc.l	0,0,0	;Screen_Mem1/2/3
	dc.l	0	;Screen link.
	dc.l	.Palette	;Address of screen palette.
	dc.l	0	;Address of rasterlist.
	dc.l	0	;Amt of colours in palette.
	dc.w	320,256	;Screen Width and Height.
	dc.w	320/8,256	;Picture Width/8 and Height.
	dc.w	AMT_PLANES	;Amt_Planes
	dc.w	0,0	;X/Y screen offset.
	dc.w	0,0	;X/Y picture offset.
	dc.l	TPLBUFFER	;Special attributes.
	dc.w	LORES|COL12BIT	;Screen mode.
	dc.b	INTERLEAVED	;Screen type
	dc.b	0	;Reserved.
	even

.Palette
	; 124   124   124   124
	dc.w	$0000,$0eee,$0ccc,$0aaa	;%000, %100, %010, %110
	dc.w	$0888,$0666,$0333,$0222	;%001, %101, %011, %111

;===========================================================================;
;                                STAR DATA
;===========================================================================;

StarXAdd
	dc.w	33	;Star stuff
StarYAdd
	dc.w	12
StarZAdd
	dc.w	-114

StarXPos
	dc.w	0	;Sinus positions
StarYPos
	dc.w	310
StarZPos
	dc.w	1280

	INCLUDE	"StarSinus.i"

	SECTION	Storage,BSS

StarCoords
	ds.w	NSTARS*3	;Star coordinates

PersTable
	ds.w	8192	;Perspective table

PlotXTable
	ds.w	SCR_WIDTH	;Plot tables
PlotBTable
	ds.w	SCR_WIDTH
PlotYTable
	ds.w	SCR_HEIGHT

