
; Listing10f2.s		Viele BOBs mit "Fake" und "Double Buffering" Hintergrund
; 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


; konstante Kanten
LOWESTFLOOR	equ	200				; Unterkante
RIGHTSIDE	equ	287				; Rand rechts


Start:
; Die ersten drei Bitplanes werden in der SwapBuffer-Routine ausgerichtet
; Lass uns die vierte Bitebene für den Hintergrund setzen

	move.l	#FakeBackground,d0	; Adresse Hintergrund
	lea	Bplpointers,a0			; Bitplanepointer	
	move.w	d0,30(a0)			; der Hintergrund ist Bitplane 4
	swap	d0	
	move.w	d0,26(a0)			; schreibe hohes Wort

	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:
	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	SwapBuffer			; Diese Routine tauscht die 2 Puffer aus
	bsr.w	ClearScreen			; Bildschirm löschen

	lea	Object1,a4				; Adresse erstes Objekt
	moveq	#6-1,d6				; 6 Objekte
ObjectLoop:
	bsr.s	MoveObject			; bewege Bob
	bsr.w	DesignObject		; zeichne Bob

	addq.l	#8,a4				; Zeige auf das nächste Objekt
	dbra	d6,ObjectLoop
	
	move.w	#$aaa,$180(a5)		; Coppermonitor: Farbe grau

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

	rts

;****************************************************************************
; Diese Routine tauscht die 2 Puffer durch den Austausch der Adressen der
; ViewBuffer und DrawBuffer Variablen aus.
; Es aktualisiert auch die Anweisungen welche die BPLxPT-Register in die 
; Copperlist laden, so dass sie auf den neuen Puffer zeigen, der angezeigt 
; werden soll.
;****************************************************************************

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

SwapBuffer:
	move.l	DrawBuffer(pc),d0	; Tausche den Inhalt 
	move.l	ViewBuffer(pc),DrawBuffer	; der Variablen aus
	move.l	d0,ViewBuffer		; in d0 steht die Adresse
								; des neuen View-Puffers
									
; Aktualisieren der copperliste, indem sie auf die Bitebenen 
; des neuen Puffers zeigen, der angezeigt werden soll

	lea	Bplpointers,a1			; Zeiger Copperlist
	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)
	addq.w	#8,a1
	dbra	d1,PointBp

	rts

;****************************************************************************
; Diese Routine bewegt einen Bob, indem überprüft wird, dass die Kanten nicht 
; überschritten werden
; a4 - zeigt auf die Datenstruktur, die die Position und die Geschwindigkeit 
; vom Bob enthält
;****************************************************************************

MoveObject:
	move.w	(a4),d0				; Position X
	move.w	2(a4),d1			; Position Y
	move.w	4(a4),d2			; dx (Geschwindigkeit X)
	move.w	6(a4),d3			; dy (Geschwindigkeit Y)
	add.w	d2,d0				; x = x + dx
	add.w	d3,d1				; y = y + dy
	btst	#15,d1				; Kontrolle hohe Kante (Y=0)
	beq.s	NoBounce4			; wenn das Y negativ ist...
	neg.w	d1					; .. springt er zurück
	neg.w	d3					; umgekehrte Bewegungsrichtung

NoBounce4:
	cmp.w	#LOWESTFLOOR,d1		; Kontrolle Unterkante
	blt.s	NoBounce1
	neg.w	d3					; ändere das Geschwindigkeitszeichen dy
								; Umkehr der Bewegungsrichtung
	move.w	#LOWESTFLOOR,d1		; Beginne von der Kante

NoBounce1:
	cmp.w	#RIGHTSIDE,d0		; Überprüfe die rechte Kante
	blt.s	NoBounce2			; wenn es die rechte Kante überschreitet..
	sub.w	#RIGHTSIDE,d0		; Abstand vom Rand
	neg.w	d0					; Die Entfernung umkehren
	add.w	#RIGHTSIDE,d0		; Board-Koordinate hinzufügen
	neg.w	d2					; umgekehrte Bewegungsrichtung
NoBounce2:
	btst	#15,d0				; Überprüfe den linken Rand (X = 0)
	beq.s	NoBounce3			; wenn das X negativ ist...
	neg.w	d0					; ..  springt er zurück
	neg.w	d2					; umgekehrte Bewegungsrichtung
NoBounce3:
	move.w	d0,(a4)				; aktualisiere Position und Geschwindigkeit
	move.w	d1,2(a4)
	move.w	d2,4(a4)
	move.w	d3,6(a4)

	rts
	
;****************************************************************************
; Diese Routine zeichnet ein BOB.
; a4 - zeigt auf die Datenstruktur, die die Position und die Geschwindigkeit 
; vom Bob enthält
;****************************************************************************

DesignObject:
	move.l	DrawBuffer(pc),a0	; Adresse Puffer Zeichnung
	move.w	2(a4),d0			; Koordinate Y
	mulu.w	#40,d0				; Adresse berechnen: Jede Zeile belegt 40 Bytes
	add.l	d0,a0				; offset hinzufügen Y
	move.w	(a4),d0				; Koordinate X
	move.w	d0,d1				; 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	#$0fca,d0			; ..rechts, um in das BLTCON0-Register zu kommen
	lsr.w	#3,d1				; (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.l	#$0000fffe,d1		; Ich schließe Bit 0 aus
	add.w	d1,a0				; addieren zur Adresse der Bitebene, 
								; um die richtige Zieladresse zu finden

	lea	BallBob,a1				; Zeiger auf die Figur
	lea	BallMask,a2				; Zeiger auf die Maske
	moveq	#3-1,d7				; Bitplane Zähler

DrawLoop:
	btst	#6,2(a5)
WaitBlit:
	btst	#6,2(a5)
	bne.s	WaitBlit

	move.w	d0,$40(a5)			; BLTCON0 - schreibe Verschiebungswert
	move.w	d0,d1				; Kopie von BLTCON0,
	and.w	#$f000,d1			; Verschiebungswert auswählen..
	move.w	d1,$42(a5)			; und schreibe es in BLTCON1 (für Kanal B)

	move.l	#$ffff0000,$44(a5)	; BLTAFWM und BLTLWM

	move.w	#$fffe,$64(a5)		; BLTAMOD
	move.w	#$fffe,$62(a5)		; BLTBMOD
	move.w	#40-6,$60(a5)		; BLTCMOD
	move.w	#40-6,$66(a5)		; BLTDMOD

	move.l	a2,$50(a5)			; BLTAPT - Zeiger Maske
	move.l	a1,$4c(a5)			; BLTBPT - Zeiger Figur
	move.l	a0,$48(a5)			; BLTCPT - Zeiger Hintergrund
	move.l	a0,$54(a5)			; BLTDPT - Zeiger Bitplanes

	move.w	#(31*64)+3,$58(a5)	; BLTSIZE - Höhe 31 Zeilen
				 				; Breite 3 Word (48 pixel).

	add.l	#40*256,a0			; Adresse nächste Bitebene Ziel
	add.l	#4*31,a1			; Adresse nächste Bitebene Bild
	dbra	d7,DrawLoop
	
	rts

;****************************************************************************
; Diese Routine löscht den Bildschirm mit dem Blitter.
;****************************************************************************

ClearScreen:
	moveq	#3-1,d7				; 3 Bitplanes
	lea	Bitplane1,a0			; Adresse pitplane

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

	move.l	#$01000000,$40(a5)	; BLTCON0 und BLTCON1: Löschung
	move	#0,$66(a5)			; BLTDMOD=0
	move.l	a0,$54(a5)			; BLTDPT
	move.w	#(64*256)+20,$58(a5)	; BLTSIZE (Blitter starten !)
								; lösche den gesamten Bildschirm

	add.l	#40*256,a0			; Adresse nächstes plane Ziel
	dbra	d7,ClearLoop
	rts

; Zeiger auf die 2 Puffer
ViewBuffer	dc.l	Bitplane1	; Puffer Anzeige
DrawBuffer	dc.l	Bitplane1b	; Puffer Design

; Datenobjekte
; Das ist die Datenstruktur, die die Geschwindigkeit und Position der 
; Bobs enthalten.
; Jede Datenstruktur besteht aus 4 Wörtern, die der Reihe nach enthalten:
; X-POSITION, Y-POSITION, X-GESCHWINDIGKEIT, Y-GESCHWINDIGKEIT

Object1:
	dc.w	32,53				;  x / y   - Position
	dc.w	-3,1				; dx / dy  - Geschwindigkeit

Object2:
	dc.w	132,62				;  x / y   - Position
	dc.w	2,-1				; dx / dy  - Geschwindigkeit

Object3:
	dc.w	232,42				;  x / y   - Position  
	dc.w	3,1					; dx / dy  - Geschwindigkeit

Object4:
	dc.w	2,20				;  x / y   - Position
	dc.w	-5,1				; dx / dy  - Geschwindigkeit

Object5:
	dc.w	60,80				;  x / y   - Position 
	dc.w	6,1					; dx / dy  - Geschwindigkeit

Object6:
	dc.w	50,75				;  x / y   - Position
	dc.w	-5,1				; dx / dy  - Geschwindigkeit

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

	SECTION	MY_COPPER,CODE_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				; MODULO
	dc.w	$10a,0

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	$180,$000			; COLOR00 - Hintergrund
	dc.w	$190,$000

 	dc.w	$182,$0a0			; Farbe von 1 bis 7
 	dc.w	$184,$040
 	dc.w	$186,$050
 	dc.w	$188,$061
 	dc.w	$18a,$081
 	dc.w	$18c,$020
 	dc.w	$18e,$6f8

	dc.w	$192,$0a0			; Farbe von 9 bis 15
	dc.w	$194,$040			; sie sind die gleichen Werte
	dc.w	$196,$050			; geladen in den Registern 1 bis 7
	dc.w	$198,$061
	dc.w	$19a,$081
	dc.w	$19c,$020
	dc.w	$19e,$6f8

	dc.w	$190,$345			; Farbe 8 - pixel zu 1 des Hintergrunds

	dc.w	$100,$3200			; BPLCON0 - 3 Bitplanes lowres

	dc.w	$8007,$fffe			; warte Linie $80
	dc.w	$100,$4200			; BPLCON0 - 4 Bitplanes lowres
								; Bitebene 4 aktivieren (Hintergrund)

; In diesem Feld wird der Teil des Hintergrunds angezeigt

	dc.w	$e007,$fffe			; warte Linie $e0
	dc.w	$100,$3200			; BPLCON0 - 3 Bitplanes lowres

	dc.w	$ffff,$fffe			; Ende Copperlist

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

; Figur Bob
BallBob:
	dc.w $0000,$0000,$0000,$0000,$0000,$0000,$003f,$8000	; plane 1
	dc.w $00c1,$e000,$017c,$e000,$02fe,$3000,$05ff,$5400
	dc.w $07ff,$1800,$0bfe,$ac00,$03ff,$1a00,$0bfe,$ac00
	dc.w $11ff,$1a00,$197d,$2c00,$0eaa,$1a00,$1454,$dc00
	dc.w $0e81,$3800,$0154,$f400,$02eb,$f000,$015f,$d000
	dc.w $00b5,$a000,$002a,$8000,$0000,$0000,$0000,$0000
	dc.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
	dc.w $0000,$0000,$0000,$0000,$0000,$0000

	dc.w $000f,$e000,$007f,$fc00,$01ff,$ff00,$03ff,$ff80	; plane 2
	dc.w $07c1,$ffc0,$0f00,$ffe0,$1e00,$3ff0,$3c40,$5ff8
	dc.w $3ce0,$1ff8,$7840,$2ffc,$7800,$1ffc,$7800,$2ffc
	dc.w $f800,$1ffe,$f800,$2ffe,$fe00,$1ffe,$fc00,$dffe
	dc.w $fe81,$3ffe,$ff54,$fffe,$ffeb,$fffe,$7fff,$fffc
	dc.w $7fff,$fffc,$7fff,$fffc,$3fff,$fff8,$3fff,$fff8
	dc.w $1fff,$fff0,$0fff,$ffe0,$07ff,$ffc0,$03ff,$ff80
	dc.w $01ff,$ff00,$007f,$fc00,$000f,$e000

	dc.w $000f,$e000,$007f,$fc00,$01e0,$7f00,$0380,$0f80	; plane 3
	dc.w $073e,$0ac0,$0cff,$0560,$198f,$c2f0,$3347,$a0b8
	dc.w $32eb,$e158,$6647,$d0ac,$660b,$e05c,$4757,$d0ac
	dc.w $c7af,$e05e,$a7ff,$d02e,$c1ff,$e05e,$a3ff,$202e
	dc.w $d17e,$c05e,$e0ab,$002e,$d014,$005e,$6800,$00ac
	dc.w $7000,$02dc,$7400,$057c,$2800,$0af8,$3680,$55f8
	dc.w $1d54,$aaf0,$0eab,$55e0,$0754,$abc0,$03eb,$ff80
	dc.w $01fe,$ff00,$007f,$fc00,$000f,$e000

; Maske Bob
BallMask:
	dc.w $000f,$e000,$007f,$fc00,$01ff,$ff00,$03ff,$ff80
	dc.w $07ff,$ffc0,$0fff,$ffe0,$1fff,$fff0,$3fff,$fff8
	dc.w $3fff,$fff8,$7fff,$fffc,$7fff,$fffc,$7fff,$fffc
	dc.w $ffff,$fffe,$ffff,$fffe,$ffff,$fffe,$ffff,$fffe
	dc.w $ffff,$fffe,$ffff,$fffe,$ffff,$fffe,$7fff,$fffc
	dc.w $7fff,$fffc,$7fff,$fffc,$3fff,$fff8,$3fff,$fff8
	dc.w $1fff,$fff0,$0fff,$ffe0,$07ff,$ffc0,$03ff,$ff80
	dc.w $01ff,$ff00,$007f,$fc00,$000f,$e000


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

; Hintergrund 320 * 100 1 Bitplane, raw normal.

FakeBackground:
	incbin	"/Sources/sfondo320x100.raw"

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

	SECTION	LEEREPLANE,BSS_C

; Dies sind die Bitebenen des ersten Puffers
Bitplane1:
	ds.b	40*256
Bitplane2:
	ds.b	40*256
Bitplane3:
	ds.b	40*256

; Dies sind die Bitebenen des zweiten Puffers
Bitplane1b:
	ds.b	40*256
Bitplane2b:
	ds.b	40*256
Bitplane3b:
	ds.b	40*256

	end

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

In diesem Beispiel lösen wir das Problem des Beispiels Listing10f1.s durch
die double buffering Technik. Diese Technik besteht in der Verwendung von
2 separaten Puffern. Einer der angezeigt wird und einer auf dem gezeichnet 
wird. Die Puffer werden bei jedem Vertical Blank ausgetauscht. Die Adressen
der 2 Puffer sind in 2 Variablen enthalten. Die Variable DrawBuffer enthält
die Adresse des Puffers, der zum Zeichnen verwendet wird. Die Routinen, die
den Bildschirm ändern (Bildschirm löschen und Objekt zeichnen) lesen die
Pufferadresse aus DrawBuffer und führen ihre Operationen darauf aus. Die
Variable ViewBuffer enthält die aktuelle Pufferadresse die angezeigt wird.
Die SwapBuffer-Routine tauscht den Inhalt der 2 Variablen mit jedem 
vertical blank aus. Es stellt auch sicher, dass der richtige Puffer angezeigt
wird (der, dessen Adresse in ViewBuffer gespeichert ist). In der Tat, um
abwechselnd die 2 Puffer anzuzeigen, ist es erforderlich, bei jedem frame
die BPLxPT-Register die auf die Bitebenen des Anzeigepuffers zeigen in die
Copperliste zu bringen. Dies bedeutet, dass die Copperliste mit jedem vertical
blank modifiziert wird, was von der SwapBuffer-Routine erledigt wird.
