
; Listing17c2.s = plasma2.s
; Plasma2.s	Plasma RGB 0-Bitplanes
; linke Taste zum Beenden

	SECTION	PLASMA,CODE

;	Include	"DaWorkBench.s"		; entferne das; vor dem Speichern mit "wo"

*****************************************************************************
	include	"/Sources/startup2.s"		; speichern Copperlist etc.
*****************************************************************************

			;5432109876543210
DMASET	equ	%1000001111000000	; Copper,Bitplane,Blitter DMA

WaitDisk	equ	10

WidthPlasma	equ	40				; Plasmabreite ausgedrückt
								; als Anzahl der Gruppen von 8 Pixeln

BytesPerLine	equ	(WidthPlasma+2)*4	; Anzahl der belegten Bytes
								; in der Copperliste von jeder Zeile
								; des Plasmas: jede 
								; Copper Anweisung belegt 4 Bytes

HighPlasma	equ	190				; Plasmahöhe ausgedrückt
								; als Anzahl der Zeilen

NewColR	equ	-2					; Wert zum Index R in der SinTab zwischen
								; einer Farbe und der andere hinzugefügt
								; Es kann zum Erhalten verschiedener Plasmen 
								; variiert werden, aber es MUSS IMMER GERADE SEIN !!

NewFrameR	equ	8				; Wert vom Index R abgezogen
								; SinTab zwischen einem Frame und einem anderen
								; Es kann zum Erhalten verschiedener Plasmen 
								; variiert werden, aber es MUSS IMMER GERADE SEIN !!

NewColG	equ	2					; wie "NewColR", aber für Komponente G
NewFrameG	equ	2				; wie "NewFrameR" aber für Komponente G

NewColB	equ	4					; wie "NewColR" aber für Komponente B
NewFrameB	equ	-6				; wie "NewFrameR" aber für Komponente B


Start:
	lea	$dff000,a5				; Custom Register Base in a5

	bsr	InitPlasma				; initialisiert die Copperlist

; Initialisieren der Blitter-Register

	btst	#6,2(a5)
WaitBlitInit:
	btst	#6,2(a5)			; auf den Blitter warten
	bne.s	WaitBlitInit

	move.l	#$4ffe8000,$40(a5)	; BLTCON0/1 - D=A+B+C
								; shift A = 4 pixel
								; shift B = 8 pixel
					
	moveq	#-1,d0				; d0 = $FFFFFFFF
	move.l	d0,$44(a5)			; BLTAFWM/BLTALWM

mod_A	set	0					; modulo Kanal A
mod_D	set	2					; modulo Kanal D: nächste Spalte

	move.l	#mod_A<<16+mod_D,$64(a5)	; Modulo-Register laden

; modulo Kanäle B und C = 0

	moveq	#0,d0
	move.l	d0,$60(a5)			; schreibt BLTBMOD und BLTCMOD


; Initialisierung andere Hardware Register

	move.w	#DMASET,$96(a5)		; DMACON - aktivieren Bitplane, Copper
	move.l	#Copperlist1,$80(a5)	; Zeiger Copperlist
	move.w	d0,$88(a5)			; Start Copperlist
	move.w	#0,$1fc(a5)			; AGA "deaktivieren"
	move.w	#$c00,$106(a5)		; AGA "deaktivieren"
	move.w	#$11,$10c(a5)		; AGA "deaktivieren"
	move.w	#$000,$180(a5)		; COLOR00 - schwarz
	move.w	#$0200,$100(a5)		; BPLCON0 - keine Bitplanes aktiviert

Mouse:
	move.l	#$1ff00,d1			; Bits durch UND auswählen
	move.l	#$13000,d2			; warte auf Zeile $130 (304)
WaitY1:
	move.l	4(a5),d0			; VPOSR und VHPOSR - $dff004/$dff006
	and.l	d1,d0				; wählen Sie nur die Bits der vertikalen Pos.
	cmp.l	D2,d0				; warte auf Zeile $130 (304)
	bne.s	WaitY1

	bsr.s	SwapClists			; Copperlist austauschen

	bsr.s	DoPlasma

	btst	#6,$bfe001			; Maus gedrückt?
	bne.w	Mouse
	rts

;****************************************************************************
; Diese Routine realisiert den "double buffer" zwischen den Copperlisten.
; In der Praxis beginnt es, wo es gezeichnet wird, und visualisiert
; es durch Kopieren der Adresse in COP1LC. Tauschen Sie die Variablen so aus,
; dass im folgenden frame auf der anderen Copperlist gezeichnet wird. 
;****************************************************************************

SwapClists:
	move.l	DrawClist(pc),d0	; Adresse clist auf dem es geschrieben wird
	move.l	ViewClist(pc),DrawClist	; austauschen clists
	move.l	d0,ViewClist

	move.l	d0,$80(a5)			; kopiere die Adresse der Copperlist
								; in COP1LC damit es
								; im nächsten Frame angezeigt wird 
	rts


;****************************************************************************
; Diese Routine initialisiert die Copperliste, die das Plasma erzeugt. System
; WAIT Anweisungen und die erste Hälfte des COPPERMOVE. Am Ende der Zeile
; des Plasmas wird ein letzter COPPERMOVE eingefügt, der die Farbe 
; schwarz in COLOR00 lädt.
;****************************************************************************

InitPlasma:
	lea	Plasma1,a0				; Adresse Plasma 1
	lea	Plasma2,a1				; Adresse Plasma 2
	move.l	#$383dfffe,d0		; Laden Sie die erste wait Anweisung in $38.
								; warte in Zeile $38 und in horizontaler
								; Position $3c
	move.w	#$180,d1			; setzt die erste Hälfte eines Befehls in d1
								; "Copper move" in COLOR00 (=$dff180)

	move.w	#HighPlasma-1,d3	; Schleife für jede Zeile
InitLoop1:
	move.l	d0,(a0)+			; schreibt das WAIT - (clist 1)
	move.l	d0,(a1)+			; schreibt das WAIT - (clist 2)
	add.l	#$01000000,d0		; Wait ändern, um in der
								; nächsten Zeile zu warten

	moveq	#WidthPlasma,d2		; loop über die gesamte Breite
								; von Plasma + einmal pro
								; der letzte "Copper move" setzt
								; schwarz als Hintergrund zurück

InitLoop2:
	move.w	d1,(a0)+			; schreibt den ersten Teil des
								; "Copper move" - clist 1
	addq.l	#2,a0				; Platz für den zweiten Teil
								; des "Copper move" - clist 1

	move.w	d1,(a1)+			; schreibt den ersten Teil des
								; "Copper move" - clist 2
	addq.l	#2,a1				; Platz für den zweiten Teil
								; des "Copper move" - clist 2
	dbra	d2,InitLoop2
	dbra	d3,InitLoop1	
	rts


;****************************************************************************
; Diese Routine macht das Plasma. Es macht jeweils eine Schleife von Blitts
; bei denen es eine "Zeile" des Plasmas schreibt, das heißt, es schreibt die
; Farben in COPPERMOVES-Reihen aneinander.
; Ein RGB-Plasma wird hergestellt. Die 3 Komponenten werden separat gelesen
; und zusammen "ge-OR-ed". Für die 3 Komponenten wird jedoch nur eine einzige 
; Tabelle verwendet. Es wird von verschiedenen Positionen gelesen und mit
; unterschiedlichen Geschwindigkeiten zwischen einer Linie und einer anderen
; und zwischen einem Frame und einem anderen "gefahren". Auf diese Weise ist
; es wie mit 3 verschiedenen Tabellen.
; Die Tabelle enthält tatsächlich die Werte der R-Komponente. Bei den Werten
; der anderen Komponenten müssen die gelesenen Daten verschoben werden
; 4 nach rechts für G und 8 für B. Dies geschieht "on the fly" vom
; Blitter Shifter.
;****************************************************************************

DoPlasma:
	lea	Color,a0				; Adresse Farben
	lea	SinTab,a6				; Adresse Tabelle offsets
	move.l	DrawClist(pc),a1	; Adresse Copperlist schreiben
	lea	22(a1),a1				; fügt Offset hinzu, das benötigt wird um
								; auf das erste Wort der ersten
								; Plasmalinie zu zeigen
								; (Sie müssen die 4 Anweisungen überspringen
								; die Start-of-Line-Wartezeit
								; und das erste Wort des "Copper move")

; liest und ändert den Index der Komponente R

	move.w	IndexR(pc),d4		; liest den Startindex vom
								; vorherigen Frame
	sub.w	#NewFrameR,d4		; den Index in der Tabelle
								; aus dem vorherigen Frame ändern
	and.w	#$00ff,d4			; hält den Index im Bereich
								; 0 - 255 (Offset in einer Tabelle von
								; 128 words)
	move.w	d4,IndexR			; speichert den Startindex für
								; das nächste Bild

; liest und ändert den Index der Komponente G

	move.w	IndexG(pc),d5		; liest den Startindex vom
								; vorherigen Frame
	sub.w	#NewFrameG,d5		; den Index in der Tabelle
								; aus dem vorherigen Frame ändern
	and.w	#$00ff,d5			; hält den Index im Bereich
								; 0 - 255 (Offset in einer Tabelle von
								; 128 words)
	move.w	d5,IndexG			; speichert den Startindex für
								; das nächste Bild

; liest und ändert den Index der Komponente B

	move.w	IndexB(pc),d6		; liest den Startindex vom
								; vorherigen Frame
	sub.w	#NewFrameB,d6		; den Index in der Tabelle
								; aus dem vorherigen Frame ändern
	and.w	#$00ff,d6			; hält den Index im Bereich
								; 0 - 255 (Offset in einer Tabelle von
								; 128 words)
	move.w	d6,IndexB			; speichert den Startindex für
								; das nächste Bild

	move.w	#WidthPlasma<<6+1,d3	; Größe Blitt
								; Breite 1 word, Höhe gesamtes Plasma

	move.w	#HighPlasma-1,d2	; Schleife für die ganze Höhe

PlasmaLoop:						; Anfang loop Blitt

; Startadresse der Komponente R berechnen

	move.w	(a6,d4.w),d1		; liest Offset aus der Tabelle

	lea	(a0,d1.w),a2			; Startadresse = Adr. Farben
								; mehr Offset

; Startadresse der Komponente G berechnen

	move.w	(a6,d5.w),d1		; liest Offset aus der Tabelle

	lea	(a0,d1.w),a3			; Startadresse = Adr. Farben
								; mehr Offset

; Startadresse der Komponente B berechnen

	move.w	(a6,d6.w),d1		; liest Offset aus der Tabelle

	lea	(a0,d1.w),a4			; Startadresse = Adr. Farben
								; mehr Offset

	btst	#6,2(a5)
WaitBlit:
	btst	#6,2(a5)			; auf den Blitter warten
	bne.s	WaitBlit

	move.l	a2,$48(a5)			; BLTCPT - Adresse Quelle R
								; (kopiert wie es ist)
	move.l	a3,$50(a5)			; BLTAPT - Adresse Quelle G
								; (wird um 4 nach rechts verschoben)
	move.l	a4,$4C(a5)			; BLTBPT - Adresse Quelle B
								; (ist 8 nach rechts verschoben)
	move.l	a1,$54(a5)			; BLTDPT - Adresse Ziel
	move.w	d3,$58(a5)			; BLTSIZE

	lea	BytesPerLine(a1),a1		; zeigt auf die nächste Zeile von
								; "Copper moves" in der Copperlist

; Ändern des Index der Komponente R für die nächste Spalte

	add.w	#NewColR,d4			; Ändern des Index in der Tabelle
								; für die nächste Farbe

	and.w	#$00ff,d4			; hält den Index im Bereich
								; 0 - 255 (Offset in einer Tabelle von
								; 128 Wörter)

; Ändern des Index der Komponente G für die nächste Spalte

	add.w	#NewColG,d5			; Ändern des Index in der Tabelle
								; für die nächste Farbe

	and.w	#$00ff,d5			; hält den Index im Bereich
								; 0 - 255 (Offset in einer Tabelle von
								; 128 Wörter)

; Ändern des Index der Komponente B für die nächste Spalte

	add.w	#NewColB,d6			; Ändern des Index in der Tabelle
								; für die nächste Farbe

	and.w	#$00ff,d6			; hält den Index im Bereich
								; 0 - 255 (Offset in einer Tabelle von
								; 128 Wörter)
	dbra	d2,PlasmaLoop
	rts


; Diese 2 Variablen enthalten die Adressen der 2 Copperlisten

ViewClist:	dc.l	Copperlist1	; Adresse clist Visualisierung
DrawClist:	dc.l	Copperlist2	; Adresse clist Zeichnen


; Diese Variablen enthalten die Indexwerte für die erste Spalte

IndexR:	dc.w	0
IndexG:	dc.w	0
IndexB:	dc.w	0

; Diese Tabelle enthält die Offsets für die Startadresse in der
; Farbtabelle

SinTab:
	dc.w	$000e,$0010,$0010,$0010,$0012,$0012,$0012,$0014,$0014,$0014
	dc.w	$0014,$0016,$0016,$0016,$0018,$0018,$0018,$0018,$001a,$001a
	dc.w	$001a,$001a,$001a,$001a,$001c,$001c,$001c,$001c,$001c,$001c
	dc.w	$001c,$001c,$001c,$001c,$001c,$001c,$001c,$001c,$001c,$001c
	dc.w	$001a,$001a,$001a,$001a,$001a,$001a,$0018,$0018,$0018,$0018
	dc.w	$0016,$0016,$0016,$0014,$0014,$0014,$0014,$0012,$0012,$0012
	dc.w	$0010,$0010,$0010,$000e,$000e,$000c,$000c,$000c,$000a,$000a
	dc.w	$000a,$0008,$0008,$0008,$0008,$0006,$0006,$0006,$0004,$0004
	dc.w	$0004,$0004,$0002,$0002,$0002,$0002,$0002,$0002,$0000,$0000
	dc.w	$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
	dc.w	$0000,$0000,$0000,$0000,$0002,$0002,$0002,$0002,$0002,$0002
	dc.w	$0004,$0004,$0004,$0004,$0006,$0006,$0006,$0008,$0008,$0008
	dc.w	$0008,$000a,$000a,$000a,$000c,$000c,$000c,$000c
EndSinTab:

;****************************************************************************

	SECTION	GRAPHIC,DATA_C

; Wir haben 2 Copperlisten 

Copperlist1:
	dc.w	$3007,$fffe			; warte auf Zeile $30
	dc.w	$0180,$c00			; color0
	dc.w	$3407,$fffe			; warte auf Zeile $34
	dc.w	$0180,$000			; color0

; Hier bleibt etwas Platz für das Stück Copperliste, dass das Plasma erzeugt.
; Dieser Raum wird von den Routinen die den Effekt erstellen ausgefüllt.

Plasma1:
	dcb.b	HighPlasma*BytesPerLine,0

	dc.w	$fa07,$fffe			; warte auf Zeile $fa
	dc.w	$0180,$c00			; color0
	dc.w	$fe07,$fffe			; warte auf Zeile $fe
	dc.w	$0180,$000			; color0

	dc.w	$ffff,$fffe			; Ende der Copperlist

;****************************************************************************

Copperlist2:
	dc.w	$3007,$fffe			; warte auf Zeile $30
	dc.w	$0180,$c00			; color0
	dc.w	$3407,$fffe			; warte auf Zeile $34
	dc.w	$0180,$000			; color0

; Hier bleibt etwas Platz für das Stück Copperliste, dass das Plasma erzeugt.
; Dieser Raum wird von den Routinen die den Effekt erstellen ausgefüllt.

Plasma2:
	dcb.b	HighPlasma*BytesPerLine,0

	dc.w	$fa07,$fffe			; warte auf Zeile $fa
	dc.w	$0180,$c00			; color0
	dc.w	$fe07,$fffe			; warte auf Zeile $fe
	dc.w	$0180,$000			; color0

	dc.w	$ffff,$fffe			; Ende der Copperlist


;****************************************************************************
; Hier ist die Tabelle, aus der die Farbkomponenten gelesen werden.
; Die Tabelle enthält die Komponenten R. Um die Komponenten G und B zu erhalten
; ist es ausreichend, die mit dem Blitter gelesenen Daten zu verschieben.
; Es müssen genügend Werte vorhanden sein, um unabhängig von der Start-Adresse
; gelesen werden zu können. In diesem Beispiel kann die Startadresse von der
; "Farbe" (erste Farbe) bis "Farbe + 28" (14. Farbe) abweichen, weil
; 60 der maximale Versatz ist, der in der "SinTab" enthalten ist.
; Wenn Width_plasm = 40 ist, bedeutet dies, dass jede Blittata 40 Werte liest.
; Insgesamt müssen also 54 Werte vorhanden sein.
;****************************************************************************

Color:
	dcb.w	2,0

	dc.w	$0100,$0300,$0500,$0600,$0800,$0a00,$0b00,$0c00,$0d00,$0e00
	dc.w	$0f00,$0f00,$0f00,$0f00,$0f00,$0e00,$0d00,$0c00,$0b00,$0a00
	dc.w	$0800,$0600,$0500,$0300,$0100

	dcb.w	2,0

	dc.w	$0100,$0300,$0500,$0600,$0800,$0a00,$0b00,$0c00,$0d00,$0e00
	dc.w	$0f00,$0f00,$0f00,$0f00,$0f00,$0e00,$0d00,$0c00,$0b00,$0a00
	dc.w	$0800,$0600,$0500,$0300,$0100

	end

;****************************************************************************

In diesem Beispiel sehen wir ein RGB-Plasma.
Angesichts der Größe des Plasmas und der Komplexität des Blitts (3-Kanal)
wäre es nicht möglich, die gesamte Copperliste vor dem Ende des vertical blank
zu ändern und folglich wird ein Teil der Copperliste zuerst angezeigt bevor es
geändert worden ist. Um das Problem zu lösen, müssen Sie das "double buffering"
von Copperlisten verwenden. Dies ist eine Technik, die wir bereits im Beispiel
Listing11i2.s gesehen haben: Es werden 2 Copperlisten verwendet, die
abwechselnd angezeigt werden. Während eine der 2 angezeigt wird, schreibt die
Plasma-Routine in die andere. Genau wie "double buffering" der Bitebenen. Der
Austausch der Copperlisten erfolgt routinemäßig durch "SwapClists".
Um das RGB-Plasma herzustellen, wird ein Blitt verwendet, der die separat
gelesenen R-, G- und B-Komponenten einer Farbe mit einer ODER-Operation
kombiniert. Um Speicherplatz zu sparen, wird nur eine Tabelle mit Komponenten
verwendet. Diese Tabelle enthält die Komponenten R. Um die Komponenten G und B
zu erhalten ist es ausreichend, die gelesenen Daten nach rechts zu verschieben,
eine Operation, die vom Blitter "on the fly" ausgeführt werden kann. Beachten
Sie jedoch, dass die Werte der Komponenten an verschiedenen Stellen aus der
Tabelle gelesen werden. In der Tat für jede Komponente haben wir einen Index,
der separat inkrementiert wird (und mit einer unterschiedlichen
Geschwindigkeit).
In diesem Plasma wird der Blitt anders als es in plasm1.s zu sehen war "pro 
Zeile" auftreten. Jeder Blitt füllt eine Linie vom Plasma, während in plasma1.s 
jeder Blitt eine Spalte füllte.
