
; Listing10e6.s		Optimierte Version von Listing10c4.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	#Bitplane1,d0		; Zeiger auf die "leere" Bitplane
	lea	Bplpointers,a1			; Bitplanepointer
	moveq	#5-1,d1				; Anzahl der Bitplanes (hier sind es 5)
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

	lea	$dff000,a5				; Custom Register Base in a5

; hier wird der Blitter definitiv gestoppt, weil er das Startup zur Verfügung 
; gestellt bekommen hat, so können wir die Register leicht einstellen.
; Die folgenden Register werden daher immer mit den gleichen Werten verwendet
; Wir initialisieren sie zu Beginn des Programms ein für allemal.

	move.l	#$ffffffff,$44(a5)	; BLTAFWM/BLTALWM
	move.w	#$0000,$42(a5)		; BLTCON1 Modus ascending
	move.l	#$00200000,$62(a5)	; BLTBMOD (40-8=32=$20)
								; BLTAMOD (=0)

	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			; Bildschirm löschen
	bsr.w	MoveMask			; Reflektorposition verschieben
	bsr.s	Reflector			; Routine Reflektoreffekt

	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 von dem Blitt
; betroffen ist
;***************************************************************************

ClearScreen:
	moveq	#5-1,d7				; 5 Bitplanes
	lea	Bitplane1+100*40,a1		; zu löschende Adresse (plane1)

	move.w	#(64*39)+20,d5		; Wert zum Schreiben in BLTSIZE
								; Wir haben es in d5 zur Optimierung gebracht			

	btst	#6,2(a5) 			; DMACONR
WaitBlit1:
	btst	#6,2(a5) 			; warte auf das Ende des Blitters
	bne.s	WaitBlit1			; vor dem Ändern der Register

	move.w	#$0100,$40(a5)		; BLTCON0 Löschung
	move.w	#$0000,$66(a5)		; BLTDMOD Diese 2 Register werden 
								; mit verschiedenen Werten in der Routine
								; Reflektor verwendet
ClearLoop:
	btst	#6,2(a5) 			; DMACONR
WaitBlit2:
	btst	#6,2(a5) 			; warte auf das Ende des Blitters
	bne.s	WaitBlit2			; vor dem Blitten

	move.l	a1,$54(a5)			; BLTDPT (Bildschirm)
	move.w	d5,$58(a5)			; Schreibe BLTSIZE
								; der Wert wurde zuvor
								; in d5 geschrieben

	add.l	#256*40,a1			; nächste Adressebene
	dbra	d7,Clearloop
	rts

;*****************************************************************************
; Diese Routine realisiert den Reflektoreffekt. Eine UND-Operation wird 
; zwischen der Figur und einer Maske ausgeführt.
;*****************************************************************************

;	   |\_._/|        |,\__/|        |\__/,|  
;	   | o o |        |  o o|        |o o  |  
;	   (  T  )        (   T )        ( T   )  
;	  .^`-^-'^.      .^`--^'^.      .^`^--'^. 
;	  `.  ;  .'      `.  ;  .'      `.  ;  .' 
;	  | | | | |      | | | | |      | | | | | 
;	 ((_((|))_))    ((_((|))_))    ((_((|))_))

Reflector:
	moveq	#5-1,d7				; 5 Bitplanes
	lea	Figur+40,a0				; Adresse Figur
	lea	Bitplane1+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 
	lsl.w	#4,d0				; des Wortes bewegt...
	or.w	#$0dc0,d0			; ...  rechts, in das BLTCON0-Register einzugeben
								; LF = $C0 (dh UND zwischen A und B)
	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,a0				; addieren zur Adresse der Bitebene, 
								; um die richtige Zieladresse zu finden
	add.w	d2,a1				; addieren zur Adresse der Bitebene, 
								; um die richtige Zieladresse zu finden

	move.l	#Maske,a2			; Wert zum Schreiben in BLTAPT
								; (Maskenzeiger)
								; Wir setzen es in a2 um es zu optimieren							

	move.w	#(64*39)+4,d5		; Wert zum Schreiben in BLTSIZE
								; Wir haben es in d5 zur Optimierung gebracht							

	btst	#6,2(a5) 			; DMACONR
WaitBlit3:
	btst	#6,2(a5) 			; warte auf das Ende des Blitters
	bne.s	WaitBlit3			; vor dem Ändern der Register

	move.w	#32,$66(a5)			; BLTDMOD (40-8=32)
	move.w	d0,$40(a5)			; BLTCON0 Diese 2 Register werden verwendet
								; mit verschiedenen Werten in der Routine
								; ClearScreen
DrawLoop:
	btst	#6,2(a5) 			; DMACONR
WaitBlit4:
	btst	#6,2(a5) 			; warte auf das Ende des Blitters
	bne.s	WaitBlit4			; vor dem blitten

	move.l	a2,$50(a5)			; BLTAPT  Zeigermaske
								; der Wert wurde zuvor
								; in a2 geschrieben
	move.l	a0,$4c(a5)			; BLTBPT Zeiger Figur
	move.l	a1,$54(a5)			; BLTDPT Zeiger Ziel
	move.w	d5,$58(a5)			; Schreibe BLTSIZE
								; den Wert der zuvor
								; in d5 geschrieben wurde

	add.w	#56*40,a0			; Adresse nächste Bitplane Figur
	add.w	#256*40,a1			; Adresse nächste Bitplane Ziel
	dbra	d7,DrawLoop
	rts

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

MoveMask:
	addq.l	#2,TabXpoint		; auf das nächste Wort zeigen
	move.l	TabXpoint(pc),a0	; Adresse, die im long 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 	; wir beginnen wieder mit dem ersten Wort-2
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

; Maske Positionstabelle

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,$5200			; BPLCON0

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
	dc.w	$f0,$0000,$f2,$0000

Colors:
	dc.w	$180,0,$182,$f10,$184,$f21,$186,$f42
	dc.w	$188,$f53,$18a,$f63,$18c,$f74,$18e,$f85
	dc.w	$190,$f96,$192,$fa6,$194,$fb7,$196,$fb8
	dc.w	$198,$fc9,$19a,$f21,$19c,$f10,$19e,$f00
	dc.w	$1a0,$eff,$1a2,$eff,$1a4,$dff,$1a6,$dff
	dc.w	$1a8,$cff,$1aa,$bef,$1ac,$bef,$1ae,$adf
	dc.w	$1b0,$9df,$1b2,$9cf,$1b4,$8bf,$1b6,$7bf
	dc.w	$1b8,$7af,$1ba,$69f,$1bc,$68f,$1be,$57f

	dc.w	$ffff,$fffe			; Ende Copperlist

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

; Hier ist das Design, 320 Pixel breit, 56 Zeilen hoch und 5 Ebenen

Figur:
	incbin	"/Sources/lava320x56x5.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
	
;*****************************************************************************

	SECTION	LEEREPLANE,BSS_C

Bitplane1:
	ds.b	40*256
Bitplane2:
	ds.b	40*256
Bitplane3:
	ds.b	40*256
Bitplane4:
	ds.b	40*256
Bitplane5:
	ds.b	40*256

	end

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

Dieses Beispiel ist die optimierte Version von Listing10c4.s. Die Optimierungen
werden im Listing erläutert.
