
; Listing23e2.s	hires, interlace, overscan - max screensize
; Zusammenhänge bei der Hires Bildschirmeinstellung

	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	= 8					; 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		= 200				; 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
BPLSHIFT	= 0					; Bitplane Verschiebungswert (BPLCON1)
BPLCON1VAL	= 0; $66			; Bitplane Verschiebungswert (BPLCON1)
ModCor		= 0					; Modulo-Korrektur wenn DDFSTOP_execute > DDFSTOP_berechnet 		

; 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)+BPLSHIFT		; 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 der 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 der 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 der Copperlist 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 der Copperlist 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	BitplaneFrame				; Bilderrahmen (Aussengrenzen) hinzufügen
	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
WarteY2:
	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	WarteY2

	;bsr.w	demoeffect			; hier irgendeinen Effekt hinzufügen

	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

******************************************************************************
; Bildrahmen
******************************************************************************

BitplaneFrame:
	lea Bitplane,a0					; erste Zeile
	lea BitplaneEnd-SCRBYTES,a1		; letzte Zeile
	move.b #$ff,d0					; die Bitplane mit Linien füllen	
	move.w #SCRBYTES-1,d1			; Anzahl Bytes (Bildschirmbreite)
Pf1:
	move.b d0,(a0)+					; obere Linie
	move.b d0,(a1)+					; untere Linie
	dbf d1,Pf1

	lea Bitplane+SCRBYTES,a0		; mit der zweiten Zeile beginnen links
	lea Bitplane+SCRBYTES+SCRBYTES-1,a1	; mit der zweiten Zeile beginnen rechts
	move.b #$80,d0					; senkrechte Linie links
	move.b #$01,d1					; senkrechte Linie rechts
	move.w #SCR_H-2-1,d2			; Höhe-2 Zeilen
Pf2:
	move.b d0,(a0)
	move.b d1,(a1)
	lea SCRBYTES(a0),a0				; nächste Zeile (SCRBYTES=80)
	lea SCRBYTES(a1),a1				; nächste Zeile (SCRBYTES=80)
	dbf d2,Pf2
	
	rts

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

	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,BPLCON1VAL				; BPLCON1	etwas nach rechts verschieben
	dc.w	$104,0						; BPLCON2
	dc.w	$108,SCRBYTES-ModCor		; BPL1MOD \ INTERLACE: modulo = Länge Zeile!
	dc.w	$10a,SCRBYTES-ModCor		; 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		; 92*566 eine bitplane Hires int. 736x566
BitplaneEnd:
	ds.b	SCRBYTES*SCR_H
	ds.b	SCRBYTES*SCR_H
	end

Erklärung:

zur Info: WinUAE bietet unter Display/ Overscan folgende Einstellmöglichkeiten
um sich das Ergebnis anzusehen:
-TV (narrow)
-TV (standard)
-TV (wide)
-Overscan					; zeigt rechts den Rand
-Overscan+					; zeigt links den Rand
-Extreme
-Ultra extreme debug
-Ultra extreme debug (HV)
-Ultra extreme debug (C)

Da wir in die Bitplane in den äusseren Rand Linien, also einen schmalen Rahmen 
gezeichnet haben, können wir nun die Ergebnisse beobachten.
Der Screen kann mit dem BPLCON1 auch noch um maximal 15 Pixel nach rechts
verschoben werden.

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

Ausgehend vom vorherigen Beispiel soll jetzt experimentiert werden.

Zunächst der 'Standard Hires/Interlace Screen' mit 512x640 und den gegebenfalls
mit einem BPLCON1-Wert nach rechts verschieben.

SCRBYTES	= 80	=> 40*16=640
SCR_H		= 512
SCR_X		= $81
SCR_Y		= $2c

-> DIWSTRT: $2c81 DIWSTOP: $2cc1 DDFSTRT: $003c DDFSTOP: $00d4

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

Zusammenhänge bei der Hires Bildschirmeinstellung

Für unsere Tests lassen wir SCR_Y = $2c und SCR_H = 512 unverändert und ändern nur: 
SCRBYTES und SCR_X

Klassisch:
'sub-blocks' per line * 16 pixel per block = pixel fetch per line
40*16=640	(mod 80)
41*16=656	(mod 82)
42*16=672	(mod 84)
43*16=688	(mod 86)
44*16=704	(mod 88)
45*16=720	(mod 90)
46*16=736	(mod 92)
47*16=752	(mod 94)
48*16=768	(mod 96)
49*16=784	(mod 98)

;------------------------------------------------------------------------------
Beispiel 1 (720x) - 45*16=720	(mod 90)

1a. 
SCRBYTES = 90
SCR_X = $61
DIWSTRT: $2c61 DIWSTOP: $2cc9 DDFSTRT: $002c DDFSTOP: $00d8
Ergebnis: Wir erhalten kein stabiles Bild. Das Problem ist, der wahre
ausgeführte DDFSTOP ist $DC. $dc liegt hinter $d8, dem letzten möglichen
DDFSTOP-Wert. Es  handelt sich also um einen Überlauf, der auf echten Maschinen
zu Abstürzen führen kann, weil Bitplane DMA mit memory refresh cycles
kollidieren.

;---
1b.
SCRBYTES = 90
SCR_X = $59
DIWSTRT: $2c59 DIWSTOP: $2cc1 DDFSTRT: $0028 DDFSTOP: $00d4
DDFSTOP_ex=d8       Pixel_fetch=736		736-720=16 --> 2 Bytes

Es funktioniert aber es benötigt eine Modulo Korrektur um -2
dc.w	$108,SCRBYTES-2
dc.w	$108,SCRBYTES-2

Und das liegt daran, dass obwohl DDFSTOP: $00d4 berechnet und eingestellt
wurde, der wahre DDFSTOP bei $d8 ist und der wahre Pixel fetch Wert 736 und
nicht 720 ist. 736/8=92.

;------------------------------------------------------------------------------
Beispiel 2 (736x) - 46*16=736	(mod 92)

SCRBYTES = 92
SCR_X = $59
DIWSTRT: $2c59 DIWSTOP: $2cc9 DDFSTRT: $0028 DDFSTOP: $00d8

Es sind gute und richtige Werte. Es gibt keine Probleme. (DDFSTOP_ex=D8)
Es ist keine Modulo Korrektur notwendig.

;------------------------------------------------------------------------------
Beispiel 3 (752x) - 47*16=752	(mod 94)

SCRBYTES = 94
SCR_X = $49
DIWSTRT: $2c49 DIWSTOP: $2cc1 DDFSTRT: $0020 DDFSTOP: $00d4
DDFSTOP_ex=d8       Pixel_fetch=768		768-752=16 --> 2 Bytes

Es funktioniert aber es benötigt eine Modulo Korrektur um -2
dc.w	$108,SCRBYTES-2
dc.w	$108,SCRBYTES-2

Und das liegt daran, dass obwohl DDFSTOP: $00d4 berechnet und eingestellt
wurde, der wahre DDFSTOP bei $d8 ist und der wahre Pixel fetch Wert 768 und
nicht 752 ist. 768/8=96.

;------------------------------------------------------------------------------
Beispiel 4 (768x) - 48*16=768	(mod 96)
SCRBYTES = 96
SCR_X = $41

DIWSTRT: $2c41 DIWSTOP: $2cc1 DDFSTRT: $001c DDFSTOP: $00d4
DDFSTOP_ex =D4       Pixel_fetch=768

Es sind gute und richtige Werte. Es gibt keine Probleme. (DDFSTOP_ex=D4)
Es ist keine Modulo Korrektur notwendig.

;------------------------------------------------------------------------------
Beispiel 5 (784x) - 49*16=784	(mod 98)

SCRBYTES = 98
SCR_X = $39

DIWSTRT: $2c39 DIWSTOP: $2cc1 DDFSTRT: $0018 DDFSTOP: $00d4
DDFSTOP_ex=D8       Pixel_fetch=800

Es funktioniert aber es benötigt eine Modulo Korrektur um -2
dc.w	$108,SCRBYTES-2
dc.w	$108,SCRBYTES-2

Und das liegt daran, dass obwohl DDFSTOP: $00d4 berechnet und eingestellt
wurde, der wahre DDFSTOP bei $d8 ist und der wahre Pixel fetch Wert 800 und
nicht 784 ist. 800/8=100.

;------------------------------------------------------------------------------
Beispiel 6 (64x) - 4*16=64	(mod 8)  (int sub_blocks=4+2*n, wenn n=0)

SCRBYTES = 8
SCR_X = $81
SCR_H = 200

DIWSTRT: $2c81 DIWSTOP: $90a1 DDFSTRT: $003c DDFSTOP: $0044
DDFSTOP_ex=44       Pixel_fetch=64

Es sind gute und richtige Werte. Es gibt keine Probleme. (DDFSTOP_ex=44)
Es ist keine Modulo Korrektur notwendig.

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

Die Gesetzmässigkeit die dem zugrunde liegt kann nach folgender Formel 
ermittelt werden. Processing-Sketch

int DIWSTRT= 0x39;      
int PixelproZeile=784; 
int Hoehe=256;
int DIWSTOP=0;         
int DDFSTRT=0;
int DDFSTOP=0;
int sub_blocks=0;
int PixelproZeile_16=0;  // vielfaches von 16

void setup(){   
  ddf_berechnung_hires();  
}

void ddf_berechnung_hires(){
   println("--- DDF-Berechnung ---");
   println("DIWSTRT-Werte von $00 bis $FF möglich");
   println("DIWSTOP-Werte von $(1)00 bis $(1)FF möglich");
        
    DDFSTRT=(((DIWSTRT*10/2)-45)/10)& 0xFC;
    DDFSTOP=(DDFSTRT+4*(PixelproZeile/16-2))& 0xFC;
    DIWSTOP=DIWSTRT+(PixelproZeile/2);
    sub_blocks=PixelproZeile/16;
    PixelproZeile_16=sub_blocks*16;
        
    print("DIWSTRT="+hex(DIWSTRT,2));
    print("   DIWSTOP="+hex(DIWSTOP,3));
    print("   DDFSTRT="+hex(DDFSTRT,2));  
    println("   DDFSTOP="+hex(int(DDFSTOP),2)); 
    print("Pixel pro Zeile="+PixelproZeile); 
    print("   Pixel pro Zeile 16*="+PixelproZeile_16); 
    print("   sub-blocks="+sub_blocks); 
    println();
    //---------------------------------------------   
    int n=round((float(DDFSTOP)-float(DDFSTRT))/8)-1;     //println("n ="+n);     
    int sub_blocks=4+2*n;                                 //println("sub_blocks ="+sub_blocks);
    int DDFSTOP_ex=DDFSTRT+n*8+8; print("DDFSTOP_ex="+hex(DDFSTOP_ex,2));      // DDFSTOP ausgeführt
    int pixel_fetch=sub_blocks*16; print("       Pixel_fetch="+pixel_fetch); // Anzahl Pixel abgerufen
    int modulo_cor=(pixel_fetch-PixelproZeile_16)/8; println("       Modulo Korrektur="+modulo_cor); 
    
    if (DDFSTOP_ex>=0xdc) println("DDFSTOP overrun!");  
}

;------------------------------------------------------------------------------
etwas mathematischer Hintergrund:

zu Beispiel 3 (752x) - 47*16=752	(mod 94)

SCRBYTES = 94
SCR_X = $49
DIWSTRT: $2c49 DIWSTOP: $2cc1 DDFSTRT: $0020 DDFSTOP: $00d4
DDFSTOP_ex=d8       Pixel_fetch=768		768-752=16 --> 2 Bytes

>?$d4-$20 -> $000000B4 = %00000000`00000000`00000000`10110100 = 180 = 180		; x=DDFSTOP-DDFSTRT
>?180/8 -> $00000016 = %00000000`00000000`00000000`00010110 = 22 = 22			; n=(DDFSTOP-DDFSTRT)/8
>?4+2*22 -> $00000030 = %00000000`00000000`00000000`00110000 = 48 = 48			; sub-blocks=4+2*n
>?$28+22*8+8 -> $000000E0 = %00000000`00000000`00000000`11100000 = 224 = 224	; DDFSTOP=n*8+8
>?48*16 -> $00000300 = %00000000`00000000`00000011`00000000 = 768 = 768			; pixel per line=sub-blocks*16px
>?(768-752)/8 -> $00000002 = %00000000`00000000`00000000`00000010 = 2 = 2		; Modulo Korrektur

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

Zusammengefasst:

Mögliche horizontale DDFSTART- und DDFSTOP-Werte für Einstellungen sind:
$18,$20,$24,$28,$2c,$30,$34,$38,$3c,$40,...,$d0,$d4,$d8 (aber nicht $dc)
Der DDFSTOP muss immer auf ein Vielfaches von 16 Pixeln gesetzt werden und wenn
der DDFSTOP nicht ausgerichtet ist, wird der nächstfolgende ausgeführt.
$dc ist ein Überlaufwert und kann auf realen Maschinen zu Problemen führen.

Am Ende läuft alles darauf hinaus, wie das Abrufen von Bitplanes funktioniert,
was nicht völlig frei ist.
In OCS können Sie eine definierte Blockgranularität (d.h. 8 aufeinanderfolgende 
Buszyklen) haben. Bei Lowres entspricht ein Block den normal maximal 
6 (bzw. 8) Bitebenen mit je 1x16 Pixel pro Abruf.
In Hires gibt es 2 Unterblöcke pro Block, also insgesamt 4 Bitebenen mit je 
2*16 Pixeln. Das bedeutet, dass man in hochauflösender Darstellung keine 
ungerade Anzahl von Unterblöcken haben kann!

Block=Unterblock*16Pixel  (Unterblock Lowres=1, Hires=2)

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

Vertikal gibt es fast keine Probleme.
Bei einem Startbildschirm bei $2c kann die Bildschirmhöhe von 168 bis zum Ende frei
eingestellt werden. Im oberen Bereich, wenn der vertikale DIWSTOP-Wert kleiner als
$80, also von $01 bis $7f ist, dann folgt daraus der DIWSTOP mit $101 bis $17f.

SCR_H		= 166
SCR_Y		= $2c

Die vertikale Startposition kann von $1a bis $ff frei eingestellt werden. 