
; Listing10x.s		Effekt morphing!!!!!!! Coded by Executor/RAM JAM

	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:
	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	#$12c00,d2			; Warte auf Zeile $12c
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 $12c
	bne.s	WarteY1

	bsr.w	SwapBuffer			; Diese Routine tauscht die 2 Puffer aus
	bsr.w	ClearScreen			; freier Zeichenpuffer
	bsr.w	DoIt				; Routine Linien zeichnen
	bsr.w	DoAnim				; Routine die die Animation verwaltet

	moveq	#0,d0				; exklusiv
	moveq	#0,d1				; CARRYIN=0
	move.l	DrawBuffer(pc),a0

	bsr.w	Fill				; füllen Puffer Zeichnen	
	bsr.w	Morph				; Berechnen Sie das nächste Bild

	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
;******************************************************************************

; Konstanten

DL_FILL		=	1				; 0=NOFILL / 1=Fill

	IFEQ	DL_FILL
DL_MINTERMS	=	$CA
	ELSE
DL_MINTERMS	=	$4a
	ENDC


DrawLine:
	sub.w	d1,d3				; d3=Y2-Y1

	IFNE	DL_FILL
	beq.s	.end				; Für die Füllung werden keine horizontalen Linien benötigt
	ENDC

	bgt.s	.y2gy1				; springen wenn positiv ..
	exg	d0,d2					; .. Ansonsten tauschen Sie Punkte aus
	add.w	d3,d1				; setzt das kleinere Y in d1
	neg.w	d3					; d3=DY
.y2gy1:
	mulu.w	#40,d1				; Offset Y
	add.l	d1,a0
	moveq	#0,d1				; d1-Index in der Oktantentabelle
	sub.w	d0,d2				; d2=X2-X1
	bge.s	.xdpos				; springen wenn positiv ..
	addq.w	#2,d1				; .. andernfalls verschieben Sie den Index
	neg.w	d2					; und machen den Unterschied positiv
.xdpos:
	moveq	#$f,d4				; Maske für die 4 niedrigen Bits
	and.w	d0,d4				; wählen sie d4 aus
		
	IFNE	DL_FILL				; Diese Anweisungen sind zusammengestellt
								; nur wenn DL_FILL = 1
	move.b	d4,d5				; berechnet die Nummer des zu invertierenden Bits
	not.b	d5					; (das BCHG nummeriert die inversen Bits)
	ENDC

	lsr.w	#3,d0				; Offset X:
								; In Bytes ausrichten (dient für BCHG)
	add.w	d0,a0				; zur Adresse hinzufügen
								; Beachten Sie, dass auch wenn die Adresse
								; Es ist seltsam, dass es nichts macht, weil
								; der Blitter berücksichtigt nicht die
								; niedrigstwertiges Bit von BLTxPT

	ror.w	#4,d4				; d4 = Wert der Verschiebung A
	or.w	#$b00+DL_MINTERMS,d4	; füge das passende hinzu
								; Minterm (OR oder EOR)
	swap	d4					; Wert von BLTCON0 im High-Word
		
	cmp.w	d2,d3				; vergleiche DiffX und DiffY
	bge.s	.dygdx				; überspringen wenn >=0..
	addq.w	#1,d1				; andernfalls setzen Sie das Bit 0 des Indexes
	exg	d2,d3					; und tausche das Diff
.dygdx:
	add.w	d2,d2				; d2 = 2*DiffX
	move.w	d2,d0				; Kopie in d0
	sub.w	d3,d0				; d0 = 2*DiffX-DiffY
	addx.w	d1,d1				; multiplizieren Sie den Index mit 2 und
								; gleichzeitig fügt er die Flagge hinzu
								; X ist 1, wenn 2 * DiffX-DiffY <0 ist
								; (eingestellt von sub.w)
	move.b	Oktants(pc,d1.w),d4	; liest den Oktanten
	swap	d2					; BLTBMOD-Wert in High-Word
	move.w	d0,d2				; niedriges Word d2=2*DiffX-DiffY
	sub.w	d3,d2				; niedriges Word d2=2*DiffX-2*DiffY
	moveq	#6,d1				; Wert der Verschiebung und Test für
								; die Wartezeit Blitter

	lsl.w	d1,d3				; berechnet den Wert von BLTSIZE
	add.w	#$42,d3

	lea	$52(a5),a1				; a1 = BLTAPTL-Adresse
								; Er schreibt einige Register
								; nacheinander mit
								; MOVE #XX,(Ax)+

	btst	d1,2(a5)			; warte auf den Blitter
.wb:
	btst	d1,2(a5)
	bne.s	.wb

	IFNE	DL_FILL				; Diese Anweisung ist zusammengestellt
								; nur wenn DL_FILL = 1
	bchg	d5,(a0)				; Invertiert das erste Bit der Zeile
	ENDC

	move.l	d4,$40(a5)			; BLTCON0/1
	move.l	d2,$62(a5)			; BLTBMOD und BLTAMOD
	move.l	a0,$48(a5)			; BLTCPT
	move.w	d0,(a1)+			; BLTAPTL
	move.l	a0,(a1)+			; BLTDPT
	move.w	d3,(a1)				; BLTSIZE
.end:
	rts

; Wenn wir Zeilen für die Füllung ausführen möchten, setzt der Octant-Code 
; durch die Konstante SML das SING-Bit auf 1

	IFNE	DL_FILL
SML		= 	2
	ELSE
SML		=	0
	ENDC

; Tabelle Oktanten

Oktants:
	dc.b	SML+1,SML+1+$40
	dc.b	SML+17,SML+17+$40
	dc.b	SML+9,SML+9+$40
	dc.b	SML+21,SML+21+$40

;******************************************************************************
; Diese Routine legt die Blitter-Register fest, die sich 
; zwischen einer Zeile und einer anderen nicht ändern
;******************************************************************************

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

	moveq	#-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
WaitBlit2:
	btst	#6,2(a5) 			; DMACONR - warte auf das Ende des Blitters
	bne.s	WaitBlit2

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


;****************************************************************************
; Diese Routine tauscht die 2 Puffer aus, indem die Adressen der
; VIEW_BUFFER- und DRAW_BUFFER-Variablen getauscht werden.
; Außerdem werden die Anweisungen aktualisiert, mit denen die Register 
; BPLxPT in der Copperlist geladen werden, damit sie auf den neuen Puffer 
; zeigen, der angezeigt werden soll.
;****************************************************************************

SwapBuffer:
	move.l	DrawBuffer(pc),d0	; den Inhalt austauschen
	move.l	ViewBuffer(pc),DrawBuffer	; der Variablen
	move.l	d0,ViewBuffer		; in d0 gibt es die Adresse
								; des neuen Puffers
								; anzeigen

; Aktualisieren Sie die Copperlist, indem Sie auf die Bitebenen des neuen Puffers 
; zeigen, der angezeigt werden soll

	lea	Bplpointers,a1			; Zeiger Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	rts

; Zeiger auf die 2 Puffer

ViewBuffer:	dc.l	Bitplane1	; Puffer Anzeigen
DrawBuffer:	dc.l	Bitplane1b	; Puffer Zeichnen

;****************************************************************************
; Diese Routine löscht den Bildschirm mit dem Blitter.
; Die Bildschirmadresse wird aus der Variablen DRAW_BUFFER gelesen
;****************************************************************************

ClearScreen:
	move.l	DrawBuffer(pc),a0	; Adresse Puffer Zeichnen

	btst	#6,2(a5)
WaitBlit3:
	btst	#6,2(a5)			; Warten Sie, bis der Blitter fertig ist
	bne.s	WaitBlit3

	move.l	#$01000000,$40(a5)	; BLTCON0 und BLTCON1: Löschung
	move.w	#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
	rts

;****************************************************************************
; Diese Routine kopiert ein Bildschirmrechteck von einer festen Position aus
; an eine als Parameter angegebene Adresse. Das Bildschirmrechteck wird 
; komplett kopiert umschließt die 2 Zeilen.
; Das Füllen erfolgt während des Kopiervorgangs. Die Art der Füllung
; wird über Parameter festgelegt.
; Die Parameter sind:
; a0 - Rechteckadresse, die gefüllt werden soll
; d0 - wenn es 0 ist, dann mache inklusive Füllung, andernfalls exklusiv
; d1 - wenn es 0 ist, wird FILL_CARRYIN = 0, andernfalls FILL_CARRYIN = 1
;****************************************************************************

Fill:
	btst	#6,2(a5)			; DMACONR
WaitBlit4:
	btst	#6,2(a5)			; DMACONR - Warten Sie, bis der Blitter fertig ist
	bne.s	WaitBlit4

	move.w	#$09f0,$40(a5)		; BLTCON0 normale Kopie

	tst.w	d0					; teste d0, um die Art der Füllung zu bestimmen
	bne.s	FillExclusiv
	move.w	#$000a,d2			; Wert von BLTCON1: setze die Bits für den
								; exklusiven Füll- und Abstiegsmodus
	bra.s	TestFillCarry

FillExclusiv:
	move.w	#$0012,d2			; Wert von BLTCON1: setze die Bits für den
								; exklusiven Füll- und Abstiegsmodus

TestFillCarry:
	tst.w	d1					; test d1, um zu sehen, ob das
								; FILL_CARRYIN-Bit gesetzt werden soll

	beq.s	MakeBltcon1			; wenn d1 = 0 überspringe..
	bset	#2,d2				; ansonsten setze Bit 2 von d2

MakeBltcon1:
	move.w	d2,$42(a5)			; BLTCON1

	move.w	#0,$64(a5)			; BLTAMOD Breite 20 words (40-40=0)
	move.w	#0,$66(a5)			; BLTDMOD (40-40=0)

	lea	40*256-2(a0),a0			; Wir zeigen auf das letzte Wort des Rechtecks
								; wegen des absteigenden Weges

	move.l	a0,$50(a5)			; BLTAPT - Adresse an das Rechteck
								; das Quellrechteck umschließt
								; das Polygon ganz 

	move.l	a0,$54(a5)			; BLTDPT - Adresse Rechteck
	move.w	#(64*256)+20,$58(a5)	; BLTSIZE (Blitter starten !)
								; Breite 20 words
								; Höhe 256 Zeilen (1 plane)
	rts

******************************************************************************
; Diese Routine berechnet die Punkte, die einen Zwischenrahmen bilden.
; Das Morphen wird auf folgende Weise realisiert: Nehmen Sie für jeden Punkt 
; die relativen Koordinaten im Startbild (Quelle) und im Zielbild (Ziel) und 
; berechnen sie die Differenz. Die Unterschiede sind die Entfernung 
; (jeweils entlang des X und des Y) durch die der Punkt verlaufen muss.
; Gehe von der Position im Startbild zu der im Zielbild. Diese Distanz muss 
; in einer variablen Anzahl von Frames zurückgelegt werden. Sie wird in der 
; Variablen MaxStep gespeichert. Wenn wir den Abstand durch die Anzahl der 
; Frames teilen, erhalten wir den Platz, den der Punkt bei seiner Reise 
; bei jedem Frame haben muss. Wenn wir diese Menge mit der Zahl von
; gezeichneten Frames multiplizieren und dann der Startposition hinzufügen
; erhalten wir die aktuelle Position des Punktes.
; Die Formel zur Berechnung des Wertes der X-Koordinate im aktuellen Frame
; ist also Folgende:

; X_aktuell = X_Start + (X_Ankunft-X_Start) * Aktuelle_Frame / Anzahl_Frame.

; Die Formel für das Y ist dieselbe. Die X_ Ankunfts- und X_Start-Koordinaten 
; sind in den Daten jedes Frames gespeichert, während Current_Frames und 
; Frames in den Variablen Step und MaxStep gespeichert sind.
; Diese Formeln werden von der Routine "Morph" auf die Koordinaten aller 
; Punkte die einen Rahmen bilden angewendet.
******************************************************************************

;	  _./\._
;	  \ __ /
;	   ·\/ \
;	  /_____\
;	 ·¯     ¯·
;	  \ o O /
;	  (  ^  )
;	  _`---'_
;	 / ¯   ¯ \
;	/ __   __ \
;	\__/---\__/
;	  |  .  |
;	 _|__¦__|_
;	/____l____\bHe

Morph:
	moveq	#24-1,d7			; 24 Punkte pro Bild
	
	move.l	MaxStep(pc),d5		; d5 = Gesamtzahl der Zwischenbilder

	move.l	Step(pc),d6			; d6 = aktueller Bildzähler

	lea	Points(pc),a2			; a2 = Vektorpunkte
	move.l	SourFrm(pc),a0
	move.l	(a0),a0				; a0 = Startbild
	move.l	DestFrm(pc),a1
	move.l	(a1),a1				; a1 = Ankunftsrahmen

; Berechnet die Koordinaten der Punkte im Zwischenrahmen

ProcX:
	moveq	#0,d0
	move.w	(a1)+,d0			; d0 = x1
	sub.w	(a0),d0				; d0 = x1-x0
	muls.w	d6,d0				; d0 = (x1-x0)·d6
	divs.w	d5,d0				; d0 = (x1-x0)·d6/d5
	add.w	(a0)+,d0			; d0 = x0+(x1-x0)·d6/d5
ProcY:
	moveq	#0,d1
	move.w	(a1)+,d1			; d1 = y1
	sub.w	(a0),d1				; d1 = y1-y0
	muls.w	d6,d1				; d1 = (y1-y0)·d6
	divs.w	d5,d1				; d1 = (y1-y0)·d6/d5
	add.w	(a0)+,d1			; d1 = y0+(y1-y0)·d6/d5

	move.w	d0,(a2)+			; speichert Zwischenrahmenkoordinaten
	move.w	d1,(a2)+

	dbra	d7,ProcX			; Laufen Sie für alle Punkte
	addq.l	#1,Step				; aktuellen Frame-Zähler erhöhen
	rts
	

*****************************************************************************
; Routine, die die Animation verwaltet
*****************************************************************************

DoAnim:
	tst.l	Fx					; Zähler testen
	bne.s	DoAm				; wenn es nicht den Wert 0 hat überspringen..

	move.l	Script(pc),a0		; ..Ansonsten Adresse des Punktes 
								; der Animation lesen, in der wir uns befinden.
At:
	tst.l	(a0)
	bne.s	DoX
	tst.l	4(a0)
	bne.s	DoX					; wenn sich die Zeiger auf die Frames von 0 
								; unterscheiden springen ..

Restart:	
	lea	Story(pc),a0			; Ansonsten beginnt die Animation wieder von vorn
	bra.s	At
	
DoX:
	move.l	(a0)+,SourFrm		; liest neuen Quellframe
	move.l	(a0)+,DestFrm		; liest neuen Zielrahmen
	move.l	(a0)+,MaxStep		; neue Anzahl von Zwischenbildern
	move.l	MaxStep(pc),Fx		; kopieren
	move.l	a0,Script			; Speichern der Ankunftspunktanimation
	move.l	#1,Step				; Zwischenrahmenzähler initialisieren
DoAm:
	subq.l	#1,Fx				; dekrementiert den Zähler
	rts
	

****************************************************************************
; Diese Routine zeichnet die Linien, aus denen der aktuelle Frame besteht
****************************************************************************

DoIt:
	lea	Points(pc),a3			; Vektorpunkte aktuelles Bild
	moveq	#24-1,d7			; 24 Punkte für jeden Frame
	bsr.w	InitLine			; Line-Modus initialisieren

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

	move.l	(a3),-(a7)			; Koordinaten zum ersten Punkt speichern
AnimLoop:
	movem.w	(a3)+,d0-d1			; Gesetz koordiniert den i-ten Punkt
	movem.w	(a3),d2-d3			; Gesetzeskoordinaten (i + 1) -ter Punkt
	tst.w	d7
	bne.s	NoLast				; wenn wir nicht am letzten Punkt sind überspringen ..
	movem.w	(a7)+,d2-d3			; ansonsten letzter Punkt = erster Punkt
NoLast:
	move.l	DrawBuffer(pc),a0	; Adresse Zeichenpuffer
	bsr.w	DrawLine			; Linie zeichnen
	dbra	d7,AnimLoop
	rts

**************************
; Variablen
**************************

Script:		dc.l	Story		; Zeiger auf die aktuelle Animationsphase
Fx:			dc.l	0			; Zähler, um den Übergang von einer Phase
								; zur anderen zu signalisieren
MaxStep:	dc.l	200			; Anzahl der Zwischenbilder zwischen Quelle und Ziel
Step:		dc.l	1			; aktuelle Zwischenbildnummer
SourFrm:	dc.l	Frm1		; Adresse Frame Quelle
DestFrm:	dc.l	Frm2		; Adresse Frame Ziel

; Animation: Jede Phase verfügt über einen Quellframe, einen Zielframe und
; die Morphing-Zeit, das ist die Anzahl der Zwischenframes, die erzeugt 
; werden müssen. z.B. Die erste Phase geht vom Frm1-Frame zum Frm2-Frame
; in 24 Zwischenbildern.

Story:
	dc.l	Frm1,Frm2,24
	dc.l	Frm2,Frm3,24
	dc.l	Frm3,Frm4,24
	dc.l	Frm4,Frm5,24
	dc.l	Frm5,Frm6,24
	dc.l	Frm6,Frm7,24
	dc.l	Frm7,Frm8,24
	dc.l	Frm8,Frm9,24
	dc.l	Frm9,Frm10,24
	dc.l	Frm10,Frm11,24
	dc.l	Frm11,Frm12,24
	dc.l	Frm12,Frm13,24
	dc.l	Frm13,Frm14,24
	dc.l	Frm14,Frm15,24
	dc.l	Frm15,Frm16,12
	dc.l	Frm16,Frm17,12
	dc.l	Frm17,Frm18,24
	dc.l	Frm18,Frm19,24
	dc.l	Frm19,Frm20,24
	dc.l	Frm20,Frm21,24
	dc.l	Frm21,Frm22,24
	dc.l	Frm22,Frm23,24
	dc.l	Frm23,Frm23,48
	dc.l	Frm23,Frm24,24
	dc.l	Frm24,Frm25,24
	dc.l	Frm25,Frm26,24
	dc.l	Frm26,Frm27,24
	dc.l	Frm27,Frm26,24
	dc.l	Frm26,Frm27,24
	dc.l	Frm27,Frm26,24
	dc.l	Frm26,Frm27,24
	dc.l	Frm27,Frm28,24
	dc.l	Frm28,Frm29,24
	dc.l	Frm29,Frm30,96
	dc.l	Frm30,Frm31,24
	dc.l	Frm31,Frm32,24
	dc.l	Frm32,Frm31,24

	dc.l	0,0					; Ende

; Vektor, der die Koordinaten des Zwischenrahmens enthält

Points:
	dcb.b	24*4,0

***************************************************************************
; Rahmendaten: Für jedes Bild gibt es die X- und Y-Koordinaten der Punkte
; die es bilden
***************************************************************************

Frames:
Frame1:
	dc.w	$13f,$7e,$13f,$ae,$13f,$ff,$11c,$ff,$da,$ff,$a5
	dc.w	$ff,$87,$ff,$6e,$ff,$4a,$ff,$2e,$ff,$13,$ff,0,$ff
	dc.w	0,$c8,0,$b6,0,$a5,0,$82,0,$38,0,0,$15,0,$7e,0,$95
	dc.w	0,$df,0,$13f,0,$13f,$37
Frame2:
	dc.w	$c9,$68,$c7,$76,$c2,$82,$ba,$8d,$af,$95,$a3,$9a
	dc.w	$96,$9b,$88,$9a,$7c,$95,$71,$8d,$69,$82,$64,$76
	dc.w	$63,$68,$64,$5b,$69,$4f,$71,$44,$7c,$3c,$88,$37
	dc.w	$96,$35,$a3,$37,$af,$3c,$ba,$44,$c2,$4f,$c7,$5b
Frame3:
	dc.w	$13f,$6f,$c7,$76,$c2,$82,$ba,$8d,$af,$95,$a3,$9a
	dc.w	$95,$ff,$88,$9a,$7c,$95,$71,$8d,$69,$82,$64,$76,0
	dc.w	$69,$64,$5b,$69,$4f,$71,$44,$7c,$3c,$88,$37,$94,0
	dc.w	$a3,$37,$af,$3c,$ba,$44,$c2,$4f,$c7,$5b
Frame4:
	dc.w	$13f,$6a,$6e,$4f,$69,$5b,$61,$66,$56,$6e,$4a,$73
	dc.w	$9d,$ff,$2f,$73,$23,$6e,$18,$66,$10,$5b,11,$4f,0
	dc.w	$82,11,$34,$10,$28,$18,$1d,$23,$15,$2f,$10,$9a,0
	dc.w	$4a,$10,$56,$15,$61,$1d,$69,$28,$6e,$34
Frame5:
	dc.w	$13f,$5a,$123,$bf,$11e,$cb,$116,$d6,$10b,$de,$ff
	dc.w	$e3,$86,$ff,$e4,$e3,$d8,$de,$cd,$d6,$c5,$cb,$c0
	dc.w	$bf,0,$77,$c0,$a4,$c5,$98,$cd,$8d,$d8,$85,$e4,$80
	dc.w	$84,0,$ff,$80,$10b,$85,$116,$8d,$11e,$98,$123,$a4
Frame6:
	dc.w	$13f,$8f,$128,$5a,$123,$66,$11b,$71,$110,$79,$104
	dc.w	$7e,$86,$ff,$e9,$7e,$dd,$79,$d2,$71,$ca,$66,$c5
	dc.w	$5a,0,$75,$c5,$3f,$ca,$33,$d2,$28,$dd,$20,$e9,$1b
	dc.w	$91,0,$104,$1b,$110,$20,$11b,$28,$123,$33,$128
	dc.w	$3f
Frame7:
	dc.w	$13f,$7a,$75,$be,$70,$ca,$68,$d5,$5d,$dd,$51,$e2
	dc.w	$a7,$ff,$36,$e2,$2a,$dd,$1f,$d5,$17,$ca,$12,$be,0
	dc.w	$72,$12,$a3,$17,$97,$1f,$8c,$2a,$84,$36,$7f,$a1,0
	dc.w	$51,$7f,$5d,$84,$68,$8c,$70,$97,$75,$a3
Frame8:
	dc.w	$9d,$77,$c7,$7f,$c2,$8b,$9e,$7b,$af,$9e,$a3,$a3
	dc.w	$9a,$7c,$88,$a3,$7c,$9e,$97,$7b,$69,$8b,$64,$7f
	dc.w	$96,$78,$64,$64,$69,$58,$96,$74,$7b,$46,$88,$40
	dc.w	$9a,$73,$a3,$40,$af,$45,$9b,$75,$c2,$58,$c7,$64
Frame9:
	dc.w	$b7,$87,$111,$98,$106,$b2,$b9,$8f,$dd,$da,$c4,$e5
	dc.w	$b0,$91,$8a,$e5,$70,$da,$aa,$8f,$47,$b2,$3d,$98
	dc.w	$a8,$88,$3d,$5e,$47,$44,$a8,$81,$6e,$1d,$8a,$11
	dc.w	$b0,$7e,$c4,$11,$dd,$1b,$b3,$83,$106,$44,$111,$5e
Frame10:
	dc.w	$ae,$86,$c4,$89,$c1,$8f,$af,$87,$b7,$98,$b1,$9b
	dc.w	$ad,$87,$a5,$9b,$9f,$98,$ac,$87,$95,$8f,$93,$89
	dc.w	$ac,$86,$93,$7c,$95,$76,$ac,$84,$9e,$6d,$a5,$6a
	dc.w	$ad,$84,$b1,$6a,$b7,$6c,$ae,$85,$c1,$76,$c4,$7c
Frame11:
	dc.w	$f4,$7f,$eb,$8e,$e0,$a3,$e1,$c2,$bf,$c1,$ab,$cb
	dc.w	$9b,$d2,$87,$cb,$72,$c1,$52,$c9,$52,$a3,$4a,$8e
	dc.w	$49,$85,$4a,$68,$52,$55,$56,$3d,$6f,$37,$87,$2e
	dc.w	$9c,$27,$ab,$2e,$bf,$34,$e3,$3d,$e0,$55,$eb,$68
Frame12:
	dc.w	$118,$ee,$e6,$f0,$d4,$bb,$91,$7e,$c4,$3c,$b9,$2e
	dc.w	$7b,$2d,$8f,$fe,$6c,$e8,$6b,$a9,$66,$74,$5f,$43
	dc.w	$56,$1f,$3a,$60,$39,$45,$48,12,$79,9,$a2,9,$d6
	dc.w	$11,$eb,$25,$eb,$38,$e9,$63,$a7,$7f,$eb,$ab
Frame13:
	dc.w	$ba,$a5,$80,$9a,$81,$77,$c3,$7a,$cb,$38,$c0,$2a
	dc.w	$82,$29,$70,$b5,$69,$f9,$52,$f7,$35,$f6,$37,$c6
	dc.w	$36,$82,$41,$5c,$40,$41,$4f,8,$80,5,$a9,5,$dd,13
	dc.w	$f2,$21,$f2,$34,$ee,$5c,$e8,$f6,$c6,$fb
Frame14:
	dc.w	$d2,$a6,$d5,$85,$d7,$26,$b1,$1d,$a1,$49,$96,$1e
	dc.w	$7b,$24,$66,$b2,$79,$f8,$62,$f6,$52,$eb,$49,$c7
	dc.w	$4a,$a5,$50,$77,$59,$40,$5f,7,$90,4,$b9,4,$ed,12
	dc.w	$102,$20,$102,$33,$fe,$5b,$f8,$f5,$d6,$fa
Frame15:
	dc.w	$e0,$ba,$e3,$99,$e5,$3a,$cc,$33,$b6,$2f,$85,$31
	dc.w	$62,$39,$46,$5b,$36,$5c,$32,$5d,$38,$1d,$70,$15
	dc.w	$99,$12,$c0,$10,$e6,15,$107,$12,$11d,$18,$11c,$73
	dc.w	$10c,$e1,$8e,$de,$55,$cb,$5a,$87,$72,$61,$8d,$bf
Frame16:
	dc.w	$d9,$94,$5f,$90,$60,$78,$d4,$72,$d7,$53,$b5,$35
	dc.w	$85,$35,$58,$4f,$57,$de,$35,$d3,$43,$35,$54,$24
	dc.w	$7c,$15,$b7,15,$cf,$1c,$ed,$3e,$f5,$61,$f3,$86
	dc.w	$f3,$b7,$f5,$dd,$103,$ec,$d7,$eb,$d9,$ce,$d8,$bb
Frame17:
	dc.w	$cf,$f4,$c4,$f4,$d0,$77,$d4,$40,$a6,$2b,$93,$56
	dc.w	$7c,$2e,$62,$48,$5e,$f8,$35,$ce,$4d,$2e,$56,$1d
	dc.w	$66,15,$76,10,$8b,8,$a0,10,$b4,14,$de,$1d,$f4,$47
	dc.w	$f7,$63,$f5,$ac,$f3,$c9,$eb,$db,$de,$ec
Frame18:
	dc.w	$ca,$f7,$c6,$f0,$bc,$f2,$a9,$f0,$95,$f4,$8a,$f3
	dc.w	$7d,$f4,$72,$f3,$68,$f7,$3f,$cd,$57,$2d,$60,$1c
	dc.w	$70,14,$80,9,$95,7,$aa,9,$be,13,$dd,$2c,$e6,$5b
	dc.w	$e7,$7f,$dd,$ba,$dc,$d3,$da,$e3,$d0,$ee
Frame19:
	dc.w	$c8,$eb,$bf,$dd,$b6,$c4,$a9,$f0,$91,$cc,$8a,$f3
	dc.w	$7d,$f4,$5c,$86,0,$8b,0,$62,$5f,$6e,$5f,$19,$70
	dc.w	14,$88,$21,$95,7,$a7,$25,$be,13,$e8,$67,$13f,$5e
	dc.w	$13f,$8c,$e6,$7e,$dc,$d3,$da,$e3,$d0,$ee
Frame20:
	dc.w	$a1,$a6,$ae,$ff,$78,$ff,$8c,$a7,$8a,$98,$7f,$8f
	dc.w	$6e,$8a,$5c,$86,0,$90,0,$64,$5f,$6e,$79,$7d,$88
	dc.w	$6b,$82,0,$ab,0,$9c,$70,$b2,$7b,$e8,$67,$13f,$5f
	dc.w	$13f,$8d,$e6,$7e,$ac,$97,$a8,$98,$a0,$99
Frame21:
	dc.w	$54,$d5,$ae,$ff,$78,$ff,$53,$ea,$42,$d4,$2b,$d1
	dc.w	$3a,$bb,$3a,$b4,0,$90,0,$64,$45,$ac,$52,$b1,$56
	dc.w	$ab,$82,0,$ab,0,$61,$a8,$56,$bb,$62,$ba,$13f,$5f
	dc.w	$13f,$8d,$d4,$ae,$86,$b9,$69,$c0,$4e,$ce
Frame22:
	dc.w	$b8,$66,$ae,$ff,$78,$ff,$ab,$60,$ad,$4f,$b0,$47
	dc.w	$9d,$52,$97,$57,0,$90,0,$64,$91,$4d,$a0,$43,$a7
	dc.w	$2b,$82,0,$ab,0,$b3,$27,$be,$36,$db,$57,$13f,$5f
	dc.w	$13f,$8d,$cf,$63,$c8,$5c,$c2,$54,$bc,$45
Frame23:
	dc.w	$a6,$96,$a6,$b5,$8a,$b5,$7d,$b5,$63,$b5,$3e,$b5
	dc.w	$25,$b5,0,$b5,0,$90,0,$64,0,$5d,0,$3d,0,$2f,0,0
	dc.w	$a6,0,$a6,$27,$a6,$36,$a6,$48,$a6,$52,$a6,$5c,$a6
	dc.w	$62,$a6,$68,$a6,$78,$a6,$84
Frame24:
	dc.w	$af,$a8,$bd,$bb,$e6,$7e,$ef,$86,$e0,$bb,$c2,$f5
	dc.w	$a4,$f9,$59,$f8,$41,$a1,$24,$4f,$2e,$42,$3b,$49
	dc.w	$57,$88,$5b,$10,$6f,$10,$79,$77,$8b,3,$96,3,$9f
	dc.w	$11,$9a,$78,$bf,$18,$d0,$1e,$ce,$31,$ad,$8d
Frame25:
	dc.w	$b4,$ab,$bd,$bb,$bb,$93,$cf,$90,$d4,$c1,$c2,$f5
	dc.w	$a4,$f9,$59,$f8,$41,$a1,$39,$81,$42,$78,$50,$77
	dc.w	$57,$88,$5a,$68,$75,$62,$79,$77,$8b,3,$96,3,$9f
	dc.w	$11,$9a,$78,$a2,$69,$b2,$69,$b5,$6d,$b4,$8d
Frame26:
	dc.w	$d6,$4a,$d1,$4b,$c8,$4c,$b9,$52,$a1,$5f,$9c,$63
	dc.w	$90,$5c,$82,$56,$79,$51,$6b,$4d,$5d,$4c,$56,$44
	dc.w	$5e,$43,$71,$44,$80,$4a,$8b,$51,$94,$5a,$9d,$53
	dc.w	$a6,$59,$b4,$4d,$c0,$46,$cf,$42,$d7,$42,$e2,$44
Frame27:
	dc.w	$db,$68,$cd,$6c,$c1,$6c,$b5,$68,$a3,$5d,$9b,$5d
	dc.w	$95,$65,$8b,$6a,$81,$6b,$7b,$6b,$68,$66,$63,$5d
	dc.w	$75,$62,$81,$63,$88,$62,$93,$5b,$96,$58,$9f,$51
	dc.w	$a8,$57,$b2,$5d,$bc,$63,$c8,$64,$d6,$62,$e2,$60
Frame28:
	dc.w	$bb,$7b,$ba,$8c,$ae,$a3,$9f,$b8,$77,$e3,$4c,$fc
	dc.w	$7e,$d1,$98,$b4,$ab,$9a,$b0,$8d,$b1,$7b,$ac,$64
	dc.w	$9f,$5c,$93,$48,$92,$35,$92,$20,$9c,13,$ac,8,$be
	dc.w	13,$c8,$1d,$ce,$36,$ce,$48,$c5,$5c,$bc,$65
Frame29:
	dc.w	$ba,$57,$c6,$64,$d0,$7d,$d4,$a9,$d9,$c9,$108,$d7
	dc.w	$d7,$d1,$d2,$cc,$c6,$82,$bf,$6b,$b2,$5f,$9d,$52
	dc.w	$8d,$57,$76,$54,$65,$46,$55,$37,$4d,$21,$55,$11
	dc.w	$65,6,$7b,9,$91,$17,$a0,$24,$a7,$37,$a9,$46
Frame30:
	dc.w	$c1,$66,$d3,$58,$10b,$a5,$106,$6a,$bd,$3a,$10e
	dc.w	$17,$c7,$3d,$10b,$64,$114,$ba,$d3,$63,$c4,$6f,$97
	dc.w	$85,$94,$92,$83,$a3,$74,$a8,$5f,$ac,$4b,$a9,$43
	dc.w	$9b,$43,$8c,$51,$7e,$63,$72,$74,$6e,$8a,$6f,$93
	dc.w	$76
Frame31:
	dc.w	$d4,$39,$ef,$61,$106,$5a,$11a,$56,$110,$62,$eb
	dc.w	$6f,$e6,$bf,$dd,$b6,$da,$70,$bf,$6e,$8e,$6d,$74
	dc.w	$6c,$64,$bb,$55,$b2,$67,$6c,$52,$70,$3e,$6d,$60
	dc.w	$59,$36,$50,$44,$42,$56,$36,$67,$32,$7d,$33,$a1
	dc.w	$32
Frame32:
	dc.w	$d2,$98,$f0,$c2,$f7,$ba,$108,$b2,$109,$bb,$ec,$d0
	dc.w	$e0,$ff,$d7,$fe,$d0,$ca,$bd,$d6,$8d,$d5,$75,$cd
	dc.w	$6f,$fe,$64,$ff,$68,$cd,$53,$d1,$3c,$be,$61,$ba
	dc.w	$3d,$ba,$45,$a3,$57,$97,$68,$93,$7b,$9a,$9f,$a4

; Adressen der Frames

Frm1:	dc.l	Frame1			; Frames+24*4*0
Frm2:	dc.l	Frame2			; Frames+24*4*1
Frm3:	dc.l	Frame3			; Frames+24*4*2
Frm4:	dc.l	Frame4			; Frames+24*4*3
Frm5:	dc.l	Frame5			; Frames+24*4*4
Frm6:	dc.l	Frame6			; Frames+24*4*5
Frm7:	dc.l	Frame7			; Frames+24*4*6
Frm8:	dc.l	Frame8			; Frames+24*4*7
Frm9:	dc.l	Frame9			; Frames+24*4*8
Frm10:	dc.l	Frame10			; Frames+24*4*9
Frm11:	dc.l	Frame11			; Frames+24*4*10
Frm12:	dc.l	Frame12			; Frames+24*4*11
Frm13:	dc.l	Frame13			; Frames+24*4*12
Frm14:	dc.l	Frame14			; Frames+24*4*13
Frm15:	dc.l	Frame15			; Frames+24*4*14
Frm16:	dc.l	Frame16			; Frames+24*4*15
Frm17:	dc.l	Frame17			; Frames+24*4*16
Frm18:	dc.l	Frame18			; Frames+24*4*17
Frm19:	dc.l	Frame19			; Frames+24*4*18
Frm20:	dc.l	Frame20			; Frames+24*4*19
Frm21:	dc.l	Frame21			; Frames+24*4*20
Frm22:	dc.l	Frame22			; Frames+24*4*21
Frm23:	dc.l	Frame23			; Frames+24*4*22
Frm24:	dc.l	Frame24			; Frames+24*4*23
Frm25:	dc.l	Frame25			; Frames+24*4*24
Frm26:	dc.l	Frame26			; Frames+24*4*25
Frm27:	dc.l	Frame27			; Frames+24*4*26
Frm28:	dc.l	Frame28			; Frames+24*4*27
Frm29:	dc.l	Frame29			; Frames+24*4*28
Frm30:	dc.l	Frame30			; Frames+24*4*29
Frm31:	dc.l	Frame31			; Frames+24*4*30
Frm32:	dc.l	Frame32			; Frames+24*4*31

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

	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,$44b			; COLOR00
	dc.w	$0182,$f88			; COLOR01
	dc.w	$ffff,$fffe			; Ende Copperlist

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

	SECTION	LEEREPLANE,BSS_C

; Puffer 1

Bitplane1:
	ds.b	40*256				; Bitplane lowres

; Puffer 2

Bitplane1b:
	ds.b	40*256				; Bitplane lowres

	end

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

In diesem Beispiel stellen wir eine Routine vor, die eine Animation mit einem
Morph-Effekt ausführt. Dies ist eine der wichtigsten Techniken, verwendet im
mythischen "State of the Art" von Spaceballs, vielleicht einem der berühmtesten
Demos aller Zeiten.
Mal sehen, wie diese Technik erreicht wird. Jeder Frame der Animation ist mit
einem einzigen verschmolzenen Polygon hergestellt. Um das Polygon zu zeichnen
müssen wir die Kanten nachzeichnen und dann mit dem Blitter füllen. Die erste
Aufgaben wird von der Routine "DO_IT" und die zweite von der Routine "FILL"
ausgeführt. Um die Animation zu erstellen, ändern Sie einfach die Form des
Polygons für jedes Bild und dies geschieht durch das Ändern der
X- und Y-Koordinaten aller seiner Eckpunkte. Wenn wir die Koordinaten aller 
Punkte für alle Frames gespeichert haben, würden wir eine riesige Menge an 
Speicher belegen. Darum verwenden wir eine andere Methode. Wir speichern nur
einige Frames und berechnen jedes Mal andere, indem Sie den Morph zwischen zwei
der Frames machen, die wir gespeichert haben. Die Animation ist daher in
verschiedene Phasen unterteilt, in denen das Morphing zwischen einem Quellframe
und einem Zielframe mit einer bestimmten Anzahl der Frames gemacht wird. Wenn
der Zielframe erreicht ist, wechselt er zu einer neue Morph-Phase, die den
Quellframe, den Zielframe und die Anzahl der Frames ändert. Die
Animationsschritte werden dabei in der Reihenfolge  gespeichert ausgehend von
der "STORY" -Adresse kommt der Übergang von einer Phase zur anderen. Dies wird
von der Routine "DO_ANIM" verwaltet.