
; Listing23c2.s		BPL-Pointer Mid-Screen Änderung
; Änderung von 2 Bitplanepointern um ein anderes playfiled anzuzeigen	
; Variante mit Speicher auf $xx0000 ausgerichtet anfordern		

; asmone Allocate: c/100kb

; exec LVOs
Forbid		equ	-132
Permit		equ	-138
AllocMem	equ	-198
FreeMem		equ	-210
AvailMem	equ	-216
AllocAbs	equ	-204

DISPLAY_DX=320
DISPLAY_DY=256
DISPLAY_DEPTH=2
SIZE = 2*(DISPLAY_DEPTH*DISPLAY_DY*(DISPLAY_DX>>3))


	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 Memory					; Speicher anfordern
	bsr FillPlayfield1
	bsr FillPlayfield2
	bsr InitCopper				; Copperliste erstellen

	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:

	; Speicher freigeben
	movea.l playfield1,a1		; Anfangsadresse
	move.l #SIZE,d0				; für beide playfields freigeben
	movea.l $4,a6
	jsr -210(a6)
	
	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

GfxName:
	dc.b	"graphics.library",0,0	

GfxBase:	     ; Hier hinein kommt die Basisadresse der graphics.library,
	dc.l	0    ; ab hier werden die Offsets gemacht

OldCop:			; Hier hinein kommt die Adresse der Orginal-Copperlist
	dc.l	0	; des Betriebssystemes

;********** Daten **********

;Playfield1:		dc.l 0		; nur zum Vergleich
Playfield1:	dc.l 0		; Anfangsadresse auf $xx0000 ausgerichtet
Playfield2:	dc.l 0		; 

*******************************************************************************
* Diese Routine fordert ein Speichersegment an, das auf $xx0000 ausgerichtet  *
* ist					                                                      *
*******************************************************************************

Memory:
; --- part 1 ---
; ein Speichersegment, das auf $xx0000 ausgerichtet ist, kann man nur selber
; anfordern. z.B.:
; zuerst die gewünschte Chip-RAM Größe + 65535 Bytes anfordern (um Raum für
; das Alignment zu haben)

	move.l #SIZE+$ffff,d0						; move.l  #SIZE+$ffff,d0
	move.l #$10002,d1							; move.l  #MEMF_CHIP,d1
	movea.l $4,a6								; Execbase in a6			
	jsr -198(a6)								; jsr     AllocMem(a6)
	; move.l d0,Playfield1						; nur zum Vergleich
	; beq     not_enough_chip_memory			

; --- part 2 ---
; dann verbietet man Task-Switching um sicher zu gehen daß kein anderer Task
; dazwischenfunkt
	move.l d0,d2								; Kopie		
	jsr -132(a6)								; jsr     Forbid(a6)
	move.l  d2,a1						
   
; --- part 3 ---  
; danach gibt man den Speicher wieder frei und belegt ihn sofort wieder mit 
; AllocAbs() an einer durch $10000 teilbaren Adresse. Die Adresse findest man
; dann in playfield1 (bzw. playfield2).

	move.l #SIZE+$ffff,d0						; move.l  #SIZE+$ffff,d0
    jsr -210(a6)								; jsr     FreeMem(a6)
   
    add.l   #$ffff,d2
    and.l   #$ffff0000,d2						; clr.w d2
    move.l  d2,Playfield1						; Adresse des angeforderten Speichers
	move.l  d2,Playfield2
	add.l	#SIZE/2,Playfield2					; playfield 2 liegt direkt dahinter
    move.l  d2,a1
    move.l  #SIZE,d0
    jsr     -204(a6)							; jsr     AllocAbs(a6)
    jsr     -138(a6)							; jsr     Permit(a6)

	rts

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

FillPlayfield1:
; playfield 1 - bitebene 1----------------
	movea.l 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----------------
	movea.l 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----------------
	movea.l 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
	movea.l Playfield2,a1
	movea.l 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:
	; 256*(8+24)+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
	ds.l	2060	
	dc.w	$ffff,$fffe		; Ende der copperlist
	dc.w	$9876,$5432		; Endetest
			
	end
	

Erklärung:

Wie eben nur das wir in diesem Beispiel zunächst für zwei playfields mit 
jeweils 2 Bitebenen leeren Speicher anfordern. Die Anfangsadresse dieses
Speicherbereiches richten wir dabei auf 64k-Grenzen ein. Dies hat für uns
den Vorteil später in der Copperliste nur noch mit den Low-Pointern zu
arbeiten, weil der Highpointer-Teil unverändert bleibt.