***********************************************************
* © 1992, Dancing Fool of Epsilon
*
* Using AsmOne, to make into executable:
* 1. Make sure that BOOT_BLOCK is EQU'ed to 0.
* 2. >a
* 3. >wo miniplasma
*
* Using AsmOne, to put on boot block:
* 1. Make sure that BOOT_BLOCK is EQU'ed to 1.
* 2. >a
* 3. >ws
* 4. RAM_PTR> Start
* 5. DISK_PTR> 0
* 6. LENGTH> 2
* 7. >cc
*
***********************************************************
* Why did I write this?
*
* Well, after spending several months trying to figure rgb plasma out (and
* finally getting it!), I got some source to an old Masters demo that had
* some zero bit plane plasma in it that looked a lot like this, only not
* as good, so I decided to make a boot block out of it.  After that, I
* decided to put the source out for the world to see, learn from, and laugh
* at.
*
* How does it work?
*
* This code is pretty much the same a any other plasma that uses bit planes.
* Zero bit plane plasma is a little bit different (and a lot faster), but looks
* crappy, so who cares? :^) Anyway, I set up four bit planes of the same bit
* map just a different offsets and scroll values.  Bit plane one is +4 into
* the bit map and has a scroll of 4, bit plane two is +6 and scroll of $c,
* bit plane 3 is +6 and scroll $c, and bit plane three is +8 and scroll of 4.
* Each frame you bit in a sine wave on the bit map "stripes".  Looking
* at this data shows that on any given scan line you will end up with the
* following bit patterns:
*
* bpl1 $00ff00ffff00ff0000ff00ffff00ff0000ff00ffff00ff0000ff00ffff00ff00
* bpl2 $  00ffff00ff0000ff00ffff00ff0000ff00ffff00ff0000ff00ffff00ff0000ff
* bpl3 $00ffff00ff0000ff00ffff00ff0000ff00ffff00ff0000ff00ffff00ff0000ff
* bpl4 $  ff00ff0000ff00ffff00ff0000ff00ffff00ff0000ff00ffff00ff0000ff00ff
*
* Across the scan line the color pattern is:
*
* color   13 6 11 5 2 9 4 10 13 6 11 5 2 9 4 10 13 6 11 5 2 9 4 10 ...
*
* So, even with four bitplanes only eight colors ever occour.  With this
* in mind, and knowing the maximum number of copper cycles per scan line,
* we know that these colors will repeat six times per raster.
*
* In standard plasma, which this is not, you would take the next value
* from your sine table and use that as an offset into your color bar.  Then,
* you blit your color bar into the first "column" of your copper list, and
* repeat for the other fourty-seven (a column is a color entry).  To do rgb
* plasma you would use all three blitter sources, one for each color component,
* and or them all together to obtain the correct values for your copper list.
*
* This plasma is a little bit different.  Instead of using a horizontal sine
* wave on my copper bars, I use a vertical sine wave.  This allows me to blit
* an entire raster at a time.  This is a little different approach from
* normal plasma, but it also takes less static space, which allows it to
* easily fit on a boot block.
*
* Do what ever you want with this source, just don't take credit for it!
* Contact me at (on InterNet):
*		idr@rigel.cs.pdx.edu
* Contact Epsilon at:
*		Epsilon
*		P.O.B. 1914
*		Beaverton, OR  97075-1914
*		U.S.A.
***********************************************************
* Equates
***********************************************************

BOOT_BLOCK	EQU	0	; 0 = normal executable, 1 = boot block

CUSTOM		EQU	$dff000	; custom chip base
CIA_A		EQU	$bfe001	; cia chip for left mouse button

S_SPEED		EQU	(2<<1)	; speed to 'scroll' copper(must be a mult of 2)
S_SIZE		EQU	72	; max scroll.  if you change the color data,
				;   then you may need to change this too.

ROWS		EQU	180	; number of plasma rasters (changeable)
COLS		EQU	6	; number of columns.  should be 6, but could
				;   be less.
COLORS		EQU	8	; number of color combinations that occour.
MOD		EQU	2	; size of 'move' instruction in copper list
AMP		EQU	$20	; amplitude of sine data.  if you change the
				;   sine data, you should change this.

MD2		EQU	(4*((COLS*COLORS)+1))	; size of one raster of
						;   clist data
SIZE		EQU	((64*COLS*COLORS)+1)	; blit size for copper list

***********************************************************
* Macros
***********************************************************

WaitBlit	MACRO
		tst.b	(a5)		; ignore first test for old Agnus
.\@		btst	#6,(a5)		; test blit done bit in high byte of
					;   DMACON
		bne.b	.\@		; loop if not done
		ENDM

WaitVblank	MACRO
.\@		move.l	4-2(a5),d0	; read full beam position
		andi.l	#$0003ff00,d0	; mask of hoizontal position
		cmpi.l	#$00002c00,d0	; top of screen?
		bne.b	.\@		; not yet.
		ENDM

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

 IFNE	BOOT_BLOCK
Start:		dc.b	"DOS",0		; boot block id long work
		dc.l	0		; checksum
		dc.l	$370		; root block
 ELSE
	 	section	plasma_bb,code_c
 ENDIF

TakeSystem:
		movem.l	d1-d7/a1-a6,-(sp)
 IFEQ	BOOT_BLOCK
		movea.l	4.w,a6		; at boot this is already done!
 ENDIF
		move.l	#(size_of_list),d0
		move.l	#($10003),d1	; MEMF_CHIP | MEMF_PUBLIC | MEMF_CLEAR
		jsr	-198(a6)	; AllocMem()
		tst.l	d0		; did we get the mem?
		beq.w	err_exit	; nope.

		move.l	d0,a6		; ptr to mem.

		lea	sine(pc),a0	; sine table
		move.l	a0,sineptr(a6)	; initial sine ptr

		move.l	#CUSTOM+2,a5	; Custom chip base + 2!!!

		move.w	(a5),d0		; Save DMACON
		ori.w	#$8000,d0	; OR in the SET bit for later
		move.l	a6,a0
		move.w	d0,(a0)		; Keep it
		move.w	#$83c0,$96-2(a5); Turn on only certain DMA channels
		move.w	#$0020,$96-2(a5); kill sprite DMA

InstallPlasmaCopper:
		lea	Copper1(a6),a0	; pointer to our copper list
		move.l	a0,$80-2(a5)	; install it
	
		move.w	#$00e0,d0	; bpl1pth
		moveq	#7,d1		; loop counter
.make_bplpt:	move.w	d0,(a0)+	; write it to our copper list
		addq.w	#2,a0		; next in list
		addq.w	#2,d0		; next value
		dbra	d1,.make_bplpt	; loop
	
		sub.w	#30,a0		; a0 points to mapptrs + 2

		move.l	a6,d0		; data segment
		add.l	#PBmap+4,d0	; plasma map plus a bit

		move.w	d0,4(a0)	; bpl1ptl
		swap	d0		; high word in low half of register
		move.w	d0,(a0)		; bpl1pth

		swap	d0		; swap back
		addq.l	#2,d0		; in a bit more
		move.w	d0,12(a0)	; bpl2ptl
		move.w	d0,20(a0)	; bpl3ptl
		swap	d0		; high word in low word
		move.w	d0,8(a0)	; bpl2pth
		move.w	d0,16(a0)	; bpl3pth

		swap	d0		; swap back
		addq.l	#2,d0		; in some more
		move.w	d0,28(a0)	; bpl4ptl
		swap	d0		; guess why I do this. :^)
		move.w	d0,24(a0)	; bpl4pth

		lea	plasma_copper1(a6),a0	; raster data
	
		move.l	#$2d1ffffe,d1	; starting raster - 1
		move.w	#ROWS-1,d5	; number of rasters
m_plasma1:	add.l	#$01000000,d1	; next raster
		move.l	d1,(a0)+	; write raster wait to clist
		moveq	#COLS-1,d4	; number of columns
m_plasma2:	move.w	#$019a,(a0)+	; write each color out to clist
		addq.w	#2,a0		; next entry
		move.w	#$018c,(a0)+
		addq.w	#2,a0
		move.w	#$0196,(a0)+
		addq.w	#2,a0
		move.w	#$018a,(a0)+
		addq.w	#2,a0
		move.w	#$0184,(a0)+
		addq.w	#2,a0
		move.w	#$0192,(a0)+
		addq.w	#2,a0
		move.w	#$0188,(a0)+
		addq.w	#2,a0
		move.w	#$0194,(a0)+
		addq.w	#2,a0
		dbra	d4,m_plasma2	; loop for columns
		dbra	d5,m_plasma1	; loop for rasters

		moveq	#-2,d0		; end of clist
		move.l	d0,(a0)		; write it out

		moveq	#0,d4

	; the following are not in the clist to save space
		move.w	#$4200,$100-2(a5)	; bplcon0 (4 bit planes)
		move.w	#$00c4,$102-2(a5)	; fine scroll
		moveq	#$0008,d0		; modulo value
		move.w	d0,$0108-2(a5)		; write to clist
		move.w	d0,$010a-2(a5)		; ...
		move.w	#$2e78,$8e-2(a5)	; window start
		move.w	#$e2c6,$90-2(a5)	; window stop
		move.w	#$0028,$92-2(a5)	; data fetch start
		move.w	#$00d8,$94-2(a5)	; data fetch stop

Plasm2:		WaitVblank
		lea	PBmap(a6),a0		; bit map
		move.l	sineptr(a6),a4		; pointer to sine table
		lea	stripes(pc),a2		; "stripe data"
		move.l	a6,d2			; data seg
		add.l	#plasma_copper1+6,d2	; raster data

		move.w	#ROWS-1,d0	; loop counter
		move.l	#$09f00000,d3	; bltcon0 & bltcon1
		moveq	#$f,d5		; mask off upper bits
		moveq	#64+26,d6	; blit window

map_top:	tst.b	(a4)		; is it -1 ($ff)?
		bpl.b	.no_sine_reset	; nope
		lea	sine(pc),a4	; reset sine pointer
.no_sine_reset:	WaitBlit		; wait for it...

		move.l	a0,a3		; ptr to bit map

	; you can replace this with a move.b (a4),d1 and see what happens
		moveq	#AMP,d1		; amplitude of sine wave
		sub.b	(a4),d1		; less sine value

		lsr.w	#4,d1		; divide by 16 (nearest word offset)
		add.w	d1,d1		; word offset
		add.w	d1,a3		; add to bit map pointer
	
	; if you made above into a move.b (a4),d1 then do it here, too.
		moveq	#AMP,d1		; amplitude of sine wave
		sub.b	(a4),d1		; less sine value

		and.l	d5,d1		; mask off upper bits to make into
					; shift value
		ror.l	#4,d1		; put shift value in high nibble
		or.l	d3,d1		; or into bplcon

	; I'm only doing one line at a time, so the modulos
	;   are irrelevant.
		move.l	d1,$40-2(a5)	; bltcon0 & bltcon1
		move.l	#-1,$44-2(a5)	; first word mask
		movem.l	a2/a3,$50-2(a5)	; source
		move.w	d6,$58-2(a5)	; blit window

		adda.w	#54,a0		; next raster in bit map

		lea	color_list(pc),a1 ; Get start of color lists.
		move.b	(a4)+,d1	; sine value (again!)
		add.w	d1,d1		; word align.
		add.w	d4,a1		; gives copper a cool 'scrolly' effect
					;   try removing.
		add.w	d1,a1		; new position in color table (sine)

		moveq	#MOD,d1		; in the clist, this is how big the
					; first part of the 'move' is.
		WaitBlit
		move.l	d3,$40-2(a5)	; bltcon0 & bltcon1
		move.l	d1,$64-2(a5)	; dest mod.
		move.l	a1,$50-2(a5)	; source A
		move.l	d2,$54-2(a5)	; dest.
		move.w	#SIZE,$58-2(a5)	; bltsize

		add.l	#MD2,d2		; Next color in copper list.
		dbra	d0,map_top	; loop

end_frame:	lea	sineptr(a6),a1	; old sine ptr
		addq.l	#1,(a1)		; next place in sine table
	
		move.l	(a1),a1		; new sine ptr
		tst.b	(a1)		; is it -1?
		bpl.b	.no_sine_reset	; no.
		lea	sine(pc),a4	; reset sine pointer
		move.l	a4,sineptr(a6)	; reset sine prt

.no_sine_reset:	addq.w	#(S_SPEED),d4	; scroll speed
		cmpi.w	#(S_SIZE),d4	; past scroll limit?
		blt.b	.no_scroll_reset
		moveq	#0,d4		; reset copper scrolly value

.no_scroll_reset:
		btst.b	#6,CIA_A	; is lmb down?
		bne.w	Plasm2		; not yet...

		move.l	a6,a4
		movea.l	4.w,a6			; ExecBase
		lea	GraphicsName(pc),a1	; "graphics.library"
		jsr	-$198(a6)		; OldOpenLibrary()
		move.l	d0,a1			; Copy ptr to GfxBase
		move.l	$26(a1),$80-2(a5)	; Install old system copperlist
		jsr	-$19e(a6)		; CloseLibrary()

		move.l	a4,a1
		move.w	#$7fff,$96-2(a5)	; Kill all DMA!
		move.w	(a1),$96-2(a5)		; Activate old DMA channels

		move.l	#(size_of_list),d0	; size of block
		jsr	-$d2(a6)		; Free()

err_exit:	lea	DosName(pc),a1	; pointer to lib. name
		jsr	-$60(a6)	; FindResident()
		tst.l	d0		; error?
		beq.b	.error		; yes.
		move.l	d0,a0		; ptr to dos base
		move.l	$16(a0),a0	; pointer to dos lib
		moveq	#0,d0		; return no error
.exit:		movem.l	(sp)+,d1-d7/a1-a6
		rts			; Done

.error:		moveq	#-1,d0		; error code
		bra.b	.exit

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

stripes:dc.l	$00ff00ff,$ff00ff00,$00ff00ff,$ff00ff00,$00ff00ff,$ff00ff00
	dc.l	$00ff00ff,$ff00ff00,$00ff00ff,$ff00ff00,$00ff00ff,$ff00ff00
	dc.l	$00ff00ff

color_list:
	dc.l	$ff00ff0,$fe10fd2,$fc30fb4,$fa50f96,$f870f78,$f690f5a
	dc.l	$f4b0f3c,$f2d0f1e,$f0f0f0f,$f0f0f0f,$f1e0f2d,$f3c0f4b
	dc.l	$f5a0f69,$f780f87,$f960fa5,$fb40fc3,$fd20fe1,$ff00ff0
	dc.l	$ff00ff0,$fe10fd2,$fc30fb4,$fa50f96,$f870f78,$f690f5a
	dc.l	$f4b0f3c,$f2d0f1e,$f0f0f0f,$f0f0f0f,$f1e0f2d,$f3c0f4b
	dc.l	$f5a0f69,$f780f87,$f960fa5,$fb40fc3,$fd20fe1,$ff00ff0
	dc.l	$ff00ff0,$fe10fd2,$fc30fb4,$fa50f96,$f870f78,$f690f5a
	dc.l	$f4b0f3c,$f2d0f1e,$f0f0f0f,$f0f0f0f,$f1e0f2d,$f3c0f4b
	dc.l	$f5a0f69,$f780f87,$f960fa5,$fb40fc3,$fd20fe1,$ff00ff0
	dc.l	$ff00ff0,$fe10fd2,$fc30fb4,$fa50f96

; Sine table MUST end with a $ff!
sine:	dc.l	$10111213,$14161718,$191a1b1c,$1c1d1e1e,$1f1f1f1f,$1f1f1f1f
	dc.l	$1f1e1e1d,$1d1c1b1a,$19181716,$15141311,$10100f0e,$0c0b0a09
	dc.l	$08070605,$04030302,$02010101,$01010101,$01010202,$03040405
	dc.w	$0607,$0809,$0a0b,$0d0e,$0fff

GraphicsName:	dc.b	'graphics.library',0
DosName:	dc.b	'dos.library',0

message:	dc.b	"Not a virus! A plasma bb by the DF of Epsilon!"

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

		rsreset
DMACONSave	rs.w	1		; save DMA bits here
sineptr		rs.l	1

PBmap		rs.b	54*ROWS+100	; plasma bit map

Copper1		rs.b	0		; start of copper list
mapptrs		rs.w	16		; bmap pointer
plasma_copper1	rs.b	(4*(ROWS*(1+(COLS*COLORS))))	; raster data
pe_1		rs.w	2		; end of clist

size_of_list	rs.b	0		; duh! :^)
