Color-Cycling

Für diesen Beitrag wurde das CBM prg Studio verwendet.
weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

CBM prg Studio…und warum diese Bezeichnung beim C64 eigentlich falsch ist.

Color-Cycling wurde in der ‚guten alten Zeit‚ verwendet, um durch einfaches Kopieren von Farbwerten den Eindruck von Bewegung zu erzeugen. Rechenzeit war knapp und die Grafikkarten weit weg von ihrer heutigen Leistung. Wen der ‚geschichtliche‚ Hintergrund nicht interressiert, der kann den gräulichen Text überspringen.

Wie funktioniert das ‚klassische‚ Color-Cycling?
Schauen wir dazu mal auf den VGA-Modus, wie er vor über 20 Jahren am PC zum Standard für Spiele wurde. Die standard VGA-Auflösung betrug, wie beim C64, 320*200 Bildschirmpunkte. Der PC kann aber 256 Farben gleichzeitig, aus einer gesamt Palette von 262144 Farben, darstellen. Dabei wurde für jeden Bildpunkt ein BYTE verwendet. Dieses BYTE zeigte dann wiederum auf eine Liste, in der für jeden BYTE-Wert eine Farbe hinterlegt wurde.

Bildpunkt zeigt auf Palette, diese enthält max. 256 Farben aus 262144 möglichen. (VGA)
Bildpunkt zeigt auf Palette, diese enthält max. 256 Farben aus 262144 möglichen. (VGA)

Um nun den Eindruck einer Bewegung, z. B. fließendes Wasser, zu erzeugen, brauchte man nicht alle Bildpunkte zu ändern, was sehr viel Rechenzeit benötigt hätte. Wenn man die Liste mit den 256-Farben geschickt aufgebaut hat und die Grafik entsprechend entworfen wurde, dann konnte man die Bewegung durch einfaches Umkopieren der Farben in der Liste erreichen. Dabei brauchte man meistens nur wenige Kopiervorgänge.

Wenn ihr auf das folgende Bild klickt, könnt ihr euch dies einmal genauer anschauen. Ihr findet dort verschiedene Color-Cycling-Bilder unter HTML 5. Wenn ihr dann noch auf den Button ‚Show Options‚ rechts oben klickt, wird euch die Liste der Farben angezeigt und ihr könnt nachverfolgen, was kopiert wird.

ColorCycling_001
Color-Cycling unter HTML 5
(Art by Mark Ferrari)

 

Wer sich schon etwas mit der Grafikprogrammierung auf dem C64 beschäftigt hat, dem wird nun auffallen, dass es dort kaum solche Farblisten gibt, die umkopiert werden können. Mit viel gutem Willen, kann man die MultiColor-Werte (z. B. vom Sprite) als micro Farbpalette ansehen, aber das sind ja auch nur zwei Farben. Wir verwenden das Color-Cycling gleich im Textmodus. Da werden wir aber die Farben im Farb-RAM ändern müssen, um einen solchen Effekt zu erzielen und somit (nach meinem Verständnis) kein ‚klassisches‚ Color-Cycling verwenden. Dies ist der Grund, weshalb ich zu Beginn behauptet habe, dass die Bezeichnung eigentlich falsch ist.

 

Wie soll der Effekt auf dem C64 funktionieren?
Um im Textmodus des C64 einen solchen Effekt zu erzielen, gehen wir nun zweistufig vor. Im Speicher legen wir eine Tabelle mit 40 BYTEs an. Dort stehen die, von uns sorgsam ausgewählten, Farbwerte drin. Diese Tabelle wird zyklisch umkopiert und dann muss noch die Farbe im Farb-RAM aktualisiert werden.

Als erstes wird nur dafür gesorgt, dass die Rahmen- und Hintergrundfarbe schwarz ist und der Text auf dem Bildschirm erscheint.

 

Einfache Textausgabe
Einfache Textausgabe

Na, dass ist doch mal unspektakulär, oder? Lasst uns diesen Text jetzt einfärben, aber nicht einfach in einer Farbe, sondern laut einer Tabelle in der für jedes Zeichen der Zeile eine Farbe steht.

Dazu fügen wir zunächst den Aufruf der neuen Funktion  jsr setColor:  hinter die Textausgabe jsr showText: ein.

Dann wird natürlich die Funktion setColor: benötigt, also diese am Besten hinter die vorhandenen Funktion showText: einfügen.

Die Funktion macht nichts Anderes, als einfach die Farbwerte aus der Tabelle colors: ins Farb-RAM für die erste Bildschirmzeile zu kopieren.

Ganz ans Ende des Programms legen wir jetzt noch unsere Farbtabelle:

Hier können nun die gewünschten Farben abgelegt werden. Man sollte darauf achten, dass diese gut harmonieren, sonst wirkt der Effekt nachher zu fahrig. Ich habe mich hier für blau Töne und weiß entschieden.

Ein neuer Start sieht zwar schon bunter, aber immer noch uninteressant aus.

Die Farben wurden laut Tabelle gesetzt.
Die Farben wurden laut Tabelle gesetzt.

Hier kann man jetzt schön sehen, dass ich die Farben so gewählt habe, dass diese erst von hell (weiß) immer dunkler werden und dann wieder aufsteigend heller. Das sorgt gleich für einen relativ ansehnlichen Effekt.

Jetzt wird etwas benötigt, um den Effekt zu ‚timen‚. Ich begnüge mich hier mit dem bekannten Interrupt der bei $EA31 verarbeitet wird. Also direkt vor dem jmp * den Interrupt umbiegen.

Dabei auch gleich wieder die Zeile jsr setColor: löschen, die Funktion wird nun im Interrupt aufgerufen.

Fügt nun die Interrupt-Routine (wie wäre es direkt hinter dem  jmp *?) ein:

Da 60 Veränderungen pro Sekunde evtl. etwas viel sind, benutzen wir einen kleinen Zähler  cycleCnt:. Bei jedem Interrupt wird der um eins verringert und wenn er negativ wird setzen wir ihn auf den Startwert zurück, kopieren die Farben in doColorCycle:, setzen dann wieder die Farben im Farb-RAM (hier ist nun das jsr setColor: von eben gelandet) und springen dann (wie beim positiven Zähler) zur System-Routine nach $EA31.

Die Variable cycleCnt: kann einfach am Programmende eingefügt werden.

Kommen wir zur ‚Kernfunktion‚, dem Umkopieren der Farben.

Die Funktion ist auch ganz simpel. Es werden die Farben von links nach rechts kopiert. Das X-Register zeigt dabei auf das aktuelle Zielfeld, hier hin wird also die links stehende Farbe kopiert. Da wir die Farben wieder rückwärts abarbeiten, retten wir die ‚letzte‚ Farbe erstmal im Y-Register. Dann wird der Schleifenzähler (X-Reg.) wieder mit #$27 (dez. 39) initialisiert. Die Schleife holt sich erstmal die Farbe ‚links‚ vom X-Register in den Akku und kopiert diese an die Position, auf die X zeigt. Dann wird X verringert und das ganze wiederholt sich, solange X größer 0 ist. Somit wurden alle Farben kopiert, nur die Farbe für die erste Stelle fehlt noch. Der benötigte Wert wurde sich zum Glück ganz zu Anfang im Y-Reg. gemerkt und kann nun direkt an die erste Position der Farbtabelle geschrieben werden. Schon sind wir fertig und können zurück zum Aufrufer.

 

Das Programm ist nun fertig und bereit von euch assembliert und gestartet zu werden.

 


Wie ihr seht, könnt ihr auch ganz ohne Rastertricks und VIC-Manipulationen schon einen netten kleinen Effekt erzielen. OK, einen Preis wird man damit nicht gewinnen, aber ein Anfang ist gemacht.

Nun ist es an euch, weiter zu experimentieren.
Sollen sich die Farben z. B. in die andere Richtung ‚bewegen‚, dann müsst ihr diese nur von rechts nach links kopieren. Testet auch mal andere Farben in der Farbtabelle, gebt mehrere Texte aus, bei denen die Farben in unterschiedliche Richtungen laufen oder ändert CycleCnt:.
Auch sind natürlich noch Optimierungen möglich, warum das Umkopieren und Setzen des Farb-RAMs trennen? Dies könnte in einem Rutsch geschehen bzw. warum nicht gleich nur das Farb-RAM umkopieren?

Man kann den Effekt zum Beispiel noch verstärken, wenn man mehrere Zeilen direkt untereinander ausgibt und die Farben in jeder Zeile um eine Position verschiebt. Ihr könnt das Color-Cycling auch mit einem Textscroller verbinden.

Auch wenn es dort etwas ruckelt, startet doch einfach mal die Demonstration im Java-Emulator, da wird bereits gescrollt (es ist dann auch ein Rasterzeileninterrupt im Spiel).
Unter WinVice oder CCS64 läuft es flüssiger. Wer das Programm offline testen möchte, findet hier noch ein D64-Image zum Download.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (8 Bewertungen | Ø 5,00 von 5 | 100,00%)

Loading...


 

<<< zurück |

 

weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

3 Gedanken zu „Color-Cycling“

  1. Hi Jörn,

    auch dieses Tutorial konnte ich wunderbar nachvollziehen, habe es auch geschafft mehrere Textzeilen ’sinnvoll‘ einzufärben 🙂

    Bei weiterer Recherche im Web habe ich gesehen, dass man auch auf die Clear Screen Routine Kernel Routine bei $E544 zugreifen kann um den Bildschirm zu löschen. Also einfach -> JSR $E544

    Das macht den Code dann nochmal schlanker 🙂

    1. Ja, es gibt durchaus mehrere Möglichkeiten, den Bildschirm zu löschen.

      Du kannst z. B. auch das bereits an anderer Stelle erwähnte:
      lda #147
      jsr $FFD2

      verwenden.

      Denk aber immer daran, dass die Kernalfunktionen nicht sonderlich schnell sind! Hier spielt es zwar keine Rolle, aber bei anderen Projekten, kann es notwendig sein, den BS schnell zu löschen. Außerdem muss hier nur auf den Sprung nach $EA31 verzichtet werden, dann kann der Code auch ohne Kernal zum Laufen gebracht werden. (Achtung: Dabei an die IRQ-Vektoren denken.)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Protected by WP Anti Spam