
; Listing8n2.s - Optimierte Punktdruckroutine. Es wird die Geschwindigkeit
; dieser Routine im Vergleich zur nicht optimierten verglichen.
; Drücken Sie die RECHTE Maustaste umd die optimierte Routine zu testen, 
; ansonsten arbeitet die normale Routine.

	SECTION	PUNKT,CODE

;	include	"DaWorkBench.s"	; entferne das; vor dem Speichern mit "wo"

*****************************************************************************
	include	"/Sources/Startup1.s"	; damit mache ich Einsparungen und 
									; schreib es nicht jedes mal neu!			
*****************************************************************************


; Mit DMASET entscheiden wir, welche DMA-Kanäle geöffnet und welche
; geschlossen werden sollen

			;5432109876543210
DMASET	equ	%1000001110000000	; Copper und Bitplane DMA aktivieren
;			 -----a-bcdefghij

BreiteBildschirm	equ	40		; Bildschirmbreite in Bytes

Start:
	move.l	#Bitplane,d0		; Adresse der Bitplane
	lea	Bplpointers,a1			; Bitplanepointer in der Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)

; Wir bereiten eine Tabelle mit den Vielfachen von 40 oder der Breite des
; Bildschirms vor, um eine Multiplikation für jeden Plot zu vermeiden.

	lea	MulTab,a0				; Adressraum von 256 zu schreibenden Wörtern
								; Vielfache von 40 ...
	moveq	#0,d0				; Start mit 0...
	move.w	#256-1,d7			; Anzahl der Vielfachen von 40 erforderlich
PreCalcLoop
	move.w	d0,(a0)+			; wir speichern das aktuelle Vielfache
	add.w	#BreiteBildschirm,d0		; Bildbreite hinzufügen, nächstes Vielfaches
	dbra	d7,PreCalcLoop		; Wir erstellen die gesamte MulTab
	
	move.w	#DMASET,$96(a5)		; DMACON - aktivieren Bitplane, Copper	
								
; Zeiger auf die Copperlist	
	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"

	lea	Bitplane,a0				; Bitplane-Adresse, an der in a0 gedruckt werden soll
	lea	MulTab,a1				; Tabellenadresse mit Vielfachen der Bildschirmbreite
								; vorberechneter Bildschirm in a1

Mouse:
	bsr.s	Koordinate			; Koordinatenschleifen für den gesamten Bildschirm
	move.w	MeinX(pc),d0		; Koordinate X
	move.w	MeinY(pc),d1		; Koordinate Y

	btst	#2,$16(a5)			; rechte Maustaste gedrückt?
	beq.s	Optimiert
	btst.b	#1,DoFlag			; Zurücksetzen oder einstellen?
	bne.s	DoDot
	bsr.s	PlotPix				; den Punkt auf die Koordinate X=d0, Y=d1 drucken
	bra.s	OkPlot
DoDot:
	bsr.s	ErasePix			; den Punkt von der Koordinate X=d0, Y=d1 zurücksetzen
	bra.s	OkPlot

Optimiert:
	btst.b	#1,DoFlag			; Zurücksetzen oder einstellen?
	bne.s	DoDotOpt
	bsr.w	PlotPixP			; den Punkt auf die Koordinate X=d0, Y=d1 drucken
	bra.s	OkPlot
DoDotOpt:
	bsr.w	ErasePixP			; den Punkt von der Koordinate X=d0, Y=d1 zurücksetzen
OkPlot:
	btst	#6,$bfe001			; linke Maustaste gedrückt?
	bne.s	Mouse
	rts							; exit



MeinX:
	dc.w	0
MeinY:
	dc.w	0
DoFlag:
	dc.w	0

;		    ___
;		   /_ -\
;		  ( ¢ ¢ )
;		   \ ° /
;		  /¯\¬/¯\
;		 /   Y   ·
;		·    `

; Routine, die kontinuierlich den gesamten Bildschirm druckt und löscht
; Punkt zu einer Zeit.

Koordinate:
	addq.w	#1,MeinX			; nächstes Pixel in der Zeile
	cmp.w	#320,MeinX			; letztes Pixel dieser Zeile?
	beq.s	FinishedLine		; wenn ja, fangen wir mit dem folgenden an!
	rts							; ansonsten machen wir diesen Punkt!

FinishedLine:
	clr.w	MeinX				; beginnen wir wieder am Anfang der Zeile
	addq.w	#1,MeinY			; in der Zeile darunter...
	cmp.w	#256,MeinY			; haben wir den Bildschirm fertiggestellt? Letzte Zeile?
	beq.s	ChangePart
	rts

ChangePart:
	bchg.b	#1,DoFlag			; ändert den Schreib- / Löschstatus
	clr.w	MeinX				; und von der Koordinate X = 0 beginnen
	clr.w	MeinY				; Y=0
	rts

*****************************************************************************
;		Routine zum Plotten eines Punktes - normal
*****************************************************************************

;	Eingehende Parameter von PlotPix:
;
;	a0 = Ziel-Bitplane-Adresse
;	d0.w = Koordinate X (0-319)
;	d1.w = Koordinate Y (0-255)


PlotPix:
	move.w	d0,d2				; Koordinate X in d2 kopieren 
	lsr.w	#3,d0				; den horizontalen Versatz finden, in dem wir
								; die X-Koordinate durch 8 teilen
	mulu.w	#BreiteBildschirm,d1
	add.w	d1,d0				; den vertikalen zum horizontalen Versatz hinzufügen

	and.w	#%111,d2			; nur die ersten 3 Bits von X auswählen (Rest)
	not.w	d2					; negieren

	bset.b	d2,(a0,d0.w)		; Bit d2 des Bytes setzen, das d0 Bytes 
								; vom Anfang des Bildschirms entfernt ist
	rts

; Routine, die ein Pixel löscht. Ersetzen Sie einfach BSET durch BCLR.

ErasePix:
	move.w	d0,d2				; Koordinate X in d2 kopieren 
	lsr.w	#3,d0				; den horizontalen Versatz finden, in dem wir
								; die X-Koordinate durch 8 teilen
	mulu.w	#BreiteBildschirm,d1
	add.w	d1,d0				; den vertikalen zum horizontalen Versatz hinzufügen

	and.w	#%111,d2			; nur die ersten 3 Bits von X auswählen (Rest)
	not.w	d2					; negieren

	bclr.b	d2,(a0,d0.w)		; Bit d2 des Bytes zurücksetzen, das d0 Bytes 
								; vom Anfang des Bildschirms entfernt ist
	rts

*****************************************************************************
;		Routine zum Plotten eines Punktes - optimiert
*****************************************************************************

;	Eingehende Parameter von PlotPixP:
;
;	a0 =  Ziel-Bitplane-Adresse
;	a1 = Adresse der Tabelle mit Vielfachen von 40 vorberechnet
;	d0.w = Koordinate X (0-319)
;	d1.w = Koordinate Y (0-255)

PlotPixP:
	move.w	d0,d2				; Koordinate X in d2 kopieren
	lsr.w	#3,d0				; den horizontalen Versatz finden, in dem wir
								; die X-Koordinate durch 8 teilen
	add.w	d1,d1				; wir multiplizieren das Y mit 2 und finden den Versatz
	add.w	(a1,d1.w),d0		; vertikaler Versatz + horizontaler Versatz
	and.w	#%111,d2			; nur die ersten 3 Bits von X auswählen (Rest)
	not.w	d2					; negieren
	bset	d2,(a0,d0.w)		; Bit d2 des Bytes setzen, das d0 Bytes 
								; vom Anfang des Bildschirms entfernt ist
	rts

; Routine, die ein Pixel löscht. Ersetzen Sie einfach BSET durch BCLR.

ErasePixP:
	move.w	d0,d2				; Koordinate X in d2 kopieren
	lsr.w	#3,d0				; den horizontalen Versatz finden, in dem wir
								; die X-Koordinate durch 8 teilen
	add.w	d1,d1				; wir multiplizieren das Y mit 2 und finden den Versatz
	add.w	(a1,d1.w),d0		; vertikaler Versatz + horizontaler Versatz
	and.w	#%111,d2			; nur die ersten 3 Bits von X auswählen (Rest)
	not.w	d2					; negieren
	bclr	d2,(a0,d0.w)		; Bit d2 des Bytes zurücksetzen, das d0 Bytes 
								; vom Anfang des Bildschirms entfernt ist
	rts

*****************************************************************************

	SECTION	GRAPHIC,DATA_C

Copperlist:
	dc.w	$8e,$2c81			; DIWSTRT
	dc.w	$90,$2cc1			; DIWSTOP
	dc.w	$92,$0038			; DDFSTRT
	dc.w	$94,$00d0			; DDFSTOP
	dc.w	$102,0				; BPLCON1
	dc.w	$104,$24			; BPLCON2 - Alle Sprites über der Bitplane
	dc.w	$108,0				; BPL1MOD
	dc.w	$10a,0				; BPL2MOD
				; 5432109876543210
	dc.w	$100,%0001001000000000	; 1 Bitplane LOWRES 320x256

Bplpointers:
	dc.w	$e0,0,$e2,0			; erste Bitplane

	dc.w	$0180,$000			; COLOR00 - Hintergrund
	dc.w	$0182,$1af			; COLOR01 - Schrift

	dc.w	$ffff,$fffe			; Ende Copperlist


*****************************************************************************

	SECTION	MEINEPLANE,BSS_C

Bitplane:
	ds.b	40*256				; eine Bitplane lowres 320x256

; Tabelle, die die vorberechneten Vielfachen der Bildschirmbreite enthält
; zur Beseitigung der Multiplikation in der PlotPix-Routine und zur Erhöhung
; ihrer Geschwindigkeit.

	SECTION	PRECALC,BSS

MulTab:
	ds.w	256

	end

Diese Listing ist als Test gedacht, um zu sehen, ob die Routine wirklich ohne
Multiplikation schneller läuft. Zu diesem Zweck wird der gesamte Bildschirm mit
'ErasePix' gelöscht, was nichts anderes ist als die normale Routine mit BCLR
anstelle von BSET zu verwenden. Normalerweise wird die nicht optimierte Routine
ausgeführt. Wenn Sie die rechte Taste gedrückt halten, wird die optimierte
Routine ausgeführt. Abhängig vom Computer und dem Vorhandensein von FAST RAM
wird das Ergebnis anders sein. Zum Beispiel, wenn die Tabelle im CHIP RAM
anstatt im FAST RAM gespeichert wird, wird die Geschwindigkeit geringer sein.
Auf dem 68040 sind Multiplikationen zum Beispiel viel schneller als bei
früheren Prozessoren, so dass die Ausführung dieses Listings ohne Fast RAM und
mit deaktivierten Caches langsamer ist als die Routine ohne Multiplikation, da
sie auf die Tabelle in CHIP RAM zugreifen muss.
Diejenigen, die einen A4000 haben, haben auch FAST RAM, aber keine Sorge, 
auch auf 68030 oder niedriger, ist das Entfernen einer Multiplikation immer eine 
gute Maßnahme.
