;3D STARFIELD
;------------
;This is a demo of a triple buffered starfield.  I didn't orginally write
;this starfield code, but it was very old so it needed a fair bit of
;cleaning up to work with the library.  It now runs in 4 colours for a
;little more depth too...
;
;And it multi-tasks :-)

	opt	o+

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

CALL	MACRO
	jsr	_LVO\1(a6)
	ENDM

NSTARS	=	1000                     ;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	Quit

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

	lea	Screen(pc),a0
	CALL	Add_Screen
	tst.l	d0
	bne	Error
	CALL	Show_Screen

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

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

	;Randomize star coordinates

	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	#80,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
;==========================================================================;

Main:	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
;===========================================================================;

	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
	lea	PlotXTable,a2
	lea	PlotBTable,a3
	lea	PlotYTable,a4
	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

.draw1	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.s	.nodraw
	muls	d6,d1                    ;Y-projection
	swap	d1
	add.w	#136,d1
	cmp.w	#SCR_HEIGHT-1,d1
	bhi.s	.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.

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

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

.draw3	bset	d0,(a6,d6.w)
	bset	d0,40(a6,d6.w)
.nodraw	dbra	d7,.draw1

.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	Main

;===========================================================================;
;                              RETURN TO DOS
;===========================================================================;

	move.l	GMS_Base(pc),a6
	lea	Screen(pc),a0
	CALL	Delete_Screen            ;Give back screen memory etc.
Error	move.l	GMS_Base(pc),a1
	move.l	($4).w,a6
	CALL	CloseLibrary
Quit	MOVEM.L	(SP)+,A0-A6/D1-D7
	moveq	#$00,d0
	rts

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

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

AMT_PLANES =	2

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	4	;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	;Amount of 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
	dc.w	$0000,$0DDD,$0666,$0222

;===========================================================================;
;                                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

