
ASSEMBLERKURS - LEKTION 24: Copper (Version 2: Stand: 09/2024)

Autor: Göran Strack


Zum Copper wurde alles gesagt, oder?

Copper-Positionen
===============================================================================

aus Buch Amiga intern:
"Horizontal gibt es 113 mögliche Positionen, da die beiden unteren Bits der
horizontalen Position, HPO und HP1, nicht angegeben werden können. Das
Befehlswort des MOVE-Befehls enthält ja nur die Bits HP2 bis HP8. Die
horizontale Koordinate eines WAIT-Befehls lässt sich nur in Schritten von vier
niedrig auflösenden Punkten angeben."

d.h. horizontale Wait-Position:	HP8,HP7,HP6,HP5,HP4,HP3,HP2,x

Eine Darstellung mit allen 9 Bits wäre:
	HP8,HP7,HP6,HP5,HP4,HP3,HP2,HP1,HP0	(1-Pixel-Genauigkeit)
	=> 9 Bits $0 bis $1FF (0 bis 511)
	
Hier haben wir jedoch eine Rechtsverschiebung um eine Stelle was einer Division
durch 2 entspricht. Zudem steht uns HP1 nicht zur Verfügung. HP2 ist also
unsere kleinstmögliche Auflösung was einer 4 Pixelgenauigkeit entspricht.

	HP8,HP7,HP6,HP5,HP4,HP3,HP2,x	(lsr #1,DIW...)(nach Verschiebung)
									--> nur 4 Pixelgenau

  HP0 = 1 Pixelgenau, HP1 = 2 Pixelgenau, HP2= 4 Pixelgenau
  HP3 = 8 Pixelgenau (siehe DDFSTRT, DDFSTOP) 
 
Formal kann HP mit Werten von $0 bis $FE (0 bis 254) geladen werden. Mit 7 Bits
sind jedoch nur 128 unterschiedliche Einstellungen für eine horizontale Position
möglich. Am Ende sind es sogar nur 113 Positionen die zur Verfügung stehen.
Warum? Weil wir nur einen Positionsbereich von $0 bis $E2 (0 bis 226) haben.

wieder aus dem Buch Amiga intern:

"Die Abfrage der aktuellen Strahlposition

Da sich das gesamte DMA-Timing an der Position innerhalb einer Rasterzeile
orientiert, möchte man manchmal wissen, an welcher Stelle der Zeile sich der
Elektronenstrahl gerade befindet. Agnus besitzt dazu einen internen Zähler, der
sowohl die horizontale als auch die vertikale Bildschirmposition enthält, nach
der sich das gesamte System richtet. Zwei Register ermöglichen dem Prozessor
den Zugriff auf diese Zähler:

VHPOS $006 (lesen, VHPOSR) und $02C (schreiben, VHPOSW)
			 Bit-Nr.: 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
			Funktion: V7 V6 V5 V4 V3 V2 V1 V0 H8 H7 H6 H5 H4 H3 H2 H1

VPOS $004 (lesen, VPOSR) und $02A (schreiben, VPOSW)
			Bit-Nr.: 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
		   Funktion: LOF										   V8

Die mit Hl bis H8 bezeichneten Bits stellen die horizontale Strahlposition dar,
sie entsprechen direkt den Nummern für die einzelnen Buszyklen in Abbildung xxx
und haben damit eine Genauigkeit von zwei niedrig- oder vier hochauflösenden
Punkten.
Der Wert für die horizontale Position kann zwischen $0 und $E3 (0 bis 227)
liegen. Die horizontale Austastlücke fällt in den Bereich von $F bis $35.
Die Bits für die vertikale Position, also die aktuelle Bildschirmzeile, sind
auf zwei Register verteilt. Die unteren Bits V0 bis V7 liegen noch in VHPOS,
das oberste Bit, V8, befindet sich in VPOS. Zusammen ergeben sie die Nummer
der aktuellen Bildschirmzeile."

Aha, wegen der 2-Pixelgenauigkeit folgt:
$0 und $E3 (0 bis 227) bedeutet $0 bis $1c6 (0 bis 454) in Pixeln

und 454/4=113 (wegen nur 4 Pixelgenau bei horizontaler Waitposition)
Es stehen somit 113 horizontale Copperpositionen zur Verfügung oder
wie oben 226/2=113.

Das Listing17g.s zeigt eine Copper-Treppe mit den 90 (bzw. 113) Positionen.


Umrechnung: Pixelposition in horizontale Copper-Wait Position
===============================================================================

Wenn wir nun unsere Pixelposition $81 (129) in eine horizontale Waitposition
umrechnen wollen, müssen wir $81 durch 2 dividieren. --> $40 oder wenn wir
ein Wait in der Mitte unseres Lowres-Screens wollen:
129+(320/2)=289	= $81+$A0=$121 dividiert durch 2 = $90
Es wäre also ein dc.w $2c91,$fffe erforderlich um in der Mitte des Screens
ein Wait zu platzieren.

Umgekehrt, wenn wir ein Copper-Wait haben müssen wir dieses mit zwei
multiplizieren um die Pixelposition zu erhalten.

dc.w $ffe1,$fffe		$E0=> $E0*2=$1c1=$81+$140	(129+320=449)

In Listing17g2.s sehen wir die Positionierung eines Copper-Moves an eine
horizontale Pixelposition unabhänig von einem festgelegten Screen und in
Abhängigkeit zu einem Lowres-Screen (320x256) mit festgelegter normaler
Screenposition.


Rasterstrahl/ Strahlposition und Copper-Positionen - Wo es schwierig wird
===============================================================================

vertikal:   in Rasterzeilen
- Zeilen von 0 bis 312 sind möglich
- vertikale Austastlücke				von 0 bis 25
- vertikaler sichtbarer Bereich		    von 26 bis 312 ($1A bis $138) beschränkt

horizontal: in Pixelposition
- Spalten von 0 bis 468 sind möglich    von 0 bis 468 (0 bis $1d4) ?
- horizontale Austastlücke			    von 30 bis 106 ($1E bis $6A) ?
- horizontaler sichtbarer Bereich		ab 107 ($6B) ?

Strahlposition:	Wait-Command
kann horizontal von: $0 bis $E2 (0 bis 227) liegen 

Amiga intern sagt:
Die horizontale Austastlücke fällt in den Bereich von $F bis $35.
$F bis $35 bedeutet in Pixelposition $1E bis $6A (von 30 bis 106)
(als Pixelposition siehe oben !)

HRM sagt:
The standard screen (320 pixels wide) has an unused horizontal portion of
$04 to $47 (during which only the background color is displayed).
$04 to $47 von 8 bis 142 ??? 	

Unsere Screenposition ist $81 (129). In unserem Fall haben wir eine
horizontale Austastlücke von $0 bis $40 bzw. Wenn $5c (92) eingestellt wird
haben wir eine horizontale Austastlücke von $0 bis $2e. Oder? 

horizontale Waitposition:
$2E => 46*2=92   ($5c)  wäre die erste sichtbare Copperposition
$E2 => 226*2=452 ($1c4) wird als Ende genannt.
452-92=360

Man sieht es den Fragezeichen an, dass es noch Unklarheiten gibt...


Ausführungszeit Copperbefehle
===============================================================================

Der Copper arbeitet (mit kleinen Einschränkungen) von $0 bis $E2 (226) und
belegt die geraden DMA-Zyklen. Diese Zyklen, bei denen der Copper auf den
Bus zugreifen kann, werden auch als Copper Cycles bezeichnet.

HRM spricht von odd-numbered memory cycles und meint damit:
1st, 3rd etc. = $00, $02.. usw.
Copper cycles können bei Zugriff von anderen (mit höherer Priorität) im 
allgemeinen Bitplane "gestohlen" werden. 

Als DMA-Diagramm sieht das so aus:

DDFSTRT on $38
 [38  56]  [39  57]  [3A  58]  [3B  59]  [3C  60]  [3D  61]  [3E  62]  [3F  63]       
    1          2        3          4        -       BPL4      BPL6      BPL2
  (free)              (free)              (free)			 (steal)
   COP                 COP                  COP                COP
  
 [40  64]  [41  65]  [42  66]  [43  67]  [44  68]  [45  69]  [46  70]  [47  71]
 COP  08C   BPL3       BPL5     BPL1
  (free)              (steal)
   COP                 COP                  COP                COP

Dabei gleich eine Besonderheit zu DDFSTRT von EAB (Toni Wilen):
DDFSTRT does not equal first bitplane slot. When DDFSTRT matches horizontal
position, it takes 4 cycles more before first bitplane slot is selected
(plane 8) because bitplane enable has multiple stages and internal RGA bus is
pipelined.

Ausführungszeit move
===============================================================================

Jedes copper-move benötigt nach einem anderen je 4 CCKs = 8 Pixel,
solange keine Bitplane copper cycles stiehlt.

	dc.w $0180,$444
	dc.w $0180,$555		; 4 CCKs (keine oder bis 4 bitplanes)

[38  56]  [39  57]  [3A  58]  [3B  59]  [3C  60]  [3D  61]  [3E  62]  [3F  63]
 COP  08C            COP  180            COP  08C            COP  180
 0   0180                0444                0180                0555

Bei 5 Bitplanes verschiebt sich ein Copper Buszugriff um 2 CCKs.
Bei 6 Bitplanes verschiebt sich ein Copper Buszugriff um 4 CCKs.

	dc.w $3031,$fffe
	dc.w $0180,$444
	dc.w $0180,$555		; 6 oder 8 CCKs (bei 5 oder 6 Bitplanes)


 [38  56]  [39  57]  [3A  58]  [3B  59]  [3C  60]  [3D  61]  [3E  62]  [3F  63]
 COP  08C            COP  180            COP  08C  BPL4 116  BPL6 11A  BPL2 112
 0   0180                0444                0180      0000      0000      8080
															 ( !!!!! )	

 [40  64]  [41  65]  [42  66]  [43  67]  [44  68]  [45  69]  [46  70]  [47  71]
 COP  180  BPL3 114  BPL5 118  BPL1 110  COP  08C  BPL4 116  BPL6 11A  BPL2 112
     0444      0000      0000      8080      0180      0000      0000      8080
					 ( !!!!! )								 ( !!!!! )

Bsp: von $3c bis $43 = 8 CCKs (bei 6 Bitplanes)

Das erste move-command nach einem wait-command benötigt weitere 2 CCKs.
Es gibt also eine Lücke von zwei Buszyklen:

	dc.w $3031,$fffe	; wait for horizontal position HP0$30
	dc.w $0180,$444		; 8 CCks, erstes move nach einem wait

[30  48]  [31  49]  [32  50]  [33  51]  [34  52]  [35  53]  [36  54]  [37  55]
   1                   2                 COP  08C            COP  180
                                            0180                0444
                                        00071808            0007180A

Erklärt wird das so:
Im ersten Buszyklus stimmt der Vergleich überein und im nächsten Buszyklus wird
eine DMA-Anfrage generiert. Schliesslich wird im nächsten Zyklus das nächste
Befehlswort gelesen. Somit ist die Ausführungszeit für den ersten move-command
nach einem wait: 4 copper cycle  => 8 CCKs = 16 pixel

"Copper comparison matches first, then in next cycle DMA request is generated. 
Finally following cycle reads next instruction word." von EAB (Toni Wilen)

Ausführungszeit wait
===============================================================================

Für ein wait-command gilt folgende Ausführungszeit:
		dc.w        $3031,$fffe
        dc.w        $180,$444
        dc.w        $3033,$fffe
        dc.w        $3035,$fffe
        dc.w        $ffff,$fffe 

Das wait-command benötigt oder endet nach 4 copper-cycles oder 8 CCKs.
(3 normal cycles: 2 to read copper instructions, 1 for wait to finish and
one "wasted")."
 
[38  56]  [39  57]  [3A  58]  [3B  59]  [3C  60]  [3D  61]  [3E  62]  [3F  63]               
 COP  08C            COP  08C
 0  3033                FFFE             (sleep)             W       
 0007180C            0007180C
 99E1CC00  99E1CE00  99E1D000  99E1D200  99E1D400  99E1D600  99E1D800  99E1DA00
 
; <IR1> <IR2> <sleep start> (sleeping) <wakeup> (next instruction's IR1 fetch).

$38 - IR1 (fetch)	; copper-cyle 1
$3A - IR2			; copper-cyle 2
$3C - sleep start	; copper-cyle 3 - wasted - First refresh cycle is cycle 3
$3E - wakeup		; copper-cyle 4
und dann
$40 - IR1 (fetch)   ; copper-cyle 1 (again)

Bei 5 Bitplanes verschiebt sich ein Copper Buszugriff um 4 CCKs. Summe=12 CCKs

 [38  56]  [39  57]  [3A  58]  [3B  59]  [3C  60]  [3D  61]  [3E  62]  [3F  63]
 COP  08C            COP  08C                      BPL4 116            BPL2 112
 0   3033                FFFE            (sleep)	   0000   W            8080

 [40  64]  [41  65]  [42  66]  [43  67]  [44  68]  [45  69]  [46  70]  [47  71]
 COP  08C  BPL3 114  BPL5 118  BPL1 110  COP  08C  BPL4 116            BPL2 112
     3035      0000      0000      8080      FFFE      0000   (sleep)      8080
					 ( !!!!! )	
 [48  72]  [49  73]  [4A  74]  [4B  75]  [4C  76]  [4D  77]  [4E  78]  [4F  79]
           BPL3 114  BPL5 118  BPL1 110  COP  08C  BPL4 116  COP  08C  BPL2 112
  W            0000      0000      8080      3037      0000      FFFE      8080
					 ( !!!!! )

Bsp: von $40 bis $48	= 12 CCks	(dc.w  $3035,$fffe)

Bei 6 Bitplanes verschiebt sich ein Copper Buszugriff um 8 CCKs. Summe=16 CCKs

[38  56]  [39  57]  [3A  58]  [3B  59]  [3C  60]  [3D  61]  [3E  62]  [3F  63]
 COP  08C            COP  08C                      BPL4 116  BPL6 11A  BPL2 112
 0   3033                FFFE             (sleep)      0000      0000      8080

 [40  64]  [41  65]  [42  66]  [43  67]  [44  68]  [45  69]  [46  70]  [47  71]
           BPL3 114  BPL5 118  BPL1 110  COP  08C  BPL4 116  BPL6 11A  BPL2 112
  W            0000      0000      8080      3035      0000      0000      8080
															( !!!!! )	
[48  72]  [49  73]  [4A  74]  [4B  75]  [4C  76]  [4D  77]  [4E  78]  [4F  79]
 COP  08C  BPL3 114  BPL5 118  BPL1 110            BPL4 116  BPL6 11A  BPL2 112
     FFFE      0000      0000      8080  (sleep)       0000      0000      8080
					( !!!!! )								( !!!!! )

 [50  80]  [51  81]  [52  82]  [53  83]  [54  84]  [55  85]  [56  86]  [57  87]
           BPL3 114  BPL5 118  BPL1 110  COP  08C  BPL4 116  BPL6 11A  BPL2 112
  W            0000      0000      8080      3037      0000      0000      8080
					( !!!!! )

Bsp: von $44 bis $53	= 16 CCks	(dc.w  $3035,$fffe)	

Ausführungszeit skip
===============================================================================

; ohne Sprung
[28  40]  [29  41]  [2A  42]  [2B  43]  [2C  44]  [2D  45]  [2E  46]  [2F  47]
 COP  08C            COP  180            COP  08C            COP  08C
     0180                00F0                3131                FF01

 [30  48]  [31  49]  [32  50]  [33  51]  [34  52]  [35  53]  [36  54]  [37  55]
                     W                    COP  08C            COP  08A
 (sleep)                                     008A                0000

 [38  56]  [39  57]  [3A  58]  [3B  59]  [3C  60]  [3D  61]  [3E  62]  [3F  63]
 COP  08C            COP  180            COP  08C            COP  180
 0   0180                0666                0180                0444

; mit Sprung
mit dc.w	; wenn dc.w $3121,$fffe auskommentiert
 [58  88]  [59  89]  [5A  90]  [5B  91]  [5C  92]  [5D  93]  [5E  94]  [5F  95]
 COP  08C            COP  08C  BPL1 110									W
     3131                FF01      8000				(sleep)

 [60  96]  [61  97]  [62  98]  [63  99]  [64 100]  [65 101]  [66 102]  [67 103]
 COP  08C            COP  08A  BPL1 110  COP  08C            COP  180
     008A                0000      8000      0180                0666

 [68 104]  [69 105]  [6A 106]  [6B 107]  [6C 108]  [6D 109]  [6E 110]  [6F 111]
 COP  08C            COP  08C  BPL1 110
     8007                FFFE      8000

	dc.w	$8007,$fffe		; ist wait-Position in Copperlist 2

Bsp: siehe Listing17g3.s
cop1:
	...
	dc.w	$3131,$ff01		; skip if VP >=31 & HP>=30
	dc.w	$8a,0			; copjmp2 start
	dc.w	$0180,$666		; cop 1
	dc.w	$0180,$444		; cop 1

cop2: ; copperlist 2
	dc.w	$8007,$fffe	 
	
Im Listing17g3.s geht es nur darum ein besseres Verständnis zu den sichtbaren und
"unsichtbaren" Copperpositionen zu bekommen. Es ist aber auch geeignet um mit
dem WinUAE Debugger verschiedene Situationen durchzuspielen.

Copper 'W' im DMA-Debugger
===============================================================================
W = "Copper wake up" (W)
W =  Skip also shows (W) if SKIP skipped.

Der SKIP WARTET nie, sondern überprüft nur die Position und führt 
gegebenenfalls den folgenden Move aus oder nicht. [Technisch gesehen ist dies 
nicht ganz korrekt, da der DMA-Abruf des Befehls tatsächlich abgeschlossen ist,
sondern lediglich das Ziel des MOVE gesperrt ist]

Sie können die Operation von W für SKIP folgendermaßen lesen: Wenn W vorhanden
ist, wird die Anweisung übersprungen, wenn kein W vorhanden ist, wird sie 
ausgeführt. Könnte das W-Signal anders sein? Klar, aber es hängt von Toni ab
und der hat mir mitgeteilt, dass er aufgrund der seltenen Verwendung des Skip-
Befehls kein Extra-Zeichen dafür einführen wollte.


Zusammenfassung:
===============================================================================

Jede Copperanweisung besteht aus 2 Wörtern und benötigt zur Ausführung folgende
Zeit.
													CCKs
	move - nach erfolgreichen wait Vergleich		= 2	= 4 Pixel
	move - bis 4 bitplanes							= 4 = 8 Pixel
	move - 5 bitplane								= 5 = 10 Pixel
	move - 6 bitplane								= 6 = 12 Pixel

	wait - bis 4 bitplanes							= 4	= 8 Pixel
	wait - 5 bitplane								= 6 = 12 Pixel
	wait - 6 bitplane								= 8 = 16 Pixel

	skip ohne Sprung wie wait
	skip - ohne bis 4								= 4 = 8 Pixel
	skip - 5 bitplane								= 5 = 12 Pixel
	skip - 6 bitplane								= 6	= 16 Pixel
	skip mit Sprung									= + 2 CCKs zusätzlich
	

Copper-Masking
===============================================================================

wieder aus dem Buch Amiga intern:
"Das zweite Befehlswort enthält die sogenannten Maskenbits. Mit ihnen kann man
festlegen, welche Bits der horizontalen und vertikalen Position überhaupt zum
Vergleich mit der aktuellen Strahlposition herangezogen werden. Nur die
Positions-Bits, deren zugehörige Masken-Bits gesetzt sind, werden beachtet.
Dies eröffnet vielfältige Möglichkeiten:

Ein Wait mit vertikaler Position $0F und vertikaler Maske $0F bewirkt, dass
alle 16 Zeilen die Wait-Bedingung erfüllt wird, nämlich immer, wenn die unteren
4 Bits auf 1 sind, da Bits 4 bis 6 nicht mehr in den Vergleich mit einbezogen
werden (Masken-Bits 4 bis 6 sind auf 0). Das 7. Bit der vertikalen Position
lässt sich nicht maskieren. Aus diesem Grund funktioniert das obige Beispiel
nur im Bereich der Zeilen 0 bis 127 und 256 bis 313."

Das Listing17g4.s dient nochmal dem Verständnis der Masken-Bits.


COPCON
===============================================================================

wieder aus dem Buch Amiga intern:
"Bei der Registeradresse gibt es einige Einschränkungen. Normalerweise kann der
Copper die Register im Bereich von $000 bis $07F nicht beeinflussen. Setzt man
das unterste (und auch einzige) Bit im COPCON-Register, ist es dem Copper auch
möglich, in die Register von $040 bis $07F zu schreiben. Dadurch kann der Copper
dann den Blitter benutzen. Ein Zugriff auf die untersten Register ($000 bis $03F)
ist allerdings immer verboten."

Das Listing17h.s zeigt ein Beispiel wo der Copper in die Blitterregister
schreibt.


Copper Stop (https://eab.abime.net/printthread.php?t=117940)
===============================================================================

Im Agnus Chip (nicht direkt im Copper) gibt es fünf (7) Copper-Register:
2xCOPxLCx, 2xCOPJMPx und 1xCOPINS.
COPxLCx sind feste Location (Pointer) Register 
	(bzw. COP1LCH $80, COP1LCL $82, COP2LCH $84, COP2LCL $86)
COPJMPx sind Strobe Register (bzw. COPJMP1 $88,  COPJMP2 $8a)	
COPINS ist ein Copper Dummy Fetch Register (COPINS $8c)

- Der Copper hat einen eigenen Copper Program Counter (COPPTR).
- Dieser wird mit einer COPxLCx Adresse durch ein Strobe-Signal geladen.
- Das Strobe-Signal kommt entweder durch ein Schreiben in COPJMP1/2 oder
  automatisch nach einem vertical blank und dann mit der Adresse aus COP1LCx.
- Der interne COPPTR wird allerdings nur neu geladen, wenn auch Copper DMA 
  aktiviert ist. 
- Wenn Copper DMA deaktiviert ist, spricht man auch von Copper Stop oder
  Copper Halt.
- Wenn mitten im Frame Copper DMA deaktiviert wird, bleibt der interne COPPTR
  eingefroren bis zum nächsten Aktivieren von Copper DMA.
  Der COPPTR setzt danach seinen Ablauf von dort fort.
- Nach einem vertical blank wird der COPPTR nur bei aktivierten Copper DMA auf
  den COP1LCx Adresswert zurückgesetzt. 
- Durch ein Strobesignal wird die Adresse zunächst nur vorbereitet und erst mit
  dem Aktivieren von Copper DMA in das interne COPPTR geschrieben.
- Vor dem Start von der neuen Adresse erfolgt jedoch noch ein Abruf von der 
  alten Copperadresse, der aber verworfen wird
- die verworfene Copperanweisung wird im DMA Debugger mit einem 'C'
  gekennzeichnet
- Der einzige Unterschied zwischen COPJMP1-Strobe und indirektem vblank
  COPJMP1-Strobe besteht darin, dass vblank auch das Copper "zurücksetzt".
  (Löscht den möglichen gestoppten Zustand)

z.B. wenn Copper DMA aktiviert bleibt, vertical blank, Copperanweisung von 10560
 wird verworfen. 'C'

>v 0 0
Line: 00   0 HPOS 00   0:
 [00 1BE -]   [01 1C0 -]   [02 1C2 -]   [03 1C4 -]   [04 1C6 -]   [05 002 -]   [06 004 -]   [07 006 -]
                                        RFS0   03A   COP    08C   RFS1   1FE   COP    08C   RFS2   1FE
                                                *B    C    0002                      00E0
                                          00065910     00010560     00065912     00010520     00065914

                                         188   12C    0B0   082    189   12C    090   082    18A   12C

oder wenn Copper DMA mitten im frame aktiviert wird, Copperanweisung von 10518
wird verworfen. 'C'

[28 048 -]   [29 04A -] M [2A 04C -]   [2B 04E -]   [2C 050 -]   [2D 052 -]   [2E 054 -]   [2F 056 -]
    CPU-RWI              O COP    08C      CPU-RWI   COP    08C      CPU-RWI   COP    180      CPU-RWI
       0001              V  C    0002         0508         0180         0080         00F0         3D7C	
   0002115E              E   00010518     00021160     00010510     00021162     00010512     00021164

  1AF   008                 08C   082    1B0   008    088   082    1B1   008    089   082    1B2   008


Frage:
Was ist die Bedeutung von 'C'?

C = Special empty copper cycles where copper allocates the cycle but leaves it
	unused are now marked with "C" in DMA debugger.

C sollte ursprünglich (glaube ich) anzeigen, dass ein Zyklus für Copper
reserviert wurde, das keine DMA-Übertragungen durchführt. Jetzt markiert es
auch den Zyklus, wenn COPxLC -> internes Zeigerkopieren stattfindet. Es
bedeutet nicht wirklich etwas Bestimmtes.


[10 018 -]   [11 01A -]   [12 01C -]   [13 01E -]   [14 020 -]   [15 022 -]   [16 024 -]   [17 026 -]
 COP    080                COP    08C                COP    082                COP    08C
       0001                      0082                      051C                      008A
   00010512                  00010514                  00010516                  00010518

  089   082                 08A   082                 08B   082                 08C   082

 [18 028 -]   [19 02A -]   [1A 02C -]   [1B 02E -]   [1C 030 -]   [1D 032 -]   [1E 034 -]   [1F 036 -]
 COP    08A                COP    08C                COP    08C                COP    08C
       0000                      00E0                 C    0002                      008E
   0001051A                  0001051C                  0001051E                  0001052C

  08D   082                 08E   082                 08F   082                 096   082

Abbildung: DMA-Debugger - Copper Jump mitten im Frame

Frage:
Wenn ein Copper Jump mitten im Frame bei aktivierten Copper DMA ausgeführt wird
werden zwei Copper-DMA Abrufe verworfen, jedoch nur einer als 'C' gekennzeichnet?
Bsp. 1A und 1C verworfen, aber nur 1C hat 'C' Marke.

Antwort:  
Nur 1C wird verworfen. Der Copper-Sequenzer ruft 1A als normalen
Operationscode (vorab) ab. Der Strobe bei 18 startet die neue COPPTR-Copper-
Sprungsequenz (Abruf der alten Adresse zu COPINS, Kopie von COPxLC, Start von
neuen COPINS) nach 1A.
In diesem Fall werden praktisch zwei Abrufe ignoriert. Aber wenn Sie den Strobe
mit der CPU geschrieben hätten, hätte Copper im darauffolgenden Zyklus 
möglicherweise eine Anweisung abschließen können.

Frage:
Vom Aktivieren von Copper DMA bis zum ersten gültigen Copper-Abruf dauert es
3 bis 5 Buszyklen? Welche Regeln gibt es hier?

COPJMPx-Schreiben -> Copper führt neue DMA-Anforderung im nächsten verfügbaren
Zyklus durch (dabei wird immer noch die alte Adresse verwendet)
-> Zeigerkopieren geschieht, wenn DMA im nächsten verfügbaren Zyklus für das
Copper abgeschlossen ist, neue DMA-Anforderung wird in die Warteschlange
gestellt -> Lesen von neuer Adresse (erster Teil des MOVE-Zyklus).


Blitter-Wait Bug 
===============================================================================

CPU-COPJMPx-Schreiben verursacht Konflikt zwischen wartendem Copper und
Blitter:

Wenn die CPU während eines ungeraden Zyklus in COPJMPx schreibt, geht der
Coppersequenzer immer noch davon aus, dass die DMA-Anforderung im nächsten 
Copperzyklus (2 CCKs) abgeschlossen ist, aber da das COPJMPx-Schreiben ein
ungerader Zyklus war, erhält die DMA-Adressierungslogik die 
DMA-Zeigerkopieranforderung des Coppers immer noch in 2 CCKs, was nicht der 
Zyklus ist, den das Copper für die DMA-Übertragung reserviert hat (es ist der 
nächste Zyklus). Und wenn dieser Zyklus von einem DMA-Kanal mit niedrigerer
Priorität (= Blitter) verwendet wird. Die DMA-Adressierungslogik erhält zwei
Adresszeiger-Auswahlsignale gleichzeitig. Wenn dieser Zyklus nicht verwendet
wird (oder von der CPU verwendet wird), funktioniert die COPJMP-Sequenz
ordnungsgemäß.

Es gibt auch einen anderen COPJMP-bezogenen Fehler: Wenn DMA ausgeschaltet ist
und beide Strobes geschrieben sind: Der neue Zeiger wird COP1LC ODER COP2LC
sein, wenn DMA fortgesetzt wird. (ODER wie bei einer logischen ODER-Operation).
Das liegt daran, dass die DMA-Adressierungslogik ein Auswahlsignal für beide
COPLC-Register erhält und mehrere Adressregisterauswahlen = ODER-Operation. 
(Datenkonflikt im internen RGA-Bus verursacht UND-Operation)

Frage:
Kann ein einfacher Beispielcode, der den Blitter-Wait Bug zeigt geteilt werden?

Es ist möglich, hierfür Code zu schreiben, Toni hat erklärt, wie das geht, also
kann es eine gute Übung sein.

Listing24xxx.s	; Blitter-Wait-Bug (vielleicht später...)

Aber ich denke, es ist besser, anzugeben, wie das NICHT geht: Warten Sie, bis
der Blitter seine Operationen abgeschlossen hat oder schalten Sie Copper aus,
bevor Sie COPJMP mit der CPU schreiben.
Noch besser: Verwenden Sie COPJMP überhaupt nicht oder nur, wenn Sie wissen,
was Sie tun (ich meine mit der CPU, mit Copper machen Sie es, wie Sie wollen,
hier gibt es keine Einschränkung).


Copper am Ende der Rasterzeile (DMA-Besonderheiten)
===============================================================================

Frage:
Wie sind die Regeln am Ende der Scanlinie? Wenn ich mich richtig erinnere gibt
es für COPJMPx am Ende der Scanlinie Besonderheiten.

Antwort:
Es gibt zwei Nebeneffekte, die beide nur auftreten, wenn der letzte Zyklus
gerade ist (immer bei PAL). Der letzte PAL-Zyklus ist 226 und der nächste
Zyklus ist 0. Das bedeutet 2 gerade Zyklen hintereinander. Wenn das Copper bei
Zyklus 226 eine DMA-Anforderung stellt, wird Zyklus 0 vom Copper zugewiesen und
für nichts verwendet und Zyklus 2 führt schließlich die DMA-Übertragung durch.
Der Coppersequenzer benötigt eine gerade->ungerade->gerade Zyklussequenz, um 
vollständig fortzufahren.

Außer wenn COPJMP während Zyklus 226 geschrieben wird, weist die COPJMP-Sequenz
Zyklus 1 zu (der normalerweise nicht für das Copper verfügbar ist, aber 
trotzdem zum Kopieren der Adresse verwendet wird, da der Zyklus zugewiesen ist,
ist kein Blitter-Konflikt möglich), Zyklus 4 ist der erste Teil des neuen 
MOVE-Zyklus. Die COPJMP-DMA-Anforderung, die normalerweise ein Wort von der
alten Adresse zurückgibt, erfolgt nie.


===============================================================================
weitere Themen bleiben:
- Blitter-Copper-Schleifen
- ...


ENDE ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++