Hallo Besucher, der Thread wurde 9,6k mal aufgerufen und enthält 61 Antworten

letzter Beitrag von Vernunftmensch am

Stabiler Raster - ein paar generelle Fragen...

  • Hallo zusammen,


    nachdem ich mir hier im Forum und durch reichliches Probrieren mal ein bisschen Assembler angeeignet habe, hab' ich's sogar schon geschafft, ein kleines Intro mit Scroller, eigenem Charset und ein paar Sprites mit Farbwechseln und Animation hinzubasteln... Music nicht zu vergessen. :freude


    So weit, so gut, nur halt alles ohne stabiles Timing, also einfache multiple IRQs, die dann die Animation machen, den Scroller, die Music, etc...


    Hab' mir das jetzt mal versucht draufzuschaffen mit dem stabilen Raster-IRQ... aber irgendwie raff ich's wohl net :wand , daher mal paar Fragen.


    - hab' ich das richtig verstanden, dass ich in einem ersten Raster-IRQ einen weiteren erzeugen kann, der dann nur noch um einen Cycle ungenau ist, wenn der erste Raster-IRQ beim Erreichen des zweiten Raster-IRQ ein nop ausführt?


    - sind dann eigentlich Raster-IRQs, die ich aus dem zweiten heraus aufbaue, auch noch stabil, oder muss ich dass für jeden einzelnen Raster-IRQ wiederholen (z.B. bei mehreren Raster-Splits im Screen)?


    - wie genau baut Ihr sowas auf, mag mir mal jemand ein paar Beispiele zeigen?


    - gibt's außer den ganzen englisch kommentierten Beispielen auch paar in deutsch? Mein Englisch ist zwar echt nicht schlecht, aber da hört's dann manchmal doch auf, weil die teilweise nur recht knapp beschrieben sind...


    Gruß und Danke für Eure Mühe,
    Mnemonic

  • Ich weiss nicht genau, was du meinst mit einem IRQ aus einem IRQ Aufrufen, meiner Meinung nach recht sinnlos. Denn es führt unweigerlich zu einem Stackdesaster.


    Es läuft so bei einem Interrupt:


    Irgendwo läuft das normale Programm. Mit Befehlen, die zwischen 2 und 6 (8?) Zyklen verbrauchen. Und zusätzlich gibt es noch den VIC/Refreshzyklus und den VIC/Grafikdatenbuszugriff-Zyklus.


    Wenn der Interrupt kommt, wartet er bis das gerade laufende Programm durch ist. Und wenn außerdem der Bus frei ist, wird dann das Interrupt-Programm ausgeführt.


    Das Programm selbst läuft jetzt stabil, es sei denn es wird vom Störfaktor VIC an Buszugriffen gehindert und verlangsamt. Solange man allerdings mit dem VIC synchronisiert ist, sollte das kein Problem sein, da der VIC dir ja nur Zyklen in den Austasts und dem Zeilenrücklauftasts klaut. Dazwischen hat der Prozessor keine Aussetzer.


    Was auch immer du in der Interruptroutine jetzt laufen hast, läuft stabil. Also du kannst das sehr genau bestimmen mit NOPs, Schleifen und dergleichen. Nur darf natürlich nichts dazwischen kommen, siehe VIC oder gar andere IRQs.


    Das Hauptprogramm steht die ganze Zeit. Du könntest natürlich jetzt das Hauptprogramm mit dem IRQ synchronisieren lassen. Auch eine Möglichkeit. Das heißt das Hauptprogramm bleibt in einer 30 x NOP Schleife (beispielsweise) und einem BEQ loop und der Interrupt setzt die Rücksprungadresse so wie du es brauchst. Dann würde dein Hauptprogramm synchron zum IRQ weiterlaufen, muss aber immer am Ende des Bildaufbaus wieder in der NOP-Schleife landen.


    Die NOP-Schleife sorgt nur dafür, dass der Prozessor keine langwierigen Befehle ausführt, wenn der IRQ kommt. Statt NOPs könntest du natürlich alle Registerbefehle benutzen, die auch nur 2 Zyklen verbrauchen wie der NOP. Man könnte also sogar etwas "tun" in der Zeit des Wartens.


    Ich persönlich halte das jedoch für schwierig, vielleicht zu kompliziert.


    Was du wahrscheinlich meinst ist, dass du in der IRQ-Routine dann nochmal einen IRQ für die nächst Zeile setzt und dann innerhalb des IRQs die oben genannte NOP-Schleife laufen läßt. Wäre eine Lösung. Nicht vergessen, dass du zweimal RTI machen musst, um da rauszukommen und den CLI auch nicht vergessen, damit der nächste Interrupt durchkommt.


    Warum holst du nicht die Spaltenposition vom Raster und gleichst das mit einer NOP-Kette aus, die du entsprechnd anspringst, wenn du Zyklengenau synchronisieren willst? Also Beispiel:


    Nimm Rasterspalte
    Je höher Spalte desto später spring in die folgende Nop-Kette (selbstmodifizierter Branch?)
    folgende NOP-Kette für Syncronisation.
    Programmm


    Das Programm wäre dann immer 100% synchron. Ohne Gewese mit 1000 zyklenfressenden Doppelinterrupts und den "es könnte dennoch danebengehens". Und du bist mit einem relativ einfachen, linearen Code auf 2 Zyklen genau justiert mit einer maximalen Abweichung von einem Zyklus meine ich. Wenn ich es richtig sehe, ist ein Bildschirmpixel rund 4-5 Zylen, oder? Oder genau 4? Macht mich mal schlau.


    Fragen wir mal so: wozu der Aufwand genau?

  • Hi Hanno,


    erstmal Danke für Deine Antwort!


    Hab's wahrscheinlich ungeschickt formuliert, ich meinte wohl das mit dem Doppelinterrupt.


    Also, ich bin darüber gestolpert, als ich so als Übung ein paar statische Rasterbars auf den Bildschirm packen wollte. Hab' dafür also brav den laufende Interrupts mit SEI gestoppt, meinen eigenen Interrupt in den IRQ-Vector gesetzt, Interrupt mit CLI wieder freigeben, und dann brav auf meine Rasterzeile mit meinem eigenen Interrupt gewartet.


    Jetzt ist es halt so, dass der zwar auf der richtigen Zeile auslöst, aber der Anfang springt im sichtbaren Bereich halt übelst hin und her, so dass ich das auch mit NOPs oder Schleifen net wirklich sauber hinbekommen habe.


    Mir geht's jetzt auch weniger darum, da die Rasterbars zu malen, sondern das Prinzip zu verstehen, wie ich einen Interrupt so stabil bekomme, dass er wirklich immer im exakt gleichen Cycle der Rasterzeile ausgelöst wird.


    Gruß,
    Mnemonic

  • Also, für Hanno Behrens: 1 Taktzyklus = 1 Char = 8 Pixel.


    Die Doppel-IRQ Methode ist eine gute Lösung für den Anfang (gibt auch etwas kompliziertere mit dem CIA).


    Also, z.b. den ersten IRQ auf Zeile 40 setzen.
    Dann in dieser IRQ Routine die Vectoren für den 2. IRQ setzen (am besten nur über das Low-Byte) und den Start auf die nächste Zeile (41). Dann noch ein INC $D019 und CLI um den nächsten IRQ auch zuzulassen. der Rest des IRQs besteht aus NOPs (so 10 Stück sollten es schon sein), damit die Abweichung nur noch max. 1 Zyklus ist.
    Am Ende der NOPs kann man 2 verschiedenen Dinge mache.
    Entweder einfach ein JMP$EA81 oder aber ein JMP zu dem Beginn der NOPs.
    Je nachdem was man wählt, muss man im 2. IRQ weitermachen.


    Zunächst muss man aber im 2. IRQ noch die Abweichung von 1 Zyklus korrigieren.
    Dazu muss man noch nach entsprechender Anzahl von Zyklen $D012 auslesen (weiss im moment nicht genau wieviel das waren... so um 21) und überprüfen ob man schon in der "nächsten" Rasterzeile ist. Wenn nicht, muss man noch genau EINEN Zyklus hinzufügen.
    Also etwas so:


    lda $d012
    cmp #$29
    beq (nächste Zeile)


    Der BEQ "springt" in die nächste Zeile wenn man noch in der "alten" Rasternzeile ist, und braucht somit 3 Zyklen, oder wenn man schon in der "neuen" Rasterzeile ist wird der BEQ übergangen (2 Zyklen).


    So, nicht vergessen wieder die Vektoren und Startzeile für den 1. IRQ zu setzen.
    Hatte man den 1. IRQ mit einem JMP zu den NOPs beendet, sollte man den Stackpointer um 6 erhöhen, um das "verlorene" IRQ-Ende auszugleichen
    z.b. so:


    tsx
    txa
    clc
    adc#06
    tax
    txs


    oder wenn man den 1. IRQ mit JMP $ea81 beendet hatte muss man nichts weiter beachten (klar, den 2. IRQ auch ganz normal "beenden"...)

  • Hier nochmal ein kleine Stück Beispielcode....


  • Hallo Roland,


    danke Dir! :freude


    Da hab' ich was zum frickeln am Wochenende!


    Sorry nochmal für die vielleicht etwas umständliche Fragestellung, aber ich beschäftige mich erst knapp drei Monaten mit Assembler für den Cevi...!


    Gruß und allen ein schönes Wochenende,
    Mnemonic

  • Zitat

    Originally posted by Hanno Behrens
    Nicht vergessen, dass du zweimal RTI machen musst, um da rauszukommen


    Oder im 2. IRQ einfach drei mal PLA.


    Zitat


    Warum holst du nicht die Spaltenposition vom Raster und gleichst das mit einer NOP-Kette aus, die du entsprechnd anspringst, wenn du Zyklengenau synchronisieren willst? Also Beispiel:


    Die X-Position aus dem Lightpen-Register zu bekommen ist schon ein enormer Aufwand und zudem darf dann niemand Space oder Feuer in Port 1 drücken.


    Zitat


    Ohne Gewese mit 1000 zyklenfressenden Doppelinterrupts und den "es könnte dennoch danebengehens".


    Also der Lightpen-Kram ist definitiv nicht weniger Zyklenfressend. Da müssen haufenweise Register beschrieben werden, im Endeffekt kommt man da auch auf seine 2 Rasterzeilen. Mal abgesehen davon, dass DoppelIRQs keineswegs danebengehen können.

  • Lach. Mit PLA / PLA hab' ich bei einigen Progs den JSR vom Stack gelöscht.
    Tssss....wemma sich im zuviel im Code verheddert hat.... :)


    @ Mnemonic :


    Double-IRQ ist 'ne geile Sache und klappt immer, braucht aber 2 Rasterlines.


    Kannst auch den VIC zwingen, mitten im Textbereich 'ne neue Zeichenzeile einzulesen, was dann einer Badline entspricht.
    Badline daher, weil der VIC unserer CPU zum lesen der Textbytes dann beide Taktphasen klaut.
    (Wenn Du schnell genug bist, könntest Du den Prozessor während dieser Zeit aus der Fassung nehmen, denn
    seine Ausgangsleitungen sind so hochohmig, dass er quasi gar nicht vorhanden ist.... :hammer:)


    Da der VIC intern am gleichen Punkt aussteigt als wäre es tatsächlich eine "reguläre" Badline,
    bist Du an diesem Punkt mit Deinem Code stabil.



    Soweit ich noch weiss, hat der VIC aber dann einen Lesefehler mit dem Zeichen $FF im aktuellen Charset.
    Das taktet der VIC dann Bitweise auf den Screen, was in der Regel störend ist, es sei denn, du lässt das
    Zeichensatzmuster auf $00...dann taktet er Nullbits...
    Wenn ich mich recht entsinne, (...ich hock' in letzter Zeit einfach zuviel am PähCäh...), ist die Badlinebedingung
    genau dann erfüllt, wenn die unteren 3 Bits von $d011 und $d012 gleich sind.


    Zu der Frage, ob der Raster über den ganzen Frame weg stabil bleibt mit mehr als einem IRQ pro Bild kann ich
    soweit nur sagen, es kommt auf die Routine an, die zwischen den beiden oder mehr Rasterbereichen liegt.
    Wenn das stabile Timing des Double-IRQs in der nächsten Routine durch unterschiedliche Laufzeiten pro
    Durchlauf der Routine wieder zerhackt wird, wirst Du wohl nicht umhinkommen, für den 2. oder 3. Rastereffekt
    oder gar AGSP erneut einen Doubleinterrupt zu starten. (grübel...:gruebel...oder ???)



    Oder halt 'ne Badline...zur Abwechsung...nur nicht grad im unteren Border machen.
    (Obwohl...existiert da schon ein neuer Trick?...Grafik im Rahmen ausser aufm C128 mit der CPU / VIC-Priorität oder Ghostbyte oder Sprites oder $d016 Gezerre...?...wär ja geil.....ECHTE Badlines im Border...) :bgdev


    Wenn Du z.B. am stabilen Punkt mit JSR einen Musikplayer anspringst, der je nach Player eine Varianz von
    bis zu 3 oder 4 Charzeilen, also im Mittel etwa 1700 (!) Zyklen hat, dürfte nach dem Rücksprung von dieser Dein Raster
    sehr unruhig sein...



    Happy Coding, :dance


    Greetz, Caddy



    Ps.


    Wer hat sich eigentlich diese herrlichen Namen immer ausgedacht...?
    ...Badlines....Ghostbytes...FLI...FLD....AGSP...Mein Liebling war immer "DYSP"...


    Sobald die in der 64er standen, waren sie Norm.



    Greetz

  • Floffy ?


    Da kenn' ich auf'm PC nur den FLV-Player Fluffy. :nixwiss:
    DLCP gabs auch mal...


    Ich glaub' manchmal, die von der 64er-Redaktion haben sich tatsächlich abends nach Feierabend beim Bier inner Kneipe getroffen und beim singen der alten Kalauer Preise für den besten Namen verteilt...
    Oder sie haben sich selbst mit 'nem Diktiergerät aufgenommen und die Favoriten aus den Satzfragmeneten zusammengesetzt...



    Was machen die eigentlich?.....Peter Klein...Jörn Burckert und so ?
    (Standart Satz von Jörn : "...Da wird der Spieler schnell zum Discjockey"...) :roll2:



    Aprospos VIC:


    Gibt es im Netz denn irgendwo mal grosse Bilder von der VIC- Oberfläche ? ?(
    Ich meine jetzt nicht diese abgeknipsten "und dies hier ist ein Chip von oben"- Bilder, sondern detaillierte Fotos, auf denen man die einzelnen Baugruppen des VIC sieht und auch nachverfolgen kann.
    Bei der (im Vergleich mit heutigen Wavern) doch noch "geringen" Anzahl von Transistoren (ca. 5000 Stück), müsste man doch mit'n "paar" Blättern den VIC zusammensetzen können...


    Und wenn schon ein Bild von oben, dann aber bis in den letzen Transistor zoombar.....




    Greetz

  • Nochmal zum Thema "x-position des rasters auslesen"...
    Ausser mit dem Lightpen geht das auch mit dem CIA.
    Man macht einmal einen stabilen IRQ, und lädt den Timer dann mit 63 (Anzahl Taktzyklen pro Zeile) und continous-Mode (also wenn er auf 0 gezählt hat, wird er wieder automatisch mit 63 geladen).


    Ist besonders sinnvoll bei mehreren stabilen irqs pro bildschirm.




    PS: Der peinlichtse Slang is "wanking" für VSP (verschieben des screens mit DMA-Tricksereien)


    Edit: Um die x-position (in char-resolution) dann auszulesen, liest man einfach den Timer des CIA.