
; Listing10n.s		Zeichnen einer Linie

	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 die "leere" Bitplane
	lea	Bplpointers,a1			; Bitplanepointer
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)

	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"

	bsr.w	InitLine			; initialisiert line-mode

	move.w	#$ffff,d0			; durchgehende Linie
	bsr.w	SetPattern			; definiert Muster

	move.w	#100,d0				; x1
	move.w	#100,d1				; y1
	move.w	#220,d2				; x2
	move.w	#120,d3				; y2
	lea	Bitplane,a0
	bsr.s	Drawline

	move.w	#160,d0				; x1
	move.w	#85,d1				; y1
	move.w	#160,d2				; x2
	move.w	#140,d3				; y2
	lea	Bitplane,a0
	bsr.s	Drawline

	move.w	#80,d0				; x1
	move.w	#130,d1				; y1
	move.w	#50,d2				; x2
	move.w	#190,d3				; y2
	lea	Bitplane,a0
	bsr.s	Drawline

	move.w	#$f0f0,d0			; gezogene Linie
	bsr.w	SetPattern			; definiert Muster

	move.w	#300,d0				; x1
	move.w	#200,d1				; y1
	move.w	#240,d2				; x2
	move.w	#90,d3				; y2
	lea	Bitplane,a0
	bsr.s	Drawline

	move.w	#$4444,d0			; gezogene Linie
	bsr.w	SetPattern			; definiert Muster

	move.w	#210,d0				; x1
	move.w	#24,d1				; y1
	move.w	#68,d2				; x2
	move.w	#50,d3				; y2
	lea	Bitplane,a0
	bsr.s	Drawline

Mouse:
	btst	#6,$bfe001			; linke Maustaste gedrückt?
	bne.s	Mouse
	rts


;******************************************************************************
; Diese Routine zeichnet die Linie. Sie benötigt als Parameter die Koordinaten
; der Punkte P1 und P2 und die Adresse der Bitebene, auf der gezeichnet werden soll.
; d0 - X1 (X-Koordinate von P1)
; d1 - Y1 (Y-Koordinate von P1)
; d2 - X2 (X-Koordinate von P2)
; d3 - Y2 (Y-Koordinate von P2)
; a0 - Bitplane Adresse
;******************************************************************************

;	    ("`-/")_.-'"``-._
;	     . . `; -._    )-;-,_`)
;	FL  (v_,)'  _  )`-.\  ``-'
;	   _.- _..-_/ / ((.'
;	 ((,.-'   ((,/

Drawline:

* bestimme Oktante

	sub.w	d0,d2				; d2=X2-X1
	bmi.s	Draw4				; Wenn negativ, überspringen Sie andernfalls d2=DiffX
	sub.w	d1,d3				; d3=Y2-Y1
	bmi.s	Draw2				; Wenn negativ, überspringen Sie andernfalls d3=DiffY
	cmp.w	d3,d2				; vergleicht DiffX und DiffY
	bmi.s	Draw1				; wenn d2 < d3 überspringt ..
								; .. sonst d3 = DY und d2 = DX
	moveq	#$10,d5				; Oktantencode
	bra.s	DrawL
Draw1:
	exg.l	d2,d3				; es schaltet zwischen d2 und d3 um, so dass d3 = DY und d2 = DX
	moveq	#0,d5				; Oktantencode
	bra.s	DrawL
Draw2:
	neg.w	d3					; macht d3 positiv
	cmp.w	d3,d2				; vergleiche DiffX und DiffY
	bmi.s	Draw3				; wenn d2 < d3 überspringt ..
								; .. sonst d3 = DY und d2 = DX
	moveq	#$18,d5				; Oktantencode
	bra.s	DrawL
Draw3:
	exg.l	d2,d3				; es schaltet zwischen d2 und d3 um, so dass d3 = DY und d2 = DX
	moveq	#$04,d5				; Oktantencode
	bra.s	DrawL
Draw4:
	neg.w	d2					; macht d2 positiv
	sub.w	d1,d3				; d3=Y2-Y1
	bmi.s	Draw6				; wenn Negativ überspringt, sonst d3 = DiffY
	cmp.w	d3,d2				; vergleiche DiffX und DiffY
	bmi.s	Draw5				; wenn d2 < d3 überspringt ..
								; .. sonst d3 = DY und d2 = DX
	moveq	#$14,d5				; Oktantencode
	bra.s	DrawL
Draw5:
	exg.l	d2,d3				; es schaltet zwischen d2 und d3 um, so dass d3 = DY und d2 = DX
	moveq	#$08,d5				; Oktantencode
	bra.s	DrawL
Draw6:
	neg.w	d3					; macht d3 positiv
	cmp.w	d3,d2				; vergleiche DiffX und DiffY
	bmi.s	Draw7				; wenn d2 < d3 überspringt ..
								; .. sonst d3 = DY und d2 = DX
	moveq	#$1c,d5				; Oktantencode
	bra.s	DrawL
Draw7:
	exg.l	d2,d3				; es schaltet zwischen d2 und d3 um, so dass d3 = DY und d2 = DX
	moveq	#$0c,d5				; Oktantencode

; Wenn die Ausführung diesen Punkt erreicht, haben wir:
; d2 = DX
; d3 = DY
; d5 = Oktantencode

DrawL:
	mulu.w	#40,d1				; Offset Y
	add.l	d1,a0				; Fügt der Adresse den Y-Offset hinzu

	move.w	d0,d1				; Kopiere die X-Koordinate
	and.w	#$000f,d0			; Wähle die 4 niedrigsten Bits des X ..
	ror.w	#4,d0				; .. und bewegt sie in die Bits 12 bis 15
	or.w	#$0b4a,d0			; mit einem OR bekomme ich den zu schreibenen Wert
								; in BLTCON0. Mit diesem LF-Wert ($4a)
								; Zeichnen Sie Linien in EOR mit dem Hintergrund.

	lsr.w	#4,d1				; lösche die 4 unteren Bits des X
	add.w	d1,d1				; Ruft den X-Offset in Bytes ab
	add.w	d1,a0				; Fügt der Adresse den X-Offset hinzu

	move.w	d2,d1				; Kopie DX in d1
	addq.w	#1,d1				; d1=DX+1
	lsl.w	#$06,d1				; berechnet in d1 den Wert, der in BLTSIZE eingegeben werden soll
	addq.w	#$0002,d1			; addiert die Breite, gleich 2 Wörtern

	lsl.w	#$02,d3				; d3=4*DY
	add.w	d2,d2				; d2=2*DX

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

	move.w	d3,$62(a5)			; BLTBMOD=4*DY
	sub.w	d2,d3				; d3=4*DY-2*DX
	move.w	d3,$52(a5)			; BLTAPTL=4*DY-2*DX

								; Bereite den Wert vor, um in BLTCON1 zu schreiben
	or.w	#$0001,d5			; Bit 0=1 (aktiver Zeilenmodus)
	tst.w	d3
	bpl.s	Ok1					; wenn 4 * DY-2 * DX> 0 überspringen ..
	or.w	#$0040,d5			; Ansonsten setze das SIGN-Bit
Ok1:
	move.w	d0,$40(a5)			; BLTCON0
	move.w	d5,$42(a5)			; BLTCON1
	sub.w	d2,d3				; d3=4*DY-4*DX
	move.w	d3,$64(a5)			; BLTAMOD=4*DY-4*DX
	move.l	a0,$48(a5)			; BLTCPT - Adresse Bildschirm
	move.l	a0,$54(a5)			; BLTDPT - Adresse Bildschirm
	move.w	d1,$58(a5)			; BLTSIZE
	rts
	
;******************************************************************************
; Diese Routine legt die Blitter-Register fest, die sich 
; zwischen einer Zeile und einer anderen nicht ändern
;******************************************************************************

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

	moveq.l	#-1,d5
	move.l	d5,$44(a5)			; BLTAFWM/BLTALWM = $ffff
	move.w	#$8000,$74(a5)		; BLTADAT = $8000
	move.w	#40,$60(a5)			; BLTCMOD = 40
	move.w	#40,$66(a5)			; BLTDMOD = 40
	rts

;******************************************************************************
; Diese Routine definiert das Muster, das zum Zeichnen der Linien verwendet
; werden soll. In der Praxis setzt man einfach das BLTBDAT-Register.
; d0 - enthält das Linienmuster
;******************************************************************************

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

	move.w	d0,$72(a5)			; BLTBDAT = Linienmuster
	rts


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

	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,$1200			; BPLCON0 - 1 Bitplane lowres

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

	dc.w	$0180,$000			; COLOR00
	dc.w	$0182,$eee			; COLOR01
	dc.w	$ffff,$fffe			; Ende Copperlist

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

	SECTION	LEEREPLANE,BSS_C

Bitplane:
	ds.b	40*256				; Bitplane lowres

	end

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

In diesem Beispiel zeigen wir die Verfolgung von Linien. Es ist realisiert
durch 3 verschiedene Routinen. Die Routine "InitLine" setzt die Register,
deren Inhalt unabhängig von den Linienparametern (den Punkten) sind und somit
kann man sie einmal alleine am Anfang des Programms einstellen.
Die Routine "SetPattern" definiert das Muster, das für eine Linie verwendet 
werden soll. Wenn Sie ein anderes Muster verwenden möchten, müssen Sie dies in
dieser Routine tun. Im Gegenteil, wenn mehrere Linien mit demselben Muster 
gezeichnet werden sollen muss diese Routine nur einmal ausgeführt werden.
Die "Drawline"-Routine ist die Routine, die effektiv die Linie zeichnet und es
ist auch die Komplexeste. Zu Beginn werden DX und DY berechnet. Sie basieren 
auf den Koordinaten der Punkte, und der zu verwendende Oktant-Code wird
bestimmt. Um diese Operationen durchzuführen, werden eine Reihe von
Subtraktionen und Vergleiche, die alle möglichen Fälle untersuchen
durchgeführt. Dann werden die in die anderen Register einzugebenden Werte
berechnet, wie in den Kommentaren erläutert.
Beachten Sie, dass LF = $4a verwendet wird, was ein EOR zwischen der Zeile 
und dem Hintergrund verursacht. Sie können dies an den zwei sich schneidenden 
Linien sehen: der Schnittpunkt ist ein Pixel mit dem Wert 0. Wenn Sie
versuchen, LF = $Ca zu setzen, werden Sie feststellen, dass die Kreuzung
stattdessen ein Pixel mit dem Wert 1 ist.