von Dietrich » So 11. Jul 2010, 18:41
OK, hier kommt die Lösung - tadaaa:
Doppel-DLIs (tm)Statt eines einzelnen DLIs verwenden wir einfach zwei kurz hintereinander, die dasselbe tun. Sollte ein DLI wegen eines seriellen IRQs ausfallen, wird der andere garantiert ausgeführt, da beim Normal-SIO die IRQs nur im Abstand von 940 Takten (das sind 8-9 Bildschirmzeilen) auftreten.
Einfach, aber wirkungsvoll. Man muss natürlich Leerzeilen benutzen. Am besten 3, damit auch extreme Highspeed-Routinen noch funktionieren. Nebenbei hat das auch den Vorteil, dass wir auf das zeitfressende sta wsync verzichten können (wenn nicht gerade die Bildschirm-Hintergrundfarbe geändert werden soll).
Beispiel: Wir wollen 4 verschiedene Texthintergrundfarben in Gr.0 haben. Ein Doppel-DLI in der Display-List sieht so aus: ...,2,2,2,$80,$80,0,2,2,2,...
Ein optimaler DLI für 4 Hintergrundfarben wert1 bis wert4 sieht so aus:
- Code: Alles auswählen
pha
lda vcount
cmp #diff23
bcs ?2
cmp #diff12
bcs ?1
lda #wert1
bne ?4
?1 lda #wert2
bne ?4
?2 cmp #diff34
bcs ?3
lda #wert3
bne ?4
?3 lda #wert4
?4 sta $d018
pla
rti
Das sind max. 35 Takte. (+1 Takt, wenn ein Branch eine Seitengrenze überschreitet. Andererseits -1 Takt, wenn wir pha, pla durch lda, sta ersetzen). Die Displaylist samt Doppel-DLIs benötigt nicht mehr Takte als das normale Gr.0:
1) Unsere 3 Leerzeilen verbraten je 10 Takte DMA+Refresh. Dazu kommen noch die DLIs: 35 Takte + 20 Takte Overhead durch CPU und OS. Macht zusammen 3*10 + 2*(35+20) = 140 Takte, die in unseren 3 Leerzeilen nicht zur Verfügung stehen. Im Vergleich verbrät eine normale Gr.0-Scanline 49 Takte DMA+Refresh, 3 Gr.0-Scanlines also 3*49=147 Takte. Das sind 7 Takte mehr als bei unseren 3 Leerzeilen.
2) In der Spitzenbelastung kommen in unseren Leerzeilen 2 Leerzeilen mit DLIs vor, die zusammen 130 Takte klauen (jede Zeile 10 DMA+Refresh + 55 DLI). Im Gr.0-Bildschirm haben wir als 2-Zeilen-Spitze eine Anfangs-Gr.0-Scanline, die fette 82 Takte DMA+Refresh klaut, sowie eine normale Gr.0-Scanline mit 49 Takten DMA+Refresh. Macht zusammen 131 Takte, einer mehr als bei uns.
Klappt also vom Timing. Jede Highspeed-Routine, die mit Gr.0 zurechtkommt (und nicht in wsync schreibt), muss auch mit unseren Doppel-DLIs zurechtkommen.
Wenn wir uns sicher sein können, dass das normale SIO nicht benutzt wird, können wir die Doppel-DLIs durch Einfach-DLIs ersetzen, was 1 Leerzeile spart. Und wenn wir keine extremen Highspeed-Raten befürchten müssen, können wir die Leerzeile ohne DLI weglassen.
Gruß Dietrich (der gerade mit Doppel-DLIs programmiert)