
    *** MiniStartup by Photon ***

	INCLUDE "PhotonsMiniWrapper1.04!.S"	;handles OS off and restore.

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

w	=640
h	=256
bpls	=4
bpl	=w/16*2
bwid	=bpls*bpl

StarsH	=72
NStars	=36

    *--- chessboard constants ---*

*NOTE: Here, the Y and Z axes have been inverted for pedagogical presentation.

;1. Decide the FOV and the speed resolution of square movement

stepspersquare	=32
FOVScale	=56

;2. Decide the Z position of the screen from your eyes and the pixel height
;of the chessboard floor

ZStart		=36*FOVScale
ChessH		=128

;3. From this, the calculation constants follow

ZStep		=FOVScale*stepspersquare
ZScale		=ZStart*128

;4. We stop before the actual horizon (infinity), so it must be moved up to
;the vertical start of the chessboard floor

horizonadjust	=-8
ChessTopY	=$74

;5. Decide speed of square movement. As a var, this allows acc-/deceleration

ZSpeed		=2
starspeed	=9			;percent

********** Demo **********

Demo:					;a4=VBR, a6=Custom Registers Base addr
    *--- init ---*
	move.l #VBint,$6c(a4)
	move.w #$c020,$9a(a6)
	move.w #$87c0,$96(a6)
    *--- poke pic bplptrs ---*
	lea Screen,a0
	moveq #bpl,d0
	lea BplPtrs+2,a1
	moveq #bpls-1,d1
	bsr.w PokePtrs

	bsr RandomizeStars

	move.l #Copper,$80(a6)

    *--- main loop ---*

MainLoop:				;;2
	lea CopperChessE,a1
	bsr PokeChessWaits

    *--- inc color offset ---*

	move.w ColorOffset(PC),d0
	addq.w #1,d0
	and.w #127,d0			;keep count within 0..127
	move.w d0,ColorOffset

    *--- poke palette ---*

	lea TextColors(PC),a0
	lsr.w #1,d0			;color cycle speed, 50/8 fps
	and.w #-2,d0			;make it even
	add.w d0,a0
	lea TextPalette+2,a1
	moveq #(15-3)-1,d1
	bsr.w PokeWords

	move.w #ChessTopY+2,d0		;Clear & plot when below horizon
	bsr.w WaitRaster

    *--- clear screen ---*		;by inverting last pixels again, if

	tst.w PointsValid		;drawn. Faster than a 4-bitplane blit.
	beq.s .noclr
	moveq #NStars,d0
	lea Points,a0
	lea Screen,a1
	bsr.w PlotPoints
.noclr:	

    *--- calc 3D -> 2D ---*

	moveq #NStars,d0
	lea Coords,a0
	lea Points,a1
	bsr.w CalcStars
	move.w #1,PointsValid		;flag that Points now contains valid xy

    *--- plot 2D points ---*

	moveq #NStars,d0
	lea Points,a0
	lea Screen,a1
	bsr.w PlotPoints

	btst #6,$bfe001
	bne.w MainLoop

    *--- exit ---*

	rts

********** Demo Routines **********

PokePtrs:				;Generic, poke ptrs into copper list
.bpll:	move.l a0,d2
	swap d2
	move.w d2,(a1)
	move.w a0,4(a1)
	addq.w #8,a1
	add.l d0,a0
	dbf d1,.bpll
	rts

PokeWords:				;Generic, poke words into copper list
.bpll:	move.w (a0)+,(a1)
	addq.w #4,a1
	dbf d1,.bpll
	rts

PlotPoints:				;a0=points, a1=screen, d0=count
	subq.w #1,d0
.l:	movem.w (a0)+,d1-d3
    *--- clipping ---*
	cmp.w #-w/2,d1
	blt.s .outside
	cmp.w #w/2,d1
	bge.s .outside
	cmp.w #-StarsH,d2
	ble.s .outside
	bsr.s Plot
.outside:	
	dbf d0,.l
	rts

Plot:					;d1=x, d2=y, d3=color, a1=screen
	movem.l d1-d5/a1,-(sp)
	add.w CenterX(PC),d1
	add.w CenterY(PC),d2

	muls #bwid,d2
	move.w d1,d4
	not.w d4
	asr.w #3,d1
	ext.l d1
	add.l d1,d2

	moveq #bpls-1,d5
.l:	ror.b #1,d3
	bpl.s .noset
	bchg d4,(a1,d2.l)		;bset -> bchg to INVERT pixels.
.noset:	lea bpl(a1),a1
	dbf d5,.l
	movem.l (sp)+,d1-d5/a1
	rts

VBint:					;Blank template VERTB interrupt
	movem.l d0/a6,-(sp)
	lea $dff000,a6
	btst #5,$1f(a6)
	beq.s .notvb
    *--- do stuff here ---*
	moveq #$20,d0
	move.w d0,$9c(a6)
	move.w d0,$9c(a6)
.notvb:	movem.l (sp)+,d0/a6
	rte

*********  Effect Routines  *********

PokeChessWaits:				;a1=destination (after last wait)
	move.l ChessColorP(PC),a0	;source for RGB colors
    *--- sub-square movement ---*
	move.w ChessZ(PC),d3
	sub.w #ZSpeed,d3		;new square?
	bpl.s .nowrap
	add.w #stepspersquare,d3	;then wrap
	addq.l #2,a0			;and toggle RGB
	cmp.l #ChessColorsE,a0
	blt.s .nowrap
	lea ChessColors(PC),a0
.nowrap:	
	move.w d3,ChessZ
	move.l a0,ChessColorP
    *--- poke Y positions ---*
	move.l #ZScale,d2
	mulu #FOVScale,d3
	add.w #ZStart,d3
	move.w #ZStep,d4

	moveq #17-1,d1			;#squares = WAIT commands to be poked
.l1:
	move.l d2,d0
	divu d3,d0
	add.w #ChessTopY+horizonadjust,d0
	lea -12(a1),a1
	move.b d0,(a1)			;wait
	move.w (a0)+,6(a1)		;color 1
	move.w (a0)+,6+4(a1)		;color 2
	add.w d4,d3
	dbf d1,.l1	
	rts

Random:				;A simple mathematical generator. d0=seed
	rol.w d0,d0
	eor.w #18565,d0
	rts				;returns next RND number/seed in d0

RandomizeStars:				;initialize x,y,z coordinate values
	lea Coords,a1
	moveq #0,d0			;start seed value
	moveq #NStars-1,d1
.l1:
    *--- x ---*
	bsr.s Random
	move.w d0,(a1)+			;signed int, scaled up in CalcStars
    *--- y ---*
	bsr.s Random
	move.w d0,d2			;y coordinates must be negative, though
	bset #15,d2			;because they are above the horizon
	move.w d2,(a1)+
    *--- z ---*
	bsr.s Random
	moveq #0,d2
	move.w d0,d2
	divu #ZStep*17,d2		;use modulo calculus to keep Z within
	swap d2				;the same range as the chessboard, to
	move.w d2,(a1)+			;get the same FOV (perspective)
	dbf d1,.l1	
	rts

CalcStars:				;a0/a1/d0=source,dest,count
	subq.w #1,d0			;decrease for dbf
	move.w #ZStart,d4		;stars frontmost Z position
	move.w #ZStep*starspeed/100,d5	;star Z movement speed
	move.w #17*ZStep,d6		;Z range for stars to stay within
.l0:
	movem.w (a0)+,d1-d3		;x,y,z (movem.w auto-sign-extends)
	asl.l #8,d1			;scale up for div - Y not so much
	asl.l #6,d2			;due to the small height and hires mode
    *--- move star ---*
	sub.w d5,d3
	bpl.s .nowr
	add.w d6,d3			;wrap to make sure Z dist is positive
.nowr:	
	move.w d3,-(a0)			;write Z value back...
    *--- x,y 3D->2D ---*
	add.w d4,d3
	divs d3,d1			;...scale down X and Y...
	divs d3,d2
    *--- set plot color ---*
	move.w d6,d3			;...and fetch it for color calculation
	sub.w (a0)+,d3			;(invert Z axis - nearer is brighter)
	divs #ZStep*17/6,d3		;shrink Z to range 0..6
	addq.w #1,d3			;-> color 1..7

	movem.w d1-d3,(a1)		;write plot x,y,color for PlotPoints
	addq.w #6,a1
	dbf d0,.l0	
	rts

********** Fastmem Data **********
Max:	dc.w 0
PointsValid:	dc.w 0
ChessZ:		dc.w 0
ChessColorP:	dc.l ChessColors
CenterX:	dc.w w/2		;center of stars
CenterY:	dc.w StarsH-1
ColorOffset:	dc.w 0

TextColors:				;grayscale from black to white and back
	REPT 2				;twice to read beyond wrap-offset
	dc.w $000,$111,$222,$333,$444,$555,$666,$777
	dc.w $888,$999,$aaa,$bbb,$ccc,$ddd,$eee,$fff
	dc.w $fff,$eee,$ddd,$ccc,$bbb,$aaa,$999,$888
	dc.w $777,$666,$555,$444,$333,$222,$111,$000
	ENDR

ChessColors:	;fade red to yellow and back, every other square is black.
	dc.w $f00,0,$f10,0,$f20,0,$f30,0,$f40,0,$f50,0,$f60,0,$f70,0
	dc.w $f80,0,$f90,0,$fa0,0,$fb0,0,$fc0,0,$fd0,0,$fe0,0,$ff0,0
	dc.w $ff0,0,$fe0,0,$fd0,0,$fc0,0,$fb0,0,$fa0,0,$f90,0,$f80,0
	dc.w $f70,0,$f60,0,$f50,0,$f40,0,$f30,0,$f20,0,$f10,0,$f00,0
ChessColorsE:		;again, colors repeated to read beyond wrap-offset
	dc.w $f00,0,$f10,0,$f20,0,$f30,0,$f40,0,$f50,0,$f60,0,$f70,0
	dc.w $f80,0,$f90,0,$fa0,0,$fb0,0,$fc0,0,$fd0,0,$fe0,0,$ff0,0
	dc.w $ff0,0,$fe0,0,$fd0,0,$fc0,0,$fb0,0,$fa0,0,$f90,0,$f80,0
	dc.w $f70,0,$f60,0,$f50,0,$f40,0,$f30,0,$f20,0,$f10,0,$f00,0

*******************************************************************************
	SECTION ChipData,DATA_C
*******************************************************************************

Copper:					;;3
	dc.w $1fc,0
	dc.w $8e,$2c81
	dc.w $90,$2cc1			;$f4c1 (and remove $ffdf WAIT) for NTSC
	dc.w $92,$38
	dc.w $94,$d0

	dc.w $108,bwid-bpl
	dc.w $10a,bwid-bpl

	dc.w $102,0

BplPtrs:
	dc.w $e0,0
	dc.w $e2,0
	dc.w $e4,0
	dc.w $e6,0
	dc.w $e8,0
	dc.w $ea,0
	dc.w $ec,0
	dc.w $ee,0
	dc.w $100,bpls*$1000+$8200
    *--- stars palette ---*
	dc.w $180,0
	dc.w $182,$555
	dc.w $184,$777
	dc.w $186,$999
	dc.w $188,$bbb
	dc.w $18a,$ddd
	dc.w $18c,$eee
	dc.w $18e,$fff
    *--- restore used star color(s) ---*	;just before chess
	dc.w (ChessTopY-1)<<8+$df,$fffe	;WAIT for $73df
	dc.w $182,0
	dc.w $184,0
    *--- text palette ---*
TextPalette:				;Palette from COLOR03 to COLOR15
	dc.w $186,0,$188,0,$18a,0,$18c,0,$18e,0
	dc.w $190,0,$192,0,$194,0,$196,0,$198,0,$19a,0,$19c,0,$19e,0
CopperChess:
    *--- chess start ---*		;color init at fixed horizon Y
.y:	SET ChessTopY<<8+$07		;WAIT for $7407 (these will be poked
	dc.w .y,$fffe			;with proper perspective Y values)
	dc.w $184,$337			;swap order of color registers
	dc.w $182,$ddf

.y:	SET .y+$0100			;next line WAIT
    *--- to-be-poked copper WAITs ---*
	REPT 8
	dc.w .y,$fffe
	dc.w $182,$337
	dc.w $184,$ddf
.y:	SET .y+$0800			;more "dummy" WAIT values
	dc.w .y,$fffe
	dc.w $184,$337			;swap order of color registers
	dc.w $182,$ddf
.y:	SET .y+$0800
	ENDR
CopperChessE:
    *--- turn off chess ---*
	dc.w $ff07,$fffe
	dc.w $182,0
	dc.w $184,0
    *--- finish up ---*
	dc.w $ffdf,$fffe
	dc.w $ffff,$fffe

Screen:	INCBIN "pic.640x256x4"

*******************************************************************************
	SECTION ChipBuffers,BSS_C
*******************************************************************************

Coords:		ds.w NStars*3		;x,y,z, x,y,z...
Points:		ds.w NStars*3		;x,y,color, x,y,color...

