
; Listing9i4.s		BOB mit "falschem" Hintergrund
; Linke Taste zum Verlassen.

	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				; untere Kante
RIGHTSIDE	equ	287				; rechter Rand	


Start:
	move.l	#Bitplane1,d0		; Zeiger auf das Bild
	lea	Bplpointers,a1			; Bitplanepointer
	moveq	#3-1,d1				; Anzahl Bitplanes (hier sind es 3)
PointBp:
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	swap	d0
	add.l	#40*256,d0			; + Bitplane-Länge (256 Zeilen hoch hier)
	addq.w	#8,a1
	dbra	d1,PointBp

;	Wir zielen auf die vierte Bitebene (den Hintergrund)

	lea	Bplpointers,a0			; Bitplanepointer
	move.l	#Background,d0		; Adresse Hintergrund
	move.w	d0,30(a0)			; Der Hintergrund ist Bitplane 4
	swap	d0	
	move.w	d0,26(a0)			; in das hohe Wort schreiben

	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:
	bsr.s	MoveObject			; bewege den Bob
	bsr.w	DesignObject		; zeichne den Bob
	
	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	ClearObject			; entferne den Bob von der alten Position
							
	btst	#6,$bfe001			; linke Maustaste gedrückt?
	bne.s	Mouse				; Wenn nicht, gehe zurück zu Mouse:

	rts


;****************************************************************************
; Diese Routine bewegt den Bob, indem überprüft wird, dass er die Kanten 
; nicht überschreitet
;****************************************************************************

MoveObject:
	move.w	ObjX(pc),d0			; Position X
	move.w	ObjY(pc),d1			; Position Y
	move.w	VelX(pc),d2			; dx (Geschwindigkeit X)
	move.w	VelY(pc),d3			; dy (Geschwindigkeit Y)
	add.w	d2,d0				; x = x + dx
	add.w	d3,d1				; y = y + dy
	addq.w	#1,d3				; fügt die Schwerkraft hinzu
								; (erhöht die Geschwindigkeit)
	cmp.w	#LOWESTFLOOR,d1		; Überprüfe die Unterkante
	blt.s	NoBounce1

	subq.w	#1,d3				; Entferne die Geschwindigkeitserhöhung
	neg.w	d3					; Ändere das Geschwindigkeitszeichen dy
								; Bewegungsrichtung umkehren
	move.w	#LOWESTFLOOR,d1		; vom Rand weggehen
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					; kehre den Abstand um
	add.w	#RIGHTSIDE,d0		; Randkoordinate hinzufügen
	neg.w	d2					; Bewegungsrichtung umkehren
NoBounce2:
	btst	#15,d0				; linke Kante prüfen (X = 0)
	beq.s	NoBounce3			; wenn das X negativ ist...
	neg.w	d0					; .. macht den Abpraller
	neg.w	d2					; Bewegungsrichtung umkehren
NoBounce3:
	move.w	d0,ObjX				; Position und Geschwindigkeit aktualisieren
	move.w	d1,ObjY
	move.w	d2,VelX
	move.w	d3,VelY

	rts


;****************************************************************************
; Diese Routine zeichnet den BOB an die in den Variablen ObjX und ObjY 
; angegebenen Koordinaten. Der BOB und der Bildschirm sind im normalen Format 
; und daher werden die zu diesem Format gehörenden Formeln bei der Berechnung 
; der Werte, die in die Blitter-Register geschrieben werden benutzt. Auch die
; Technik, das letzte Wort des BOBs zu maskieren, ist in der Lektion zu sehen.
;****************************************************************************

;	     ,-^---^-.
;	   _/  -- --  \_
;	   l_ /¯¯T¯¯\ _|
;	  (¯T \_°|°_/ T¯)
;	   ¯T _ ¯u¯ _ T¯
;	   _| l_____| |_
;	  |¬|   ¯¬¯   |¬|
;	xCz l_________| l

DesignObject:
	lea	Bitplane1,a0			; Ziel in a0
	move.w	ObjY(pc),d0			; Koordinate Y
	mulu.w	#40,d0				; Adresse berechnen: Jede Zeile besteht aus 40 Bytes
	add.l	d0,a0				; zur Anfangsadresse hinzufügen

	move.w	ObjX(pc),d0			; Koordinate X
	move.w	d0,d1				; Kopie
	and.w	#$000f,d0			; wir wählen die ersten 4 Bits aus, 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			; ... rechts in das BLTCON0-Register einzugeben
	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.w	#$fffe,d1			; Ich schließe Bit 0 aus
	add.w	d1,a0				; addieren zur Adresse der Bitebene, 
								; um die richtige Zieladresse zu finden
	
	move.l	a0,AdresseObject	; speichert die Adresse des Ziels
								; für die Lösch-Routine						

	lea	Ball_Bob,a1				; Zeiger auf die Figur
	moveq	#3-1,d7				; Bitplane counter

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

	move.w	d0,$40(a5)			; BLTCON0 - Shift-Wert schreiben
	move.w	#$0000,$42(a5)		; BLTCON1 - aufsteigender Modus
	move.l	#$ffff0000,$44(a5)	; BLTAFWM und BLTLWM
	move.w	#$fffe,$64(a5)		; BLTAMOD
	move.w	#40-6,$66(a5)		; BLTDMOD
	move.l	a1,$50(a5)			; BLTAPT - Zeiger Figur
	move.l	a0,$54(a5)			; BLTDPT - Zeiger Bitplanes

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

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

	dbra	d7,DrawLoop
	rts


;****************************************************************************
; Diese Routine löscht das BOB durch den Blitter. Die Löschung
; wird auf dem Rechteck gemacht, das den Bob einschließt
;****************************************************************************

ClearObject:
	moveq	#3-1,d7				; 3 Bitplanes
	move.l	AdresseObject(pc),a0	; Zieladresse erneut lesen

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

	move.l	#$01000000,$40(a5)	; BLTCON0 und BLTCON1: Löschung
	move	#$0022,$66(a5)		; BLTDMOD=40-6=34=$22
	move.l	a0,$54(a5)			; BLTDPT
	move.w	#(64*31)+3,$58(a5)	; BLTSIZE (Starte Blitter !)
								; Lösche das umschließende Rechteck des Bobs
							
	add.l	#40*256,a0			; nächste Adresse Zielebene
	dbra	d7,ClearLoop
	rts


; Objektdaten

AdresseObject:
	dc.l	0					; Diese Variable enthält die Adresse des
								; Ziels

ObjX:	dc.w	32				; Position X
ObjY:	dc.w	50				; Position Y
VelX:	dc.w	-3				; Geschwindigkeit X
VelY:	dc.w	1				; Geschwindigkeit Y

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

	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			; color 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			; color von 9 bis 15
	dc.w	$194,$040			; es sind die gleichen Werte
	dc.w	$196,$050			; wie 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			; color 8 - Pixel 1 des Hintergrunds

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

	dc.w	$8007,$fffe			; Warte Zeile $80
	dc.w	$100,$4200			; BPLCON0 - 4 Bitplanes lowres
								; aktiviere die Bitplane 4 (Hintergrund)

; In diesem Bereich wird der Teil des Hintergrunds angezeigt

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

	dc.w	$ffff,$fffe			; Ende Copperlist

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

; Figur Bob
Ball_Bob:
	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

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

; Hintergrund 320 * 100 1 Bitplane, raw normal.

Background:
	incbin	"/Sources/sfondo320x100.raw"
	
;****************************************************************************

	SECTION	LEEREPLANE,BSS_C
Bitplane1:
	ds.b	40*256
Bitplane2:
	ds.b	40*256
Bitplane3:
	ds.b	40*256

	end

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

In diesem Beispiel sehen wir einen Bob, der sich auf einem Hintergrund bewegt. 
Den Effekt haben wir aber mit einem Trick erhalten, der die Leistung stark
einschränkt. Der Trick ist Folgender: Wir verwenden 4 Bitebenen, die ersten 3
zum Zeichnen des Bobs und die vierte für den Hintergrund. Der Hintergrund und
der Bob haben daher getrennte Ebenen. Damit der Bob über dem Hintergrund
angezeigt wird, wird die Bitebene erstellt. Der Hintergrund wirkt sich nicht
auf die Farben des Bobs aus. Betrachten Sie zum Beispiel das Pixel des Bobs,
das gebildet wird, indem Ebene 1 = 0, Ebene 2 = 1, Ebene 3 = 1 genommen wird.
Diese Bits der sich bewegenden Pixel werden mit der Ebene 4 überlagert.
Entspricht es einem auf 0 gesetzten Bit, bildet sich für die 4 Ebenen die
Ebene 1 = 0, Ebene 2 = 1, Ebene 3 = 1, Ebene 4 = 0, die Farbe 6.
Wenn stattdessen ein auf 1 gesetztes Bit gefunden wird, bildet sich für die 
Ebene 1 = 0, Ebene 2 = 1, Ebene 3 = 1, Ebene 4 = 1, die Farbe 14. So ändern 
sich die Farben des Bobs in Abhängigkeit der Hintergrundbereichskreuzung. Wir
möchten stattdessen, dass der Bob immer auf dem gleichen Hintergrund erscheint.
Wir können diesen Effekt auf sehr einfache Weise simulieren, indem wir die
Farben in den Registern gleich machen, die sich nur in den Hintergrundbits
unterscheiden.
Zurück zum Beispiel, wenn sie den gleichen RGB-Wert in das COLOR06-Register und
in COLOR14 eingeben. Damit ist der Wert des Bits der Ebene 4 egal und unser
Pixel erscheint immer in der gleichen Farbe. Dasselbe machen wir für alle
anderen Register (dh wir platzieren COLOR01 = COLOR09, COLOR02 = COLOR10,
COLOR03 = COLOR11 usw.) So können wir das Problem lösen.
Der "transparente" Teil des Bobs ist derjenige, der die 3 Ebenen bei 0 hat.
Dies zeigt Farbe 0 oder Farbe 8 an, abhängig vom Wert des Bits in der Ebene 4.
Indem Sie diese beiden Farben unterschiedlich halten, können Sie den
Hintergrund anzeigen: Die Bits bei 0 des Hintergrunds werden in Farbe 0
angezeigt, während die bei 1 in der Farbe 8 angezeigt werden.
Um besser zu verstehen, was passiert, versuchen Sie ein wenig die COLOR01-07
Register auf andere Werte als COLOR09-15 zu setzen: Sie werden den Trick sofort
feststellen. Diese Technik hat den Nachteil, dass einige Farben "verschwendet"
werden. In der Tat sind wir gezwungen, gleiche RGB-Werte in einige Register zu
schreiben und verringern damit die Anzahl der anzeigbaren Farben. In diesem
Beispiel verwenden wir 4 Bitplanes, aber wir können nur 8 Farben für den Bob
und 2 für den Hintergrund verwenden. Wir verschwenden daher 6 Farben. Wenn wir
3 Bitplanes für den Bob und 2 für den Hintergrund verwendet haben, könnten wir
8 + 4 = 12 Farben anzeigen, gegenüber den 32, die normalerweise durch
5 Bitplanes möglich sind. Wie Sie sehen, ist diese Technik daher nicht ideal.
Aber keine Sorge, früher oder später können wir einen richtigen Bob machen!
Beachten Sie in der Zwischenzeit ein paar Dinge in diesem Listing:
1) Wir verwenden den (bereits gesehen) Trick von BLTLWM bei 0, um die
   Wortspalte rechts vom Bob zu speichern;
2) Wir verwenden einen NICHT interleaved Bildschirm, um die
   Hintergrundplane von der Bob Plane zu trennen.
3) In den vorherigen Beispielen berechnen wir die Zieladresse des Bobs, sowohl
   in der Zeichenroutine wie auch in der Löschroutine. Eigentlich zwischen
der Zeichnung und dem anschließenden Löschung ändert der Bob seine Position
nicht. (Erst nach dem Löschen tut er es.) So ist die Berechnung immer gleich
und wird nur einmal gemacht. In diesem Beispiel machen wir genau das:
Die Berechnung erfolgt in der DesignObject-Routine und wird in der Variablen 
AdresseObject gespeichert. Die Löschroutine liest einfach das Ergebnis aus der
Variablen erneut und verwendet sie.               