*-------------------------------------------------------*
*	fVDI->driver interface (assembly routines)	*	
*-------------------------------------------------------*
doaline		equ	0	; Do actual drawing w/ linea (still clip)
both		equ	1	; Write in both FastRAM and on screen
upto8		equ	0	; Handle 8 bit drawing

	include		"..\vdi.inc"
	ifne	doaline
	include		"linea.inc"
	endc


	xdef		_display_lines
	xdef		_display_pline
	xdef		_line
	xdef		_set_pixel
	xdef		_get_pixel
	xdef		_expand
	xdef		_fill
	xdef		_blit
	xdef		_text
	xdef		_set_palette
	xdef		_initialize_palette
	xdef		get_colour

	xref		line_draw,write_pixel,read_pixel,expand_area
	xref		fill_area,blit_area,text_area,set_colours
	xref		_colour


	dc.b		"set_pixel",0
*---------
* Set a coloured pixel
* In:	a0	VDI struct, destination MFDB
*	d0	colour
*	d1	x
*	d2	y
* Call:	a1	VDI struct, destination MFDB
*	d0	colour
*	d1	x
*	d2	y
*---------
_set_pixel:
set_pixel:
	movem.l		d0-d7/a0-a6,-(sp)	; Used to have -3/4/6 for normal/both/upto8

	move.l		a0,a1

	ifeq	doaline
	bsr		write_pixel
	endc
	ifne	doaline
	bsr		get_colour
	move.l		(a1),a1
	move.l		vwk_real_address(a1),a1
	move.l		wk_screen_linea(a1),a0
	move.w		d1,x1(a0)
	move.w		d2,y1(a0)
	move.l		a2,colbit0(a0)	; Two at once
	move.l		a3,colbit2(a0)	; Two at once
	dc.w		$a001
	endc

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


	dc.b		"get_pixel",0
*---------
* Get a coloured pixel
* In:	a0	VDI struct, source MFDB
*	d1	x
*	d2	y
* Call:	a1	VDI struct, source MFDB
*	d1	x
*	d2	y
* Out:	d0	line colour
*---------
_get_pixel:
get_pixel:
	movem.l		d1-d7/a0-a6,-(sp)	; Used to have -3/4/6 for normal/both/upto8

	move.l		a0,a1
	
	ifeq	doaline
	bsr		read_pixel
	endc
	ifne	doaline
	move.l		(a1),a1
	move.l		vwk_real_address(a1),a1
	move.l		wk_screen_linea(a1),a0
	move.w		d1,x1(a0)
	move.w		d2,y1(a0)
	dc.w		$a002
	endc

	movem.l		(sp)+,d1-d7/a0-a6
	rts


*----------
* Draw lines from a table (x1, y1, x2, y2, colour)
* In:	a0	VDI struct
*	a1	pointer to table
*	d0	number of lines
*	d1	x offset
*	d2	y offset
*----------
_display_lines:
display_lines:
	movem.l		d0-d7/a0,-(a7)

	move.w		d0,d7
	move.w		d1,d5
	move.w		d2,d6

	bra		.lend

.loop:
	move.w		(a1)+,d1
	move.w		(a1)+,d2
	move.w		(a1)+,d3
	move.w		(a1)+,d4
	move.w		(a1)+,d0

	add.w		d5,d1
	add.w		d6,d2
	add.w		d5,d3
	add.w		d6,d4

	bsr		line

.lend:
	dbra		d7,.loop

	movem.l		(a7)+,d0-d7/a0
	rts


*----------
* Draw a polyline from a table (x, y)
* In:	a0	VDI struct
*	a1	pointer to table
*	d0	colour
*	d1	number of points
* Call:	d0	logic operation
*	d1/2	start coordinates
*	d3/4	end coordinates
*----------
_display_pline:
display_pline:
	movem.l		d0-d7/a0-a6,-(sp)	; Used to have -3/4/6 for normal/both/upto8

	move.w		d1,d7
	beq		.end

	subq.w		#1,d7

	bsr		get_colour

	exg		a0,a1
	move.l		(a1),a1
	move.w		vwk_mode(a1),d0
	move.l		vwk_real_address(a1),a1

	bra		.lend

.loop:
	move.w		(a0)+,d1	; Clipping destroys
	move.w		(a0)+,d2	;  coordinates, so we
	move.w		(a0),d3		;  can't use those
	move.w		2(a0),d4	;  read last time

; This must be done _somewhere_!
;	bsr		clip

	movem.l		d7/a0,-(a7)
	ifeq	doaline
	bsr		line_draw
	endc
	ifne	doaline
	move.l		wk_screen_linea(a1),a0
	move.w		d1,x1(a0)
	move.w		d2,y1(a0)
	move.w		d3,x2(a0)
	move.w		d4,y2(a0)

	move.l		a2,colbit0(a0)	; Two at once
	move.l		a3,colbit2(a0)	; Two at once

	dc.w		$a003
	endc
	movem.l		(a7)+,d7/a0

.lend:
	dbra		d7,.loop

.end:
	movem.l		(a7)+,d0-d7/a0-a6
	rts


	dc.b		"line"
*---------
* Draw a colored line between 2 points
* In:	a0	VDI struct
*	d0	colour
*	d1	x1
*	d2	y1
*	d3	x2
*	d4	y2
* Call:	a1	workstation
*	d0	logic operation
*	d1/2	start coordinates
*	d3/4	end coordinates
* 	a2-a3	first four colour bits
*	a5-a6	last four colour bits (only when 'upto8')
*---------
_line:
line:
	movem.l		d0-d7/a0-a6,-(sp)	; Used to have -3/4/6 for normal/both/upto8

	move.l		vwk_real_address(a0),a1

	bsr		get_colour	; Bad idea for anything but bitplanes!

	move.w		vwk_mode(a0),d0	; Probably not a good idea to do here

	ifeq	doaline
	bsr		line_draw
	endc
	ifne	doaline
	move.l		wk_screen_linea(a1),a0
	move.w		d1,x1(a0)
	move.w		d2,y1(a0)
	move.w		d3,x2(a0)
	move.w		d4,y2(a0)

	move.l		a2,colbit0(a0)	; Two at once
	move.l		a3,colbit2(a0)	; Two at once

	dc.w		$a003
	endc

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


	dc.b		"expand"
*---------
* Expand a monochrome area to multiple bitplanes
* In:	a0	VDI struct, destination MFDB, VDI struct, source MFDB
*	d0	colour
*	d1-d2	x1,y1 source
*	d3-d6	x1,y1 x2,y2 destination
*	d7	logic operation
* Call:	d0	height and width to move (high and low word)
*	d1-d2	source coordinates
*	d3-d4	destination coordinates
*	d6	background and foreground colour
*	d7	logic operation
*---------
_expand:
expand:
	movem.l		d0-d7/a0-a6,-(sp)	; Used to have -3(/6)/4(/6)/6 for normal/both/upto8

	move.l		a0,a1

	exg		d0,d6
	sub.w		d4,d0
	addq.w		#1,d0
	swap		d0
	move.w		d5,d0
	sub.w		d3,d0
	addq.w		#1,d0

	ifeq	doaline
	bsr		expand_area
	endc
	ifne	doaline
;	move.l		(a1),a1
;	move.l		vwk_real_address(a1),a1
;	move.l		wk_screen_linea(a1),a0
;	move.w		d1,x1(a0)
;	move.w		d2,y1(a0)
;	move.l		a2,colbit0(a0)	; Two at once
;	move.l		a3,colbit2(a0)	; Two at once
;	dc.w		$a001
	endc

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


	dc.b		"fill"
*---------
* Fill a multiple bitplane area using a monochrome pattern
* In:	a0	VDI struct
*	d0	colour
*	d1-d4	x1,y1 x2,y2 destination
*	d5	pattern address
* Call:	a1	VDI struct
*	d0	height and width to fill (high and low word)
*	d1-d2	destination coordinates
*	d3	pattern address
*	+colour in a really dumb way...
*---------
_fill:
fill:
	movem.l		d0-d7/a0-a6,-(sp)	; Used to have -3/4/6 for normal/both/upto8

	move.l		a0,a1

; The colour fetching has been expanded to put the address
; of the background colour on the stack.
; That's needed for non-solid replace mode.
; None of this is any kind of good idea except for bitplanes!

; ******************** Should probably use get_colour like the rest **************
	lea		_colour,a3
	ifne	upto8
;	move.w		d0,d5
;	lsr.w		#1,d5		; (d5 >> 4) << 3
;	and.w		#$0078,d5
;	move.l		(a3,d5.w),a5
;	move.l		4(a3,d5.w),a6
	move.l		d0,d5
	lsr.l		#1,d5		; (d5 >> 4) << 3
	and.l		#$00780078,d5
	swap		d5
	pea		(a3,d5.w)
	swap		d5
	move.l		(a3,d5.w),a5
	move.l		4(a3,d5.w),a6
	endc
;	and.w		#$000f,d0
;	lsl.w		#3,d0
;	move.l		(a3,d0.w),a2
;	move.l		4(a3,d0.w),a3
	and.l		#$000f000f,d0
	lsl.l		#3,d0
	swap		d0
	pea		(a3,d0.w)
	swap		d0
	move.l		(a3,d0.w),a2
	move.l		4(a3,d0.w),a3

	move.w		d4,d0
	sub.w		d2,d0
	addq.w		#1,d0
	swap		d0
	move.w		d3,d0
	sub.w		d1,d0
	addq.w		#1,d0

	move.l		d5,d3

	ifeq	doaline
	bsr		fill_area
	endc
	ifne	doaline
;	move.l		(a1),a1
;	move.l		vwk_real_address(a1),a1
;	move.l		wk_screen_linea(a1),a0
;	move.w		d1,x1(a0)
;	move.w		d2,y1(a0)
;	move.l		a2,colbit0(a0)	; Two at once
;	move.l		a3,colbit2(a0)	; Two at once
;	dc.w		$a001
	endc

	ifeq	upto8
	addq.l		#4,a7
	endc
	ifne	upto8
	addq.l		#8,a7
	endc
	movem.l		(sp)+,d0-d7/a0-a6
	rts


	dc.b		"blit"
*---------
* Blit an area
* In:	a0	VDI struct, destination MFDB, VDI struct, source MFDB
*	d0	logic operation
*	d1-d2	x1,y1 source
*	d3-d6	x1,y1 x2,y2 destination
* Call:	a1	VDI struct,destination MFDB, VDI struct, source MFDB
*	d0	height and width to move (high and low word)
*	d1-d2	source coordinates
*	d3-d4	destination coordinates
*	d5	logic operation
*---------
_blit:
blit:
	movem.l		d0-d7/a0-a6,-(sp)	; Used to have -3/4/6 for normal/both/upto8

	move.l		a0,a1

	move.l		d0,d7

	move.w		d6,d0
	sub.w		d4,d0
	addq.w		#1,d0
	swap		d0
	move.w		d5,d0
	sub.w		d3,d0
	addq.w		#1,d0

	ifeq	doaline
	bsr		blit_area
	endc
	ifne	doaline
;	move.l		(a1),a1
;	move.l		vwk_real_address(a1),a1
;	move.l		wk_screen_linea(a1),a0
;	move.w		d1,x1(a0)
;	move.w		d2,y1(a0)
;	move.l		a2,colbit0(a0)	; Two at once
;	move.l		a3,colbit2(a0)	; Two at once
;	dc.w		$a001
	endc

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


	dc.b		"text"
*---------
* Draw some text
* In:	a0	VDI struct
*	a1	string address
*	d0	string length
*	d1	x1,y1 destination
* Call:	a1	VDI struct
*	d0	string length
*	d3-d4	destination coordinates
*	a4	string address
*---------
_text:
text:
	movem.l		d2-d7/a3-a6,-(sp)

	move.l		a1,a4
	move.l		a0,a1

	move.w		d1,d4
	swap		d1
	move.w		d1,d3

	ifeq	doaline
	bsr		text_area
	endc
	ifne	doaline
;	move.l		(a1),a1
;	move.l		vwk_real_address(a1),a1
;	move.l		wk_screen_linea(a1),a0
;	move.w		d1,x1(a0)
;	move.w		d2,y1(a0)
;	move.l		a2,colbit0(a0)	; Two at once
;	move.l		a3,colbit2(a0)	; Two at once
;	dc.w		$a001
	endc

	movem.l		(sp)+,d2-d7/a3-a6
	rts


	dc.b		"set_palette",0
*---------
* Set palette colours
* In:	a0	VDI struct
*	d0	number of entries, start entry
*	a1	requested colour values (3 word/entry)
*	a2	colour palette
*---------
_set_palette:
set_palette:
	movem.l		d0-d7/a0-a6,-(sp)	; Overkill

	ifeq	doaline
	bsr		set_colours
	endc
	ifne	doaline
	bsr		get_colour
	move.l		(a1),a1
	move.l		vwk_real_address(a1),a1
	move.l		wk_screen_linea(a1),a0
	move.w		d1,x1(a0)
	move.w		d2,y1(a0)
	move.l		a2,colbit0(a0)	; Two at once
	move.l		a3,colbit2(a0)	; Two at once
	dc.w		$a001
	endc

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


	dc.b		"initialize_palette"
*---------
* Set palette colours
* initialize_palette(Virtual *vwk, int start, int n, int requested[][3], Colour palette[])
* To be called from C
*---------
_initialize_palette:
	movem.l		d0-d7/a0-a6,-(sp)	; Overkill

	move.l		15*4+4(a7),a0
	move.l		15*4+8(a7),d1
	move.l		15*4+12(a7),d0
	swap		d0
	move.w		d1,d0
	move.l		15*4+16(a7),a1
	move.l		15*4+20(a7),a2

	bsr		set_colours

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


*---------
* Get colour masks
* get_colour(int colour)
* In:	d0	background colour, foreground colour
* Out:	a2-a3	First four colour bits
*	a5-a6	Last four colour bits (only when 'upto8')
* XXX:	d0
*---------
get_colour:
	lea		_colour,a3
	ifne	upto8
	move.w		d0,a2
	lsr.w		#1,d0		; (d5 >> 4) << 3
	and.w		#$0078,d0
	move.l		(a3,d0.w),a5
	move.l		4(a3,d0.w),a6
	move.w		a2,d0
	endc
	and.w		#$000f,d0
	lsl.w		#3,d0
	move.l		(a3,d0.w),a2
	move.l		4(a3,d0.w),a3
	rts

	end
