
; Listing10i1.s		2-Pixel-Sinus-Scroller
; linke Taste zum Beenden.

	SECTION	BLIT,CODE

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

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

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


Start:
	move.l	#Bitplane,d0		; Zeiger auf die "leere" Bitplane
	lea	Bplpointers,a1			; Bitplanepointer
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	swap	d0

	lea	$dff000,a5				; Custom Register Base in a5
	move.w	#DMASET,$96(a5)		; DMACON - einschalten Bitplane, Copper, Blitter
	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"

	lea	Text(pc),a0				; zeigt auf den Scrolltext

Mouse:
	move.l	#$1ff00,d1			; Bit zur Auswahl durch UND
	move.l	#$10800,d2			; Warte auf Zeile $108
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 $108
	bne.s	WarteY1
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 $108
	beq.s	WarteY2

	bsr.s	PrintChar			; Routine, die ein neues Zeichen druckt
	bsr.s	Scroll				; führt die Scroll-Routine aus

	bsr.w	ClearScreen			; reinigt den Bildschirm
	bsr.w	Sine				; führt die Sinus-Bildlauffunktion aus

	btst	#6,$bfe001			; linke Maustaste gedrückt?
	bne.s	Mouse				; Wenn nicht, gehe zurück zu Mouse:
	rts

;****************************************************************************
; Diese Routine druckt ein Zeichen. Das Zeichen wird in einem 
; Teil des unsichtbaren Bildschirms gedruckt.
; a0 zeigt auf den zu druckenden Text.
;****************************************************************************

PrintChar:
	subq.w	#1,Counter			; Verringere den Zähler um 1
	bne.s	NoPrint				; wenn es sich von 0 unterscheidet, drucken wir nicht,
	move.w	#16,Counter			; sonst ja; den Zähler zurücksetzen

	moveq	#0,d2				; d2 löschen
	move.b	(a0)+,d2			; Nächstes Zeichen in d2
	bne.s	NoReset				; Wenn es anders als 0 ist, drucken Sie es
	lea	Text(pc),a0				; Andernfalls starten Sie den Text erneut
	move.b	(a0)+,d2			; Erstes Zeichen in d2
NoReset
	sub.b	#$20,d2				; SUBTRAHIERE 32 VOM ASCII-WERT DES CHARAKTERS
								; SOMIT VERWANDELN WIR Z.B. DAS LEERZEICHEN
								; (Das $20 entspricht), IN $00, DAS
								; AUSRUFUNGSZEICHEN ($21) IN $01...
	add.l	d2,d2				; MULTIPLIZIERE DIE ERHALTENE ZAHL MIT 2,
								; weil jedes Zeichen 16 Pixel breit ist
	move.l	d2,a2

	add.l	#Font,a2			; DEN GESUCHTEN CHARAKTER IM FONT FINDEN ...

	btst	#6,$02(a5)			; DMACONR - warte auf das Ende des Blitters
WaitBlit:
	btst	#6,$02(a5)
	bne.s	WaitBlit

	move.l	#$09f00000,$40(a5)	; BLTCON0: Kopie von A nach D
	move.l	#$ffffffff,$44(a5)	; BLTAFWM und BLTALWM es passiert alles
	
	move.l	a2,$50(a5)			; BLTAPT: Adresse Font
	move.l	#Buffer+40,$54(a5)	; BLTDPT: Adresse Bitplane
	move	#120-2,$64(a5)		; BLTAMOD: Modulo Font
	move	#42-2,$66(a5)		; BLTDMOD: Modulo Bitplane
	move	#(20<<6)+1,$58(a5) 	; BLTSIZE: Font 16*20
NoPrint:
	rts

Counter:
	dc.w	16

;****************************************************************************
; Diese Routine scrollt den Text nach links
;****************************************************************************

Scroll:

; Die Quell- und Zieladressen sind gleich.
; Wir bewegen uns nach links, also benutzen wir den absteigenden Weg.

	move.l	#Buffer+((21*20)-1)*2,d0	; Adresse Quelle und Ziel										
ScrollLoop:
	btst	#6,2(a5)			; warte auf das Ende des Blitters
WaitBlit2:
	btst	#6,2(a5)
	bne.s	WaitBlit2

	move.l	#$19f00002,$40(a5)	; BLTCON0 und BLTCON1 - Kopie von A nach D
								; mit einer Ein-Pixel-Verschiebung

	move.l	#$ffff7fff,$44(a5)	; BLTAFWM und BLTALWM
								; BLTAFWM = $ffff - es passiert alles
								; BLTALWM = $7fff = %0111111111111111
								; lösche das linke Bit
; Lade die Zeiger
	move.l	d0,$50(a5)			; BLTAPT - Quelle
	move.l	d0,$54(a5)			; BLTDPT - Ziel

; Lassen Sie uns dann ein breites Bild über den Bildschirm scrollen
; Das Modulo Register wird zurückgesetzt.

	move.l	#0,$64(a5)			; BPLAMOD und BPLDMOD 
	move.w	#(20*64)+21,$58(a5)	; BLTSIZE
								; Höhe 20 Zeilen, Breite 21
	rts							; words (der ganze Bildschirm)


;****************************************************************************
; Diese Routine realisiert den Sinus-Scroll-Effekt. Achten Sie auf BLTALWM, 
; weil es das Register ist, in dem wir jedes Mal die vertikale "Scheibe" oder 
; "Strich" auswählen, auf dem zu operieren ist.
;****************************************************************************

;	  ,-~~-.___.
;	 / |  '     \
;	(  )         0
;	 \_/-, ,----'
;	    ====           //
;	   /  \-'~;    /~~~(O)
;	  /  __/~|   /       |
;	=(  _____| (_________|   W<

Sine:
	lea	Buffer,a2				; Zeiger auf den enthaltenden Puffer
								; Scrolltext
	lea	Bitplane,a1				; Zeiger auf das Ziel

	lea	SinusTab(pc),a3			; Sinus-Tabellenadresse, mit Werten die
								; bereits mit 42 multipliziert sind, um 
								; sie direkt zur Adresse
								; der Bitebene hinzufügen zu können.

	move.w	#$c000,d5			; Maskenwert zu Beginn
	moveq	#20-1,d6			; Wiederholen für alle Wörter im Text
DoOneWord:
	moveq	#8-1,d7				; 2-Pixel-Routine. Für jedes Wort
								; gibt es 8 "Scheiben" von 2 Pixeln
DoOneColumn:
	move.w	(a3)+,d0			; liest einen Wert aus der Tabelle
	cmp.l	#EndSinusTab,a3		; wenn wir am Ende der Tabelle sind
	blo.s	NoStartSine			; fang wieder von vorn an
	lea	sinustab(pc),a3
NoStartSine:
	move.l	a1,a4				; Kopie Adresse Bitplane
	add.w	d0,a4				; Fügt die Y-Koordinate, Offset hinzu
								; aus dem sintab genommen ...

	btst	#6,2(a5)			; warte auf das Ende des Blitters
WaitBlit3:
	btst	#6,2(a5)
	bne.s	WaitBlit3

	move.w	#$ffff,$44(a5)		; BLTAFWM
	move.w	d5,$46(a5)			; BLTALWM - enthält die Maske, die
								; den Scrolltext "Streifen" auswählt

	move.l	#$0bfa0000,$40(a5)	; BLTCON0/BLTCON1 - aktiviere A,C,D
								; D=A OR C

	move.w	#$0028,$60(a5)		; BLTCMOD=42-2=$28
	move.l	#$00280028,$64(a5)	; BLTAMOD=42-2=$28
								; BLTDMOD=42-2=$28

	move.l	a2,$50(a5)			; BLTAPT (Puffer)
	move.l	a4,$48(a5)			; BLTCPT (Bildschirm)
	move.l	a4,$54(a5)			; BLTDPT (Bildschirm)
	move.w	#(64*20)+1,$58(a5)	; BLTSIZE (ein Rechteck gemischt
								; 20 Zeilen hoch und 1 Wort breit)

	ror.w	#2,d5				; zur nächsten "Scheibe" bewegt
								; geht nach rechts und nach der letzten "Scheibe"
								; eines Wortes fängt das folgende
								; Wort wieder vom Anfang an.
								; für den 2 Pixel Scroll ist die
								; "Scheibe" 2 Pixel breit

	dbra	d7,DoOneColumn

	addq.w	#2,a2				; Zeige auf das nächste Wort
	addq.w	#2,a1				; Zeige auf das nächste Wort
	dbra	d6,DoOneWord
	rts

; Dies ist der Text. mit 0 endet es. Die verwendete Schriftart enthält nur 
; die Zeichen Großbuchstaben, Achtung!

Text:
	;dc.b	" ECCO COME SINUSCROLLARE... IL FONT E' DI 16*20 PIXEL!..."
	;dc.b	" LO SCROLL AVVIENE CON TRANQUILLITA'...",0
	;even

	dc.b	" HIER KOMMT DER SINUSSCROLLER... DER FONT IST 16*20 PIXEL! ... "
	dc.b	" DAS SCROLLEN ERFOLGT MIT RUHE ...",0
	even

;****************************************************************************
; Diese Routine löscht den Bildschirm mit dem Blitter.
; Nur der Teil des Bildschirms, auf dem der Text fließt, wird gelöscht:
; von Zeile 130 bis Zeile 193
;****************************************************************************

ClearScreen:
	btst	#6,2(a5)
WaitBlit4:
	btst	#6,2(a5)			; warte auf das Ende des Blitters
	bne.s	WaitBlit4

	move.l	#$01000000,$40(a5)	; BLTCON0 und BLTCON1: Löschung
	move	#$0000,$66(a5)		; BLTDMOD=0
	move.l	#Bitplane+42*130,$54(a5)	; BLTDPT
	move.w	#(64*63)+20,$58(a5)	; BLTSIZE (Blitter starten!)
								; lösche von Zeile 130 bis Zeile 193
	rts

;***************************************************************************
; Dies ist die Tabelle, die die Werte der vertikalen Positionen des 
; Scrolltextes enthält. Die Positionen sind daher bereits mit 42
; multipliziert. So können sie direkt zur Bitplane-Adresse hinzugefügt werden.
;***************************************************************************

SinusTab:
	dc.w	$18c6,$191a,$1944,$1998,$19ec,$1a16,$1a6a,$1a94,$1ae8,$1b12
	dc.w	$1b3c,$1b66,$1b90,$1bba,$1bba,$1be4,$1be4,$1be4,$1be4,$1be4
	dc.w	$1bba,$1bba,$1b90,$1b66,$1b3c,$1b12,$1ae8,$1a94,$1a6a,$1a16
	dc.w	$19ec,$1998,$1944,$191a,$18c6,$1872,$181e,$17f4,$17a0,$174c
	dc.w	$1722,$16ce,$16a4,$1650,$1626,$15fc,$15d2,$15a8,$157e,$157e
	dc.w	$1554,$1554,$1554,$1554,$1554,$157e,$157e,$15a8,$15d2,$15fc
	dc.w	$1626,$1650,$16a4,$16ce,$1722,$174c,$17a0,$17f4,$181e,$1872
EndSinusTab:

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

	SECTION	GRAPHIC,DATA_C

Copperlist:
	dc.w	$8e,$2c81			; DIWSTRT
	dc.w	$90,$2cc1			; DIWSTOP
	dc.w	$92,$38				; DDFSTRT
	dc.w	$94,$d0				; DDFSTOP
	dc.w	$102,0				; BPLCON1
	dc.w	$104,0				; BPLCON2

	dc.w	$108,2				; Die Bitebene ist 42 Bytes breit, aber nur 40
								; Bytes sind sichtbar,
								; dann ist der Registerwert 42-40 = 2		
								; dc.w $10a,2; Wir verwenden nur eine Bitebene, 
								; dann ist BPLMOD2 nicht notwendig

	dc.w	$100,$1200			; BPLCON0 - 1 Bitplanes lowres

Bplpointers:
	dc.w	$e0,$0000,$e2,$0000	; erste Bitplane

	dc.w	$0180,$000			; COLOR00
	dc.w	$0182,$f50			; COLOR01

	dc.w	$ffff,$fffe			; Ende Copperlist

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

; Das Font von 16x20 Zeichen ist hier gespeichert

Font:
	incbin	"/Sources/font16x20.raw"

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

	SECTION	LEEREPLANE,BSS_C

Bitplane:
	ds.b	42*256				; Bitplane rücksetzen lowres

Buffer:
	ds.b	42*20				; unsichtbarer Puffer, wo der Text gescrollt wird
						
	end

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

In diesem Beispiel sehen wir einen 2-Pixel-Sinus-Scroll. Die Routinen, die
die Zeichen drucken und die den Text scrollen sind die gleichen wie in 
Listing9n1.s nur, dass sie nicht auf den Bildschirm, sondern in einen 
unsichtbaren Puffer zeichnen. Die "Sinus" -Routine realisiert den Effekt.
Er blittet den gesamten Inhalt des Puffers auf den Bildschirm in "Scheiben" 
von 2 Pixel. Dafür muss er 1 Wort weite Blitts durchführen. Jede Wortspalte
enthält 8 "Scheiben" mit einer Breite von 2 Pixeln. Also die Routine hat 2
verschachtelte Schleifen: Die innerste führt 8 Kopieraufrufe auf die ganze
Wortspalte aus, während die äußere die innere für alle Bildschirmwortspalten
wiederholt. So wählen Sie die "Scheiben" aus. Innerhalb des Wortes verwenden
wir eine Maske, die in d5 enthalten ist. Nach jedem Blitt wird die Maske
gedreht, um jedes Mal eine andere "Scheibe" auszuwählen. Da die aus einer
Seite des Registers kommenden Bits gedreht wieder werden auf der anderen
Seite erneut eingehen muss nicht jedes Mal d5 am Ausgang rechts mit 1 gesetzt
werden. Jedes Scheibe wird an eine andere y-Position kopiert die aus einer
Tabelle gelesen wird. Die Bildschirmlöschroutine löscht nur den betroffenen
Teil aus der Zeichnung. Um zu berechnen, welcher Teil betroffen ist, muss man
die minimale und maximale y-Koordinate der "Scheiben" berücksichtigen, und
auch dass die "Scheiben" 20 Pixel hoch sind. Die erste zu löschende Zeile ist
also das minimale Y der "Scheiben", während die letzte Zeile die Summe des
maximalen Y und der Höhe der "Scheiben" ist.
