C 64
Grafik

Vier Pseudo-VICs mit 32 Sprites

Sie wollen mit 32 Sprites und vier Bildschirmbereichen gleichzeitig arbeiten? Nichts leichter als das. Mit Provic 64 können simultan Grafik, Text oder veränderte Zeichensätze dargestellt werden.

So werden die Fähigkeiten von »Provic 64« demonstriert

Die Autoren (Jürgen, 21, Physikstudent, und Stefan, 18, Schüler) haben sich 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 Tl$ 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:
  • Bit 3: Umschaltung 24/25-Zeilendarstellung
  • Bit 4: Bild an/aus: es hat keinen Sinn, das Bild teilweise ausschalten zu wollen, da der VIC dieses Bit nur einmal pro Fernsehbild prüft (also entweder das ganze Bild an oder aus)
  • Bit 5: HiRes-Grafik-Modus an
  • Bit 6: Hintergrundmehrfarb-Modus an
  • Bit 7: Nummer der Interrupt-Rasterzeile Bit 8; es hat wenig Sinn, dieses Bit zu setzen, da so nur Rasterzeilen angesprochen werden, die unterhalb des Bildschirms liegen. Ist in irgendeinem Pseudo-VIC die 9-Bit-Zahl für die Rasterzeile größer als 311, so wird überhaupt kein IRQ mehr ausgelöst.
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:
  • Bits 0 bis 2: Softscrolling in X-Richtung
  • Bit 3: Umschaltungen 38/40-Spaltendarstellung
  • Bit 4: Multicolor-Modus ein
  • Bit 5 bis 7: unbenutzt
REG 23: Sprite vergrößern in Y-Richtung
REG 24:
  • Bits 1 bis 3: Adresse Zeichengenerator (Bits 11 bis 13)
  • Bits 4 bis 7: Adresse Video-RAM (Bits 10 bis 13)
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.

Der Basic-Lader:

Der Lader erzeugt Provic 64 aus den DATA-Zeilen und falls kein Prüfsummenfehler vorliegt, wird Provic 64 sofort als Maschinenprogramm auf Floppy oder Datasette (Zeile 400 entsprechend ändern!) abgespeichert. Dieses Maschinenprogramm enthält auch gleich die Standardwerte der Pseudo-VICs.

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.

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/rg)

Belegter Adreßraum:
$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
Provic 64 einschalten:
  • in Basic: SYS 52544
  • in Maschinensprache: JSR $CD40
Provic 64 ausschalten:
  • in Basic: SYS 52970
  • in Maschinensprache JSR $CEEA
Benutzte RAM-Adressen:
  • in der Zero-Page: 187 ($BB)
  • 188 ($BC)
Rechenzeitzuwachs bei aktiviertem Provic 64:
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 Tl 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
Tabellarische Übersicht zu Provic
10 rem interrupt-routine zur erzeugung
11 rem
12 rem eines maximal vierteiligen
13 rem
14 rem bildschirmes und 32 sprites
15 rem
16 rem auf einem commodore 64 computer
17 rem
18 rem       1984 by gebr. haas
19 rem
100 rem pruefsummen-kontrolle
101 rem
110 restore:ps=0
120 fora=0to511
130 read wert
140 ps=ps+wert
150 nexta
160 ifps<>60913thenprint"data-pruefsumme falsch !":end:*
199 rem
200 rem maschinencode uebertragen
201 rem
210 restore
220 fora=0to447
230 read wert
240 poke52544+a,wert
250 nexta
260 fora=0to63
265 read wert
270 forb=0to3
280 poke52992+b*64+a,wert
290 poke52992+b*64+18,95+50*b
295 nextb,a
299 rem
300 rem provic 64 abspeichern
301 rem
310 n$="provic 64"
320 fora=1tolen(n$)
330 poke49151+a,asc(mid$(n$,a,1))
340 nexta
350 poke183,len(n$)
360 poke187,0:poke188,192
370 poke185,1
380 poke193,64:poke194,205
390 poke174,0:poke175,208
400 poke186,8: rem fuer floppy   : 8                       fuer datasette: 1
410 sys62957:  rem save routine
420 end
999 rem
1000 rem provic 64 maschinencode
1001 rem
1002 data120,169,88,162,205,141,20,3,142,21,3,169,1,141,13,220,141,26,208
1003 data141,255,207,88,96,169,1,141,25,208,172,255,207,240,15,136,240,9,136
1004 data240,3,162,192,44,162,128,44,162,64,44,162,0,189,18,207,141,18,208
1005 data189,47,207,208,3,76,141,206,173,30,208,29,30,207,157,30,207,173,31
1006 data208,29,31,207,157,31,207,189,21,207,141,21,208,189,23,207,141,23
1007 data208,189,29,207,141,29,208,189,0,207,141,0,208,189,1,207,141,1,208
1008 data189,2,207,141,2,208,189,3,207,141,3,208,189,4,207,141,4,208,189,5
1009 data207,141,5,208,189,6,207,141,6,208,189,7,207,141,7,208,189,8,207,141
1010 data8,208,189,9,207,141,9,208,189,10,207,141,10,208,189,11,207,141,11
1011 data208,189,12,207,141,12,208,189,13,207,141,13,208,189,14,207,141,14
1012 data208,189,15,207,141,15,208,189,16,207,141,16,208,189,27,207,141,27
1013 data208,189,28,207,141,28,208,189,37,207,141,37,208,189,38,207,141,38
1014 data208,189,39,207,141,39,208,189,40,207,141,40,208,189,41,207,141,41
1015 data208,189,42,207,141,42,208,189,43,207,141,43,208,189,44,207,141,44
1016 data208,189,45,207,141,45,208,189,46,207,141,46,208,189,56,207,133,188
1017 data169,248,133,187,160,0,189,48,207,145,187,200,189,49,207,145,187,200
1018 data189,50,207,145,187,200,189,51,207,145,187,200,189,52,207,145,187
1019 data200,189,53,207,145,187,200,189,54,207,145,187,200,189,55,207,145
1020 data187,189,57,207,240,67,189,58,207,41,3,157,58,207,173,0,221,41,252
1021 data29,58,207,141,0,221,189,17,207,141,17,208,189,22,207,141,22,208,189
1022 data24,207,141,24,208,189,32,207,141,32,208,189,33,207,141,33,208,189
1023 data34,207,141,34,208,189,35,207,141,35,208,189,36,207,141,36,208,224
1024 data192,208,5,169,255,141,255,207,238,255,207,138,240,3,76,129,234,76
1025 data49,234,120,169,49,162,234,141,20,3,142,21,3,169,129,141,13,220,169
1026 data0,76,80,205,234,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,95,0,0,0,200
1027 data0,21,121,240,0,0,0,0,0,14,6,1,2,3,4,0,1,2,3,4,5,6,7,8,0,0,0,0,0,0
1028 data0,0,0,7,1,3,0,0,0,0,0
Basic-Lader »Provic 64«
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
Demo-Listing »Provic 64«
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →