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

	opt	o+

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

CALL	MACRO
	jsr	_LVO\1(a6)
	ENDM

NSTARS	=	600                      ;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
	CALL	SetUserPri

	move.l	GMS_Base(pc),a6          ;Tell GMS that we want to add a
	lea	ScreenStruct(pc),a0      ;screen for use.
	CALL	Add_Screen
	tst.l	d0
	bne	Error

	lea	ScreenStruct(pc),a0      ;Now show the screen/pic.
	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	#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	ScreenStruct(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.

.wait	btst	#6,$dff002
	bne.s	.wait
	move.l	ScreenStruct+SS_MemPtr3(pc),$dff054
	move.w	#0,$dff066
	move.l	#$01000000,$dff040
	move.w	#(SCR_HEIGHT*AMT_PLANES<<6)+SCR_WIDTH/16,$dff058

;==========================================================================;
;                               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	ScreenStruct+SS_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

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

ReturnToDOS:
	move.l	GMS_Base(pc),a6
	lea	ScreenStruct(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 =	3

ScreenStruct:
	dc.l	"GSV1",0
	dc.l	0,0,0            ;Screen_Mem1/2/3
	dc.l	0                ;Screen link.
	dc.l	ScreenPalette    ;Address of screen palette.
	dc.l	0                ;Address of rasterlist.
	dc.l	0                ;Amt of colours in palette.
	dc.w	320,256,320,256  ;Screen & Pic Height/Width.
	dc.w	AMT_PLANES       ;Amt_Planes
	dc.w	0,0              ;Top Of Screen, X/Y
	dc.w	0,0              ;X/Y counters (for scrolling).
	dc.l	TPLBUFFER        ;Special attributes.
	dc.w	LORES            ;Screen mode.
	dc.b	INTERLEAVED      ;Screen type
	dc.b	0                ;Reserved.
	even

ScreenPalette:                           ; 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

