
; Listing11l4.s	 - Welle der Figur, erhalten durch Ändern jeder Zeile
; Zeiger auf Bitplanes sowie die Nuance von COLOR00
; fließt nach oben.

	SECTION BITPLANE,CODE

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

*****************************************************************************
	include "/Sources/startup2.s"	; speichern interrupt, dma etc.
*****************************************************************************


; Mit DMASET entscheiden wir, welche DMA-Kanäle geöffnet und welche geschlossen werden sollen

			;5432109876543210
DMASET	equ	%1000001110000000	; nur Copper und Bitplane DMA

WAITDISK	equ	30				; 50-150 zur Rettung (je nach Fall)

SCRBYTES	= 40				; Anzahl der Bytes für jede horizontale Zeile.
								; Daraus berechnen wir die Bildschirmbreite,
								; Multiplizieren von Bytes mit 8: normaler Bildschirm 320/8 = 40
								; z.B. für einen 336 Pixel breiten Bildschirm 336/8 = 42
								; Beispielbreiten:
								; 264 pixel = 33 / 272 pixel = 34 / 280 pixel = 35
								; 360 pixel = 45 / 368 pixel = 46 / 376 pixel = 47
								; ... 640 pixel = 80 / 648 pixel = 81 ...

SCR_H		= 256				; Bildschirmhöhe in Zeilen
SCR_X		= $81				; Startbildschirm, XX-Position (normal $xx81) (129)
SCR_Y		= $2c				; Startbildschirm, YY-Position (normal $2cxx) (44)
SCR_RES		= 1					; 2 = HighRes (640*xxx) / 1 = LowRes (320*xxx)
SCR_LACE	= 0					; 0 = non interlace (xxx*256) / 1 = interlace (xxx*512)
HAM			= 0					; 0 = nicht HAM / 1 = HAM
SCR_BPL		= 1					; Anzahl Bitplanes

; Parameter automatisch berechnet

SCR_W		= SCRBYTES*8		; Bildschirmbreite
SCR_SIZE	= SCRBYTES*SCR_H	; Größe des Bildschirms in Bytes
BPLC0		= ((SCR_RES&2)<<14)+(SCR_BPL<<12)+$200+(SCR_LACE<<2)+(HAM<<11)		; BPLCON0
DIWS		= (SCR_Y<<8)+SCR_X													; DIWSTRT
DIWST		= ((SCR_Y+SCR_H/(SCR_LACE+1))&255)<<8+(SCR_X+SCR_W/SCR_RES)&255		; DIWSTOP
DDFS		= (SCR_X-(16/SCR_RES+1))/2											; DDFSTRT
DDFST		= DDFS+(8/SCR_RES)*(SCRBYTES/2-SCR_RES)								; DDFSTOP


Start:
	bsr.s	SetCop				; Copperlist erstellen

	move.w	#DMASET,$96(a5)		; DMACON - aktivieren Bitplane, Copper								
	move.l	#Copperlist,$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"

Mouse:
	move.l	#$1ff00,d1			; Bit zur Auswahl durch UND
	move.l	#$13000,d2			; warte auf Zeile $130 (304)
WarteY1:
	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	WarteY1

	bsr.w	PrintCharacter		; Drucken Sie jeweils ein Zeichen
	bsr.w	SystemCop			; Kopieren Sie die Werte aus den Tabellen in den Cop
	bsr.w	RotTabOsc			; Drehen Sie die Werte in der Wellentabelle
	bsr.w	RotTabColor			; Drehen Sie die Farbtabelle

	move.l	#$1ff00,d1			; Bit zur Auswahl durch UND
	move.l	#$13000,d2			; warte auf Zeile $130 (304)
WarteY2:
	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)
	beq.s	WarteY2

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

;***************************************************************************
; Diese Routine erstellt die Copperliste und gibt die ersten Werte ein
;***************************************************************************

;	           ° o·
;	___   _)))  .  °
;	\ -\_/ (_.)  ·°
;	 \-     ___)o·
;	 /-/`-----'
;	 ¯¯ g®m

SetCop:
	lea	Copper1,a0				; Adresse Coppereffekt
	move.l	AdrCol1(pc),a2		; Zeiger auf die Farbtabelle
	move.l	#$2c07fffe,d7		; Wait (erste Zeile $2c)
	move.l	#Bitplane,d0		; Adresse der Bitplane
	lea	TabOsc(pc),a1			; Tabelle Rolle
	moveq	#39-1,d5			; Anzahl der für diesen Effekt verwendbaren Tabellenwerte.
								; (Anmerkung: es ist es nicht leicht zu verstehen
								; wie viele Zeilen in der Praxis entlang des Effekts sind,
								; warum es notwendig ist, jeden von diesen zu berechnen
								; die Schleife kann die Zeile mehrmals wiederholen.
MakeEffect:
	move.b	(a1)+,d6			; nächster Wellenwert in d6
	tst.b	d6					; müssen wir die Linie schon schneiden?
	bne.s	ResumeLine			; wenn nicht, zeigen auf...
	addi.l	#40,d0				; oder addieren Sie die Länge von 1 Strich - Spitze
								; zur nächsten Bitplane-Zeile
	dbra	d5,MakeEffect		; und die Schleife geht weiter
	bra.w	EndEffect

ResumeLine:
	move.l	d7,(a0)+			; das Wait in die Coplist eintragen
	swap	d0					; austauschen Bitplane-Adresse 
	move.w	#$e0,(a0)+			; BPL1PTH
	move.w	d0,(a0)+			; Zeiger hohes word
	swap	d0					; austauschen Bitplane-Adresse 
	move.w	#$e2,(a0)+			; BPL1PTL
	move.w	d0,(a0)+			; Zeiger niedriges word
	tst.w	(a2)				; Ende Farbtabelle?
	bne.s	SetCop2				; Wenn noch nicht, ok
	move.l	AdrCol2(pc),a2		; Ansonsten: Farbetabelle -> Neustart
SetCop2:
	move.w	#$180,(a0)+			; Register COLOR00
	move.w	(a2)+,(a0)+			; Wert COLOR00
	addi.l	#$01000000,d7		; Lassen Sie eine Zeile tiefer warten
	bcc.s	SetCop3				; sind wir an $ff angekommen? wenn noch nicht ok
	move.l	#$ffdffffe,(a0)+	; ansonsten Bereichsende ntsc ($ff)
	move.l	#$0011fffe,d7		; Und Sie müssen diese 2 wait setzen .
SetCop3:
	subq.b	#1,d6				; Sub-Wert der "Zeilenwiederholung" aus TabOsc.
	tst.b	d6					; Haben wir die Zeile oft genug wiederholt?
	bne.s	ResumeLine			; Wenn noch nicht, legen Sie es zurück und wiederholen Sie es

	addi.l	#40,d0				; Andernfalls zielen wir auf weniger als 1 Linie ab
	dbra	d5,MakeEffect		; und lassen Sie uns den Effekt fortsetzen.

EndEffect:
	move.l	#$01000200,(a0)+	; eintragen BPLCON0 = no Bitplanes
	move.l	#$fffffffe,(a0)+	; eintragen Ende Copperlist
	rts

;****************************************************************************
; Diese Routine dreht die Farben direkt in die Farbtabelle!
;****************************************************************************

;	 ______________
;	 \    \__/    / 
;	  \__________/
;	  __|______|__
;	__(\___)(___/)__
;	\_\    \/    /_/
;	   \ \____/ /
;	    \______/ g®m
;

RotTabColor:
	lea	ColorsTab(pc),a0		; Farbtabelle
	move.w	(a0)+,d0			; speichern der ersten Farbe in d0
RotTabColor2:
	tst.w	(a0)				; Ende Tabelle?
	bne.s	RotTabColor1		; Wenn noch nicht, ok
	move.w	d0,-2(a0)			; andernfalls wird die erste Farbe als letzte Farbe verwendet
	rts

RotTabColor1:
	move.w	(a0)+,-4(a0)		; verschiebe (drehe) die Farbe "zurück"
	bra.s	RotTabColor2

;***************************************************************************
; Diese Routine dreht die Werte in der Tabelle "TabOsc"
;***************************************************************************

RotTabOsc:
	lea	TabOsc(pc),a0			; Adresse Tabelle
	moveq	#63-1,d7			; Anzahl der Werte in der Tabelle
	move.b	(a0),d0				; speichere den ersten Wert in d0
RotTabOsc1:
	move.b	1(a0),(a0)+			; Werte "zurück" verschieben.
	dbra	d7,RotTabOsc1
	move.b	d0,-1(a0)			; Gibt den ersten Wert als den letzten zurück
	rts

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

AdrCol1:
	dc.l	ColorsTab
AdrCol2:
	dc.l	ColorsTab

ColorsTab:
	dc.w	$fc9,$ec9,$dc9,$cc9,$cb9,$ca9,$c99,$c9a,$c9b,$c9c
	dc.w	$c9d,$c9e,$c9f,$b9f,$a9f,$99f,$9af,$9bf,$9cf,$acf
	dc.w	$bcf,$ccf,$dcf,$ecf,$fcf,$fbf,$faf,$f9f,$f9e,$f9d
	dc.w	$f9c,$e9c,$d9c,$c9c,$cac,$cbc,$ccc,$cdc,$cec,$cfc
	dc.w	$cfb,$cfa,$cf9,$bf9,$af9,$9f9,$9fa,$9fb,$9fc,$afc
	dc.w	$bfc,$cfc,$dfc,$efc,$ffc,$fec,$fdc,$fcc,$fcb,$fca
	dc.w	0					; Die Tabelle endet mit der Null

;***************************************************************************
; Die Routine ist nichts als SetCop ohne die Teile, die die Register schreiben
; und das wait: nur das notwendige steht geschrieben.
; Diese Routine wirkt auf die Copperliste, die jede Zeile die Zeiger auf die
; Bitplanes neu definiert. Lesen von einer Tabelle, kennen Sie jede Zeile der
; pic wie oft, um es zu wiederholen, das heißt, um es zurückzugeben. Sind zum 
; Beispiel in der Tabelle die Werte 1,2,3, dann zeigt es auf die erste Zeile 
; in der ersten Zeile des Bildschirms (einmal), dann zeigt es zweimal auf die 
; zweite und die dritte Zeile 3 mal. Hier ist eine "Zeichnung":
;
; Zeile 1
; Zeile 2
; Zeile 2
; Zeile 3
; Zeile 3
; Zeile 3
;
; Beachten Sie, dass sich die Lücke verlängert...
;***************************************************************************

;	 /) ________ (\
;	(__/        \__)
;	  / ___  ___ \
;	  \ \°_)(_°/ /
;	   \__ `' __/
;	    /      \
;	    \("""")/g®m
;	     ¯    ¯

SystemCop:
	lea	Copper1,a0				; Adresse Coppereffekt
	move.l	AdrCol1(pc),a2		; Zeiger auf die Farbtabelle
	move.l	#$2c07fffe,d7		; Wait (erste Zeile $2c)
	move.l	#Bitplane,d0		; Adresse Bitplane
	lea	TabOsc(pc),a1			; Tabelle Rolle
	moveq	#39-1,d5			; Anzahl der hierfür verwendbaren Tabellenwerte
								; für den Effekt. (Anmerkung: es ist nicht leicht zu verstehen
								; wie viele Zeilen es in der Praxis entlang des Effekts sind?
								; weil es notwendig ist zu berechnen, dass jeder von diesen 
								; Schleife die Zeile mehrmals wiederholen kann.
MakeEffect2:
	move.b	(a1)+,d6			; Setzen Sie den nächsten Schwankungswert in d6
	tst.b	d6					; Müssen wir die Zeile schon schneiden?
	bne.s	ResumeLine2			; Wenn nicht, wollen wir es anzeigen...
	addi.l	#40,d0				; Oder addieren Sie die Länge von 1 Zeile
								; zur nächsten Zeile der Bitebene
	dbra	d5,MakeEffect2		; Und setzen Sie die Schleife fort
	bra.w	EndEffect2

ResumeLine2:
	addq.w	#6,a0				; Überspringen Sie WAIT und BPL1PTH
	swap	d0					; Tauschen Sie die Adresse der Bitplane aus
	move.w	d0,(a0)+			; Zeigen Sie auf das hohe Wort
	swap	d0					; Tauschen Sie die Adresse der Bitplane erneut aus
	addq.w	#2,a0				; überspringen Sie BPL1PTL
	move.w	d0,(a0)+			; Zeigen Sie auf das niedrige Wort
	tst.w	(a2)				; Ende Farbtabelle?
	bne.s	SetCop22			; Wenn noch nicht, ok
	move.l	AdrCol2(pc),a2		; Ansonsten: FarbTabelle -> erneut starten
SetCop22:
	addq.w	#2,a0				; überspringen Sie das Register COLOR00
	move.w	(a2)+,(a0)+			; Wert COLOR00
	addi.l	#$01000000,d7		; eine Zeile tiefer warten
	bcc.s	SetCop32			; sind wir an $ff angekommen? Wenn noch nicht ok,
	addq.w	#4,a0				; Überspringen FFDFFFFE
	move.l	#$0011fffe,d7		; Und Sie müssen diese 2 waits setzen 
SetCop32:
	subq.b	#1,d6				; Sub den Wert "Zeilenwiederholung" von TabOsc 
	tst.b	d6					; Haben wir die Zeile oft genug wiederholt?
	bne.s	ResumeLine2			; Wenn noch nicht, wiederhole es

	addi.l	#40,d0				; Ansonsten setzen wir weniger als 1 Zeile
	dbra	d5,MakeEffect2		; und lassen Sie uns den Effekt fortsetzen.

EndEffect2:
	rts

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

; Tabulator mit 64 .byte-Werten. Zeigt an, für wie viele Zeilen dieselbe
; Zeile ist. Bei einem Wert von 2 zum Beispiel wird die Zeile 2 Mal wiederholt,
; d.h. sie wird in der Höhe verdoppelt.

TabOsc:
	dc.b	1,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
	dc.b	9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,2
	dc.b	2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9
	dc.b	9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,1

	even

*****************************************************************************
;			Druck Routine
*****************************************************************************

PrintCharacter:
	movem.l	d2/a0/a2-a3,-(sp)
	move.l	PointerText(pc),a0	; Adresse des zu druckenden Textes a0
	moveq	#0,d2				; d2 löschen
	move.b	(a0)+,d2			; Nächstes Zeichen in d2
	cmp.b	#$ff,d2				; Ende des Textsignals? ($ff)
	beq.s	EndText				; Wenn ja, beenden Sie ohne zu drucken
	tst.b	d2					; Zeilenende-Signal? ($00)
	bne.s	NotEndLine			; Wenn nicht, nicht aufhören

	add.l	#40*7,PointerBitplane	; wir gehen zum Anfang
	addq.l	#1,PointerText		; erste Zeichenzeile danach
								; (überspringe die NULL)
	move.b	(a0)+,d2			; erstes Zeichen der Zeile nach
								; (überspringe die NULL)

NotEndLine:
	sub.b	#$20,d2				; ZÄHLE 32 VOM ASCII-WERT DES BUCHSTABEN WEG
								; SOMIT VERWANDELN WIR Z.B. DAS LEERZEICHEN
								; (Das $20 entspricht), IN $00, DAS
								; AUSRUFUNGSZEICHEN ($21) IN $01...
	lsl.w	#3,d2				; MULTIPLIZIERE DIE ERHALTENE ZAHL MIT 8,
								; da die Charakter ja 8 Pixel hoch sind
	move.l	d2,a2
	add.l	#Font,a2			; FINDE DEN GEWÜNSCHTEN BUCHSTABEN IM FONT...

	move.l	PointerBitplane(pc),a3 ; Adresse Ziel-Bitplane in a3

								; DRUCKE DEN BUCHSTABEN ZEILE FÜR ZEILE
	move.b	(a2)+,(a3)			; Drucke Zeile 1 des Zeichens
	move.b	(a2)+,40(a3)		; Drucke Zeile  2  " "
	move.b	(a2)+,40*2(a3)		; Drucke Zeile  3  " "
	move.b	(a2)+,40*3(a3)		; Drucke Zeile  4  " "
	move.b	(a2)+,40*4(a3)		; Drucke Zeile  5  " "
	move.b	(a2)+,40*5(a3)		; Drucke Zeile  6  " "
	move.b	(a2)+,40*6(a3)		; Drucke Zeile  7  " "
	move.b	(a2)+,40*7(a3)		; Drucke Zeile  8  " "

	addq.l	#1,PointerBitplane	; wir rücken 8 Bits vor (NÄCHSTES ZEICHEN)
	addq.l	#1,PointerText		; nächstes zu druckendes Zeichen

EndText:
	movem.l	(sp)+,d2/a0/a2-a3
	rts


PointerText:
	dc.l	Text

PointerBitplane:
	dc.l	Bitplane

;	$00 für "Zeilenende" - $ff für "Textende"

		; Anzahl der Zeichen pro Zeile: 40
Text:	     ;		  1111111111222222222233333333334
             ;   1234567890123456789012345678901234567890
	dc.b	'  * * * * * * * * * * * * * * * * *     ',0 ; 1
	dc.b	'  * MAMMA MIA MI BALLA            *     ',0 ; 2
	dc.b	'  *                    LO SCHERMO *     ',0 ; 3
	dc.b	'  * * * * * * * * * * * * * * * * *     ',$ff ; 4

	even

; Die FONT 8x8-Zeichen, die in CHIP von der CPU und nicht vom Blitter kopiert wurden,
; so kann es auch im FAST RAM sein. In der Tat wäre es besser!

Font:
	incbin "/Sources/nice.fnt"

;********************************************************************
;				Copperlist
;********************************************************************

	SECTION	GRAPHIC,DATA_C

Copperlist:
	dc.w	$8e,DIWS			; DIWSTRT
	dc.w	$90,DIWST			; DIWSTOP
	dc.w	$92,DDFS			; DDFSTRT
	dc.w	$94,DDFST			; DDFSTOP
	dc.w	$100,BPLC0			; BPLCON0
	dc.w	$108,0				; BPL1MOD
	dc.w	$10a,0				; BPL2MOD
	dc.w	$182,$000			; COLOR01 (Schrift) - schwarz

Copper1:
	dcb.b	4000,0	; Achtung! Die Länge des Effekts hängt von 
; der TabOsc-Tabelle ab und es ist nicht einfach, es zu berechnen...
	dc.l	$fffffffe

;********************************************************************
;	die Bitplane
;********************************************************************
	
	SECTION	LEEREPLANE,BSS_C

Bitplane:
	ds.b	40*320

	end

Wir haben schon früher einen ähnlichen Effekt gesehen, als wir die Modulos
wechselten und jetzt wechseln stattdessen die Bplpointers. Dieses System
ist langsamer als das mit den Modulos, da sie für jede Zeile die Zeiger
vieler Bitebenen ändern müssen. Jedoch könnte es für jede Ebene anders
definiert werden, um seinen Geschäften nachzugehen, wenn der bplmod alle
geraden und / oder ungeraden Planes einbezieht.

Eine Besonderheit dieses Quelltextes ist, dass die Werte der Tabellen für
die Planes und Farben nicht "gedreht" werden, indem sie von der Copperlist
erneut gelesen und bewegt werden, sondern indem Sie die Werte in den
Tabellen selbst drehen, kopieren Sie einfach aus der Copperlistentabelle,
nachdem die Tabelle "gedreht" wurde.

Dieses System ist schneller als andere, wenn Sie sie so wie sie ist im 
FAST RAM haben. Wenn Sie den Wert aus der Copperliste lesen und später neu
zurück schreiben würden, wir sollten zweimal auf den CHIP-RAM zugreifen, mit
den damit verbundenen "Verzögerungen".
In unserem Fall greifen wir in FAST mit Minimum Zeitverlust auf die Tabelle
zu und wir schreiben nur einmal pro Farbe / Ebene in CHIP. Auf Computern wie
A4000 wird die einzige Verlangsamung durch Lesen / Schreiben in CHIP RAM 
gegeben, daher verdoppelt sich die Geschwindigkeit der Ausführung der Routine.
                                                                                    