* $Id: graphics.s 1.7 1998/09/06 10:18:26 jah Exp jah $
**************************************************************************
*	GRAPHICS LIBRARY
**************************************************************************
**************************************************************************
*	INITIALIZATION
**************************************************************************

GFXINIT		move.l	_gfxbase,d0
		beq	.init
		rts

.init		move.l	#-_LVOBltBitMapRastPort,d0
		move.l	#242,d1
		lea	_gfxname,a0
		bsr	_InitLibrary
		move.l	d0,a0
		move.l	d0,_gfxbase
		
		patch	_LVOOwnBlitter(a0),MYRTS(PC)
		patch	_LVODisownBlitter(a0),MYRTS(PC)
		patch	_LVOInitView(a0),_InitView(PC)
		patch	_LVOInitVPort(a0),_InitVPort(PC)
		patch	_LVOInitBitMap(a0),_InitBitMap(PC)
		patch	_LVOInitRastPort(a0),_InitRastPort(PC)
		patch	_LVOMakeVPort(a0),_MakeVPort(PC)
		patch	_LVOMrgCop(a0),_MrgCop(PC)
		patch	_LVOLoadView(a0),_LoadView(PC)
		patch	_LVOLoadRGB4(a0),_LoadRGB4(PC)
		patch	_LVOSetRGB4(a0),_SetRGB4(PC)
		patch	_LVOFreeSprite(a0),_FreeSprite(PC)
		patch	_LVOGetSprite(a0),_GetSprite(PC)
		patch	_LVOChangeSprite(a0),_ChangeSprite(PC)
		patch	_LVOMoveSprite(a0),_MoveSprite(PC)
		patch	_LVOWaitBlit(a0),_WaitBlit(PC)
		patch	_LVOBltBitMap(a0),_BltBitMap(PC)
		patch	_LVOVBeamPos(a0),_VBeamPos(PC)
		patch	_LVODraw(a0),MYRTS(PC)
		patch	_LVOMove(a0),MYRTS(PC)
		patch	_LVOSetAPen(a0),MYRTS(PC)
		patch	_LVOSetDrMd(a0),MYRTS(PC)
		patch	_LVOWaitTOF(a0),_WaitTOF(PC)
		patch	_LVOReadPixel(a0),_ReadPixel(PC)
		patch	_LVOWritePixel(a0),_WritePixel(PC)
		patch	_LVOBltTemplate(a0),_BltTemplate(PC)

		lea	STDCOPPER(PC),a1
		MOVE.L	a1,(gb_LOFlist,A0)
		MOVE.L	a1,(gb_SHFlist,A0)
		MOVE.L	a1,(_custom+cop2lc)
		lea	CPJMP2,a1
		move.l	a1,(gb_copinit,a0)
		MOVE.L	a1,(_custom+cop1lc)

		moveq	#4,d0				;pal
		cmp.l	#PAL_MONITOR_ID,_monitor
		beq	.1
		moveq	#1,d0				;ntsc
.1		MOVE.W	d0,(gb_DisplayFlags,A0)

		clr.b	(gb_SpriteReserved,a0)

		clr.l	-(a7)				;TAG_DONE
		pea	(RESTORECOPPER2,pc)
		move.l	#WHDLTAG_CBSWITCH_SET,-(a7)
		move.l	a7,a0
		move.l	(_RESLOAD,pc),a1
		jsr	(resload_Control,a1)
		lea	(12,a7),a7                      ;restore sp
		
		tst.w	(_custom+copjmp1)
		move.w	#DMAF_SETCLR!DMAF_MASTER!DMAF_COPPER!DMAF_BLITTER,(_custom+dmacon)
 
		rts

RESTORECOPPER2	move.l	a1,.save
		move.l	_gfxbase,a1
		move.l	(gb_LOFlist,a1),(_custom+cop2lc)
		move.l	.save,a1
		jmp	(A0)

	CNOP 0,4
.save		dc.l	0
CPJMP2		dc.l	$0201fffe	;wait 0,2
		DC.L	$008A0000
STDCOPPER	DC.L	$FFFFFFFE

**************************************************************************
*	GRAPHICS LIBRARY FUNCTIONS
**************************************************************************

_InitView
_InitVPort
_InitRastPort	;blitz
		rts

_InitBitMap	;a0=bm d0=depth d1=width d2=height
		addq.w	#7,d1
		lsr.w	#3,d1
		move.w	d1,(bm_BytesPerRow,a0)
		move.w	d2,(bm_Rows,a0)
		clr.b	(bm_Flags,a0)
		move.b	d0,(bm_Depth,a0)
		clr.w	(bm_Pad,a0)
		move.l	#$bbbbbbbb,d1
		move.l	d1,(bm_Planes,a0)
		move.l	d1,(bm_Planes+4,a0)
		move.l	d1,(bm_Planes+8,a0)
		move.l	d1,(bm_Planes+12,a0)
		move.l	d1,(bm_Planes+16,a0)
		move.l	d1,(bm_Planes+20,a0)
		move.l	d1,(bm_Planes+24,a0)
		move.l	d1,(bm_Planes+28,a0)
		rts

_MakeVPort	;a0=view a1=viewport
		move.l	a2,-(a7)
		movem.l	a0-a1/a6,-(a7)
		move.l	#200,d0
		move.l	#MEMF_CHIP,d1
		move.l	(4),a6
		jsr	(_LVOAllocMem,a6)
		movem.l	(a7)+,a0-a1/a6
		tst.l	d0
		trapeq
		move.l	d0,a2				;A2 = coplist
		move.l	a2,(vp_DspIns,a1)
		move.l	(vp_RasInfo,a1),a0
		move.l	(ri_BitMap,a0),a0
		move.w	#diwstrt,(a2)+
		move.w	#$2981,d0
		move.w	d0,(a2)+
		move.w	#diwstop,(a2)+
		move.w	(bm_BytesPerRow,a0),d1
		lsl.w	#3,d1				;bytes -> pixel
		add.b	d1,d0
		move.w	(bm_Rows,a0),d1
		lsl.w	#8,d1
		add.w	d1,d0
		move.w	d0,(a2)+
		move.l	#ddfstrt<<16+$0038,(a2)+
		move.l	#ddfstop<<16+$00d0,(a2)+
		move.l	#bplcon1<<16,(a2)+
		move.l	#bpl1mod<<16,(a2)+
		move.l	#bpl2mod<<16,(a2)+
		move.w	#bplcon0,(a2)+
		moveq	#0,d0
		move.b	(bm_Depth,a0),d0
		ror.w	#4,d0
		or.w	#$200,d0
		move.w	d0,(a2)+
		move.b	(bm_Depth,a0),d0
		lea	(bm_Planes,a0),a0
		move.w	#bplpt,d1
.lp		move.w	d1,(a2)+
		addq.w	#2,d1
		move.w	(a0)+,(a2)+
		move.w	d1,(a2)+
		addq.w	#2,d1
		move.w	(a0)+,(a2)+
		subq.b	#1,d0
		bne	.lp
		move.l	#dmacon<<16+DMAF_SETCLR+DMAF_RASTER,(a2)+
		moveq	#-2,d0
		move.l	d0,(a2)+
		move.l	(a7)+,a2
		rts

_MrgCop		;a1=view
		move.l	(v_ViewPort,a1),a0
		move.l	(vp_DspIns,a0),(v_LOFCprList,a1)
		rts

_LoadView	;a1=view
		move.l	(v_LOFCprList,a1),d0
		move.l	d0,(gb_LOFlist,a6)
		move.l	d0,(_custom+cop2lc)
		rts

_LoadRGB4	;a0=viewport a1=colors d0=count
		bsr	_waitvb
		lea	(_custom+color),a0
.cpy		move.w	(a1)+,(a0)+
		subq.w	#1,d0
		bne	.cpy
		rts

_SetRGB4	;a0=viewport d0=pen d1=red d2=green d3=blue
	;	bsr	_waitvb
		lea	(_custom+color),a0
		ext.w	d0
		add.w	d0,a0
		add.w	d0,a0
		lsl.w	#4,d1
		or.w	d2,d1
		lsl.w	#4,d1
		or.w	d3,d1
		move.w	d1,(a0)
		rts

_VBeamPos	move.l	(_custom+vposr),d0
		lsr.l	#8,d0
		and.l	#$1ff,d0
		rts

_WaitTOF	waitvb
		rts

_ReadPixel	;d0=x d1=y a1=rastport
		move.l	(rp_BitMap,a1),a0
		ext.l	d0
		ror.l	#3,d0
		cmp.w	(bm_BytesPerRow,a0),d0
		bhs	.bad
		cmp.w	(bm_Rows,a0),d1
		bhs	.bad
		mulu	(bm_BytesPerRow,a0),d1
		add.w	d0,d1			;byte offset
		rol.l	#3,d0			;bit offset
		
		movem.l	d2-d4,-(a7)
		moveq	#0,d2
		moveq	#0,d3
		move.b	(bm_Depth,a0),d4
		lea	(bm_Planes,a0),a0
		
.next		move.l	(a0)+,a1
		btst	d0,(a1,d1.l)
		beq	.1
		bset	d2,d3
.1		addq.l	#1,d2
		cmp.b	d2,d4
		bhi	.next
		
		move.l	d3,d0
		movem.l	(a7)+,d2-d4
		rts

.bad		moveq	#-1,d0
		rts

_WritePixel	;d0=x d1=y a1=rastport
		move.l	(rp_BitMap,a1),a0
		ext.l	d0
		ror.l	#3,d0
		cmp.w	(bm_BytesPerRow,a0),d0
		bhs	.bad
		cmp.w	(bm_Rows,a0),d1
		bhs	.bad
		mulu	(bm_BytesPerRow,a0),d1
		add.w	d0,d1			;byte offset
		rol.l	#3,d0			;bit offset
		
		movem.l	d2-d4,-(a7)
		moveq	#0,d2
		move.b	(rp_FgPen,a1),d3
		move.b	(bm_Depth,a0),d4
		lea	(bm_Planes,a0),a0
		
.next		move.l	(a0)+,a1
		btst	d2,d3
		beq	.clear
.set		bset	d0,(a1,d1.w)
		bra	.1
.clear		bclr	d0,(a1,d1.w)
.1		addq.l	#1,d2
		cmp.b	d2,d4
		bhi	.next
		
		move.l	d3,d0
		movem.l	(a7)+,d2-d4
		rts

.bad		moveq	#-1,d0
		rts

**************************************************************************
*	SPRITES
**************************************************************************

_FreeSprite	;d0=pick
		bclr	d0,(gb_SpriteReserved,a6)
		rts

_GetSprite	;a0=sprite d0=pick
		tst.w	d0
		bmi	.any
		bset	d0,(gb_SpriteReserved,a6)
		bne	.error
.end		move.b	d0,(ss_num,a0)
		ext.l	d0
		rts

.error		moveq	#-1,d0
		rts

.any		cmp.b	(gb_SpriteReserved,a6),d0
		beq	.error
.next		addq.w	#1,d0
		bset	d0,(gb_SpriteReserved,a6)
		bne	.next
		bra	.end

_ChangeSprite	;a0=viewport a1=simplesprite a2=data
		moveq	#0,d0
		move.b	(ss_num,a1),d0
		lsl.w	#2,d0
		lea	(_sprites),a0
		move.l	a2,(a0,d0.w)
		move.w	#DMAF_SETCLR!DMAF_SPRITE,(_custom+dmacon)
		rts

_MoveSprite	;a0=viewport a1=simplesprite d0=x d1=y
		;129,41 top,left
		move.l	d2,-(a7)
		moveq	#0,d2
		move.b	(ss_num,a1),d2
		lsl.w	#2,d2
		lea	(_sprites),a0
		move.l	(a0,d2.w),a0
		add.w	#129,d0			;d0 hor
		add.w	#41,d1			;d1 top
		move.w	d1,d2
		add.w	(ss_height,a1),d2	;d2 bottom
		move.b	d1,(a0)+		;top7..top0
		ror.w	#1,d0
		move.b	d0,(a0)+		;hor8..hor1
		move.b	d2,(a0)+		;bot7..bot0
		lsr.w	#8,d1
		lsl.w	#7,d2
		addx.w	d2,d2
		addx.w	d1,d1
		addx.w	d0,d0
		addx.w	d1,d1
		move.b	d1,(a0)+
		move.l	(a7)+,d2
		rts

**************************************************************************
*	BLITTER
**************************************************************************

_WaitBlit
.wait		tst.b	(_ciaa)
		tst.b	(_ciaa)
		btst	#DMAB_BLTDONE-8,(_custom+dmaconr)
		bne.b	.wait
		tst.b	(_ciaa)
		rts

_BltBitMap	;a0=sbitmap d0=sx d1=sy
		;a1=dbitmap d2=dx d3=dy
		;d4=width d5=height d6=minterm d7=mask a2=buffer

		movem.l	d2-d7/a2-a3,-(a7)
		lea	(_custom),a3

		mulu	(bm_BytesPerRow,a0),d1
		ext.l	d0
		ror.l	#4,d0
		add.w	d0,d1
		add.w	d0,d1			;d1 = byte offset src

		mulu	(bm_BytesPerRow,a1),d3
		ext.l	d2
		ror.l	#4,d2
		add.w	d2,d3
		add.w	d2,d3			;d3 = byte offset dest

		lsl.w	#6,d5			;height
		
		and.w	#$00f0,d6
		or.w	#$070a,d6
		bsr	_WaitBlit
		move.w	d6,(bltcon0,a3)
		
		moveq	#-1,d6
		move.w	d6,(bltadat,a3)
		clr.w	d2
		rol.l	#4,d2			;d2 = amount of pixels to skip in the first word in dest
		lsr.w	d2,d6			;d6.w = afwm
		swap	d6
		addq.w	#1,d5			;d5 = width++ (the first word)
		sub.w	#16,d4
		add.w	d2,d4			;d4 = pixels left to copy
		ext.l	d4
		ror.l	#4,d4
		add.w	d4,d5			;d5.w = size
		clr.w	d4
		rol.l	#4,d4			;d4 = pixels left to copy (0..15)
		beq	.1
		addq.w	#1,d5			;d5 = width++ (the last word)
		lsr.w	d4,d6			;d6.w = ~(alwm)
		not.w	d6
.1		move.l	d6,(bltafwm,a3)
		
		clr.w	d0
		rol.l	#4,d0			;pixel offset src
		sub.w	d0,d2
	;	spl	d4			;d4 = 0 if first src word must be preloaded (dma-b)
		bpl	.2
	;this works only if the destination is word aligned !!!!!!
	;(in deuteros it is...) normally a second blit is neccessary in this case
		addq.w	#1,d5			;bltsize++
		subq.w	#2,d3			;dst-2
		move.w	#0,(bltafwm,a3)
		add.w	#16,d2
.2		ror.w	#4,d2
		move.w	d2,(bltcon1,a3)
		
		move.w	d5,d0
		and.w	#$003f,d0
		add.w	d0,d0
		move.w	(bm_BytesPerRow,a0),d2
		sub.w	d0,d2
		move.w	d2,(bltbmod,a3)
		move.w	(bm_BytesPerRow,a1),d2
		sub.w	d0,d2
		move.w	d2,(bltcmod,a3)
		move.w	d2,(bltdmod,a3)

		moveq	#0,d6
.do		btst	d6,d7			;mask ?
		beq	.next

		lsl.w	#2,d6
		move.l	(bm_Planes,a0,d6.w),a2
		add.l	d1,a2
		move.l	(bm_Planes,a1,d6.w),d0
		add.l	d3,d0
		bsr	_WaitBlit
		movem.l	d0/a2,(bltcpt,a3)
		move.l	d0,(bltdpt,a3)
		move.w	d5,(bltsize,a3)
		lsr.w	#2,d6

.next		addq.w	#1,d6
		cmp.b	(bm_Depth,a0),d6
		beq	.end
		cmp.b	(bm_Depth,a1),d6
		bne	.do
.end
		movem.l	(a7)+,d2-d7/a2-a3
		rts

_BltTemplate	;a0=src d0=bitoffset d1=modulo
		;a1=rp d2=x d3=y d4=width d5=height

		movem.l	d2-d7/a2-a3,-(a7)
		lea	(_custom),a3

		ext.l	d0
		ror.l	#4,d0
		add.w	d0,a0
		add.w	d0,a0			;a0 = src ptr

		move.l	(rp_BitMap,a1),a2
		mulu	(bm_BytesPerRow,a2),d3
		ext.l	d2
		ror.l	#4,d2
		add.w	d2,d3
		add.w	d2,d3			;d3 = byte offset dest

		lsl.w	#6,d5			;height
		
		bsr	_WaitBlit
		move.w	#$07aa,(bltcon0,a3)
		
		moveq	#-1,d6
		move.w	d6,(bltadat,a3)
		clr.w	d2
		rol.l	#4,d2			;d2 = amount of pixels to skip in the first word in dest
		lsr.w	d2,d6			;d6.w = afwm
		swap	d6
		addq.w	#1,d5			;d5 = width++ (the first word)
		sub.w	#16,d4
		add.w	d2,d4			;d4 = pixels left to copy
		ext.l	d4
		ror.l	#4,d4
		add.w	d4,d5			;d5.w = size
		clr.w	d4
		rol.l	#4,d4			;d4 = pixels left to copy (0..15)
		beq	.1
		addq.w	#1,d5			;d5 = width++ (the last word)
		lsr.w	d4,d6			;d6.w = ~(alwm)
		not.w	d6
.1		move.l	d6,(bltafwm,a3)
		
		clr.w	d0
		rol.l	#4,d0			;pixel offset src
		sub.w	d0,d2
	;	spl	d4			;d4 = 0 if first src word must be preloaded (dma-b)
		bpl	.2
	;this works only if the destination is word aligned !!!!!!
	;(in deuteros it is...) normally a second blit is neccessary in this case
		addq.w	#1,d5			;bltsize++
		subq.w	#2,d3			;dst-2
		move.w	#0,(bltafwm,a3)
		add.w	#16,d2
.2		ror.w	#4,d2
		move.w	d2,(bltcon1,a3)
		
		move.w	d5,d0
		and.w	#$003f,d0
		add.w	d0,d0
		move.w	d1,d2
		sub.w	d0,d2
		move.w	d2,(bltbmod,a3)
		move.w	(bm_BytesPerRow,a2),d2
		sub.w	d0,d2
		move.w	d2,(bltcmod,a3)
		move.w	d2,(bltdmod,a3)

		moveq	#0,d6
.do		lsl.w	#2,d6
		move.l	(bm_Planes,a2,d6.w),d0
		add.l	d3,d0
		bsr	_WaitBlit
		movem.l	d0/a0,(bltcpt,a3)
		move.l	d0,(bltdpt,a3)
		move.w	d5,(bltsize,a3)
		lsr.w	#2,d6

.next		addq.w	#1,d6
		cmp.b	(bm_Depth,a2),d6
		bne	.do

		movem.l	(a7)+,d2-d7/a2-a3
		rts

