
; Listing9i3r.s		BOB rawblit mit Hintergrundwiederherstellung.
; 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


Start:
	move.l	#Bitplane,d0			; Zeiger auf das Bild
	lea	Bplpointers,a1				; Zeiger Copperlist
	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
									; HIER IST DER ERSTE UNTERSCHIED
									; ZU DEN NORMALEN BILDERN !!!!!!
	add.l	#40,d0					; + LÄNGE EINER Zeile !!!!!
	addq.w	#8,a1
	dbra	d1,PointBp

	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.w	ReadMouse				; Koordinaten lesen
	bsr.s	ControlCoordinate		; verhindert, dass der Bob den Bildschirm verlässt
	bsr.w	SaveBackground			; speichert den Hintergrund
	bsr.s	DesignObject			; zeichnet 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	RestoreBackground		; stellt den Hintergrund wieder her

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

	rts


;****************************************************************************
; Diese Routine stellt sicher, dass die Bob-Koordinaten 
; innerhalb des Bildschirms immer enthalten bleiben.
;****************************************************************************

ControlCoordinate:
	tst.w	ObjX				; X überprüfen
	bpl.s	NoMinX				; den linken Rand überprüfen
	clr.w	ObjX				; Wenn X negativ ist, setze X = 0
	bra.s	ControlY			; Geh und überprüfe das Y

NoMinX:
	cmp.w	#319-32,ObjX		; die rechte Kante überprüfen in ObjX
								; Die Kantenkoordinate wird links vom Bob
								; gespeichert. Wenn es 319-32 erreicht hat,
								; dann ist die rechte Kante erreicht
								; d.h. die Koordinate X=319.
	bls.s	ControlY			; Wenn alles in Ordnung ist, überprüfe das Y
	move.w	#319-32,ObjX		; Andernfalls wird die Koordinate an der Kante fixiert.

ControlY:
	tst.w	ObjY				; überprüfe die obere Kante
	bpl.s	NoMinY				; Wenn es positiv ist, überprüfe unten
	clr.w	ObjY				; andernfalls setze Y = 0
	bra.s	EndControl			; und geh raus

NoMinY:
	cmp.w	#255-11,ObjY		; die untere Kante überprüfen in ObjY
								; Die Kantenkoordinate wird oben vom Bob
								; gespeichert. Wenn es Y = 255-11 erreicht hat,
								; dann ist die untere Kante erreicht
								; die Koordinate Y = 255 
	bls.s	EndControl			; Wenn alles in Ordnung ist, überprüfe das Y
	move.w	#255-11,ObjY		; Andernfalls wird die Koordinate an der Kante fixiert.
EndControl:
	rts

;***************************************************************************
; Diese Routine zeichnet den BOB an die in den Variablen ObjX und ObjY 
; angegebenen Koordinaten. Der BOB und der Bildschirm sind im interleaved 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 //
;	     |__|//
;	     (___/
;	     C__)
;	    /`--'\
;	   /_/  \_\
;	  (,,)  (,,)
;	   ¯T____T¯
;	    /  _ \
;	    \__\  \ xCz
;	    /  X___\__
;	   (__/ `-----'

DesignObject:
	lea	Bitplane,a0				; Ziel in a0
	move.w	ObjY(pc),d0			; Koordinate Y
	mulu.w	#3*40,d0			; Adresse berechnen: Jede Zeile besteht aus
								; 3 Ebenen mit je 40 Bytes
	add.w	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

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

	move.l	#$ffff0000,$44(a5)	; BLTAFWM = $ffff es passiert alles
								; BLTALWM = $0000 setzt das letzte Wort zurück
								
	move.w	d0,$40(a5)			; BLTCON0 (A+D)
	move.w	#$0000,$42(a5)		; BLTCON1 (keine Spezialmodi)
	move.l	#$fffe0022,$64(a5)	; BLTAMOD=$fffe=-2 komm zurück
								; an den Anfang der Zeile.
								; BLTDMOD=40-6=34=$22 wie immer
	move.l	#Figur,$50(a5)		; BLTAPT  (an der Quellfigur fixiert)
	move.l	a0,$54(a5)			; BLTDPT  (Bildschirm)
	move.w	#(64*11*3)+3,$58(a5)	; BLTSIZE (start Blitter!)
	rts

;****************************************************************************
; Diese Routine kopiert das Hintergrundrechteck, das von dem Bob 
; überschrieben wird in einem Puffer
;****************************************************************************

SaveBackground:
	lea	Bitplane,a0				; Ziel in a0
	move.w	ObjY(pc),d0			; Koordinate Y
	mulu.w	#3*40,d0			; Adresse berechnen: Jede Zeile besteht aus
								; 3 Ebenen mit je 40 Bytes
	add.w	d0,a0				; zur Anfangsadresse hinzufügen

	move.w	ObjX(pc),d1			; Koordinate X
	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

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

	move.l	#$ffffffff,$44(a5)	; BLTAFWM = $ffff es passiert alles
								; BLTALWM = $ffff es passiert alles
								
	move.l	#$09f00000,$40(a5)	; BLTCON0 und BLTCON1 Kopie von A nach D
	move.l	#$00220000,$64(a5)	; BLTAMOD=40-4=36=$24
								; BLTDMOD=0 im Puffer
	move.l	a0,$50(a5)			; BLTAPT - Adresse Quelle
	move.l	#Buffer,$54(a5)		; BLTDPT - Puffer
	move.w	#(64*11*3)+3,$58(a5)	; BLTSIZE (starte Blitter !)
	rts

;****************************************************************************
; Diese Routine kopiert den Inhalt des Puffers in das Bildschirmrechteck
; welches es vor dem Zeichnen des BOB enthielt. Auf diese Weise kommt auch
; das gelöschte BOB von der alten Position.
;****************************************************************************

RestoreBackground:
	lea	Bitplane,a0				; Ziel in a0
	move.w	ObjY(pc),d0			; Koordinate Y
	mulu.w	#3*40,d0			; Adresse berechnen: Jede Zeile besteht aus
								; 3 Ebenen mit je 40 Bytes
	add.w	d0,a0				; zur Anfangsadresse hinzufügen

	move.w	ObjX(pc),d1			; Koordinate X
	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

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

	move.l	#$ffffffff,$44(a5)	; BLTAFWM = $ffff es passiert alles
								; BLTALWM = $ffff es passiert alles
								
	move.l	#$09f00000,$40(a5)	; BLTCON0 und BLTCON1 Kopie von A nach D
	move.l	#$00000022,$64(a5)	; BLTAMOD=0 (buffer)
								; BLTDMOD=40-6=34=$22
	move.l	#Buffer,$50(a5)		; BLTAPT (Puffer)
	move.l	a0,$54(a5)			; BLTDPT (Bildschirm)
	move.w	#(64*11*3)+3,$58(a5)	; BLTSIZE (starte Blitter !)
	rts

;****************************************************************************
; Diese Routine liest die Maus und aktualisiert die Werte in den
; Variablen ObjX und ObjY 
;****************************************************************************

ReadMouse:
	move.b	$dff00a,d1			; JOY0DAT - vertikale Mausposition
	move.b	d1,d0				; Kopie in d0
	sub.b	MouseY(pc),d0		; subtrahieren der alten Mausposition
	beq.s	NoVert				; Wenn die Differenz = 0 ist, steht die Maus still
	ext.w	d0					; wandelt das Byte in ein Wort um
	add.w	d0,ObjY				; Objektposition ändern

NoVert:
  	move.b	d1,MouseY			; speichern der Mausposition für das nächste Mal

	move.b	$dff00b,d1			; JOY0DAT - horizontale Mausposition
	move.b	d1,d0				; Kopie in d0
	sub.b	MouseX(pc),d0		; subtrahieren der alten Mausposition
	beq.s	NoHoriz				; Wenn die Differenz = 0 ist, steht die Maus still
	ext.w	d0					; wandelt das Byte in ein Wort um
	add.w	d0,ObjX				; Objektposition ändern
NoHoriz
  	move.b	d1,MouseX			; speichern der Mausposition für das nächste Mal
	rts

ObjY:		dc.w	0			; hier wird das Y des Objektes gespeichert
ObjX:		dc.w	0			; hier wird das X des Objektes gespeichert
MouseY:		dc.b	0			; hier wird das Y der Maus gespeichert
MouseX:		dc.b	0			; hier wird das X der Maus gespeichert


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

	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

								; HIER IST DER ZWEITE UNTERSCHIED
								; ZU DEN NORMALEN BILDERN !!!!!!
	dc.w	$108,80				; WERT Modulo = 2*20*(3-1)= 80
	dc.w	$10a,80				; BEIDE MODULO MIT GLEICHEM WERT.

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

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

	dc.w	$0180,$000			; COLOR00
	dc.w	$0182,$475			; COLOR01
	dc.w	$0184,$fff			; COLOR02
	dc.w	$0186,$ccc			; COLOR03
	dc.w	$0188,$999			; COLOR04
	dc.w	$018a,$232			; COLOR05
	dc.w	$018c,$777			; COLOR06
	dc.w	$018e,$444			; COLOR07

	dc.w	$ffff,$fffe			; Ende Copperlist

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

; Dies sind die Daten, aus denen sich die Bob-Figur zusammensetzt.
; Der Bob ist interleaved, 32 Pixel breit (2 Wörter)
; 11 Zeilen hoch und wird von 3 Bitplanes gebildet

Figur:	
	dc.l	$007fc000,$00000000,$007fc000
	dc.l	$03fff800,$007fc000,$03803800
	dc.l	$07fffc00,$03fff800,$04000400
	dc.l	$0ffffe00,$07fffc00,$081f8200
	dc.l	$1fe07f00,$0fe07e00,$10204100
	dc.l	$1fe07f00,$0fe07e00,$10204100
	dc.l	$1fe07f00,$0fe07e00,$10204100
	dc.l	$0ffffe00,$07fffc00,$081f8200
	dc.l	$07fffc00,$03fff800,$04000400
	dc.l	$03fff800,$007fc000,$03803800
	dc.l	$007fc000,$00000000,$007fc000

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

Bitplane:
	incbin	"/Sources/amiga.rawblit"	
								; hier laden wir die Figur in
								; RAWBLIT-Format (oder Interleaved-Format)
								; konvertiert mit KEFCON.

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

	SECTION	BUFFER,BSS_C

; Dies ist der Puffer, in dem wir von Zeit zu Zeit den Hintergrund speichern.
; Er hat die gleichen Abmessungen wie ein Blitt: Höhe 11, Breite 3 Wörter
; 3 Bitplanes

Buffer:
	ds.w	11*3*3

	end

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

Dieses Beispiel ist die Rawblit-Version von Listing9i3.s.
Vergleichen Sie die Unterschiede in den Formeln zur Berechnung der zu 
schreibenden Werte in die Blitter-Register.
