Der MOS 6567/6569 Videocontroller (VIC-II) und seine Anwendung im Commodore 64
Inhalt 3. Funktionsweise des VIC 3.8. Sprites
3.8.1. Speicherzugriff und Darstellung |
Die zur Darstellung von 24×21 Pixeln notwendigen 63 Bytes an Spritedaten sind linear im Speicher abgelegt: Jeweil 3 aufeinanderfolgende Bytes bilden eine Zeile des Sprites. Diese 63 Bytes lassen sich in 64-Byte-Schritten innerhalb des 16KB-Adreßraumes des VIC verschieben. Dazu liest der VIC in jeder Rasterzeile für jedes Sprite aus den letzten 8 Bytes der Videomatrix einen Spritedatenzeiger (p-Zugriff), der bei den Spritedatenzugriffen (s-Zugriffe) die oberen 8 Bits der Adresse bildet. Die unteren 6 Bits stammen aus einem Spritedatenzähler (MC0-MC7, für jedes Sprite einen), der für die Sprites eine ähnliche Aufgabe übernimmt wie der VC für die Videomatrix. Da die p-Zugriffe in jeder Rasterzeile stattfinden und nicht nur dann, wenn das jeweilige Sprite gerade dargestellt wird, kann man durch ändern des Spritedatenzeigers das Aussehen eines Sprites mitten innerhalb der Darstellung ändern. Wenn für ein Sprite s-Zugriffe notwendig sind, finden diese innerhalb der Rasterzeile in den drei Halbzyklen direkt nach dem zu dem jeweiligen Sprite gehörenden p-Zugriff statt. Der VIC benutzt dazu ebenfalls die BA- und AEC-Signale (wie in den Bad Lines), um in der zweiten Taktphase auf den Bus zugreifen zu können. Auch in diesem Fall geht BA drei Zyklen vor dem eigentlichen Zugriff auf Low. Die s-Zugriffe finden in jeder Rasterzeile statt, in der das Sprite sichtbar ist (bei den Sprites 0-2 jeweils in der Zeile davor, siehe die Timing-Diagramme in Abschnitt 3.6.3.), für jedes Sprite in festgelegten Zyklen innerhalb der Zeile. Wie die Text- und Bitmap-Grafik, so besitzen auch die Sprites einen Standard-Modus und einen Multicolor-Modus. Im Standardmodus entspricht jedes Bit direkt einem Pixel auf dem Bildschirm. Ein "0" Pixel ist transparent und läßt die darunterliegende Grafik durchscheinen, ein "1" Pixel stellt die zum jeweiligen Sprite gehörende Spritefarbe aus den Registern $d027-$d02e dar. Im Multicolor-Modus bilden je zwei benachbarte Bits ein Pixel, wodurch die Auflösung des Sprites auf 12×21 sinkt (die Pixel werden doppelt so breit). Außerdem lassen sich die Sprites in X- und Y-Richtung getrennt in ihrer Ausdehung auf dem Bildschirm verdoppeln (X-/Y-Expansion). Dabei wird jedes Sprite-Pixel einfach doppelt so breit und/oder hoch dargestellt, die Auflösung ändert sich nicht. Ein Pixel eines X-expandierten Multicolor-Sprites ist also insgesamt viermal so breit wie ein Pixel eines nicht-expandierten Standard-Sprites. Obwohl beide Expansionen ähnlich aussehen, sind sie doch auf vollkommen verschiedene Weise im VIC implementiert. Die X-Expansion weist einfach den Spritedatensequenzer an, die Pixel mit halber Frequenz auszugeben. Die Y-Expansion hingegen bewirkt, daß der Sprite-Adreßgenerator in je zwei aufeinanderfolgenden Zeilen von denselben Adressen liest, so daß jede Spritezeile doppelt ausgegeben wird. Zu jedem Sprite gehört ein eigener Spritedatensequenzer, dessen Kernstück ein 24-Bit-Schieberegister ist. Darüberhinaus gehören zu jedem Sprite noch zwei Register: "MC" (MOB Data Counter) ist ein 6-Bit-Zähler, der mit dem Wert aus MCBASE geladen werden kann. "MCBASE" (MOB Data Counter Base) ist ein 6-Bit-Zähler mit Löscheingang. Außerdem gibt es pro Sprite noch ein Expansions-Flipflop, daß die Y-Expansion steuert. Die Darstellung eines Sprites geschieht nach den folgenden Regeln (die Zyklusangaben gelten nur für den 6569): Das Expansions-Flipflop ist gesetzt, solange das zum jeweiligen Sprite gehörende Bit MxYE in Register $d017 gelöscht ist. In der ersten Phase von Zyklus 55 wird das Expansions-Flipflop invertiert, wenn das MxYE-Bit gesetzt ist. In den ersten Phasen von Zyklus 55 und 56 wird für jedes Sprite geprüft, ob das entsprechende MxE-Bit in Register $d015 gesetzt und die Y-Koordinate des Sprites (ungerade Register $d001-$d00f) gleich den unteren 8 Bits von RASTER ist. Ist dies der Fall und der DMA für das Sprite noch ausgeschaltet, wird der DMA angeschaltet, MCBASE gelöscht und, wenn das MxYE-Bit gesetzt ist, das Expansions-Flipflop gelöscht. In der ersten Phase von Zyklus 58 wird für jedes Sprite MC mit MCBASE geladen (MCBASE->MC) und geprüft, ob der DMA für das Sprite angeschaltet und die Y-Koordinate des Sprites gleich den unteren 8 Bits von RASTER ist. Ist dies der Fall, wird die Darstellung des Sprites angeschaltet. Ist der DMA für ein Sprite angeschaltet, finden in den entsprechenden, für jedes Sprite festgelegten Zyklen (siehe die Diagramme in Abschnitt 3.6.3.) drei aufeinanderfolgende s-Zugriffe statt (die p-Zugriffe finden immer statt, auch wenn das Sprite abgeschaltet ist). Die gelesenen Daten des ersten Zugriffes werden in den oberen 8 Bit des Schieberegisters gespeichert, die des zweiten in den mittleren 8 Bit und die des dritten in den unteren 8 Bit. Nach jedem s-Zugriff wird der MC um 1 erhöht. Ist die Sprite-Darstellung für ein Sprite angeschaltet, wird, sobald die aktuelle X-Koordinate des Rasterstrahls mit der X-Koordinate des Sprites (gerade Register $d000-$d00e und $d010) übereinstimmt, mit jedem Pixel das Schieberegister um ein Bit nach links geschoben und das "herausgefallene" Bit dargestellt. Ist das zum Sprite gehörige MxXE-Bit aus Register $d01d gesetzt, wird nur jedes zweite Pixel geschoben und das Sprite erscheint doppelt so breit. Wenn das Sprite im Multicolor-Modus ist, werden jeweils zwei Bits zu einem Pixel zusammengefaßt. In der ersten Phase von Zyklus 15 wird geprüft, ob das Expansions-Flipflop gesetzt ist. Wenn ja, wird MCBASE um 2 erhöht. In der ersten Phase von Zyklus 16 wird geprüft, ob das Expansions-Flipflop gesetzt ist. Wenn ja, wird MCBASE um 1 erhöht. Dann wird geprüft, ob MCBASE auf 63 steht und bei positivem Vergleich der DMA und die Darstellung für das jeweilige Sprite abgeschaltet. Dadurch, daß der Test in Punkt 3. gegen Ende der Rasterzeile gemacht wird, müssen die in den Registern angegebenen Sprite-Y-Koordinaten um 1 kleiner als die gewünschte Y-Position der ersten Sprite-Zeile sein, da die Darstellung der Sprites erst in der folgenden Zeile beginnt, nachdem die ersten Spritedaten gelesen wurden (sofern das Sprite nicht über die X-Koordinate $164 (Zyklus 58, siehe Punkt 4.) hinaus positioniert wird). Sprites lassen sich vertikal "wiederverwenden": Wenn man während oder nach erfolgter Darstellung eines Sprites dessen Y-Koordinate auf eine spätere Rasterzeile setzt, so daß die in Punkt 1. und 2. genannten Vergleiche nochmal ansprechen, wird das Sprite ab dieser Y-Koordinate noch einmal dargestellt (wobei man natürlich X-Koordinate und den Spritedatenzeiger beliebig ändern kann). So ist es möglich, mehr als 8 Sprites auf dem Bildschirm erscheinen zu lassen. Horizontal ist dies nicht möglich. Nach 24 dargestellten Pixeln ist das Schieberegister leergelaufen und auch wenn man die X-Koordinate innerhalb der Zeile so ändert, daß der Vergleich von Punkt 4. erneut anspricht, werden keine Spritedaten mehr angezeigt. Man kann also innerhalb einer Rasterzeile nur maximal 8 Sprites gleichzeitig darstellen. Hier noch einmal das Schema der p- und s-Zugriffe im Überblick: p-Zugriff
Adressen
13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
VM13 | VM12 | VM11 | VM10 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | Spr.-Nummer
Daten
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
MP7 | MP6 | MP5 | MP4 | MP3 | MP2 | MP1 | MP0
s-Zugriff
Adressen
13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
MP7 | MP6 | MP5 | MP4 | MP3 | MP2 | MP1 | MP0 | MC5 | MC4 | MC3 | MC2 | MC1 | MC0
Daten
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
MxMC=0
8 Pixel (1 Bit/Pixel) "0": Transparent "1": Spritefarbe ($d027-d02e)
MxMC=1
4 Pixel (2 Bit/Pixel) "00": Transparent "01": Sprite Multicolor 0 ($d025) "10": Spritefarbe ($d027-d02e) "11": Sprite Multicolor 1 ($d026)