
; Listing15f2b.s		Sprite Größe 32 pixel. Verwenden Sie die rechte Maustaste
; zum Wechseln zwischen LowRes und HighRes
; später ergänztes Beispiel um die Wiederverwendung des Sprites mit dem Bit SSCAN2 
; zu demonstrieren

	SECTION	AGARULEZ,CODE

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

*****************************************************************************
	include	"/Sources/startup2.s"	; speichern Copperlist etc.
*****************************************************************************

			;5432109876543210
DMASET	equ	%1000001110100000	; Copper, Bitplane, Sprite DMA

WaitDisk	equ	30	; 50-150 zur Rettung (je nach Fall)

Start:
	move.l	#Bitplane,d0		; Zeiger auf das leere Bild	
	lea	Bplpointers,a1			; Zeiger in Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)

;	alle Sprites zeigen auf das Null-Sprite 

	move.l	#SpriteNull,d0		; Adresse des Sprites in d0
	lea	SpritePointers,a1		; Zeiger in Copperlist
	moveq	#8-1,d1				; alle 8 Sprites
NulLoop:
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	swap	d0
	addq.w	#8,a1
	dbra	d1,NulLoop

;	Zeiger auf Sprite

	move.l	#MeinSprite32,d0	; Adresse des Sprites in d0
	lea	SpritePointers,a1		; Zeiger in Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)

	move.w	#DMASET,$96(a5)		; DMACON - aktivieren Bitplane, Copper
	move.l	#Copperlist,$80(a5)	; Zeiger Copperlist
	move.w	d0,$88(a5)			; Start Copperlist
	move.w	#0,$1fc(a5)			; Fmode zurücksetzen, burst normal
	move.w	#$c00,$106(a5)		; BPLCON3 zurücksetzen
	move.w	#$11,$10c(a5)		; BPLCON4 zurücksetzen

	move.b	$dff00a,MouseY
	move.b	$dff00b,MouseX

Mouse:
	move.l	#$1ff00,d1			; Bit zur Auswahl durch UND
	move.l	#$12000,d2			; warte auf Zeile $120
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 $120
	bne.s	WarteY1

	bsr.s	ReadMouse			; das liest die Maus
	move.w	SpriteY(pc),d0		; Parameter für die 
	move.w	SpriteX(pc),d1		; universelle Routine vorbereiten
	lea	MeinSprite32,a1			; Adresse Sprite
	moveq	#26,d2				; Höhe Sprite
	bsr.w	UniMoveSprite32		; ruft die universelle Routine auf

	move.l	#$1ff00,d1			; Bit zur Auswahl durch UND
	move.l	#$12000,d2			; warte auf Zeile $120
WarteY2:
	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 $120
	beq.s	WarteY2

	btst.b	#2,$dff016		; rechte Maustaste gedrückt?
	bne.s	DoNotChangeRes	; Wenn nicht, ändern Sie das Ergebnis des Sprites nicht

	bchg.b	#7,BplCon3		; Wenn ja, wechseln Sie von LowRes zu Hires oder umgekehrt.

DoNotChangeRes:
	btst.b	#6,$bfe001		; linke Maustaste gedrückt?
	bne.s	Mouse
	rts
	
; Diese Routine liest die Maus und aktualisiert die Werte der Variablen
; SpriteX und SpriteY

ReadMouse:
	move.b	$dff00a,d1		; JOY0DAT vertikale Mausposition
	move.b	d1,d0			; Kopie in d0
	sub.b	MouseY(pc),d0	; alte Mausposition subtrahieren
	beq.s	NoVert			; Wenn die Differenz = 0 ist, wird die Maus gestoppt
	ext.w	d0				; Byte in Word umwandeln
							; (siehe am Ende des Listings)
	add.w	d0,SpriteY		; Sprite-Position bearbeiten
NoVert:
  	move.b	d1,MouseY		; Speichern der Mausposition für das nächste Mal

	move.b	$dff00b,d1		; horizontale Mausposition
	move.b	d1,d0			; Kopie in d0
	sub.b	MouseX(pc),d0	; alte Mausposition subtrahieren
	beq.s	NoHoriz			; Wenn die Differenz = 0 ist, wird die Maus gestoppt
	ext.w	d0				; Byte in Word umwandeln
							; (siehe am Ende des Listings)
	add.w	d0,SpriteX		; Sprite-Position bearbeiten
NoHoriz
  	move.b	d1,MouseX		; Speichern der Mausposition für das nächste Mal
	rts

SpriteY:	dc.w	0	; Hier wird das Y des Sprites gespeichert
SpriteX:	dc.w	0	; Hier wird das X des Sprites gespeichert
MouseY:		dc.b	0	; Hier wird das Y der Maus gespeichert
MouseX:		dc.b	0	; Hier wird das X der Maus gespeichert


; Universelle Positionierungsroutine für Sprites mit einer Breite von 32 Pixel.
 
;
;	Eingehende Parameter von UniMoveSprite32:
;
;	a1 = Adresse des Sprites
;	d0 = vertikale Y-Position des Sprites auf dem Bildschirm (0-255)
;	d1 = horizontale X-Position des Sprites auf dem Bildschirm (0-320)
;	d2 = Höhe des Sprites
;

UniMoveSprite32:
; vertikale Platzierung
	add.w	#$2c,d0		; Versatz des Bildschirmanfangs hinzufügen

; a1 enthält die Adresse des Sprites
	move.b	d0,(a1)		; Kopie Byte in Vstart
	btst.l	#8,d0
	beq.s	NichtVstartSet
	bset.b	#2,3+2(a1)	; Bit 8 von Vstart setzen (Nummer > $FF)
	bra.s	ToVstop
NichtVstartSet:
	bclr.b	#2,3+2(a1)	; Bit 8 von Vstart zurücksetzen (Nummer <$FF)
ToVstop:
	add.w	d2,d0		; die Höhe des Sprites hinzufügen
						; Bestimmen der Endposition (Vstop)
	move.b	d0,2+2(a1)	; den richtigen Wert in Vstop verschieben
	btst.l	#8,d0
	beq.s	NichtVstopSet
	bset.b	#1,3+2(a1)	; Bit 8 von Vstop setzen  (Nummer > $FF)
	bra.w	VstopEnde
NichtVstopSet:
	bclr.b	#1,3+2(a1)	; Bit 8 von Vstop zurücksetzen (Numer < $FF)
VstopEnde:

; horizontale Platzierung
	add.w	#128,d1		; 128 - um das Sprite zu zentrieren.
	btst.l	#0,d1		; niedriges Bit der X-Koordinate gelöscht?
	beq.s	NiederBitNull
	bset.b	#0,3+2(a1)	; das niedrige Bit von Hstart setzen
	bra.s	PlaceCoords

NiederBitNull:
	bclr.b	#0,3+2(a1)	; das niedrige Bit von Hstart löschen
PlaceCoords:
	lsr.w	#1,d1		; SHIFT, das heißt, wir verschieben den Wert von
						; Hstart um 1 Bit nach rechts, um ihn in "umzuwandeln"
						; Wert setzt in das Hstart-Byte, ohne das
						; niedrige Bit.
	move.b	d1,1(a1)	; wir setzen den Wert XX in das Hstart-Byte
	rts

;*****************************************************************************
;*				COPPERLIST				     *
;*****************************************************************************

	cnop	0,8	; auf 64 Bit ausrichten

	SECTION	GRAPHIC,DATA_C

Copperlist:
SpritePointers:
	dc.w	$120,0,$122,0,$124,0,$126,0,$128,0 ; SPRITE
	dc.w	$12a,0,$12c,0,$12e,0,$130,0,$132,0
	dc.w	$134,0,$136,0,$138,0,$13a,0,$13c,0
	dc.w	$13e,0

	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,0		; BPLCON2
	dc.w	$108,-8		; BPL1MOD (burst 64bit, modulo=modulo-8)
	dc.w	$10a,-8		; BPL2MOD (wie oben)

			    ; 5432109876543210
	dc.w	$100,%0001001000000001	; 1 Bitplane LORES 320x256.

	dc.w	$1fc,$8007	; SSCAN2 + Burst mode 64 bit, Sprite Größe 32 pixel
	;dc.w	$1fc,%0111	; Burst mode 64 bit, Sprite Größe 32 pixel

; Diese andere Einstellung ist ähnlich. Versuchen Sie es, wenn Sie keine 
; DMA-Probleme haben. Der oberste würde funktionieren.

;	dc.w	$1fc,%1011	; Burst mode 64 bit, Sprite Größe 32 pixel

Bplpointers:
	dc.w	$e0,0,$e2,0	; erste 	Bitplane
	dc.w	$e4,0,$e6,0	; zweite	   "
	dc.w	$e8,0,$ea,0	; dritte	   "
	dc.w	$ec,0,$ee,0	; vierte	   "
	dc.w	$f0,0,$f2,0	; fünfte	   "
	dc.w	$f4,0,$f6,0	; sechste	   "
	dc.w	$f8,0,$fa,0	; siebte	   "
	dc.w	$fc,0,$fe,0	; achte		   "

; Beachten Sie, dass die Sprite-Farben 24 Bit sind, auch wenn es nur 3 sind.

	dc.w	$106,$c00	; Auswahl Palette 0 (0-31), Nibble hoch
ColP0:
	dc.w	$180,$000	; COLOR00	; schwarzer Hintergrund
	dc.w	$182,$123	; COLOR01	; Farbe 1 der Bitebene, die
									; in diesem Fall leer ist,
									; so erscheint sie nicht.

	dc.w	$1a2,$f00	; COLOR17, das ist COLOR1 von sprite0 - rot
	dc.w	$1a4,$0f0	; COLOR18, das ist COLOR2 von sprite0 - grün
	dc.w	$1a6,$ff0	; COLOR19, das ist COLOR3 von sprite0 - gelb


	dc.w	$106,$e00	; Auswahl Palette 0 (0-31), Nibble niedrig
ColP0b:
	dc.w	$180,$000	; COLOR00	; schwarzer Hintergrund
	dc.w	$182,$000	; COLOR01	; Farbe 1 der Bitebene, die
									; in diesem Fall leer ist,
									; so erscheint sie nicht.

	dc.w	$1a2,$462	; COLOR17, Nibble niedrig
	dc.w	$1a4,$2e4	; COLOR18, Nibble niedrig
	dc.w	$1a6,$672	; COLOR19, Nibble niedrig

	dc.w	$106		; BPLCON3
	dc.b	0
BplCon3:
	       ; 76543210
	dc.b	%00000000	; bit 7: Sprites hires oder lowres. Wenn
		; sowohl Bit 7 als auch Bit 6 gesetzt sind ist das Sprite
		; in Superhires (1280x256), aber es kommt viel zu  "eng",
		; ich denke es ist nutzlos, nur hires!

	dc.w	$ffff,$fffe	; Ende Copperlist


;*****************************************************************************
; Hier sind die Sprites: Offensichtlich müssen sie sich im CHIP-RAM befinden!
;*****************************************************************************

	cnop	0,8

SpriteNull:			; Null-Sprite, um in der copperliste auf sie zu zeigen
	dc.l	0,0,0,0		; in nicht verwendeten Zeigern


	cnop	0,8

MeinSprite32:	; Länge 13*2 Zeilen
Vstart:
	dc.b $2c	; Vertikale Sprite-Startposition ($2c bis $f2)
Hstart:
	dc.b $40	; Horizontale Sprite-Startposition ($40 bis $d8)
	dc.w 0		; word "hinzugefügt" im 32 Pixel breiten Sprite			
Vstop:
	dc.b $46	; $2c+26=$46	; vertikale Position des Endsprites
Vhbits:
	dc.b $00	; bit
	dc.w 0		; word "hinzugefügt" im 32 Pixel breiten Sprite

 dc.l	%00000000000000000000000000000000,%00000000011000000000011000000000
 dc.l	%00000000000000000000000000000000,%00000000011100000000111000000000
 dc.l	%00000000000000000000000000000000,%00000000001110000001110000000000
 dc.l	%00000000000000000000000000000000,%00000000000111000011100000000000
 dc.l	%00000000000000000000000000000000,%00000000000011000011000000000000
 dc.l	%00000000000000000000000000000000,%00000000000011100111000000000000
 dc.l	%00000000000000111100000000000000,%00000111000001111110000011100000
 dc.l	%00000000000001111110000000000000,%00001110000001111110000001110000
 dc.l	%00000000000111111111100000000000,%00011100000111111111100000111000
 dc.l	%00000000001111111111110000000000,%00111000001111111111110000011100
 dc.l	%00000000001111111111110000000000,%01110000011001111110011000001110
 dc.l	%00000000011111111111111000000000,%11110000110000111100001100001111
 dc.l	%00000000111100111100111100000000,%11111111110000111100001111111111
 dc.l	%00000000111100111100111100000000,%01111111111000111100011111111110
 dc.l	%00000000011111111111111000000000,%00000000011111111111111000000000
 dc.l	%00000000001111111111110000000000,%00000000111111111111111100000000
 dc.l	%00000000001111111111110000000000,%00000001111110000001111110000000
 dc.l	%00000000000111111111100000000000,%00000011111111000011111111000000
 dc.l	%00000000000011111111000000000000,%00000111110011111111001111100000
 dc.l	%00000000000011111111000000000000,%00001111100011111111000111110000
 dc.l	%00000000000001111110000000000000,%00001111000001111110000011110000
 dc.l	%00000000000000011000000000000000,%00001111000000011000000011110000
 dc.l	%00000000000000000000000000000000,%11111111000000000000000011111111
 dc.l	%00000000000000000000000000000000,%11111111000000000000000011111111
 dc.l	%00000000000000000000000000000000,%11111111000000000000000011111111
 dc.l	%00000000000000000000000000000000,%11111111000000000000000011111111
 dc.l	0,0		; Ende des Sprites (2 Langwörter statt 2 Wörter).

; binär 00=COLOR00 (transparent)
; binär 10=COLOR01 (rot)
; binär 01=COLOR02 (grün)
; binär 11=COLOR02 (gelb)

	cnop	0,8

	SECTION	LEEREPLANE,BSS_C	; Die von uns verwendete Reset-Bitebene,
								; weil um die Sprites zu sehen
								; muss es aktivierte Bitebenen geben
Bitplane:
	ds.b	40*256				; Bitplane leer lowres

	end

Hast du das schöne 32 Pixel breite Insekt gesehen?
Die UniMuoviSprite Routine wurde auf sehr einfache Weise modifiziert.
Tatsächlich wurden die 2 Bytes VSTOP und VHBITS ein Wort nach vorne
verschoben. Es war also genug zu ersetzen:

	2(a1) und 3(a1)

In:

	2+2(a1) und 3+2(a1)

Nichts einfacher! (Sie werden sich vorstellen können, wie man 
UniMuoviSprite 64 Pixel macht!)

;------------------------------------------------------------------------------

Der einzige Unterschied zum originalen Code-Beispiel ist, dass hier das Bit15
SSCAN2 in Register FMODE gesetzt ist.

dc.w	$1fc,$8007	; SSCAN2 + Burst mode 64 bit, sprite Größe 32 pixel

Dieses Bit führt zu einer Wiederholung des Sprites bzw. zu einer 
Spriteverdoppelung 256 Pixel weiter rechts auf dem Bildschirm. 

z.B. wenn die horizontale Position des Sprites $40 ist, erfolgt die 
Wiederholung des Sprites an Position: $c0

>?!256/2
$00000080 = %00000000`00000000`00000000`10000000 = 128 = 128

>?$40+$80
$000000C0 = %00000000`00000000`00000000`11000000 = 192 = 192

Solange das Bit SH10 in SPRxPOS '0' ist wird das Sprite normal angezeigt. 
Ist das Bit SH10 dagegen aufgrund der horizontalen Position gesetzt, kommt es
zu einem Effekt den man "Scan-Verdoppelung" nennen kann.

Die Methode zum Wiederholen der Sprites ist effizient, da man mit nur einem
Schreibvorgang alle Sprite-Kanäle wiederholen kann, jedoch nicht so flexibel,
da die Position im festen Abstand erfolgt.
Die Standardmethode mit dem Copper benötigt dazu jedenfalls mehr 
Schreibvorgänge.


WinUAE-Debugger

>sp 687e8 2
    0687E8 2C40 0000 4600 0000
 44 0687F0 00000000022000000000022000000000
 45 0687F8 00000000022200000000222000000000
 46 068800 00000000002220000002220000000000
 47 068808 00000000000222000022200000000000
 48 068810 00000000000022000022000000000000
 49 068818 00000000000022200222000000000000
 50 068820 00000222000002333320000022200000
 51 068828 00002220000003333330000002220000
 52 068830 00022200000333333333300000222000
 53 068838 00222000003333333333330000022200
 54 068840 02220000023113333331132000002220
 55 068848 22220000231111333311113200002222
 56 068850 22222222331100333300113322222222
 57 068858 02222222333100333300133322222220
 58 068860 00000000033333333333333000000000
 59 068868 00000000223333333333332200000000
 60 068870 00000002223331111113332220000000
 61 068878 00000022222333111133322222000000
 62 068880 00000222220033333333002222200000
 63 068888 00002222200033333333000222220000
 64 068890 00002222000003333330000022220000
 65 068898 00002222000000033000000022220000
 66 0688A0 22222222000000000000000022222222
 67 0688A8 22222222000000000000000022222222
 68 0688B0 22222222000000000000000022222222
 69 0688B8 22222222000000000000000022222222
Sprite address 000687E8, width = 32
OCS: StartX=128 StartY=44 EndY=70
ECS: StartX=512 (128.0) StartY=44 EndY=70
Attach: 0. AGA SSCAN/SH10 bit: 0
>

>sp 687e8 2
    0687E8 2C95 0000 4601 0000
 44 0687F0 00000000022000000000022000000000
 45 0687F8 00000000022200000000222000000000
 46 068800 00000000002220000002220000000000
 47 068808 00000000000222000022200000000000
 48 068810 00000000000022000022000000000000
 49 068818 00000000000022200222000000000000
 50 068820 00000222000002333320000022200000
 51 068828 00002220000003333330000002220000
 52 068830 00022200000333333333300000222000
 53 068838 00222000003333333333330000022200
 54 068840 02220000023113333331132000002220
 55 068848 22220000231111333311113200002222
 56 068850 22222222331100333300113322222222
 57 068858 02222222333100333300133322222220
 58 068860 00000000033333333333333000000000
 59 068868 00000000223333333333332200000000
 60 068870 00000002223331111113332220000000
 61 068878 00000022222333111133322222000000
 62 068880 00000222220033333333002222200000
 63 068888 00002222200033333333000222220000
 64 068890 00002222000003333330000022220000
 65 068898 00002222000000033000000022220000
 66 0688A0 22222222000000000000000022222222
 67 0688A8 22222222000000000000000022222222
 68 0688B0 22222222000000000000000022222222
 69 0688B8 22222222000000000000000022222222
Sprite address 000687E8, width = 32
OCS: StartX=299 StartY=44 EndY=70
ECS: StartX=1196 (299.0) StartY=44 EndY=70
Attach: 0. AGA SSCAN/SH10 bit: 1