
; Listing23c.s		BPL-Pointer Mid-Screen Änderung
; Änderung von 2 Bitplanepointern um ein anderes playfiled anzuzeigen
; asmone Allocate: c/100kb

	SECTION SCREEN,CODE

Start:
	move.l	4.w,a6				; Execbase in a6
	jsr	-$78(a6)				; Disable - verhindert Interrupts
	lea	GfxName(PC),a1			; Libname
	jsr	-$198(a6)				; OldOpenLibrary
	move.l	d0,GfxBase
	move.l	d0,a6
	move.l	$26(a6),OldCop		; wir speichern die alte Copperlist
	
	; Pointen auf das "leere" Bitplane - wird hier nicht benötigt
	; Pointen auf den Sprite	  - wird hier nicht benötigt
		
	bsr FillPlayfield1
	bsr FillPlayfield2
	bsr InitCopper

	lea	$dff000,a5				; Custom Register Base in a5
	move.l	#Copperlist,$80(a5)	; Zeiger Copperlist	
	move.w	#0,$1fc(a5)			; AGA "deaktivieren"
	move.w	#$c00,$106(a5)		; AGA "deaktivieren"
	move.w	#$11,$10c(a5)		; AGA "deaktivieren"

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

	move.l	OldCop(PC),$dff080	; Pointen auf die alte System Copperlist
	move.l	4.w,a6
	jsr	-$7e(a6)				; Enable
	move.l	GfxBase(PC),a1
	jsr	-$19e(a6)				; Closelibrary
	rts
	
;	Daten
GfxName:
	dc.b	"graphics.library",0,0

GfxBase:
	dc.l	0

OldCop:
	dc.l	0

*******************************************************************************
* Diese Routine füllt die Playfield/ Bitplanes mit Daten					  *
*******************************************************************************

FillPlayfield1:
; playfield 1 - bitebene 1----------------
	lea Playfield1,a0
	move.l #-1,d0			; die Bitplane füllen	
	move.w #2560-1,d1		; 320/8=40 Bytes 10.l*256 Zeilen
Fb1_1:
	move.l d0,(a0)+
	dbf d1,Fb1_1

; playfield 1 - bitebene 2----------------
	lea Playfield1,a0
	lea 40*256(a0),a0
	move.l #$10001000,d0	; senkrechte Linien	
	move.w #2560-1,d1		; 320/8=40 Bytes 10.l
Fb1_2:
	move.l d0,(a0)+
	dbf d1,Fb1_2

	rts

FillPlayfield2:
; playfield 2 - bitebene 2----------------
	lea Playfield2,a0
	lea 40*256(a0),a0
	move.l #$ffffffff,d0
	moveq #16-1,d2	
Fb2_2b:	
	moveq #10-1,d1			; 320/8=40 Bytes 10.l
Fb2_2:
	move.l d0,(a0)+
	dbf d1,Fb2_2
	lea 15*40(a0),a0
	dbf d2,Fb2_2b
							
	rts
	
*******************************************************************************
* Diese Routine erstellt den Teil der Copperliste für die Mid-Screen		  *
* Änderung																	  *
*******************************************************************************

InitCopper:
	lea CopMidScreen,a0
	lea Playfield2,a1
	lea Playfield1,a2
	move.b  #$2c,d0					; Startzeile
	move.l	#$2c03fffe,d1			; wait am Start	
	move.l	#$2c83fffe,d2			; wait mid-screen
	;move.l #Playfield1,d3			; Basisadresse Playfield1
	;move.l #Playfield2,d4			; Basisadresse Playfield2
	moveq #0,d5						; + Anzahl Zeilen 
	moveq #0,d6						; + Anzahl Zeilen
	;moveq #0,d7					; Anzahl der Zeilen

	move.w #256-1,d7				; Anzahl der Zeilen
Lines:	
	movea.l	a1,d3					; Basisadresse playfield1
	movea.l	a2,d4					; Basisadresse playfield2
	add.l d5,d3						; + Anzahl Zeilen 
	add.l d6,d4						; + Anzahl Zeilen 
	move.l d1,(a0)+					; 1. wait setzen
	;1. Bitebene
	move.w  #$00e2,(a0)+			; BPL1PTL - playfield 1
    move.w  d3,(a0)+				; low-Teil
	swap d3							; hi-low tauschen
	move.w  #$00e0,(a0)+			; BPL1PTH - playfield 1
    move.w  d3,(a0)+				; hi-Teil
	swap d3							; Adresse in richtige Reihenfolge bringen
	;2. Bitebene
	add.l #40*256,d3				; an den Start von Bitebene 2 von playfield2
	move.w  #$00e6,(a0)+			; BPL2PTL - playfield 1
    move.w  d3,(a0)+				; low-Teil
	swap d3							; hi-low tauschen
	move.w  #$00e4,(a0)+			; BPL2PTH - playfield 1
    move.w  d3,(a0)+				; hi-Teil
	swap d3							; Adresse in richtige Reihenfolge bringen
	add.l #40,d5					; 40 Bytes hinzufügen - eine Zeile
	; in der Mitte des Screens auf das zweite playfield pointen
;----------
	move.l d2,(a0)+					; wait mid-screen setzen
	
	;2. Bitebene	
	add.l #40*256,d4				; an den Start von Bitebene 2 von playfield2
	move.w  #$00e6,(a0)+			; BPL2PTL - playfield 2
    move.w  d4,(a0)+				; low-Teil	
	;swap d4						; hi-low tauschen
	;move.w  #$00e4,(a0)+			; BPL2PTH - playfield 2
    ;move.w  d4,(a0)+				; hi-Teil
	;swap d4						; Adresse in richtige Reihenfolge bringen
	;1. Bitebene
	sub.l #40*256,d4
	move.w  #$00e2,(a0)+			; BPL1PTL - playfield 2
	move.w  d4,(a0)+				; low-Teil	
	;swap d4						; hi-low tauschen
	;move.w  #$00e0,(a0)+			; BPL1PTH - playfield 2
    ;move.w  d4,(a0)+				; hi-Teil
    ;swap d4						; Adresse in richtige Reihenfolge bringen	
	
	cmp.b  #$ff,d0					; Zeile $ff erreicht?
	bne No_ff
	move.l #$ffdffffe,(a0)+			; wenn ja, wait am Ende einfügen
No_ff:
	add.l #40,d6					; 40 Bytes hinzufügen - eine Zeile	
	add.l #$01000000,d1				; nächste Zeile wait am Start
	add.l #$01000000,d2				; nächste Zeile wait Mitte
	add.b #1,d0
	dbf d7,Lines

	; für den Rest des Screens Bitplanepointer auf playfield 1 setzen
	
	move.l #playfield1,d3			; Basisadresse playfield1
	add.l d5,d3						; + Anzahl Zeilen 
	move.l d1,(a0)+					; wait am Start setzen
	;1. Bitebene
	move.w  #$00e2,(a0)+			; BPL1PTL - playfield 1
    move.w  d3,(a0)+				; low-Teil
	swap d3							; hi-low tauschen
	move.w  #$00e0,(a0)+			; BPL1PTH - playfield 1
    move.w  d3,(a0)+				; hi-Teil
	swap d3							; Adresse in richtige Reihenfolge bringen
	;2. Bitebene
	add.l #40*256,d3				; an den Start von Bitebene 2 von playfield2
	move.w  #$00e6,(a0)+			; BPL2PTL - playfield 1
    move.w  d3,(a0)+				; low-Teil
	swap d3							; hi-low tauschen
	move.w  #$00e4,(a0)+			; BPL2PTH - playfield 1
    move.w  d3,(a0)+				; hi-Teil
	swap d3							; Adresse in richtige Reihenfolge bringen
	
	move.l  #$2c07fffe,(a0)+		; Warte auf Zeile $60
	move.l  #$0142000,(a0)+			; SPR0CTL - "deaktiviert" den Sprite	
	rts
		
******************************************************************************
	
	SECTION GRAPHIC,DATA_C

Copperlist:
SpritePointers:
	dc.w	$120,$0000,$122,$0000,$124,$0000,$126,$0000,$128,$0000
	dc.w	$12a,$0000,$12c,$0000,$12e,$0000,$130,$0000,$132,$0000
	dc.w	$134,$0000,$136,$0000,$138,$0000,$13a,$0000,$13c,$0000
	dc.w	$13e,$0000
		
	dc.w	$8e,$2c81	; DIWSTRT	Register mit Standartwerten
	dc.w	$90,$2cc1	; DIWSTOP	
	dc.w	$92,$0038	; DDFSTRT
	dc.w	$94,$00d0	; DDFSTOP
	dc.w	$102,0		; BPLCON1
	dc.w	$104,$22	; BPLCON2
	dc.w	$108,0		; BPL1MOD
	dc.w	$10a,0		; BPL2MOD

	; das BPLCON0 ($dff100) für einen Bildschirm mit 1 Bitplane: (2 Farben)
				; 5432109876543210
	;dc.w	$100,%0001001000000000	; bit 12 an!!		  (1 = %001)	1 Bitplanes: (2 Farben)
	dc.w	$100,%0010001000000000	; bit 13 an!!		  (2 = %010)	2 Bitplanes: (4 Farben)
	;dc.w	$100,%0011001000000000	; bits 13 und 12 an!! (3 = %011)	3 Bitplanes: (8 Farben)
	;dc.w	$100,%0100001000000000	; bit 14 an!!		  (4 = %100)	4 Bitplanes: (16 Farben)
	;dc.w	$100,%0101001000000000	; bits 14 und 12 an!! (5 = %101)	5 Bitplanes: (32 Farben)
	;dc.w	$100,%0110001000000000	; bits 14 und 13 an!! (6 = %110)	6 Bitplanes: (64 Farben)
	
;	Wir lassen die Bitplanes direkt anpointen, indem wir die Register
;	$dff0e0 und folgende hier in der Copperlist einfügen. Die
;	Adressen der Bitplanes werden dann von der Routine PointBp
;	automatisch eingetragen
	
Bplpointers:
	dc.w $e0,$0000,$e2,$0000	; erste	Bitplane - BPL0PT
	dc.w $e4,$0000,$e6,$0000	; zweite Bitplane - BPL1PT
	;dc.w $e8,$0000,$ea,$0000	; dritte Bitplane - BPL2PT
	;dc.w $ec,$0000,$ee,$0000	; vierte Bitplane - BPL3PT
	;dc.w $f0,$0000,$f2,$0000	; fünfte Bitplane - BPL4PT
	;dc.w $f4,$0000,$f6,$0000	; sechste Bitplane - BPL5PT
	
; Die 8 Farben des Bildes werden hier definiert:
	dc.w	$0180,$000	; COLOR00
	dc.w	$0182,$fff	; COLOR01
	dc.w	$0184,$f00	; COLOR02
	dc.w	$0186,$00f	; COLOR03
	dc.w	$0188,$0f0	; COLOR04
	dc.w	$018a,$ff0	; COLOR05
	dc.w	$018c,$0f0	; COLOR06
	dc.w	$018e,$0ff	; COLOR07

; die weiteren Farben
	dc.w	$0190,$0ff	; COLOR08
	dc.w	$0192,$444	; COLOR09
	dc.w	$0194,$444	; COLOR10
	dc.w	$0196,$444	; COLOR11
	dc.w	$0198,$444	; COLOR12
	dc.w	$019a,$444	; COLOR13
	dc.w	$019c,$444	; COLOR14
	dc.w	$019e,$444	; COLOR15
	dc.w	$01a0,$444	; COLOR16
	dc.w	$01a2,$0FF	; COLOR17
	dc.w	$01a4,$F00	; COLOR18
	dc.w	$01a6,$F00	; COLOR19
	;dc.w	$01a8,$444	; COLOR20
	;dc.w	$01aa,$444	; COLOR21
	;dc.w	$01ac,$444	; COLOR22
	;dc.w	$01ae,$444	; COLOR23
	;dc.w	$01b0,$444	; COLOR24
	;dc.w	$01b2,$444	; COLOR25
	;dc.w	$01b4,$444	; COLOR26
	;dc.w	$01b6,$444	; COLOR27
	;dc.w	$01b8,$444	; COLOR28
	;dc.w	$01ba,$444	; COLOR29
	;dc.w	$01bc,$444	; COLOR30
	;dc.w	$01be,$444	; COLOR31

	dc.w	$2b07,$fffe		; Warte auf Zeile $2b um rechtzeitig das Sprite vorzubereiten
	dc.w	$140,$0090		; SPR0POS - Horizontale Position
	dc.w	$142,$0000		; SPR0CTL
	dc.w	$146,$0000		; SPR0DATB
	dc.w	$144,$e000		; SPR0DATA - aktiviert Sprite
	
CopMidScreen:
	; Anzahl Zeilen*(Anzahl Copper Wait/Move pro Zeile * 4 Bytes)+Rest
	; 256*(8*4)
	; 
	; 256*(8+24)+4=4=8200	
	; 2 x wait			2*4
	; 6 x copper-move	6*4
	; + extra wait		4
		
	blk.l	2060,$fffffffe	; ca. blk.b	8200/2/2,0
	blk.l	6000,$fffffffe	; erhöhe den Wert (try and error) um das Problem mit den 
							; Bitplane Highpointern zu "beheben"
	
	dc.w	$ffff,$fffe		; Ende der copperlist

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

	SECTION LEEREPLANE,BSS_C	

Playfield1:
	ds.b	2*40*256			; 2 Bitebenen auf 0 Lowres
	
Playfield2:
	ds.b	2*40*256
	
	end
	

Erklärung:

In diesem Beispiel ändern wir die Bitplanepointer in der Mitte des Screens.

Um nur die Low-Bitplanepointer in der Copperliste zu ändern müssen wir mit
dem Bereich hinter dem Ende der Copperliste unseren Playfield Beginn 
einstellen. Dazu ändern wir in dieser Zeile: blk.l	6000,$fffffffe
einfach den Wert bis es passt. Im nächsten Beispiel sehen wir wie man es
besser machen kann.

Dann füllen wir die leeren Bitebenen mit Mustern.
-Playfield1, Bitebene1: gesamte Bitebene füllen
-Playfield1, Bitebene2: senkrechte Linien alle 16 Spalten
-Playfield2, Bitebene1: bleibt leer
-Playfield2, Bitebene2: waagerechte Linien alle 16 Zeilen

Dann erstellen wir die Copperliste, die die Bitplanepointer in der Mitte des
Screens ändert.

Das Schema für jede Zeile sieht dabei in etwa wie folgt aus:
Wir setzen ein Wait am Start der Zeile und stellen danch die Bitplanepointer
ein. In der Mitte des Screens setzen wir ein zweites wait und setzen hier nur
die Bitplanepointer low-Anteile. Bei der Erstellung der Copperliste müssen wir
natürlich immer die Bitplanepointer entsprechend selbst erhöhen.

 00030a18: 3a03 fffe [039 090]  ;  Wait for vpos >= 0x3a and hpos >= 0x02
                                ;  VP 3a, VE 7f; HP 02, HE fe; BFD 1
 00030a1c: 00e2 a8b0 [03a 008]  ;  BPL1PTL := 0xa8b0
 00030a20: 00e0 0003 [03a 00c]  ;  BPL1PTH := 0x0003
 00030a24: 00e6 d0b0 [03a 010]  ;  BPL2PTL := 0xd0b0
 00030a28: 00e4 0003 [03a 014]  ;  BPL2PTH := 0x0003
 00030a2c: 3a83 fffe [03a 018]  ;  Wait for vpos >= 0x3a and hpos >= 0x82
                                ;  VP 3a, VE 7f; HP 82, HE fe; BFD 1
 00030a30: 00e6 80b0 [03a 088]  ;  BPL2PTL := 0x80b0
 00030a34: 00e2 58b0 [03a 08c]  ;  BPL1PTL := 0x58b0
 ;--- nächste Zeile ---
 00030a38: 3b03 fffe [03a 090]  ;  Wait for vpos >= 0x3b and hpos >= 0x02
                                ;  VP 3b, VE 7f; HP 02, HE fe; BFD 1

Jetzt gibt es noch eine Besonderheit zu beachten:
Um die Bitplanepointer bis zum Ende des nächsten 16pixel Bitplane-Datafetch in
der Mitte einer Scanline zu ändern darf die Änderung des Bitplanepointer nicht
direkt 1 Zyklus vor seinem BPLx-DMA-Zyklus liegen.
Zwischen zwei 16pixel Bitplane-Datafetch können genau 2 Copper-Move platziert
werden und somit zwei Zeiger neu eingestellt werden. Die Reihenfolge dieser
Copper-Moves ist dabei: zuerst bpl2-Zeiger vor bpl1 ändern

z.B. Für diese waits würde der Wechsel richtig erfolgen: 

move.l	#$2c83fffe,d2
move.l	#$2c85fffe,d2
move.l	#$2c87fffe,d2

 [88     -]   [89     -]   [8A     -]   [8B     -]   [8C     -]   [8D     -]   [8E     -]   [8F     -]
                                        BPL1   110   COP    08C                COP    0E2   BPL2   112
                           W                  0000         00E2                      5d00         0000
                                          0003AD12     0002C02C                  0002C02E     0003D514

                                         189   0D6    116   060                 117   060    18A   0EA

 [90     -]   [91     -]   [92     -]   [93     -]   [94     -]   [95     -]   [96     -]   [97     -]
 COP    08C                COP    0E6   BPL1   110   COP    08C                COPW   08C   BPL2   112
       00E6                      8500         FFFF         4103                      FFFE         1000
   0002C030                  0002C032     00035d00     0002C034                  0002C036     00038500

  118   060                 119   060    180   0AE    11A   060                 11B   060    180   0C2

und für diese Waits wäre die Änderung der Bitplanepointer wirkungslos. 

move.l	#$2c81fffe,d3
move.l	#$2c89fffe,d3

 [80     -]   [81     -]   [82     -]   [83     -]   [84     -]   [85     -]   [86     -]   [87     -]
                                        BPL1   110   COP    08C                COP    0E6   BPL2   112
                           W                  0000         00E6                      86C0         0000
                                          0003AEd0     0002C034                  0002C036     0003D6D2

                                         168   0D7    11A   060                 11B   060    169   0EB

 [88     -]   [89     -]   [8A     -]   [8B     -]   [8C     -]   [8D     -]   [8E     -]   [8F     -]
 COP    08C                COP    0E2   BPL1   110   COP    08C                COPW   08C   BPL2   112
       00E2                      5EC0         0000         4103                      FFFE         0000
   0002C038                  0002C03A     0003AED2     0002C03C                  0002C03E     0003D6D4

  11C   060                 11D   060    169   0D7    11E   060                 11F   060    16A   0EB

  
Bei einer Änderung von mehr als 2 Bitplanepointer:
von 3 auf 4 bitplanes beginnt das ändern 16pixel später zu den 
bitplanes 1 und 2, daher müssen die Bitplanepointer für die Bitebenen 3 und 4
für jede Zeile (2Bytes) 16pixel später gesetzt werden  dies führt zu einem 
nicht korrekten Anzeigebereich am Start von 16pixel

An die Übergangsstelle könnte ein Sprite gelegt werden um diesen Bereich zu überdecken.

;-----
https://eab.abime.net/showthread.php?t=117348

to change the bitplanepointer maybe for a 2nd playfield on a middle of a scanline:
  - it is possible to change up to 2 bitplanepointer on a scanline for the next 16pixel bpl fetch   
    for a correct change without loosing or destroying bitplanedata 
    when changing bitplanepointer are realized with only two copper-moves by changing only the BPLxPTL
    and if the changing the pointer is not directly 1 cycle before his BPLx DMA cycle.
    in copperlist copper-moves series: change first bpl2 pointer before bpl1
	
  - if more then 2 bitplanepointer:
    from 3 to 4 bitplanes the changing starts 16pixel later to the bitplanes 1 and 2,
    so the bitplanepointer for bitplanes 3 and 4 have to set 16pixel later for every line (2Bytes) 
    this leaves a not correct displayed area in the beginning from 16pixel
	
idea: 
    put a 16x256pixel attached sprite over this lack of playfield with the bitplanedata from this area