Programmierrätsel #2: SIO und DLIs


Programmierrätsel #2: SIO und DLIs

von Dietrich » So 4. Jul 2010, 19:51
Hi,

zur Abwechslung mal etwas praktisches:

Ihr wollt ein Programm mit farbverändernden DLIs schreiben, das auch auf Disk zugreift. Aber leider flackert bei Verwendung der Original-SIO-Routine der Bildschirm (weil offenbar die DLIs nicht richtig ausgeführt werden).

1) Woran liegt das?

2) Wie kann man das Flackern vermeiden?

Re: Programmierrätsel #2: SIO und DLIs

von Bernd » So 4. Jul 2010, 21:14
Hallo Dietrich,
hier meine Lösung....

1)Warum dies geschieht, kann ich leider nicht sagen. Ich denke, der anstehende DLI
wird so lange ausgesetzt, bis ein 2ter ansteht und diesen dann überschreibt.

2)Beim Nachladen von der Diskette wird die Farbe im 6ten Feld konstant verändert,
gestartet wird die Farbenauswahl durch einen Wert ungleich 0 in DRUN.
Die DLI wird insgesamt 7 mal gestartet, beim letzten Durchlauf der Zähler auf Null gesetzt.
Dabei kam es sporadisch vor, dass das Farbfeld vom 6ten auf den 7ten
übersprangt. Dieser Fehler stand danach immer an, die Farbauswahl war jeweils
um ein Feld verschoben. Behoben habe ich es mit einer kleinen Vertical
Blank Interrupt Routine, die den richtigen Startpunkt wieder herstellte.
Der Fehler ist natürlich immer noch da, jedoch tritt er nur in einem einzigen
Durchlauf auf und ist für unser Auge nicht feststellbar.

Fröhliches Proggen,
Bernd

Code: Alles auswählen
Der DLI-Prgrammteil
1630 IRQ PHA
1640     TYA
1650     PHA
1660     LDY ZEILEN
1670     LDA COLOR,Y
1680     INY
1690     CPY #6
1700     BEQ ?SIGNAL
1710     CPY #7
1720     BCC ?NULL
1730     LDY #0
1740 ?NULL STY ZEILEN
1750     STA $D018
1760     STA $D40A
1770     PLA
1780     TAY
1790     PLA
1800     RTI
1810 ?SIGNAL LDY DRUN
1820     BEQ ?NAKA
1830     LDA $14
1840 ?NAKA LDY #6
1850     JMP ?NULL

Der Vertcal Blank Interrupt
1860 VBV LDA #0
1865     STA  ZEILEN
1870     JMP SYSVBV

Re: Programmierrätsel #2: SIO und DLIs

von HiassofT » Mo 5. Jul 2010, 11:38
Dietrich hat geschrieben:zur Abwechslung mal etwas praktisches:

Ihr wollt ein Programm mit farbverändernden DLIs schreiben, das auch auf Disk zugreift. Aber leider flackert bei Verwendung der Original-SIO-Routine der Bildschirm (weil offenbar die DLIs nicht richtig ausgeführt werden).

Oh, das ist mal eine einfache Frage (evtl. aber deshalb, weil ich vor kurzem darüber gelesen habe)

1) Woran liegt das?

Der Antic setzt den NMI beim 8. Zyklus einer Bildschirmzeile, wenn aber in den Zyklen 4-10 ein IRQ auftritt geht der NMI "verloren".

Siehe zB Altirra Hardware Reference Manual, am Ende von Abschnitt 4.7 (ANTIC, Display List Interrupts).

2) Wie kann man das Flackern vermeiden?

Eigene SIO Routine im Polled Mode nehmen die keine IRQs verwendet.

Aber eigentlich sind DLIs während SIO sowieso pfuibäh :-)

so long,

Hias

Re: Programmierrätsel #2: SIO und DLIs

von pps » Di 6. Jul 2010, 09:43
HiassofT hat geschrieben:Aber eigentlich sind DLIs während SIO sowieso pfuibäh :-)Hias

So pfuibäh finde ich das nicht. Wenn man mal andere Systeme betrachtet: dort wird regelmäßig während des Nachladens von Diskette das Programm nicht angehalten, wie eigentlich in fast allen Programmen auf dem XL/XE. Man kann während eines Spieles - ohne, daß der Spieler es merkt - weitere Daten nachladen und benötigt so auch keine Speichererweiterungen für aufwendige Spiele. Auch in Demos wird auf anderen Systemen schon während man etwas sieht (und auch hört) nachgeladen.

Re: Programmierrätsel #2: SIO und DLIs

von HiassofT » Di 6. Jul 2010, 14:18
Hi!

pps hat geschrieben:So pfuibäh finde ich das nicht. Wenn man mal andere Systeme betrachtet: dort wird regelmäßig während des Nachladens von Diskette das Programm nicht angehalten, wie eigentlich in fast allen Programmen auf dem XL/XE. Man kann während eines Spieles - ohne, daß der Spieler es merkt - weitere Daten nachladen und benötigt so auch keine Speichererweiterungen für aufwendige Spiele. Auch in Demos wird auf anderen Systemen schon während man etwas sieht (und auch hört) nachgeladen.

So allgemein habe ich das auch nicht gemeint, deshalb auch der Smiley.

zB damals Seven Cities of Gold habe ich es echt nett gefunden, daß es im Hintergrund nachgeladen hat ohne das Spiel zu unterbrechen. Oder der Vorspann mit Musik zB bei BallBlazer war auch schön.

Was mich aber eher stört sind DLIs in Anwendungs-Programmen und Loadern (zB GameDos) die dann zu Fehlern bei Übertragungsraten grösser 50-60kBit/sec führen. Wenn eine Demo (wie Numen) mal eben 200k in die Ramdisk lädt oder wenn ich ein 512k Flash am Atari programmieren will möchte ich, daß die Übertragung so schnell wie möglich geht. Da fahre ich dann mit 110 oder 125kBit/sec. Bei grossen Datenmengen macht das schon einen spürbaren Unterschied zu 50-60kBit/sec - auch wenn es natürlich nicht ganz doppelt so schnell ist.

so long,

Hias

Re: Programmierrätsel #2: SIO und DLIs

von Dietrich » Di 6. Jul 2010, 22:22
@Hias:

zu 1) richtig. NMIs können durch IRQs verloren gehen

zu 2) OK, eine eigene Highspeed-Routine ohne IRQs ist eine Möglichkeit. Aber es gibt auch Möglichkeiten, das Normal-SIO mit DLIs ohne Flackern zu betreiben. Wie?

@Bernd: Man kann das Flackern auch bei Deiner Routine noch sehen, 1/50 Sekunde reicht fürs Auge. Deutlich sichtbar wird es, wenn die Farbveränderung auch die Helligkeit (stark) ändert.

Man kann durchaus DLIs beim Laden auch in Highspeed verwenden. Allerdings nur mit Highspeed-Routinen, die nicht $e45c (setvbv) aufrufen, weil dort in wsync geschrieben wird, was die DLIs verzögern kann und damit die Highspeed-Routine evtl. ins Stottern kommt.

Gruß Dietrich

Re: Programmierrätsel #2: SIO und DLIs

von HiassofT » Di 6. Jul 2010, 23:48
Dietrich hat geschrieben:zu 2) OK, eine eigene Highspeed-Routine ohne IRQs ist eine Möglichkeit. Aber es gibt auch Möglichkeiten, das Normal-SIO mit DLIs ohne Flackern zu betreiben. Wie?

Das würde mich nun auch interessieren, ich weiss dazu keine Lösung.

Vor einiger Zeit hatte ich diverse Artikel über den Pokey gelesen, kann mich aber nicht erinnern ob man das IRQ Timing irgendwie so beeinflussen kann, daß der Pokey nie in der kritischen Zeit auslöst. Bei den Pokey Timern geht's noch recht einfach, die werden ja regelmässig gestartet und man kann den Pokey (zB per Reset) manuell so synchronisieren, daß der erste Timer bei einem gewissen Zyklus losstartet.

Aber bei den anderen IRQs (seriell, keyboard, break) bin ich da im Moment echt überfragt.

Man kann durchaus DLIs beim Laden auch in Highspeed verwenden.

Nicht bei 100kBit und mehr (oder über ca 50-60kbit wenn ein "STA WSYNC" im DLI ist), dann bleibt der SIO Routine zu wenig CPU Zeit und es gibt einen Overrun Error.

so long,

Hias

Re: Programmierrätsel #2: SIO und DLIs

von Bernd » Mi 7. Jul 2010, 22:40
[quote="Dietrich"@Bernd: Man kann das Flackern auch bei Deiner Routine noch sehen, 1/50 Sekunde reicht fürs Auge. Deutlich sichtbar wird es, wenn die Farbveränderung auch die Helligkeit (stark) ändert. Gruß Dietrich[/quote]

Macht nichts. Lieber etwas fürs Auge mit einen (kleinen) Fehler als nur Piep Piep über den Lautsprecher
und der Hinweis ..... Bitte warten... Bitte warten....

Bye,bye,
Bernd

Re: Programmierrätsel #2: SIO und DLIs

von Dietrich » Mi 7. Jul 2010, 23:00
Das würde mich nun auch interessieren, ich weiss dazu keine Lösung.


Denkt noch mal nach, eigentlich ist die Lösung ganz banal.
Tipp 1: Ich habe nur nach der Original-SIO-Routine gefragt, nicht nach Pokey-IRQs und anderen IRQ-Auslösern. Es geht auch nicht darum, die IRQs zu verhindern, sondern das Flackern zu verhindern.
Tipp 2: Man muss in der Display-List Rücksicht darauf nehmen und diese entsprechend anpassen.

hias hat geschrieben:Nicht bei 100kBit und mehr (oder über ca 50-60kbit wenn ein "STA WSYNC" im DLI ist), dann bleibt der SIO Routine zu wenig CPU Zeit und es gibt einen Overrun Error.

Hmm, rechnerisch müsste mein Beispiel aber klappen, vorausgesetzt die Highspeed-Routine kommt mit Gr.0 zurecht. Kann es leider nur bis 89000 bps ausprobieren, mehr schafft mein SIO2SD nicht (nach der Anzeige zu urteilen, arbeitet das SIO2SD wohl leider mit den NTSC-Werten). Wenn das Rätsel gelöst ist, schreibe ich mal meinen Beispiel-DLI hier rein :-)

Macht nichts. Lieber etwas fürs Auge mit einen (kleinen) Fehler als nur Piep Piep über den Lautsprecher
und der Hinweis ..... Bitte warten... Bitte warten....

Dann aktiviere doch den Super-Flackereffekt wieder (ohne Rücksetzen des Zählers im VBI). DAS ist dann wirklich was fürs Auge ;-)

Gruß Dietrich

Re: Programmierrätsel #2: SIO und DLIs

von HiassofT » Do 8. Jul 2010, 01:21
Hallo Dietrich!

Dietrich hat geschrieben:Denkt noch mal nach, eigentlich ist die Lösung ganz banal.
Tipp 1: Ich habe nur nach der Original-SIO-Routine gefragt, nicht nach Pokey-IRQs und anderen IRQ-Auslösern. Es geht auch nicht darum, die IRQs zu verhindern, sondern das Flackern zu verhindern.
Tipp 2: Man muss in der Display-List Rücksicht darauf nehmen und diese entsprechend anpassen.

Ich steh im Moment komplett auf der Leitung. Werd' mal eine Nacht drüber schlafen, vielleicht fällt mir dann was ein :-)

hias hat geschrieben:Nicht bei 100kBit und mehr (oder über ca 50-60kbit wenn ein "STA WSYNC" im DLI ist), dann bleibt der SIO Routine zu wenig CPU Zeit und es gibt einen Overrun Error.

Hmm, rechnerisch müsste mein Beispiel aber klappen, vorausgesetzt die Highspeed-Routine kommt mit Gr.0 zurecht.

Bei 125kBit genügt es Player/Missile DMA in GR.0 einzuschalten um Fehler zu bekommen, das Timing ist also wirklich knapp :-)

Das mit dem (von mir gekürzten) VBI klappt wohl auch nur deshalb, weil zu der Zeit kein Screen DMA stattfindet. Gr.0 ist aber wirklich übel, da bleibt fast keine Zeit mehr für die CPU übrig.

Genauer hab' ich aber nur die Geschwindigkeiten 110 und 125 kBit analysiert, wie's darunter aussieht kann ich nicht 100% sagen. Jedenfalls ist ein DLI mit STA WSYNC Gift ab ca. 70kBit.

so long,

Hias

Re: Programmierrätsel #2: SIO und DLIs

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)