Vier Pseudo-VICs mit 32 Sprites
Erweitern Sie Ihren Videochip. Nur duch Software lassen sich ungeahnte Bilder aus dem VIC zaubern. So sind 32 Sprites sowie HiRes-Grafik und Text gleichzeitig nur die leichtesten Übungen für Provic 64.

Sie wollen mit 32 Sprites und vier Bildschirmbereichen gleichzeitig arbeiten? Nichts leichter als das. Mit Provic 64 können simultan hochauflösende Grafik, Text oder veränderte Zeichensätze dargestellt werden.
Wir (Jürgen, 21, Physikstudent, und Stefan, 18, Schüler) haben uns Mitte 1983 einen Commodore 64 angeschafft. Schon nach kurzer Zeit stellte sich der bei den C 64-Fans übliche Frust über die schlechte Dokumentation und die schwierige Informationsbeschaffung ein, besonders wenn es um die speziellen Grafikfähigkeiten dieses Computers geht. So sitzen wir oft stundenlang vor dem Bildschirm, der nur undefinierbare Zeichen zeigt, weil wir bei dem Versuch, die Geheimnisse des C 64 zu enträtseln, in irgendeinen unbekannten Darstellungsmodus geraten sind.
Dabei entdeckten wir, daß der C 64 nicht nur acht, sondern auch 16, 24, 32 oder noch mehr Sprites gleichzeitig zeigen kann. Zusätzlich ergibt sich die Möglichkeit, mehrere Bildschirmmodi zu mischen.
Nun haben wir uns entschlossen, den Kunstgriff, der dies ermöglicht, anderen C 64-Fans nicht vorzuenthalten. Also entwickelten wir ein Programm in Maschinensprache und dazu ein kleines Demonstrationsprogramm in Basic.
Zum Programm
Durch Aufruf der Initialisierungsroutine wird der Interruptmechanismus des C 64 verändert. Nicht mehr der Timer der CIA 1, sondern der VIC 6567 löst jetzt den Interrupt aus, und zwar synchron zum Takt des Bildschirmsignals. Außerdem werden vier sogenannte Pseudo-VICs eingerichtet. Alle POKEs, von Spritebewegung über Bildschirmfarbe bis zur Grafikkonfiguration, müssen ab jetzt in diese Pseudo-VICs erfolgen. Jeder dieser Pseudo-VICs ist für einen der vier Bildschirmbereiche zuständig:
Der Bildschirm wird in vier waagerechte Bereiche aufgeteilt, deren Grenzlinien fast beliebig nach oben oder unten verschoben werden können. Jeder einzelne Bereich kann acht Sprites darstellen und eine eigene Farb- und Grafikkonfiguration aufweisen. So können zum Beispiel Normalschrift, HiRes-Grafik, Multicolor-Grafik und eventuell ein selbstdefinierter Zeichensatz gleichzeitig auf dem Bildschirm gezeigt werden.
Provic 64 kann selbstverständlich wieder abgeschaltet werden (bei Kassetten- oder Diskettenoperationen nötig).
Für Maschinensprachefreaks nun eine kurze Funktionsbeschreibung der Interruptroutine:
Bei Aufruf der Einschaltroutine (SYS 52544) wird der IRQ-Vektor auf die Hauptroutine des Provic 64 gestellt und der bisherige Interrupt durch den Timer A der CIA 1 verboten, während der Raster-IRQ des VIC 6567 erlaubt wird.
Sobald der Bildschirmstrahl die eingestellte Rasterzeile erreicht, wird ein Interrupt ausgelöst und der Prozessor bearbeitet die Hauptroutine des Provic 64. In dieser wird zunächst anhand eines Zählers ($ CFFF) festgestellt, welcher Bildschirmbereich an der Reihe ist. Dann wird die Rasterzeile, die das Ende dieses Bildschirms kennzeichnet, eingestellt.
Anschließend werden, falls ein entsprechendes Flag gesetzt ist, die Sprite- und andere Bildschirmparameter in den VIC 6567 übertragen. Nach dem Weiterzählen des IR-Zählers ($ CFFF) wird entweder der Interrupt beendet, oder zur IRQ-Routine des Betriebssystems gesprungen (nach jedem vierten Interrupt). So werden in der Sekunde 200 Interrupts (vier pro Fersehbild) ausgelöst und 50 mal in der Sekunde (einmal pro Bild) die normale IRQ-Routine abgearbeitet. Dadurch zählt die interne Uhr TI in 50stel Sekunden und TI$ wird unbrauchbar.
Beim Aufruf der Ausschaltroutine wird der Raster-IRQ des VIC 6567 unterbunden, der Interrupt des Timers A in CIA 1 erlaubt und der IRQ-Vektor auf die IRQ-Routine des Betriebssystems eingestellt.
Handhabung der Pseudo-VICs
Im Grunde ist jeder der vier Pseudo-VICs wie der echte VIC zu behandeln. Ausnahmen sind hier nur die Register 30 (Sprite-Sprite-Kollision) und 31 (Sprite-Hintergrund-Kollision), die sich auf den jeweils vorausgegangenen Bildschirmbereich beziehen. Die Register 19 und 20 (Lightpenkoordinaten), sowie 25 und 26 (IRQ-Flags und -maske) werden nicht behandelt, da diese Funktionen nur direkt über den VIC 6567 sinnvoll gehandhabt werden können. Außerdem hat jeder Pseudo-VIC noch zusätzliche Register für zwei Flags (REG 47 und REG 57), acht Sprite-Pointer (REG 48 bis REG 55), Videomatrix-Anfangsadresse Highbyte (REG 56) und die CIA 2, REG 0, Bits 0 und 1 (REG 58) (Adreßbits 14 und 15 des VIC 6567).
Die vier Basisadressen der PVICs sind:
| PVIC 1 | 52992 ($ CF00) | = REG 0 |
| PVIC 2 | 53056 ($ CF40) | = REG 0 |
| PVIC 3 | 53120 ($ CF80) | = REG 0 |
| PVIC 4 | 53184 ($ CFC0) | = REG 0 |
Da die Pseudo-VICs praktisch gleichberechtigt sind, hier die Registerbeschreibung eines Pseudo-VICs:
| REG 0: | X-Koordinate des Sprite 0 |
| REG 1: | Y-Koordinate des Sprite 0 Beachte: Die Y-Koordinaten sollten im Bereich des zugehörigen Bildschirmbereichs liegen, sonst ist der Sprite nicht zu sehen. Näheres siehe unten. |
| REG 2 bis 15: | Wie REG 0 und 1, aber für Sprites 1 — 7 |
| REG 16: | MSB (höchstes Bit) der X-Koordinaten |
| REG 17: | Bits 0 bis 2: Y-Abstand der Zeichen vom oberen Bildrand in Rasterzeilen (Softscrolling!) |
| REG 17: |
|
| REG 18: | Nummer der Rasterzeile Bits 0 — 7; hier ist anzugeben, wann der nächste Interrupt ausgelöst werden soll, das heißt wo der Bildschirmbereich dieses PVICs zu Ende sein soll. Dabei sollte folgende Reihenfolge eingehalten werden: REG 18: PVIC 1 < PVIC 2 < PVIC 3 <PVIC 4 (Zyklische Vertauschungen möglich!) |
| REG 19 und 20: | nicht verwendet (siehe oben) |
| REG 21: | Sprite enable (einschalten) |
| REG 22: |
|
| REG 23: | Sprite vergrößern in Y-Richtung |
| REG 24: |
|
| REG 25 und 26: | nicht verwendet (siehe oben) |
| REG 27: | Sprite-Priorität vor Hintergrund |
| REG 28: | Flags für Multicolor-Sprites |
| REG 29: | Sprite vergrößern in X-Richtung |
| REG 30: | Sprite-Sprite-Kollision |
| REG 31: | Sprite-Hintergrund-Kollision Achtung: Geben die Kollisionen des vorangegangenen Bildschirmbereichs an: Findet im Bereich von PVIC 3 eine Kollision statt, wird dies im PVIC 4 registriert. Kollisionen im Bereich von PVIC 4 werden im PVIC 1 registriert. Dieses Register muß gelöscht werden, um neue Kollisionen anzeigen zu können! |
| REG 32: | Rahmenfarbe |
| REG 33 bis 36: | Hintergrundfarben 0 bis 3 |
| REG 37 und 38: | Multicolor-Sprite-Farben 0 und 1 |
| REG 39 bis 46: | Farben für Sprites 0 bis 7 |
| REG 47: | Flag für Spritebehandlung; nur wenn der Inhalt dieses Registers nicht Null ist, werden die Register, die etwas mit Sprites zu tun haben, vom PVIC in den VIC 6567 übertragen. Das sind REG 0 bis REG 16, REG 21, REG 23, REG 27 bis REG 31, REG 37 bis 46 sowie REG 48 bis 55. Ist der Inhalt Null, gelten für die Sprites die Werte des vorherigen PVICs, während die Kollisionen erst im nächsten PVIC, in dem REG 48 ungleich Null ist, angezeigt werden. |
| REG 48 bis 55: | Sprite-Pointer für Sprites 0 bis 7; Die Pointer auf die Bitmuster der Sprites werden nicht mehr in die Speicherzellen 2040 bis 2047 geschrieben, sondern in diese Register des PVICs. |
| REG 56: | In diesem Register muß das Highbyte der Video-RAM-Anfangsadresse plus 3 stehen; normalerweise also 4 + 3 = 7 (da der Bildschirm nach dem Einschalten des Computers bei 1024 beginnt, 1024 = $ 0400). Bei Verlegung des Video-RAMs ist also der Inhalt dieses Registers zu korrigieren. |
| REG 57: | Flag für Bildschirmparameter-Behandlung; nur wenn der Inhalt dieses Registers nicht Null ist, werden die REG 17, 22, 24, sowie 32 bis 36 und REG 58 in den VIC 6567 übertragen. |
| REG 58: | Bits 0 und 1: Adressbits 14 und 15 des VIC 6557; werden nach CIA 2 REG 0 Bits 0 und 1 übertragen. Mit diesen Bits kann Video-RAM, Charaktergenerator, Grafik-Bitmap in 16-KByte- Schritten verschoben werden. Da die Bits low- aktiv sind, sind sie beim Einschalten gesetzt (also REG 58 = 3). Bits 2 bis 7: unbenutzt, immer 0. |
Übergang eines Sprites zwischen zwei Bildschirmbereichen:
Soll ein Sprite zwischen zwei Bildschirmbereichen wechseln, muß in beiden Bereichen derselbe Sprite (also zum Beispiel beidesmal Sprite 4) die gleiche Position besitzen, und zwar so lange, wie der Sprite die Trennlinie zwischen den Bereichen überdeckt. Wird dies nicht beachtet, werden die entsprechenden Sprites zerschnitten und verschoben.
Aktivieren von Provic 64: Von Basic aus mit SYS 52544 und von Maschinensprache aus mit JSR $CD40.
Ausschalten von Provic 64: Von Basic aus mit SYS 52970 und von Maschinensprache aus mit JSR $CEEA.
Eingabe von Provic 64:
Die Eingabe des Listing 1 erfolgt mit dem MSE, das Speichern ebenfalls.
Laden von Provic 64:
Im Programm am besten mit der Zeile IF PEEK(52544)><120 THEN LOAD "PROVIC64",Gerätenummer, 1 die am Anfang des Basic-Programms stehen sollte.
Das Demonstrationsprogramm zeigt einige der Vorzüge von Provic 64. Es ist nur als Anregung gedacht, deshalb verzichten wir hier auf eine nähere Beschreibung.
Bei Kassetten- und Disketten- sowie Drucker-Zugriffen muß Provic vorher abgeschaltet werden. Sonst beginnt der Bildschirm wild zu flackern und Provic stürzt vielleicht ab.
Provic 64 ist nicht nur für Basic-Programmierer, sondern vor allem auch für Maschinensprache-Freaks gedacht, da erst durch schnelle Maschinenprogramme die Möglichkeiten von Provic 64 voll ausgeschöpft werden können.
(Jürgen und Stefan Haas/bs)
| $CD40 | Einschaltroutine |
| $CD58 | Interruptroutine |
| $CEEA | Ausschaltroutine |
| $CF00 | Pseudo-VIC 1 |
| $CF40 | Pseudo-VIC 2 |
| $CF80 | Pseudo-VIC 3 |
| $CFCO | Pseudo-VIC 4 |
| $CFFF | Interruptzähler |
- in Basic: SYS 52544
- in Maschinensprache: JSR $CD40
- in Basic: SYS 52970
- in Maschinensprache JSR $CEEA
- in der Zero-Page: 187 ($BB)
- 188 ($BC)
| alle Spriteflags (REG 47) und Bildschirmparameterflags (REG 57) gelöscht: | + 2,5% |
| für jedes gesetzte Spriteflag (REG 47): | zirka + 2,4% |
| für jedes gesetzte Bildschirmflag (REG 57): | + 0,5% |
| alle Sprite- und Bildschirmflags gesetzt: | zirka + 15,0% |
- Falls der Rechner abstürzt rettet Run-Stop/Restore!
- Die Zeitvariable TI zählt bei aktiviertem Provic 64 in 50stel Sekunden (statt 60stel);
- TI$ wird somit unbrauchbar.
- Zeiger für Interruptaussprung von PVIC 3 bis PVIC 4: $CEE5
- Zeiger für Interruptaussprung von PVIC 1: $CEE8
PROGRAMM : PROVIC 64 CD40 D000 ----------------------------------- CD40 : 78 A9 58 A2 CD 8D 14 03 97 CD48 : 8E 15 03 A9 01 8D 0D DC C1 CD50 : 8D 1A D0 8D FF CF 58 60 71 CD58 : A9 01 8D 19 D0 AC FF CF 1A CD60 : F0 0F 88 F0 09 88 F0 03 B7 CD68 : A2 C0 2C A2 80 2C A2 40 3E CD70 : 2C A2 00 BD 12 CF 8D 12 9F CD78 : D0 BD 2F CF D0 03 4C 8D 5E CD80 : CE AD 1E D0 1D 1E CF 9D 04 CD88 : 1E CF AD 1F D0 1D 1F CF EF CD90 : 9D 1F CF BD 15 CF 8D 15 99 CD98 : D0 BD 17 CF 8D 17 D0 BD 57 CDA0 : 1D CF 8D 1D D0 BD 00 CF 46 CDA8 : 8D 00 D0 BD 01 CF 8D 01 E8 CDB0 : D0 BD 02 CF 8D 02 D0 BD 81 CDB8 : 03 CF 8D 03 D0 BD 04 CF 11 CDC0 : 8D 04 D0 BD 05 CF 8D 05 4A CDC8 : D0 BD 06 CF 8D 06 D0 BD BA CDD0 : 07 CF 8D 07 D0 BD 08 CF BE CDD8 : 8D 08 D0 BD 09 CF 8D 09 AC CDE0 : D0 BD 0A CF 8D 0A D0 BD F3 CDE8 : 0B CF 8D 0B D0 BD 0C CF 6A CDF0 : 8D 0C D0 BD 0D CF 8D 0D 0F CDF8 : D0 BD 0E CF 8D 0E D0 BD 2C CE00 : 0F CF 8D 0F D0 BD 10 CF 17 CE08 : 8D 10 D0 BD 1B CF 8D 1B 26 CE10 : D0 BD 1C CF 8D 1C D0 BD 38 CE18 : 25 CF 8D 25 D0 BD 26 CF 60 CE20 : 8D 26 D0 BD 27 CF 8D 27 22 CE28 : D0 BD 28 CF 8D 28 D0 BD B4 CE30 : 29 CF 8D 29 D0 BD 2A CF 0D CE38 : 8D 2A D0 BD 2B CF 8D 2B 84 CE40 : D0 BD 2C CF 8D 2C D0 BD ED CE48 : 2D CF 8D 2D D0 BD 2E CF B9 CE50 : 8D 2E D0 BD 38 CF 85 BC 72 CE58 : A9 F8 85 BB A0 00 BD 30 B7 CE60 : CF 91 BB C8 BD 31 CF 91 C7 CE68 : BB C8 BD 32 CF 91 BB C8 47 CE70 : BD 33 CF 91 BB C8 BD 34 4E CE78 : CF 91 BB C8 BD 35 CF 91 00 CE80 : BB C8 BD 36 CF 91 BB C8 DF CE88 : BD 37 CF 91 BB BD 39 CF 35 CE90 : F0 43 BD 3A CF 29 03 9D 66 CE98 : 3A CF AD 00 DD 29 FC 1D 7B CEA0 : 3A CF 8D 00 DD BD 11 CF D5 CEA8 : 8D 11 D0 BD 16 CF 8D 16 EC CEB0 : D0 BD 18 CF 8D 18 D0 BD B7 CEB8 : 20 CF 8D 20 D0 BD 21 CF 46 CEC0 : 8D 21 D0 BD 22 CF 8D 22 E5 CEC8 : D0 BD 23 CF 8D 23 D0 BD EA CED0 : 24 CF 8D 24 D0 E0 C0 D0 7C CED8 : 05 A9 FF 8D FF CF EE FF 9D CEE0 : CF 8A F0 03 4C 81 EA 4C A6 CEE8 : 31 EA 78 A9 31 A2 EA 8D D1 CEF0 : 14 03 8E 15 03 A9 81 8D 6B CEF8 : 0D DC A9 00 4C 50 CD EA 32 CF00 : 00 00 00 00 00 00 00 00 01 CF08 : 00 00 00 00 00 00 00 00 09 CF10 : 00 1B 5F 00 00 00 C8 00 99 CF18 : 15 79 F0 00 00 00 00 00 26 CF20 : 0E 06 01 02 03 04 00 01 04 CF28 : 02 03 04 05 06 07 08 00 06 CF30 : 00 00 00 00 00 00 00 00 31 CF38 : 07 01 03 00 00 00 00 00 81 CF40 : 00 00 00 00 00 00 00 00 41 CF48 : 00 00 00 00 00 00 00 00 49 CF50 : 00 1B 91 00 00 00 C8 00 65 CF58 : 15 79 F0 00 00 00 00 00 66 CF60 : 0E 06 01 02 03 04 00 01 44 CF68 : 02 03 04 05 06 07 08 00 46 CF70 : 00 00 00 00 00 00 00 00 71 CF78 : 07 01 03 00 00 00 00 00 C1 CF80 : 00 00 00 00 00 00 00 00 81 CF88 : 00 00 00 00 00 00 00 00 89 CF90 : 00 1B C3 00 00 00 C8 00 32 CF98 : 15 79 F0 00 00 00 00 00 A6 CFA0 : 0E 06 01 02 03 04 00 01 84 CFA8 : 02 03 04 05 06 07 08 00 86 CFB0 : 00 00 00 00 00 00 00 00 B1 CFB8 : 07 01 03 00 00 00 00 00 01 CFC0 : 00 00 00 00 00 00 00 00 C1 CFC8 : 00 00 00 00 00 00 00 00 C9 CFD0 : 00 1B F5 00 00 00 C8 00 FE CFD8 : 15 79 F0 00 00 00 00 00 E6 CFE0 : 0E 06 01 02 03 04 00 01 C4 CFE8 : 02 03 04 05 06 07 08 00 C6 CFF0 : 00 00 00 00 00 00 00 00 F1 CFF8 : 07 01 03 00 00 00 00 00 41
6 rem dieses kurze demo-programm soll
8 rem ein paar darstellungsformen
10 rem zeigen, wie sie mit provic-64
12 rem relativ einfach erreichbar sind.
14 rem 1984 by gebr. haas
19 rem
20 rem laden der provic-64 routine
21 rem
30 ifpeek(52544)=120then100
40 print"{down}{down} auf welchem datentraeger ist provic-64"
50 print"{down} verfuegbar ( floppy =8 / datasette =1 )"
60 input" ";a$:a=val(a$)
70 if a<>1 and a<>8 then40
80 load"provic 64",a,1
99 rem
100 rem pseudo-vic's initialisieren
101 rem
110 p1=52992:p2=53056:p3=53120:p4=53184:rem basisadressen der pseudo-vic's
120 pokep1+21,255:pokep1+24,22:pokep1+47,1:pokep1+27,255:pokep2+21,255
130 pokep2+17,59:pokep2+24,24:pokep2+32,7:pokep2+47,1:pokep2+27,255
140 pokep3+21,255:pokep3+32,9:pokep3+47,1:pokep3+27,255:pokep4+32,5
150 pokep4+21,255:pokep4+24,22:pokep4+47,1:pokep4+18,230:pokep4+27,255
199 rem
200 rem sprite-daten uebertragen
201 rem
210 restore
220 fora=0to126
230 read wert
240 poke832+a,wert
250 nexta
299 rem
300 rem bilschirm aufbauen
301 rem
310 print"{clr}{wht}{down}{rvon}{rght}{rght}{rght}{rght}{rght}{rght}{rght}P{$a0}R{$a0}O{$a0}V{$a0}I{$a0}C{$a0}{$a0}{$a0}6{$a0}4{$a0}{$a0}{$a0}D{$a0}E{$a0}M{$a0}O"
320 print"{down}{down} In diesem Bereich: GROSS/klein-Schrift{down}":
330 fora=0to7:print"{blu}rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr{wht}";:nexta
335 fora=0to14:poke1289+a,34:nexta
340 print" ^ dort oben: hires-grafik-modus ^"
350 print"{down} hier: gross-schrift/grafik"
360 print"{down} QWERTYUIO{SHIFT-@}{SHIFT-*}~LKJHFSAZXCVBNM{CBM-Q}{CBM-W}{CBM-E}{CBM-R}{CBM-T}{CBM-F}{CBM-G}{CBM-Z}{CBM-X}{CBM-C}{CBM-V}{CBM-B}"
370 print"{down}{down}{down}{down}{down} ^ Dort oben: Laufschrift ^{up}{up}{up}":printtab(6);
390 sys52544:rem provic-64 activieren
399 rem
400 rem hires-grafik zeichnen
401 rem
410 fora=10110to12360:pokea,0:nexta
420 fora=0to8*~step.08
430 x=3+a/.08:y=77-11*sin(a)-9*cos(a/.7)
440 av=8192+320*int(y/8)+(y and7)+8*int(x/8)
450 pokeav,peek(av) or 2^(7-(x and 7))
460 nexta
470 la$="*** von HaasiSoft *** Fuer das 64'er Magazin "
480 la$=la$+"*** P{$a0}R{$a0}O{$a0}V{$a0}I{$a0}C{$a0}{$a0}{$a0}6 4 "
490 la$=la$+left$(la$,25):r=53266
499 rem
500 rem demonstratins-schleife
501 rem
510 rem sprites setzen
511 rem
520 fora=0to7
530 pokep1+2*a,30+24*a+7*rnd(1):pokep1+2*a+1,60+6*rnd(1)
540 pokep1+39+a,rnd(1)*16:pokep1+48+a,13.5+rnd(1)
550 pokep2+2*a,30+24*a+7*rnd(1):pokep2+2*a+1,110+6*rnd(1)
560 pokep2+39+a,rnd(1)*16:pokep2+48+a,13.5+rnd(1)
570 pokep3+2*a,30+24*a+7*rnd(1):pokep3+2*a+1,160+6*rnd(1)
580 pokep3+39+a,rnd(1)*16:pokep3+48+a,13.5+rnd(1)
590 pokep4+2*a,30+24*a+7*rnd(1):pokep4+2*a+1,207+6*rnd(1)
600 pokep4+39+a,rnd(1)*16:pokep4+48+a,13.5+rnd(1)
610 nexta
619 rem
620 rem laufschrift setzen
621 rem
625 forlp=1tolen(la$)-25
630 lz=lz-1:iflz>0thenpokep4+22,lz or 8:fora=0to9:nexta:goto630
640 printtab(6);:wait53265,128:wait53266,64:poke53206,15:printlf$:print"{up}{up}"
660 lz=7:lf$=mid$(la$,lp,25)
670 nextlp
680 geta$:ifa$=""then500
690 sys52970:rem provic-64 desaktivieren
999 rem
1000 rem sprite-daten
1001 rem
1002 data0,0,0,0,126,0,1,255,128,7,255,224,15,255,240,15,253,240,31,255,248
1003 data31,255,248,63,255,252,63,255,252,63,243,252,63,252,0,63,255,252,63
1004 data255,252,31,255,248,31,255,248,15,255,240,15,255,240,7,255,224,1,255
1005 data128,0,126,0,0,0,0,0,0,126,0,1,255,128,7,255,224,15,255,240,15,251
1006 data240,31,255,248,31,255,248,63,255,240,63,255,0,63,240,0,63,252,0,63
1007 data255,0,63,255,224,31,255,248,31,255,248,15,255,240,15,255,240,7,255
1008 data224,1,255,128,0,126,0