
; Listing23d.s		Routine Interlaced Mode Management (640x512)
; der das Bit 15 (LOF) von VPOSR ($dff004) liest.
; Wechsel der Halbbilder durch Copperliste	

	SECTION	INTERLACE,CODE

;	Include	"DaWorkBench.s"		; entferne das; vor dem Speichern mit "WO"

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

			;5432109876543210
DMASET	equ	%1000001110000000	; nur Copper und Bitplane DMA

WAITDISK	equ	30

SCRBYTES	= 80				; Anzahl der Bytes für jede horizontale Zeile.
								; Daraus berechnen wir die Bildschirmbreite,
								; Multiplizieren von Bytes mit 8: normaler Bildschirm 320/8 = 40
								; z.B. für einen 336 Pixel breiten Bildschirm 336/8 = 42
								; Beispielbreiten:
								; 264 pixel = 33 / 272 pixel = 34 / 280 pixel = 35
								; 360 pixel = 45 / 368 pixel = 46 / 376 pixel = 47
								; ... 640 pixel = 80 / 648 pixel = 81 ...

SCR_H		= 256				; Bildschirmhöhe in Zeilen
SCR_X		= $81				; Startbildschirm, XX-Position (normal $xx81) (129)
SCR_Y		= $2c				; Startbildschirm, YY-Position (normal $2cxx) (44)
SCR_RES		= 2					; 2 = HighRes (640*xxx) / 1 = LowRes (320*xxx)
SCR_LACE	= 1					; 0 = non interlace (xxx*256) / 1 = interlace (xxx*512)
HAM			= 0					; 0 = non HAM / 1 = HAM
SCR_BPL		= 1					; Anzahl Bitplanes

; Parameter automatisch berechnet

SCR_W		= SCRBYTES*8		; Bildschirmbreite
SCR_SIZE	= SCRBYTES*SCR_H	; Größe in Bytes des Bildschirms
BPLC0		= ((SCR_RES&2)<<14)+(SCR_BPL<<12)+$200+(SCR_LACE<<2)+(HAM<<11)		; BPLCON0
DIWS		= (SCR_Y<<8)+SCR_X													; DIWSTRT
DIWST		= ((SCR_Y+SCR_H/(SCR_LACE+1))&255)<<8+(SCR_X+SCR_W/SCR_RES)&255		; DIWSTOP
DDFS		= (SCR_X-(16/SCR_RES+1))/2											; DDFSTRT
DDFST		= DDFS+(8/SCR_RES)*(SCRBYTES/2-SCR_RES)								; DDFSTOP

Start:
	move.l	#Bitplane,d0		; Adresse des Bitplane in d0
	lea	Bplpointers1,a1			; Pointer in der Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)	

	move.l	#Bitplane+SCRBYTES,d0		; Adresse des Bitplane in d0
	lea	Bplpointers2,a1			; Pointer in der Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)
	
	move.l	#Copperlist2,d0		; Adresse des Bitplane in d0
	lea	CopPtr1,a1				; Pointer in der Copperlist
	move.w	d0,6(a1)
	swap	d0
	move.w	d0,2(a1)

	move.l	#Copperlist1,d0		; Adresse des Bitplane in d0
	lea	CopPtr2,a1				; Pointer in der Copperlist
	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 - aktivieren Bitplane, Copper
	move.l	#Copperlist,$84(a5) ; Zeiger Copperlist COPL2
	move.w	#0,$1fc(a5)			; AGA "deaktivieren"
	move.w	#$c00,$106(a5)		; AGA "deaktivieren"
	move.w	#$11,$10c(a5)		; AGA "deaktivieren"

	bsr LaceInt					; LOF-Bit testen und Copperpointer eintragen

Mouse:
	move.l	#$1ff00,d1			; Bit zur Auswahl durch UND
	move.l	#$01000,d2			; warte auf Zeile $010
WarteY1:
	move.l	4(a5),d0			; VPOSR und VHPOSR - $dff004/$dff006
	andi.l	d1,d0				; wählen Sie nur die Bits der vertikalen Pos.
	cmpi.l	d2,d0				; warte auf Zeile $010
	bne.s	WarteY1
Waity2:
	move.l	4(a5),d0			; VPOSR und VHPOSR - $dff004/$dff006
	andi.l	d1,d0				; wählen Sie nur die Bits der vertikalen Pos.
	cmpi.l	d2,d0				; warte auf Zeile $010
	beq.s	Waity2

	bsr.w	PrintCharacter		; Drucken Sie jeweils ein Zeichen

	btst	#6,$bfe001			; Maus gedrückt?
	bne.s	Mouse

	rts
	

******************************************************************************
; INTERLACE ROUTINE - Test Bit LOF (Long Frame) um zu wissen, ob Sie
; gerade oder ungerade Zeilen anzeigen und entsprechend wechseln müssen.
******************************************************************************
LaceInt:
	btst.b	#15-8,4(a5)			; VPOSR LOF bit?
	beq.s	MakeOdd				; wenn ja, zeigen Sie auf ungerade Zeilen
	
								; Starten der Ansicht von den geraden Zeilen!
	move.l	#Copperlist1,$dff080	; unsere COP
	rts

MakeOdd:
	move.l	#Copperlist2,$dff080	; unsere COP
	rts


*****************************************************************************
;			Druck Routine
*****************************************************************************

PrintCharacter:
	move.l	PointerText(pc),a0	; Adresse des zu druckenden Textes a0
	moveq	#0,d2				; d2 löschen
	move.b	(a0)+,d2			; Nächstes Zeichen in d2
	cmp.b	#$ff,d2				; Ende des Textsignals? ($ff)
	beq.s	EndText				; Wenn ja, beenden Sie ohne zu drucken
	tst.b	d2					; Zeilenende-Signal? ($00)
	bne.s	NotEndLine			; Wenn nicht, nicht aufhören

	add.l	#SCRBYTES*7,PointerBitplane	; wir gehen zum Anfang
	addq.l	#1,PointerText		; erste Zeichenzeile danach
								; (überspringe die NULL)
	move.b	(a0)+,d2			; erstes Zeichen der Zeile nach
								; (überspringe die NULL)

NotEndLine:
	sub.b	#$20,d2				; ZÄHLE 32 VOM ASCII-WERT DES BUCHSTABEN WEG
								; SOMIT VERWANDELN WIR Z.B. DAS LEERZEICHEN
								; (Das $20 entspricht), IN $00, DAS
								; AUSRUFUNGSZEICHEN ($21) IN $01...
	lsl.w	#3,d2				; MULTIPLIZIERE DIE ERHALTENE ZAHL MIT 8,
								; da die Charakter ja 8 Pixel hoch sind
	move.l	d2,a2
	add.l	#Font,a2			; FINDE DEN GEWÜNSCHTEN BUCHSTABEN IM FONT...

	move.l	PointerBitplane(pc),a3 ; Adresse Ziel-Bitplane in a3

								; DRUCKE DEN BUCHSTABEN ZEILE FÜR ZEILE
	move.b	(a2)+,(a3)			; Drucke Zeile 1 des Zeichens
	move.b	(a2)+,SCRBYTES(a3)		; Drucke Zeile  2  " "
	move.b	(a2)+,SCRBYTES*2(a3)	; Drucke Zeile  3  " "
	move.b	(a2)+,SCRBYTES*3(a3)	; Drucke Zeile  4  " "
	move.b	(a2)+,SCRBYTES*4(a3)	; Drucke Zeile  5  " "
	move.b	(a2)+,SCRBYTES*5(a3)	; Drucke Zeile  6  " "
	move.b	(a2)+,SCRBYTES*6(a3)	; Drucke Zeile  7  " "
	move.b	(a2)+,SCRBYTES*7(a3)	; Drucke Zeile  8  " "

	addq.l	#1,PointerBitplane	; wir rücken 8 Bits vor (NÄCHSTES ZEICHEN)
	addq.l	#1,PointerText		; nächstes zu druckendes Zeichen

EndText:
	rts

PointerText:
	dc.l	Text

PointerBitplane:
	dc.l	Bitplane

;	$00 für "Zeilenende" - $FF für "Textende"


	; Anzahl der Zeichen pro Zeile: 40
Text:	     ;		  1111111111222222222233333333334
             ;   1234567890123456789012345678901234567890
	dc.b	' Che scritte piccole! Non si leggono nem'   ; 1	; Was fuer eine kleine Schrift! Man kann sie 
	dc.b	'meno... ma sono in 640x512!             ',0 ; 1b	; fast nicht lesen... aber sie ist in 640x512!
;
	dc.b	'Provate a premere il tasto destro e potr'   ; 2	; Wenn Sie die rechte Taste druecken koennen
	dc.b	'ete verificare cosa vedono i coder che  ',0 ; 2b	; Sie überprüfen, was die Programmierer sehen
;
	dc.b	"non sanno come funziona l'interlace, hah"   ; 3	; Sie wissen nicht, wie Interlace funktioniert, hah	
	dc.b	"aha! In fondo e' semplice, no?          ",0 ; 3b	; Aha! Es ist schließlich einfach, oder?
;
	dc.b	'Programmate, fate qualche demo o qualche'   ; 4	; Programmieren, ein paar Demos machen oder so oder ein
	dc.b	" gioco, e' la cosa piu' creativa che si ",0 ; 4b	; Spiel, es ist das Kreativste, was man tun kann
;
	dc.b	'possa fare nel mondo contemporaneo.     '   ; 5	; in der heutigen Welt.
	dc.b	'                                        ',$ff ; 5b - Ende
			
;	Die Font-Zeichen 8x8.

Font:
	incbin	"/Sources/nice.fnt"

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

	SECTION	GRAPHIC,DATA_C
	
Copperlist1:
Bplpointers1:
	dc.w	$e0,0,$e2,0		; erste Bitplane
CopPtr1:
	dc.w 	$80,$0,$82,$0	; auf Copperlist2 setzen 
	dc.w 	$8a,$0			; COPJMP2

Copperlist2:
Bplpointers2:
	dc.w	$e0,0,$e2,0		; erste Bitplane+80
CopPtr2:
	dc.w 	$80,$0,$82,$0	; auf Copperlist1 setzen 

Copperlist:	
	dc.w	$8e,DIWS	; DIWSTRT
	dc.w	$90,DIWST	; DIWSTOP
	dc.w	$92,DDFS	; DDFSTRT
	dc.w	$94,DDFST	; DDFSTOP

	dc.w	$102,0		; BPLCON1
	dc.w	$104,0		; BPLCON2
	dc.w	$108,80		; BPL1MOD \ INTERLACE: modulo = Länge Zeile!
	dc.w	$10a,80		; BPL2MOD / um sie zu überspringen (die geraden)

				; 5432109876543210
;	dc.w	$100,%1001001000000100	; 1 bitplane, HIRES LACE 640x512
;								; Beachten Sie das Bit 2 Set für LACE!!

	dc.w	$100,BPLC0			; BplCon0 -> lassen Sie es uns automatisch berechnen!
	
	dc.w	$180,$226			; color0 - Hintergrund
	dc.w	$182,$0b0			; color1 - plane 1 Position normal, und
								; der "klebende" Teil an der Spitze.

	dc.w	$ffff,$fffe			; Ende copperlist


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

	SECTION	LEEREPLANE,BSS_C

Bitplane:
	ds.b	SCRBYTES*SCR_H		; 80*512 eine bitplane Hires int. 640x512

	end


Erklärung:

Bei interlace muss entsprechend des Zustands des LOF-Bit's jedes zweite Halbbild
etwas tiefer beginnen, was bei einem 320 Pixel breiten Bild 40 Bytes entspricht.
Bei hires ist es das doppelte, also 80 Bytes.

Die bekannten Verfahren sind dabei gewöhnlich:
1. Copperlisten verdoppeln und nur die Bitplanepointer sind in den Copperlisten
   unterschiedlich

2. In jedem Frame einen Test des LOF-Bit's durchführen und je nach Ergebnis
die Bitplanepointer in der Copperliste mit oder ohne dem Abstand jedesmal
aktualisieren.

3. In diesem Beispiel wird eine andere Variante vorgeschlagen, die sehr schnell
und effektiv ist und zwar einzig durch die Copperliste selbst erfolgt.

Nach jedem vertikal Blank wird die Copperliste von dort gestartet auf die der
COP1LC aktuell zeigt. Und es gibt zwei Zieladressen für den COP1LC. In beiden
Fällen steht als erste Anweisung die Bitplanepointer, einmal mit und einmal ohne
dem 80 Bytes Abstand. Wobei diese Bitplanepointer auch nur einmal während der
Initialisierung zur Laufzeit dort eingetragen werden.
Nach dem Start der Copperliste und der Aktualisierung der Bitplanepointer erfolgt
nun der "Rest" in der Copperliste, wobei nur in jedem zweiten Frame ein Teil der
Copperliste übersprungen werden muss, was durch den COPJMP2 erfolgt.

Init:
	LOF-Bit testen
	COPPT setzen
	Start on the fly mit Copperlist1 oder Copperlist2
	
2 Copperlisten anlegen

Copperlist2:			Copperlist1:
	BPLPTH+x			BPLPTH
	COP1=Copperlist1	COP1=Copperlist2
	|					COP2JMP to Copperlist
Copperlist:
	|
	Cop Wait, Moves
	|
	Cop_Ende		


Vergleiche Listing11l6.s dazu.
