* TABSTOP : 8
**	Assemble with Macro68

		exeobj
		objfile	"st"
		mc68000
		odderror
		copper

		incdir	"ainc:"
		macfile	"offsets/exec.i"
		macfile	"offsets/graphics.i"
		macfile	"exec/types.i"
		macfile	"graphics/gfxbase.i"
		macfile	"graphics/gfx.i"
		macfile	"graphics/rastport.i"
		macfile	"hardware/custom.i"

custom		equ	$dff000			;I dont want to link

*----------------------------------------------------------------------------
* Written cause I always wanted to write a stars.
* (for the last year or so anyway )
*
* by Robin Luiten
*    10 Chartwell St
*    Aspley 4034
*    Brisbane QLD Australia
*
* This code is Public Domain so do what you will.
* If anyone out there gets carried away with modifying this little
* piece of code and comes up with something cute I'd appreciate seeing
* the trans-mogrified code/executable some time.
*
* Note that I have not bothered to disable sprites fully so the occasional
* sprite bar may appear when you run this program.
*
* NOTE : "Yes I know its messy code but its only a quick hack."
*
* Assembly Notes:
*
* DISPLAY - if non zero then copper lists used for display of data.
*           if zero no graphic display ( so I can use a debugger )
*
* NUMSTARS - is set at 28 because I cant draw any more stars in one
* vertical blank period. I am to lazy right now to move my faster
* pixel plotter into this code or to make the star field double
* buffered. Besides 28 looks reasonable.
*
* TRACE - if not zero a visible trace of execution time is display.
*
*----------------------------------------------------------------------------
* Wierd & Wonderful Observations
*
* 1 Works fine on my Amiga 1000, dead smooth and very pretty.
*   I have 2 Megs of Fast memory and a Interrupt driven locally
*   brewed hard disk interface.
*
* 2 On a friends Amiga 500 with A590 Hardrive it becomes jerky.
*   If some one can tell me why I would like to know.
*   ( NOTE: friend has 1 Meg of chip ram and 2 Megs of Fast memory )
*----------------------------------------------------------------------------

DISPLAY		equ	1
SPREAD		equ	30
SIZE_BITPLANE	equ	(320*256)/8
NUM_STARS	equ	28
TRACE		equ	0


* Type Vector. ( a point or a vector )
vec_X		equ	0
vec_Y		equ	4
vec_Z		equ	8
vec_SIZEOF	equ	12

coord_X		equ	0
coord_Y		equ	2
coord_SIZEOF	equ	4

*****************************************************************************
		SECTION	star,code
DT:
		lea	(DT,pc),a4
		lea	(custom).l,a5
		move.l	(4).w,a6
		jsr	(_LVOForbid,a6)

		lea	(gfxname.MSG,pc),a1
		jsr	(_LVOOldOpenLibrary,a6)
		move.l	d0,a6

		bsr.b	GoForIt

		move.l	a6,a1				;retrieve GFX base.
		move.l	(4).w,a6
		jsr	(_LVOCloseLibrary,a6)
		jsr	(_LVOPermit,a6)
		rts


GoForIt:	move.l	(vhposr,a5),(rndseed-DT,a4) ;seed random numbers
		lea	(stars,pc),a0
		bsr	InitStars
		bsr	initgraph

************************************************ Top of star loop *********
waitlmb:
..again:
		btst	#5,(intreqr+1,a5)	;? vertical blank
		beq.b	..again

	ifne TRACE
		move.w	#$600,($dff180).l
	endc

		lea	(screen_locs,pc),a3
		lea	(stars,pc),a2
		moveq	#NUM_STARS-1,d7
						;a2 - current star
DrawStar:
		subq.l	#2,(vec_Z,a2)		;one step closer
		bgt.b	UseStar			;ONLY on > 0

		moveq	#0,d2			;one star only (dbra)
		move.l	a2,a0
		bsr	NextStar		;generate new location

UseStar:	move.l	(vec_Z,a2),d2		;pre-fetch Z loc
		bne.b	.ok

* I check here just to make sure I dont divide by zero I dont like
* my machine crashing if I make a silly mistake when I change something.
		move.w	#$000f,($dff180).l	;oops Got a ZERO
		bra	next_star

.ok:		move.l	(vec_X,a2),d3
		muls.w	#SPREAD,d3
		move.l	(vec_Y,a2),d4
		muls.w	#SPREAD,d4
		divs.w	d2,d3
		divs.w	d2,d4
		add.w	(center_x,pc),d3	;d3=X*SPREAD/Z + center_X
		add.w	(center_y,pc),d4	;d4=X*SPREAD/Z + center_Y

************************************* Erase current star position *********
		moveq	#0,d0
		lea	(myRastPort,pc),a1
		jsr	(_LVOSetAPen,a6)

		moveq	#0,d0
		move.w	(coord_X,a3),d0		;last X pos
		moveq	#0,d1
		move.w	(coord_Y,a3),d1		;last Y pos
		lea	(myRastPort,pc),a1
		jsr	(_LVOWritePixel,a6)

************************************************ Calc star colour *********
		move.l	#256,d0
		sub.l	d2,d0			;256-Z
		lsr.l	#4,d0			;(256-z)/16 gives 0-16
		lea	(myRastPort,pc),a1
		jsr	(_LVOSetAPen,a6)

	; if ( X(d3)>319 || X(d3)<0 || Y(d4)>256 || Y(d4)<0 )
	;     generate newpoint
	; else
	;     render
		cmp.w	#320,d3
		bhi.b	NewPoint
		tst.w	d3
		bmi.b	NewPoint

		cmp.w	#256,d4
		bhi.b	NewPoint
		tst.w	d4
		bpl.b	Render

NewPoint:	moveq	#0,d2			; one star only (dbra)
		move.l	a2,a0
		bsr	NextStar		; gen new star
		bra.b	next_star

Render:		moveq	#0,d0
		move.w	d3,d0
		moveq	#0,d1
		move.w	d4,d1
		lea	(myRastPort,pc),a1
		jsr	(_LVOWritePixel,a6)

		move.w	d3,(a3)+		;save X location
		move.w	d4,(a3)+		;save Y location

next_star:	lea	(vec_SIZEOF,a2),a2	;to next star
		dbra	d7,DrawStar

	ifne TRACE
		move.w	#$000,($dff180).l
	endc

..		btst	#10-8,($dff016).l	;pause Right Mouse Button
		beq.b	..

		btst	#6,($bfe001).l		;? test Left Mouse Button
		bne	waitlmb

		bsr	closegraph
		rts

*----------------------------------
* Initialise 3-D star coordinates.
*
InitStars:	moveq	#NUM_STARS-1,d2
NextStar:	move.l	a0,a1
.next:		move.l	#$1ff,d0
		bsr	rand
		sub.l	#$ff,d0
		move.l	d0,(a1)+			;new X coord

		move.l	#$1ff,d0
		bsr	rand
		sub.l	#$ff,d0
		move.l	d0,(a1)+			;new Y coord
		
		move.l	#$ff,d0
		bsr	rand
		move.l	d0,(a1)+			;new Z coord
		dbra	d2,.next

		rts

*------------------------------
* Restore system copper lists.
*
closegraph
..waithigh:	btst	#0,(vposr+1,a5)		;wait for ZERO beam pos
		beq.b	..waithigh
..waitlow:	btst	#0,(vposr+1,a5)
		bne.s	..waitlow

	ifne	DISPLAY
		move.w	#%0000000010000000,(dmacon,a5)	;Copper OFF
		move.l	(gb_copinit,a6),(cop1lc,a5)	;restore copper
		move.b	#0,(copjmp1,a5)			;use copper
		move.w	#%1000000010100000,(dmacon,a5)	;Copper & Sprite ON
	endc
		rts

*---------------------------------------
* Initialise graphics mode.
* Sets Up 'myRastPort' and copper list.
* Installs custom copper list.
*
initgraph:	lea	(myRastPort,pc),a2
		lea	(myBitMap,pc),a3

		move.l	a2,a1
		jsr	(_LVOInitRastPort,a6)
		
		move.l	a3,(rp_BitMap,a2)		;rastports bitmap

		moveq	#4,d0
		move.w	#320,d1
		move.w	#256,d2
		move.l	a3,a0
		jsr	(_LVOInitBitMap,a6)

		lea	(Bitplane1).l,a0
		move.l	a0,d0			;save bitplane address
		move.l	#((4*SIZE_BITPLANE)/4)-1,d2
		moveq	#0,d1
clr_bitplanes:	move.l	d1,(a0)+
		dbra	d2,clr_bitplanes

		lea	(bm_Planes,a3),a1
		lea	(cl_planes).l,a2	;copper list planes
		moveq	#4-1,d1			;4 planes to install

.nextplane:	move.l	d0,(a1)+		;install bitmap
		move.w	d0,(6,a2)		;bitplane ptr low
		swap	d0
		move.w	d0,(2,a2)		;bitplane ptr high
		swap	d0
		addq	#8,a2			;next bitplane data area
		add.l	#SIZE_BITPLANE,d0	;next bitplane
		dbra	d1,.nextplane

; Sprite's are disabled.
	ifne	DISPLAY
		move.w	#%0000000010100000,(dmacon,a5)	;Copper & Sprite OFF
		move.l	#CopperList,(cop1lc,a5)
		move.b	#0,(copjmp1,a5)			;use new copper list
		move.w	#%1000000110000000,(dmacon,a5)	;Copper ON
	endc
		rts

*
* Pseudo random number generator.
*
* INPUTS:
* d0 - range arg for random number.
*      negative number initialised seed.
*
* OUTPUTS:
* d0 - random number in range.
*      guarantee high word always zero coming out.
*
rand		lea	(rndseed).l,a0	;Get address of seed
		move.l	(a0),d1		;Get seed
		add.l   d1,d1
		bhi.b   over
		eori.l  #$e43f7431,D1
over
		move.l	d1,(a0)		;Save new seed
		andi.l	#$ffff,d1	;Coerce into word
		divu.w	d0,d1		;Divide by range
		swap	d1		;and get remainder (modulus)
		moveq	#0,d0
		move.w	d1,d0
		rts

rndseed		dc.l	0

gfxname.MSG:	db	"graphics.library",0
		cnop	0,2

center_x:	dc.w	160
center_y:	dc.w	100

myRastPort:	dx.b	rp_SIZEOF
myBitMap:	dx.b	bm_SIZEOF
stars:		dx.b	NUM_STARS*vec_SIZEOF	;X,Y,Z star coords
screen_locs:	dx.w	coord_SIZEOF*NUM_STARS	;last drawn coordinates

		SECTION	ChipData,DATA,CHIP
CopperList:
		cmove	#$4000,(bplcon0)
		cmove	#$0038,(ddfstrt)
		cmove	#$00d0,(ddfstop)
		cmove	#$2981,(diwstrt)
		cmove	#$29c1,(diwstop)

		cmove	#0,(bplcon1)
		cmove	#0,(bpl1mod)
		cmove	#0,(bpl2mod)

cl_planes:
		cmove	#0,(bplpt)		;addresses install by code
		cmove	#0,(bplpt+2)
		cmove	#0,(bplpt+4)
		cmove	#0,(bplpt+6)
		cmove	#0,(bplpt+8)
		cmove	#0,(bplpt+10)
		cmove	#0,(bplpt+12)
		cmove	#0,(bplpt+14)

		cmove	#$0000,(color)
		cmove	#$0111,(color+2)
		cmove	#$0222,(color+4)
		cmove	#$0333,(color+6)
		cmove	#$0444,(color+8)
		cmove	#$0555,(color+10)
		cmove	#$0666,(color+12)
		cmove	#$0777,(color+14)
		cmove	#$0888,(color+16)
		cmove	#$0999,(color+18)
		cmove	#$0aaa,(color+20)
		cmove	#$0bbb,(color+22)
		cmove	#$0ccc,(color+24)
		cmove	#$0ddd,(color+26)
		cmove	#$0eee,(color+28)
		cmove	#$0fff,(color+30)

		cend

Bitplane1:	dx.b	SIZE_BITPLANE
Bitplane2:	dx.b	SIZE_BITPLANE
Bitplane3:	dx.b	SIZE_BITPLANE
Bitplane4:	dx.b	SIZE_BITPLANE

		end
