; routines necessary for producing small cars in the mirror
; initially all the same car, but will eventually have to be 6 different cars


Mirrors::
	movem.l	d0-d5/a0,-(sp)
	tst.l	viewmove.w		; check if in cockpit
	beq.b	.exit			; if not then abandon immediately
	bsr	clear_mirrors		; wipe upper half to current sky colour, lower half to road colour
	tst.b	real_num_drones.w
	beq.b	.exit
	bsr	generate_list		; prepare list of (mirror) visible vehicles - not ordered yet
	bsr	sort_list		; orders list so that furthest back comes first
	bsr	draw_cars
.exit:	movem.l	(sp)+,d0-d5/a0
	rts

generate_list:
	movem.l	d0-d5/a0,-(sp)
	movea.w	#WkSpc,a0		; get address of some space where we can hold things
	move.l	12(a1),d4		; read current cars x co-ord
	move.l	20(a1),d5		; and z co-ord
	move.l	#23000,d2		; absolute limit beyond which nothing is considered [chosen because it will rotate in 15 bits]
	moveq	#0,d3
	move.b	real_num_drones.w,d3	; counter - count through the cars, outputting results where applicable
					; this value allows your car to be checked as well (necessary)

.lp:	bsr	prepare_pointers	; get a1,a2 pointing at cars 3d data and cars ai data
	moveq	#$f,d0
	and.b	STATS(a2),d0		; reads status of this car
	cmpi.b	#human,d0		; check for drivers car
	bne.b	.nh
.ze:	moveq	#0,d0
	moveq	#0,d1
	bra.b	.write
.nh:	move.l	12(a1),d0		; read x-coord
	sub.l	d4,d0			; calc distance
	asr.l	#1,d0		; HALF IT FOR TEST
	move.l	d0,d1			; move because its wanted elsewhere
	bpl.b	.nn1
	neg.l	d0
.nn1:	cmp.l	d2,d0			; see if more than limit
	bgt	.ze			; if so then zero it
	move.l	20(a1),d0		; read z-coord
	sub.l	d5,d0			; calc distance
	asr.l	#1,d0		; HALF IT FOR TEST
	bpl.b	.nn2
	neg.l	d0			; if negative make positive
	cmp.l	d2,d0			; and test
	bgt	.ze			; and zero if too big
	neg.l	d0
	bra.b	.twist			; then skip check for +ve values
.nn2:	cmp.l	d2,d0			; and test
	bgt	.ze			; and zero if too big
.twist:	bsr.b	twistem			; rotate round to be car relative
	tst.l	d0			; check that z is negative - ie car is behind you
	bpl	.ze
.write:	move.w	d1,(a0)+		; write out x and z co-ordinates
	move.w	d0,(a0)+
	move.w	d3,(a0)+		; write out car number as well - need to identify after sorting
	dbra	d3,.lp

	movem.l	(sp)+,d0-d5/a0
	rts

twistem:movem.l	d3-d4,-(sp)
	move.l	d0,d3			; copy of z value
	move.l	d1,d4			; copy of x value

	muls	zspd.w,d0		; zspd * z
	muls	xspd.w,d4		; xspd * x
	muls	zspd.w,d1		; zspd * x
	muls	xspd.w,d3		; xspd * z

	add.l	d4,d0			; rotated new z
	sub.l	d3,d1			; and x

	asl.l	#2,d0
	asl.l	#2,d1
	swap	d0			; 
	swap	d1
	ext.l	d0
	ext.l	d1

	movem.l	(sp)+,d3-d4
	rts

sort_list:
	movem.l	d0-d4,-(sp)
	moveq	#0,d0			; number of times through to be sure of sort
	move.b	real_num_drones.w,d0
	subq.w	#1,d0	
	beq.b	.ns			; don't have to sort 1
	subq.w	#1,d0			; gives right number of sort passes required

.lp0:	move.w	d0,d1			; number to test against
	movea.w	#WkSpc,a0		; get address of the start of the list
	addq.w	#1,d1

.lp1:	move.l	(a0)+,d2		; read x,z together
	move.w	(a0)+,d4		; read car number in case swapping
	move.l	(a0),d3
	
	cmp.w	d2,d3
	bge.b	.nex
	move.l	d3,-6(a0)		; write out x,z into each other
	move.l	d2,(a0)
	move.w	4(a0),-2(a0)		; move next car number into last
	move.w	d4,4(a0)		; and write last into next
.nex:	dbra	d1,.lp1

	dbra	d0,.lp0

.ns:	movem.l	(sp)+,d0-d4
	rts


clear_mirrors:
	move.l	sky_colour.w,d0		; read sky fill colour
	bsr	WaitBlit
	move.l	d0,B_SRCD
	move.l	d0,B_SRCD+4
	move.l	#$130030,B_COUNT	; whole thing
;	move.l	#left_mirror,A1_BASE
;	move.l	#(PIXEL16|PITCH1|WID48),A1_FLAGS
;	move.l	#0,A1_PIXEL
	move.l	#obj_store,d0
	tst.l	screen.w
	bne.b	.sk
	addq.l	#8,d0
.sk:	tst.l	viewmove.w
	beq.b	.ok
	bchg	#3,d0
.ok:	move.l	d0,A1_BASE
	move.l	#PIXEL16|PITCH2|WID320,A1_FLAGS
	moveq	#0,d0
	move.w	#193,d0
	tst.b	ntsc_type.w
	bne.b	.nt
	add.w	#22,d0
.nt:	swap	d0
	move.w	#26,d0
	move.l	d0,A1_PIXEL
	move.l	#$1ffce,A1_STEP

	move.l	#LFUSRC|UPDA1,B_CMD
	clr.l	blitsem.w

	bsr	WaitBlit
	move.l	#$130030,B_COUNT	; whole thing
;	move.l	#right_mirror,A1_BASE
;	move.l	#0,A1_PIXEL
	move.w	#(320-74),d0
	move.l	d0,A1_PIXEL

	move.l	#LFUSRC|UPDA1,B_CMD
	clr.l	blitsem.w

	rts

draw_cars:
	movea.w	#WkSpc,a0		; list of cars
	moveq	#0,d0			; counter
	move.b	real_num_drones.w,d0

.lp0:	move.w	(a0)+,d1		; read x
	asr.w	#4,d1			; scale down so that co-ordinates are appropriate
	ext.l	d1
	move.w	(a0)+,d3		; read z
	move.w	(a0)+,d2		; read car number
	neg.w	d3			; make as if distance is in front
	beq	.nor			; if z=0 then there is nothing to do !
	ext.l	d3

	bsr	WaitBlit
	move.l	#mirror_car0,d4		; base of all car bitmaps - when available, adjust to take account of which car it is
	move.l	d4,A1_BASE		; source address

	move.l	#obj_store,d5
	tst.l	screen.w
	bne.b	.sk
	addq.l	#8,d5
.sk:	tst.l	viewmove.w
	beq.b	.ok
	bchg	#3,d5
.ok:	move.l	d5,A2_BASE

	add.l	#800,d3			; allowance for distance to mirror from viewpoint
	bsr	Z_to_INC
	bsr	scalebits
	tst.l	d4
	beq.b	.nor
	move.l	bitmap_width.w,bitmap_width2.w
	bsr	leftpos
	bsr	clipit
	tst.l	d4
	beq.b	.nol
	add.l	#26,bitmap_xoff.w
	add.l	#193,bitmap_yoff.w
	bsr	blit_it
.nol:	move.l	bitmap_width2.w,bitmap_width.w
	bsr	rightpos
	bsr	clipit
	tst.l	d4
	beq.b	.nor
	add.l	#320-74,bitmap_xoff.w
	add.l	#193,bitmap_yoff.w
	clr.l	blitsem.w
	bsr	WaitBlit
	bsr	blit_it

.nor:	clr.l	blitsem.w
	dbra	d0,.lp0

	rts


Z_to_INC:
	movem.l	d0-d3,-(sp)
	move.l	d3,d0			; copy for generating a scale value
	asl.l	#4,d0			; this is the scale multiplier for converting back from output pixels to source pixels
	moveq	#0,d1
	move.w	d0,d1			; makes d1 into 0:xlo
	move.w	#0,d0
	swap	d0			; so d0 is now 0:xhi

	move.l	d0,A1_INC
	move.l	d1,A1_FINC

	movem.l	(sp)+,d0-d3
	rts

scalebits:
	lsr.l	#4,d3			; scale down z - guessed amount
	beq.b	.not
	moveq	#1,d4
	swap	d4
	divu	d3,d4			; d4 holds scale factor for co-ordinates
	ext.l	d4
	move.l	d4,bitmap_scale.w	; keep in memory because short of registers - this value is 24.8 fraction
	asr.l	#2,d4			; turns 1.00 into 64 which is correct width
	move.l	d4,bitmap_width.w	; 
	move.l	bitmap_scale.w,d4
	mulu	#20,d4			; height of original
	asr.l	#8,d4
	move.l	d4,bitmap_height.w
	bpl.b	.ok			; positive means usable
.not:	moveq	#0,d4			; negative means not !
.ok:	rts

rightpos:
	movem.l	d0-d3,-(sp)
	sub.w	#15,d1			; 'mirror offset'
	move.l	#12,d2
	bra.b	cht
leftpos:
	movem.l	d0-d3,-(sp)
	add.w	#15,d1			; 'mirror offset'
	move.l	#36,d2
cht:	moveq	#0,d0
	move.l	d0,source_xoff.w
	move.l	d0,source_yoff.w
	move.l	d0,A1_FPIXEL
	muls	bitmap_scale+2.w,d1
	asr.l	#8,d1			; scale down to whole pixels
	add.l	d2,d1			; apply centring offset for either mirror
	move.l	bitmap_width.w,d0
	asr.l	#1,d0
	sub.l	d0,d1			; to complete the picture
	bpl.b	.ok
	add.l	d1,bitmap_width.w	; this is the distance the image is off the left
	bpl.b	.nm			; if made to go negative, then should wipe out
	clr.l	bitmap_width.w
.nm:	muls	d3,d1
	asr.l	#8,d1
	sub.l	d1,source_xoff.w	
	moveq	#0,d1	
.ok:	move.l	d1,bitmap_xoff.w

	moveq	#20,d0
	sub.l	bitmap_height.w,d0
	bpl.b	.oky
	add.l	d0,bitmap_height.w	; reduces height to right amount
	neg.l	d0
	asr.l	#1,d0			; get amount off top
	muls	d3,d0
	asr.l	#8,d0
	move.l	d0,source_yoff.w
	moveq	#0,d0
.oky:	asr.l	#1,d0
	move.l	d0,bitmap_yoff.w
	movem.l	(sp)+,d0-d3
	rts	


clipit:	movem.l	d0-d1,-(sp)
	moveq	#48,d1
	moveq	#1,d4
	move.l	bitmap_xoff.w,d0	; see where will be within mirror
	cmp.l	d1,d0			; see if off side
	bgt.b	.kill
	add.l	bitmap_width.w,d0	; get final edge
	sub.l	d1,d0			; see how much crosses edge
	bmi.b	.exit
	sub.l	d0,bitmap_width.w
	bra.b	.exit
.kill:	moveq	#0,d4
.exit:	movem.l	(sp)+,d0-d1
	rts

blit_it:
	movem.l	d0-d3,-(sp)

	move.l	bitmap_xoff.w,d0
	move.l	bitmap_yoff.w,d1
	tst.b	ntsc_type.w
	bne.b	.us
	add.w	#22,d1
.us:	swap	d1
	move.w	d0,d1
	move.l	d1,A2_PIXEL		; destination start point

	move.l	bitmap_height.w,d0
	bmi	nothing_to_do
	move.l	bitmap_width.w,d1
	bmi	nothing_to_do
	beq	nothing_to_do
	swap	d0
	move.w	d1,d0
	move.l	d0,B_COUNT		; size of output copy

	move.l	bitmap_width.w,d0
	neg.l	d0
	swap	d0
	move.w	#1,d0
	swap	d0
	move.l	d0,A2_STEP

	move.l	#(PITCH2|PIXEL16|WID320|XADDPIX),A2_FLAGS

	move.l	source_xoff.w,d0
	move.l	source_yoff.w,d1
	swap	d1
	move.w	d0,d1
	move.l	d1,A1_PIXEL		; stuff the fractions !

	move.l	bitmap_width.w,d0	
	neg.l	d0
	muls	d3,d0
	asl.l	#8,d0			; xhi:xlo of step
	move.l	d3,d1
	asl.l	#8,d1			; Yhi:ylo of step
	swap	d1
	move.w	d0,d2
	move.w	d1,d0			; xhi:yhi
	move.w	d2,d1			; ylo:xlo
	swap	d0
	move.l	d0,A1_STEP
	move.l	d1,A1_FSTEP

	moveq.l	#0,d3

	move.l	d3,B_PATD
	move.l	d3,B_PATD+4

	move.l	#(PITCH1|PIXEL16|WID64|XADDINC),A1_FLAGS

	move.l	#(SRCEN|UPDA1F|UPDA1|UPDA2|DSTA2|LFUSRC|DCOMPEN),B_CMD

nothing_to_do:
	movem.l	(sp)+,d0-d3
	rts
