; code for blitting a bitmap onto screen using the new structure for bitmaps
; structure is as follows
; point count = 0
; point number - for defining depth
; data address
; structure at data address is :
; depth to start at (ie use this definition after this depth)
; scaling factor (shift count)			example : car width in reality is 1956 ~ 2048, bitmap is 32 so scale is 6 (32<<6=2048)
; width in pixels
; height in pixels
; width in blitter flags setup
; graphic data address
.if 0
place_bitmap::
	movem.l	d0-d7/a0-a1,-(sp)

	movea.w	#point_2d,a0
	movea.w	#point_3d+8,a1

	move.w	(a5)+,d0		; read point number (around which the bitmap will be centred)
	asl.w	#2,d0			; scale up to read x,y screen co-ordinates

	adda.w	d0,a0
	move.l	(a0)+,d1		; screen x in 16.16 fractions
	move.l	(a0),d2			; screen y

	asl.w	#1,d0			; scale up to read z co-ordinate
	adda.w	d0,a1
	move.l	(a1),d3			; viewpoint z

	move.l	(a5)+,a0		; address of bitmap structure

;===============================================
; read through to valid substructure

.lp:	move.l	(a0)+,d0		; z limit
	beq.b	.drop
	cmp.l	d0,d3
	bpl.b	.take
	lea	12(a0),a0		; skip rest of data
	bra	.lp

;===============================================
; read data for this bitmap and process

.take:	tst.l	(a0)			; check for empty record (ie nothing to draw)
	beq.b	.drop
	bsr	calculate_scale		; scale returned in 'bitmap_scale.w'
	bmi.b	.drop
	bsr	output_size		; returned in 'bitmap_width.w' etc
	bsr	clip_output		; calculate clipped (to screen) output zone and also source start offsets required
	bsr	blit_it			; produce screen output using information created before


.drop:	movem.l	(sp)+,d0-d7/a0-a1
	rts
	
;==============================================

calculate_scale:

	move.w	(a0)+,d0		; get shift factor
	lsr.l	d0,d3			; use it to reduce z value
	beq.b	.fail

	moveq.l	#1,d0
	swap	d0
	divu	d3,d0			; to give a factor for multiplying coordinates

	move.l	d0,bitmap_scale.w
	rts

.fail:	moveq	#-1,d0
	rts

output_size:
	mulu	(a0)+,d0		; multiply by width
	asl.l	#8,d0			; shift up to give 16.16 fraction of width
	move.l	d0,bitmap_width.w

	move.l	bitmap_scale.w,d0
	mulu	(a0)+,d0		; multiply by height
	asl.l	#8,d0			; shift up to give 16.16 fraction of height
	move.l	d0,bitmap_height.w
	rts

clip_output:			; working throughout in 16.16 fractional pixel values
	move.l	d1,d5			; keep centre point for right hand edge
	move.l	d2,d6			; ditto for bottom edge
	moveq.l	#0,d7

	move.l	bitmap_width.w,d0
	asr.l	#1,d0			; half width
	sub.l	d0,d1			; giving left hand edge which must be >=0
	bpl.b	.okl			; if not crossing left edge, test for right
	add.l	d1,bitmap_width.w	; reduce bitmap width by overflow amount
	move.l	d1,d7			; retain overflow amount for calculating source clipped start point (negative amount)
	moveq.l	#0,d1			; make left edge 0

.okl:	add.l	d0,d5			; calculate right hand edge
	move.l	#320<<16,d0		; right hand edge limit (in 16.16)
	sub.l	d0,d5			; test by calculating overflow
	bmi.b	.okr			; if not crossing right edge, move on to top
	sub.l	d5,bitmap_width.w	; reduce width by overflow amount

.okr:	neg.l	d7			; correct to give pixel offset into source image (16.16)
	move.l	d7,bitmap_xoff.w	; store for future use
	moveq.l	#0,d7			; clear for vertical offset

	move.l	bitmap_height.w,d0
	asr.l	#1,d0			; half width
	sub.l	d0,d2			; giving top edge which must be >=0
	bpl.b	.okt			; if not crossing top edge, test for bottom
	add.l	d2,bitmap_height.w	; reduce bitmap height by overflow amount
	move.l	d2,d7
	moveq.l	#0,d2			; make top edge 0

.okt:	add.l	d0,d6			; calculate bottom edge
	move.l	#240<<16,d0		; bottom edge limit (in 16.16)
	sub.l	d0,d6			; test by calculating overflow
	bmi.b	.exit			; if not crossing bottom edge, move on to exit
	sub.l	d6,bitmap_height.w	; reduce height by overflow amount

.exit:	neg.l	d7
	move.l	d7,bitmap_yoff.w	; this value is in 16.16 output pixels - not source ones
	rts

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

fail:	message	"Impossible Blitter count"

blit_it:

	bsr	WaitBlit

.if Trace_on
	move.l	"Blit",(a6)+
	move.l	"ter:",(a6)+
.endif

			; DESTINATION START CO-ORDINATE

	swap	d1			; make x coordinate low:high
	move.w	d1,d2			; and combine both high words together
	move.l	d2,A2_PIXEL		; d2 = high y:high x - there is no fractional side for A2

.iif Trace_on,	move.l	d2,(a6)+

				; DESTINATION PIXEL COUNT (WIDTH BY HEIGHT)

	move.l	bitmap_height.w,d1	; full height in fractional pixels of output
	move.l	bitmap_width.w,d2	; full width in fractional pixels
	swap	d2			; put x integer in low word
	move.w	d2,d1			; to give pixel count for output side (y:x)
	beq.b	fail
	move.l	d1,B_COUNT

.iif Trace_on,	move.l	d1,(a6)+

				; DESTINATION PIXEL STEP - to make lines line up

	move.l	bitmap_width.w,d0	; get width (16.16)
	move.w	#1,d0			; put 1 in for y step - down one line
	swap	d0
	neg.w	d0			; make negative because we will go back the amount written and down one line
	move.l	d0,A2_STEP

.iif Trace_on,	move.l	d0,(a6)+

				; DESTINATION FLAGS - to control pixel steppng etc
	move.l	#(PITCH2|PIXEL16|WID320|XADDPIX),A2_FLAGS

				; SOURCE PIXEL INCREMENT AND FRACTIONAL INCREMENT

	asl.l	#8,d3			; push z up to give 16.16 fraction for blitter
	move.l	d3,d0			; make a copy
	swap	d0			; make d0 high word = fractional part
	clr.w	d3			; clear what will be the y inc
	clr.w	d0			; and the fractional y inc
	swap	d3			; re-order into correct y:x ordering
	swap	d0
	move.l	d3,A1_INC		; and output to blitter
	move.l	d0,A1_FINC

.iif Trace_on,	move.l	d3,(a6)+
.iif Trace_on,	move.l	d0,(a6)+


				; SOURCE PIXEL START CO-ORDINATES (from clip offsets in destination and pixel increments)

	move.l	bitmap_xoff.w,d1	; get clip offset value
	beq.b	.nox
	bsr	special_32bit_multiply
.nox:	move.l	d1,d4			; temporary holding place

	move.l	bitmap_yoff.w,d1	; now do same for y offset
	beq.b	.noy
	bsr	special_32bit_multiply

.noy:	swap	d4			; put x high in low part
	eor.w	d4,d1
	eor.w	d1,d4
	eor.w	d4,d1			; exchange low parts
	swap	d4			; and make d4 into lowy:lowx

	move.l	d1,A1_PIXEL
	move.l	d4,A1_FPIXEL

.iif Trace_on,	move.l	d1,(a6)+
.iif Trace_on,	move.l	d4,(a6)+

				; SOURCE PIXEL STEP AND FRACTIONAL STEP (ie between lines)

	move.l	bitmap_width.w,d1
	clr.w	d1			; remove low part so that the result of n steps is calculated
	bsr	special_32bit_multiply	; where n is the number in BCOUNT

	neg.l	d1			; negate because I want it to go back a line and down an increment
	swap	d0			; put y:low into high word
	move.w	d1,d0			; put x:low in with it
	swap	d1
	swap	d3
	move.w	d1,d3			; put x:high in with y:high

	move.l	d3,A1_STEP
	move.l	d0,A1_FSTEP

.iif Trace_on,	move.l	d3,(a6)+
.iif Trace_on,	move.l	d0,(a6)+

				; SOURCE FLAGS - including variable width

	move.l	#(PITCH1|PIXEL16|XADDINC),d0
	or.w	(a0)+,d0		; bring in the bitmap width
	move.l	d0,A1_FLAGS


	moveq.l	#0,d4

	move.l	d4,B_PATD
	move.l	d4,B_PATD+4

	move.l	(a0)+,A1_BASE

	move.l	screen.w,d0
;	asl.w	#3,d0
	add.l	#obj_store,d0
	move.l	d0,A2_BASE

.iif Trace_on,	move.l	d0,(a6)+

; ** optional clipping for A1 - maybe no necessary
;	move.l	-10(a0),d0	; gets x,y together
;	swap	d0
;	move.l	d0,A1_CLIP

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

	rts




special_32bit_multiply:		; multiplying an offset (not zero) by a 16.16 bit positive value
				; where 16.16 value is in d0.w (high) and d3.w (low)

	move.l	d1,d7		; copy for multiple uses
	move.l	d1,d2

	swap	d1		; make d1 = high part
	mulu	d3,d1		; high * high
	swap	d1		; push up - don't expect overflow here

	mulu	d3,d2		; high * low
	add.l	d2,d1

	move.l	d7,d2		; recover original
	swap	d2		; use high part
	mulu	d0,d2		; low * high
	add.l	d2,d1

	mulu	d0,d7		; use copy
	move.l	d7,d2		; prepare for adding in
	clr.w	d2
	swap	d2
	add.l	d2,d1		; done

	move.l	d7,d2		; remainder
	swap	d2
	clr.w	d2

	rts
.endif
