***********************************************************
* Shade Bobs
*
* These little things are basically an implementation of the blitter
* to do addition.  If you think of each pixel as an 'n' bit number
* (where 'n' is your number of bitplanes) the idea is to add one to
* that number.  The logic is very simple.  First off you take your
* bob and the screen and 'and' them to a carry area.  Then you take
* your bob and 'xor' it to the proper bit plane.  Now you just
* continue this using your carry area as your bob for each bit plane.
* As you can see you'll need to carry areas.  This code is very easy
* and should be simple enough to follow.  Enjoy.
*
***********************************************************
* Includes
***********************************************************

		incdir	"DevpacAm:include/"
		include	"exec/exec_lib.i"
		include	"exec/execbase.i"
		include	"graphics/gfxbase.i"
		include	"graphics/graphics_lib.i"
		include	"hardware/custom.i"

***********************************************************
* Other Macros
***********************************************************

CALL		MACRO
		jsr	_LVO\1(a6)
		ENDM

WaitBlit:	macro
		tst.w	$2-2(a5)
.\@		btst.b	#6,$2-2(a5)
		bne.s	.\@
		endm
	
WRAST:		macro			; Wait for a scanline
.\@		move.l	$4-2(a5),d0
		lsr.l	#8,d0
		and.w	#$1FF,d0
		cmp.w	#\1,d0
		bne.b	.\@
		endm

***********************************************************
* Other Equates
***********************************************************

 IFND	gb_ActiView
gb_ActiView	EQU	32
 ENDIF

 IFND	gb_CopInit
gb_CopInit	EQU	36
 ENDIF

***********************************************************

		section	ShadeBobs,code

		bsr.w	TakeSystem
		bsr.w	START

		lea	Sine1,a3
		lea	Sine2,a4
		move.w	#$8400,$96-2(a5)

MAIN:		WRAST	$0f4

		move.l	x_ptr,a3
		move.l	y_ptr,a4

		cmp.l	xl_ptr,a3
		bne.b	.xok
		move.l	xr_ptr,a3
.xok:		cmp.l	yl_ptr,a4
		bne.b	.yok
		move.l	yr_ptr,a4
.yok:		moveq	#0,d0
		moveq	#0,d1
		move.b	(a3)+,d0
		move.b	(a4)+,d1
		add.w	d0,d0
		move.l	a3,x_ptr
		move.l	a4,y_ptr	
		bsr	ShadeBob

		moveq	#0,d0
		moveq	#0,d1
		move.b	10(a3),d0
		move.b	(a4),d1
		add.w	d0,d0
		bsr	ShadeBob

		moveq	#0,d0
		moveq	#0,d1
		move.b	(a3),d0
		move.b	10(a4),d1
		add.w	d0,d0
		bsr	ShadeBob

		btst	#6,$BFE001	; Left button pressed?
		bne.w	MAIN

		bsr.w	RestoreSystem
		rts

***********************************************************
* Shade Bob
* d0 : x
* d1 : y

ShadeBob:	WaitBlit
	
		movem.l	d0-d5/a0-a3,-(a7)
		move.l	d0,d2		; save x in d2
		lsr.w	#4,d2		; turn d2 into the word offset
		add.w	d2,d2		;   that contains the pixel at 'x'

		andi.l	#$f,d0		; turn d0 into a blitter shift
		ror.l	#4,d0		;   value

		mulu	#40,d1		; turn d1 into to offset into bmap
					;   that is the 'y' scan line
		add.w	d1,d2		; total offset

		lea	Bob,a0
		lea	Bmap,a1
		lea	Carry1,a2
		lea	Carry2,a3

		adda.l	d2,a1		; correct pos. in bmap for bob

		moveq	#0,d2		; modulo
		moveq	#$22,d3		; modulo
		move.w	#(31*64)+3,d5	; bltsize

		move.l	#$0ba00000,d4		; d = a eor c
		or.l	d0,d4
	
		WaitBlit
		move.l	a0,bltapt-2(a5)
		move.l	a1,bltcpt-2(a5)
		move.l	a2,bltdpt-2(a5)
		move.w	d3,bltcmod-2(a5)
		move.l	d2,bltamod-2(a5)	; no modulo
		move.l	d4,bltcon0-2(a5)
 		move.w	d5,bltsize-2(a5)

		move.l	#$0b5a0000,d4		; d = a and c
		or.l	d0,d4
	
		WaitBlit
		move.l	a0,bltapt-2(a5)
		move.l	a1,bltcpt-2(a5)
		move.l	a1,bltdpt-2(a5)
		move.w	d3,bltdmod-2(a5)
		move.l	d4,bltcon0-2(a5)
 		move.w	d5,bltsize-2(a5)

		adda.l	#8000,a1
		moveq	#3,d7
	
.1		move.w	#$0ba0,d4		; a = a eor c
		WaitBlit
		move.l	a2,bltapt-2(a5)
		move.l	a1,bltcpt-2(a5)
		move.l	a3,bltdpt-2(a5)
		move.w	d3,bltcmod-2(a5)
		move.l	d2,bltamod-2(a5)
		move.w	d4,bltcon0-2(a5)
 		move.w	d5,bltsize-2(a5)

		move.w	#$0b5a,d4		; a = a and c
	
		WaitBlit
		move.l	a2,bltapt-2(a5)
		move.l	a1,bltcpt-2(a5)
		move.l	a1,bltdpt-2(a5)
		move.w	d3,bltdmod-2(a5)
		move.w	d4,bltcon0-2(a5)
 		move.w	d5,bltsize-2(a5)

		adda.l	#8000,a1
		exg	a2,a3

		dbf	d7,.1

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

***********************************************************
* This is my TakeSystem and ResotreSystem routines that I now use
* in all my demos.  I am spreading them in hopes to get rid of the
* crapy coding pracitces that people have had since the C64 days.
* I'd like to thank Comrade J for his excelent "howtocode" files.
* A lot of the stuff here is based on his words of wisdom. :^).  Anyway,
* these routines, as of version 3.0, handle the following:
*		Getting the VBR.
*		Saving DMACON.
*		Saving and reseting WB view modes.
*		Owning/Disowning the blitter.
*		Pal/Ntsc/AGA modes.
*		Killing multitasking.
*		Killing interrupts.
*
***********************************************************

TakeSystem:	movea.l	4.w,a6		; exec base
		lea	$dff002,a5	; custom chip base + 2

		lea	GraphicsName,a1	; "graphics.library"
		moveq	#0,d0		; any version
		CALL	OpenLibrary	; open it.
		move.l	d0,gfx_base	; save pointer to gfx base
		beq.b	.exit		; if we got a NULL, then exit
		move.l	d0,a6		; for later callls...

		move.l  gb_ActiView(a6),OldView	; save old view

		move.w	#0,a1		; clears full long-word
		CALL	LoadView	; Open a NULL view (resets display
					;   on any Amiga)

		CALL	WaitTOF		; Wait twice so that an interlace
		CALL	WaitTOF		;   display can reset.

		CALL	OwnBlitter	; take over the blitter and...
		CALL	WaitBlit	;   wait for it to finish so we
					;   safely use it as we please.

		movea.l	4.w,a6		; exec base
		CALL	Forbid		; kill multitasking
		CALL	Disable		; kill interrupts so that we can
					;   safely install our own.

.pal:		move.w	$7c-2(a5),d0	; AGA register...
		cmpi.b	#$f8,d0		; are we AGA?
		bne.b	.not_aga	; nope.
		st	AGA		; set the AGA flag.

.not_aga:	move.w	dmaconr-2(a5),d0	; old DMACON bits
		ori.w	#$8000,d0	; or it set bit for restore
		move.w	d0,OldDMACon	; save it
.exit:		rts

***********************************************************

RestoreSystem:	lea	$dff002,a5	; custom chip base + 2
		move.w	OldDMACon,dmacon-2(a5)	; restore old dma bits

		move.l	OldView,a1	; old Work Bench view
		move.l	gfx_base,a6	; gfx base
		CALL	LoadView	; Restore the view
		CALL	DisOwnBlitter	; give blitter back to the system.

		move.l	gb_CopInit(a6),$80-2(a5) ; restore system clist
		move.l	a6,a1
		movea.l	4.w,a6		; exec base
		CALL	CloseLibrary

		movea.l	4.w,a6		; exec base
		CALL	Enable		; restore ints.
		CALL	Permit	 	; restart multitasking
		rts

***********************************************************

START:		lea	$dff002,a5

		bsr.b	InstallBmaps
		bsr.w	InstallSprites
		move.l	#Copper,$80-2(a5)	; New copperlist

		move.w	#$7FFF,$96-2(a5)	; kill all dma
		move.w	#$87E0,$96-2(a5)	; turn on what I need
		rts

***********************************************************

InstallBmaps:	lea	BmapPtrs+2,a0		; Insert planes in copper
		move.l	#Bmap+[0*200*40],d0
		move.w	d0,4(a0)
		swap	d0
		move.w	d0,(a0)

		move.l	#Bmap+[1*200*40],d0
		move.w	d0,12(a0)
		swap	d0
		move.w	d0,8(a0)

		move.l	#Bmap+[2*200*40],d0
		move.w	d0,20(a0)
		swap	d0
		move.w	d0,16(a0)

		move.l	#Bmap+[3*200*40],d0
		move.w	d0,28(a0)
		swap	d0
		move.w	d0,24(a0)

		move.l	#Bmap+[4*200*40],d0
		move.w	d0,36(a0)
		swap	d0
		move.w	d0,32(a0)

		move.l	#Bmap+[5*200*40],d0
		move.w	d0,44(a0)
		swap	d0
		move.w	d0,40(a0)
		rts

***********************************************************

InstallSprites:	move.l	#NullSpr,d0		; Insert sprites in copper
		lea	SprPtrs+2,a1
		move.w	d0,4(a1)
		move.w	d0,12(a1)
		move.w	d0,20(a1)
		move.w	d0,28(a1)
		move.w	d0,36(a1)
		move.w	d0,44(a1)
		move.w	d0,52(a1)
		move.w	d0,60(a1)
		swap	d0
		move.w	d0,(a1)
		move.w	d0,8(a1)
		move.w	d0,16(a1)
		move.w	d0,24(a1)
		move.w	d0,32(a1)
		move.w	d0,40(a1)
		move.w	d0,48(a1)
		move.w	d0,56(a1)
		rts

***********************************************************

		section	THEDATA,data_c	

Copper:	; Display size
	dc.l	$00920038,$009400D0,$008E2C81,$0090F4C1
	; Bplcon0, bplcon1, and modulos
	dc.l	$01005200,$01020000,$01080000,$010A0000
	; Sprite pointers
SprPtrs:dc.l	$01200000,$01220000,$01240000,$01260000,$01280000,$012A0000
	dc.l	$012C0000,$012E0000,$01300000,$01320000,$01340000,$01360000
	dc.l	$01380000,$013A0000,$013C0000,$013E0000
	; colors
	dc.l	$01800000,$01820003,$01840004,$01860005,$01880006,$018a0007
	dc.l	$018c0008,$018e0009,$0190000a,$0192000b,$0194000c,$0196000d
	dc.l	$0198000e,$019a000f,$019c020f,$019e030f,$01a0040f,$01a2050f
	dc.l	$01a4060f,$01a6070e,$01a8080d,$01aa090c,$01ac0a0b,$01ae0b0a
	dc.l	$01b00c09,$01b20d08,$01b40e07,$01b60f06,$01b80e35,$01ba0d44
	dc.l	$01bc0c53,$01be0b62
	; Bit Plane pointers
BmapPtrs:dc.l	$00E00000,$00E20000,$00E40000,$00E60000,$00E80000,$00EA0000
	dc.l	$00EC0000,$00EE0000,$00F00000,$00F20000,$00F40000,$00F60000
	dc.l	-2,-2

		incdir	''
Bob:		incbin	'ShadeStuff:circle.48.raw'

***********************************************************

		section	my_bum,data

GraphicsName:	GRAFNAME		; name of gfx library
		EVEN

x_ptr:		dc.l	Sine1
y_ptr:		dc.l	Sine2
xr_ptr:		dc.l	Sine1
yr_ptr:		dc.l	Sine2
xl_ptr:		dc.l	Sine1e
yl_ptr:		dc.l	Sine2e

	
Sine1:		incbin	'ShadeStuff:sine1'
Sine1e:		incbin	'ShadeStuff:sine1'
	
Sine2:		incbin	'ShadeStuff:sine2'
Sine2e:		incbin	'ShadeStuff:sine2'

***********************************************************

		section	thpt,bss_c

gfx_base	ds.l	1		; pointer to graphics base
OldView		ds.l    1		; old Work Bench view addr.
OldDMACon:	ds.w	1		; old dmacon bits

AGA:		ds.b	1		; 0 = ESC/standard, 1 = AGA
		even

NullSpr:	ds.l	16		; null sprite data

Carry1:		ds.w	31*3		; first carry pad
Carry2:		ds.w	31*3		; second carry pad
Bmap:		ds.b	8000*5		; screen buffer
