
; Listing10c3.s		Reflektoreffekt
; 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	#Figur,d0			; Zeiger Figur
	lea	Bplpointers,a1			; Bitplanepointer
	moveq	#3-1,d1				; Anzahl der Bitplanes
PointBp:
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	swap	d0
	add.l	#40*256,d0			; + Bitplane Länge (hier 256 Zeilen hoch)
	addq.w	#8,a1
	dbra	d1,PointBp

	move.l	#Bitplane4,d0		; Zeiger auf die Bitebene 4,
	move.w	d0,6(a1)			; wo der Reflektor gezeichnet wird
	swap	d0
	move.w	d0,2(a1)

	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"

Mouse:

WarteY1:
	cmp.b	#$ff,$6(a5)			; VHPOSR - Warte auf Zeile $ff
	bne.s	WarteY1
WarteY2:
	cmp.b	#$ff,$6(a5)			; noch Zeile $ff?
	beq.s	WarteY2

	bsr.s	ClearScreen			; sauberer Bildschirm
	bsr.w	MoveMask			; Reflektorposition verschieben
	bsr.s	Reflector			; Routine Reflektor

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

	rts

;***************************************************************************
; Diese Routine löscht den Teil des Bildschirms, der vom Blitt betroffen ist
;***************************************************************************

ClearScreen:
	lea	Bitplane4+100*40,a1		; Adresse Bereich der gelöscht werden soll
								; (Bitebene 4)

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

	move.l	#$01000000,$40(a5)	; BLTCON0 + BLTCON1 Löschung
	move.w	#0,$66(a5)			; BLTDMOD
	move.l	a1,$54(a5)			; BLTDPT Zeiger Ziel
	move.w	#(64*39)+20,$58(a5)	; BLTSIZE (Blitter starten !)
	rts

;*****************************************************************************
; Diese Routine realisiert den Reflektoreffekt.
; die Maske wird einfach auf die Bitebene 4 gezeichnet
;*****************************************************************************

;	      ___________
;	     /           \
;	    /\            \
;	   / /\____________)____
;	   \/:/\___   ___/\     \
;	    \/ ___ \_/ ___ \     \
;	    ( /  o)   (  o\ )____/
;	     \\__/ /Y\ \__//
;	     (___/(_n_)\___)
;	   __//\ _ _ _ _ /\\__
;	  /==\\_Y Y Y Y Y_//==\
;	 /    `-| | | | |-'    \
;	/       `-^-^-^-'       \

Reflector:
	lea	Bitplane4+100*40,a1		; Adresse Ziel
	move.w	MaskeX(pc),d0		; Reflektorposition
	move.w	d0,d2				; Kopie
	and.w	#$000f,d0			; wir wählen die ersten 4 Bits, weil sie
								; in den Shifter von Kanal A eingefügt werden
	lsl.w	#8,d0				; die 4 Bits werden zum High-Nibble bewegt
	lsl.w	#4,d0				; des Wortes...
	or.w	#$09f0,d0			; ...nur um in das Register BLTCON0 zu kommen
								; LF=$f0 (d.h. Kopie A nach D)
	lsr.w	#3,d2				; (entspricht einer Division durch 8)
								; Runden auf ein Vielfaches von 8 für den Zeiger
								; auf den Bildschirm, also auch auf ungerade Adressen
								; (also zu Bytes)
								; zB: eine 16 als Koordinate wird zu Byte 2
	and.w	#$fffe,d2			; Ich schließe Bit 0 aus
	add.w	d2,a1				; addieren zur Adresse der Bitebene, 
								; um die richtige Zieladresse zu finden

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

	move.l	#$ffffffff,$44(a5)	; Maske
	move.w	d0,$40(a5)			; BLTCON0
	move.w	#$0000,$42(a5)		; BLTCON1 Modus ascending
	move.w	#0,$64(a5)			; BLTAMOD (=0)
	move.w	#32,$66(a5)			; BLTDMOD (40-8=32)

	move.l	#Maske,$50(a5)		; BLTAPT Zeiger Quelle
	move.l	a1,$54(a5)			; BLTDPT Zeiger Ziel
	move.w	#(64*39)+4,$58(a5)	; BLTSIZE (Blitter starten!)
								; Breite 4 Word, Höhe 39 Zeilen
	rts

;*****************************************************************************
; Diese Routine liest die horizontale Koordinate aus einer Tabelle
; und speichert sie in der Variable MaskeX
;*****************************************************************************

MoveMask:
	addq.l	#2,TabXpoint		; Zeiger auf das nächste Wort
	move.l	TabXpoint(pc),a0	; Adresse die in TabXpoint enthalten ist
								; nach a0 kopieren
	cmp.l	#EndeTabX-2,a0  	; sind wir beim letzten Wort der Tabelle?
	bne.s	NobStartX			; noch nicht? dann weiter
	move.l	#TabX-2,TabXpoint 	; erneut mit dem ersten Wort-2 beginnen
NobStartX:
	move.w	(a0),MaskeX			; den Wert in die Variable kopieren 
	rts

MaskeX:
		dc.w	0				; aktuelle Maskenpositition
TabXpoint:
		dc.l	TabX			; Zeiger auf die Tabelle

; Tabelle Maskenpositionen

TabX:
	dc.w	$12,$16,$19,$1d,$21,$25,$28,$2c,$30,$34
	dc.w	$37,$3b,$3f,$43,$46,$4a,$4e,$51,$55,$58
	dc.w	$5c,$60,$63,$67,$6a,$6e,$71,$74,$78,$7b
	dc.w	$7f,$82,$85,$89,$8c,$8f,$92,$95,$98,$9c
	dc.w	$9f,$a2,$a5,$a8,$aa,$ad,$b0,$b3,$b6,$b8
	dc.w	$bb,$be,$c0,$c3,$c5,$c8,$ca,$cc,$cf,$d1
	dc.w	$d3,$d5,$d8,$da,$dc,$de,$e0,$e1,$e3,$e5
	dc.w	$e7,$e8,$ea,$ec,$ed,$ee,$f0,$f1,$f2,$f4
	dc.w	$f5,$f6,$f7,$f8,$f9,$fa,$fb,$fb,$fc,$fd
	dc.w	$fd,$fe,$fe,$ff,$ff,$ff,$100,$100,$100,$100
	dc.w	$100,$100,$100,$100,$ff,$ff,$ff,$fe,$fe,$fd
	dc.w	$fd,$fc,$fb,$fb,$fa,$f9,$f8,$f7,$f6,$f5
	dc.w	$f4,$f2,$f1,$f0,$ee,$ed,$ec,$ea,$e8,$e7
	dc.w	$e5,$e3,$e1,$e0,$de,$dc,$da,$d8,$d5,$d3
	dc.w	$d1,$cf,$cc,$ca,$c8,$c5,$c3,$c0,$be,$bb
	dc.w	$b8,$b6,$b3,$b0,$ad,$aa,$a8,$a5,$a2,$9f
	dc.w	$9c,$98,$95,$92,$8f,$8c,$89,$85,$82,$7f
	dc.w	$7b,$78,$74,$71,$6e,$6a,$67,$63,$60,$5c
	dc.w	$58,$55,$51,$4e,$4a,$46,$43,$3f,$3b,$37
EndeTabX:

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

	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,0				; BPL1MOD
	dc.w	$10a,0				; BPL2MOD

	dc.w	$100,$4200			; BPLCON0 - 4 Bitplane lowres

Bplpointers:
	dc.w	$e0,$0000,$e2,$0000	; erste Bitplane
	dc.w	$e4,$0000,$e6,$0000
	dc.w	$e8,$0000,$ea,$0000
	dc.w	$ec,$0000,$ee,$0000

Colors:
	dc.w	$0180,$000			; Farben von 0-7 alle dunkel. Auf diese Weise werden
								; die Teile der Figur in Übereinstimmung mit der
								; der entworfenen Maske dunkler gefärbt
	dc.w	$0182,$011			; COLOR01
	dc.w	$0184,$223			; COLOR02
	dc.w	$0186,$122			; COLOR03
	dc.w	$0188,$112			; COLOR04
	dc.w	$018a,$011			; COLOR05
	dc.w	$018c,$112			; COLOR06
	dc.w	$018e,$011			; COLOR07

	dc.w	$0190,$000			; color 8-15 enthält die Palette
	dc.w	$0192,$475
	dc.w	$0194,$fff
	dc.w	$0196,$ccc
	dc.w	$0198,$999
	dc.w	$019a,$232
	dc.w	$019c,$777
	dc.w	$019e,$444

	dc.w	$ffff,$fffe			; Ende Copperlist

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

; Hier ist die Zeichnung, 320 Pixel breit, 256 Zeilen hoch und von 3 Ebenen gebildet

Figur:
	incbin	"/Sources/amiga.raw"

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

; Dies ist die Maske. Es ist eine Figur, die von einer einzelnen Bitebene 
; gebildet wird, 39 Zeilen hoch und 4 Wörter breit

Maske:
	dc.l	$00007fc0,$00000000,$0003fff8,$00000000,$000ffffe,$00000000
	dc.l	$001fffff,$00000000,$007fffff,$c0000000,$00ffffff,$e0000000
	dc.l	$01ffffff,$f0000000,$03ffffff,$f8000000,$03ffffff,$f8000000
	dc.l	$07ffffff,$fc000000,$0fffffff,$fe000000,$0fffffff,$fe000000
	dc.l	$1fffffff,$ff000000,$1fffffff,$ff000000,$1fffffff,$ff000000
	dc.l	$3fffffff,$ff800000,$3fffffff,$ff800000,$3fffffff,$ff800000
	dc.l	$3fffffff,$ff800000,$3fffffff,$ff800000,$3fffffff,$ff800000
	dc.l	$3fffffff,$ff800000,$3fffffff,$ff800000,$3fffffff,$ff800000
	dc.l	$1fffffff,$ff000000,$1fffffff,$ff000000,$1fffffff,$ff000000
	dc.l	$0fffffff,$fe000000,$0fffffff,$fe000000,$07ffffff,$fc000000
	dc.l	$03ffffff,$f8000000,$03ffffff,$f8000000,$01ffffff,$f0000000
	dc.l	$00ffffff,$e0000000,$007fffff,$c0000000,$001fffff,$00000000
	dc.l	$000ffffe,$00000000,$0003fff8,$00000000,$00007fc0,$00000000
	
;*****************************************************************************

; Hier ist die vierte Bitebene, wo die Maske gezeichnet wird.

	SECTION	LEEREPLANE,BSS_C

Bitplane4:
	ds.b	40*256

	end

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

In diesem Beispiel erzeugen wir einen "Reflektor"-Effekt mit Hilfe einer
Bitplane-Maske. Die Technik ist wie folgt. Wir haben ein Set-Design aus 
3 Bitebenen 320 Pixel breit und 256 Zeilen hoch. Um den Effekt zu erzielen,
benutzen wir eine "Maske" oder eine Zeichnung eines Kreises, der nur aus 
einer Bitplane besteht. Diese Maske wird gezeichnet und auf einer vierten 
Bitebene bewegt, als wäre es ein Bob. Es wird auf einer Bitebene getrennt 
von der Abbildung gezeichnet. Wir müssen uns nicht um den Hintergrund
kümmern. Es ist im Grunde derselbe Trick, wie der in Listing9i4.s, das 
Beispiel des Bobs mit dem Hintergrund als Fälschung. Diesmal aber, um den 
Reflektoreffekt einzustellen. Ansonsten sind die Farben in den Registern: 
die Palette der 3-farbigen Figur, das heißt, die Werte, die wir normalerweise
in die COLOR00-COLOR07-Register schreiben würden. Sie werden diesmal in den
Registern COLOR08-COLOR15 geschrieben. Stattdessen die Register
COLOR00-COLOR07 werden alle etwas dunkler (oder schwarz) eingestellt. Auf diese
Weise werden die Pixel des Bildes, über die vierte Bitebene eingestellt.
Bei 0 erscheinen sie alle dunkler (wir könnten sie alle sogar schwarz machen).
Auf der anderen Seite werden, wenn die Pixel des Bildes der vierten Bitebene
auf 1 sind (dh an der Maske) sie mit der richtigen Farben erscheinen. Diese
Technik ist sehr schnell, hat aber wie das Beispiel Listing9i4.s einen
Nachteil: Wir verwenden 4 Bitebenen für ein 8-Farben-Bild. Im nächsten
Beispiel werden wir sehen, wie dieses Problem vermieden werden kann.                                                                                                 00000000
