Zeichen

Aus C64-Wiki
(Weitergeleitet von Zeichensatz)
Zur Navigation springenZur Suche springen
Der Zeichensatz des C64 im Bitmap-Modus

Der C64 bzw. sein Grafikchip VIC-II beherrscht 256 Zeichen (0-255), die im Zeichenspeicher enthalten sind und über mehrere Methoden genutzt werden können. Ein einzelnes Zeichen hat im normalen Textmodus eine Auflösung von 8×8 Pixeln. Die Gesamtheit aller Zeichen eines Modus im Computer wird auch Zeichensatz genannt und belegt damit 256×8 gleich 2048 Bytes. Der C64 besitzt 2 Zeichensätze, und zwar Großschrift/Grafikzeichen (Zeichensatz 1, Standard) und Groß-/Kleinschrift (Zeichensatz 2). Sowohl im Direktmodus als auch während der Programmausführung kann der Zeichensatz durch Drücken der Tastenkombination C= +SHIFT  umgeschaltet werden.

Zeichenausgabe[Bearbeiten | Quelltext bearbeiten]

Die einfachste Methode ist die Eingabe der Zeichen im Bildschirmeditor im Direktmodus oder die Ausgabe von Zeichen per BASIC-Befehl PRINT bzw. per PRINT CHR$(x) auf Basis einer ASCII-ähnlichen Tabelle. Allerdings sind damit nicht alle 256 Zeichen darstellbar: Gewisse Steuerzeichen üben lediglich ihre entsprechende Funktion aus und andere Zeichen sind bestimmten Tasten der Tastaturbelegung zugeordnet, z.B. die Funktionstasten!
Das Umschalten vom Zeichensatz 1 (Großschrift/Grafikzeichen) in den Zeichensatz 2 (Groß-/Kleinschrift) funktioniert mit dem Steuercode PRINT CHR$(14). Zurück in den Zeichensatz 1 führt PRINT CHR$(142).

Alternativ kann aber auch mit Hilfe das BASIC-Befehls POKE der Bildschirmcode eines der 256 Zeichen direkt in den Bildschirmspeicher (1024-2023) geschrieben werden. POKE 1024,0 setzt z.B. auf die oberste linke Position des Bildschirmspeichers das Zeichen "@". Während mit CHR$() auch Steuerzeichen (Farbwahl oder Cursorsteuerung) erreicht werden, ist dies via POKE nicht möglich. Allerdings ist der Zeichensatz bei POKE besser zu handhaben, da die Zeichen 0-127 die normalen Zeichen sind, während nach einer Addition von 128 die dazugehörigen Zeichen in Inversdarstellung (128-255) gezeigt werden (siehe Bilder). Die Farbsetzung für jedes Zeichen aus dem Bildschirmspeicher kann mit Hilfe von POKE auf den Farbspeicher (55296-56295) gemäß Farbtabelle erfolgen.

Bildschirmcodes des C64[Bearbeiten | Quelltext bearbeiten]

Normale Zeichen mit Bildschirmcodes 0-127, inverse Zeichen mit Bildschirmcodes 128-255.
Für eine vergrößerte Darstellung bitte auf die Bilder klicken.

Zeichensatz 1[Bearbeiten | Quelltext bearbeiten]

Zeichensatz 2[Bearbeiten | Quelltext bearbeiten]

Umschaltung[Bearbeiten | Quelltext bearbeiten]

Das Umschalten von Zeichensatz 1 (Großschrift/Grafikzeichen) in den Zeichensatz 2 (Groß-/Kleinschrift) erfolgt über POKE 53272,23.
Zurück geht es in den Zeichensatz 1 mit POKE 53272,21.
Übersicht der Zeichensatzumschaltung:

Zeichensatz POKE PRINT CHR$(...)
1 53272,23 14
2 53272,21 142

Die Umschaltung des Zeichensatzes kann durch Ausgabe bestimmter Codes verhindert oder erlaubt werden:

Umschaltung PRINT CHR$(...)
C64 C128
verhindern 8 11
erlauben 9 12

Zeichen mit doppelter Höhe oder Breite[Bearbeiten | Quelltext bearbeiten]

Ultraflash-Noter: Doppelt hohe Zeichen mit buntem Farbverlauf

Prinzipiell ist in einem Zeichensatz jedes Zeichen vier Mal vorhanden: Normal, Ge-Shift-et, Reverse, und Reverse-Shift. Je nach verwendetem Zeichensatz sind mit Shift Grafikzeichen oder Großbuchstaben zu erreichen. Durch Erstellung eines eigenen Zeichensatzes kann man jedoch auch Zeichen mit doppelter Höhe (1×2) darstellen: Hierzu wird die obere Hälfte in den Bereich für die normalen Zeichen platziert, die untere Hälfte findet im Bereich für geshiftete oder (ganz nach Bedarf) reverse Zeichen Platz. Um ein doppelt hohes Zeichen erscheinen zu lassen, muss dann zunächst das Zeichen mit der oberen Hälfte des Buchstabens auf den Bildschirm gebracht werden, dann genau darunter (sprich im Bildschirmspeicher 40 Zeichen weiter) das Zeichen für die untere Hälfte. Genauso funktioniert auch die Darstellung doppelt breiter Zeichen (2×1). Hierbei muss mit einem Zeichensatz-Editor ein Zeichensatz erstellt worden sein, der die linke Hälfte des Buchstabens im Bereich für normale Zeichen platziert, die rechte Hälfte im Bereich für geshiftete oder reverse Zeichen. Die Ausgabe von Wörtern in doppelter Breite ist dann etwas einfacher als bei doppelter Höhe: Für ein 'A' beispielsweise muss man lediglich zunächst das Zeichen für das normale 'A' ausgeben, direkt dahinter folgt dann schon das geshiftete (bzw. reverse) 'A', und schon sieht man ein 'A' doppelter Breite. Nutzt man diese Art von Zeichensätzen, verzichtet man natürlich bewusst auf geshiftete oder reverse Zeichendarstellung.

Kombiniert man doppelt hoch und doppelt breit, hat man zwar keine geshifteten und keine reversen Zeichen mehr, dafür jedoch einen Satz sehr große Zeichen (2×2).

Der Vorteil dieser Art Schriftdarstellung ist, dass man sehr vielfältige Schrifttypen darstellen kann, ohne dabei auf die schnelle Darstellung im Zeichensatz-Modus des C64 verzichten zu müssen. Wie u.a. bei GEOS zu sehen, bietet die Alternative der Darstellung im Hires Bitmap-Modus natürlich wesentlich höhere Flexibilität bei Höhe und Breite der Zeichen, jedoch zum Preis von ziemlich langsamer Darstellung. Der Ultraflash-Noter beispielsweise zeigt hingegen unter Nutzung eines 1×2-Zeichensatzes deutlich höhere Geschwindigkeit beim Bildschirmaufbau sowie beim Editieren von Text.

Mehrfarbige Zeichen[Bearbeiten | Quelltext bearbeiten]

Der C64 ist außerdem in der Lage, mehrfarbige Zeichen (Multicolor) darzustellen. Dabei halbiert sich die horizontale Auflösung eines Zeichens, da jeweils 2 Bit als Bit-Paar die Farbinformation eines dafür optisch doppelt so breiten Pixels tragen.

Bitpaar Speicheradresse Bezeichnung
00 53281 Bildschirmfarbe
01 53282 Multicolorfarbe 1
10 53283 Multicolorfarbe 2
11 55296-56295 Farbspeicher (Zeichenfarbe)

Bevor der Multicolor-Modus genutzt wird, muss dieser eingeschaltet werden. Dies geschieht mit Register 22 des VIC-II, das an Speicherstelle 53270/$D016 sichtbar ist:

POKE 53270,PEEK(53270) OR 16 

Dieser Modus lässt er sich mit

POKE 53270,PEEK(53270) AND 239

wieder abschalten.

Der Fähigkeit zur Darstellung mehrfarbiger Zeichen verdankt der C64 seine Stärke bei Spielen. Im Gegensatz zum Amiga, der nur Grafikmodi kennt, kann der C64 dank Zeichensatzdarstellung trotz seiner vergleichsweise geringen CPU-Geschwindigkeit ansehnliche Spielegrafik darstellen. Hierzu wird die Spiele-Grafik aus vom Grafiker definierten Zeichen zusammengesetzt.

Zeichen mit mehrfarbigem Hintergrund[Bearbeiten | Quelltext bearbeiten]

Wechselnde Rasterbars innerhalb von Zeichen in einem Diskmag

Beim C64 gibt es auch einen erweiterten Hintergrundfarbenmodus, der es erlaubt, für jedes Zeichen aus drei zusätzlich festgelegten Hintergrundfarben zu wählen. In diesem Fall reduziert sich aber der Zeichensatzumfang auf die ersten 64 Zeichen, da mit den beiden höchstwertigen Bits eines Zeichencodes die Hintergrundfarbe angegeben wird.

Eine interessante Anwendung dieses Modus stellen Blinkeffekte in Notemakern (z.B. Facenoter) dar. Viele invertieren den Zeichensatz, schalten in den erweiterten Hintergrundfarbenmodus und beschreiben dann die entsprechenden Register zyklisch mit Werten aus Farbtabellen. So entstehen die blinkenden Buchstaben, ohne dass das Farb-RAM an der entsprechenden Position verändert werden muss. Grafikzeichen werden dabei ja in der Regel nicht gebraucht und der Verzicht auf Groß/Kleinschreibung ist zu verschmerzen.

Einige Demos sowie das Diskettenmagazin Metal Force gehen noch weiter und bauen sogar Rasterbars im Text mithilfe dieses Modus auf, wodurch auf einer Zeile unterschiedlich farbige Effekte für Schrift möglich werden. Ein ähnlicher Effekt ist alternativ nur mittels Rastersplit möglich. Diese Art Farbänderung von Zeichen ist aufgrund der Anforderungen an das Timing allerdings nicht von BASIC aus realisierbar, sondern kann nur mit Maschinensprache programmiert werden.


Zeichenprogrammierung[Bearbeiten | Quelltext bearbeiten]

Der C64 besitzt die Möglichkeit, eigene Zeichen zur Bildschirmdarstellung zu nutzen. Diese werden dann aber beim Ausdruck nicht richtig dargestellt, da hierfür erstens der Zeichensatz des Druckers maßgeblich ist und zweitens die eigenen, manipulierten Zeichen nur auf dem Bildschirm dargestellt werden.

Zuerst muss der Zeichensatz aus dem Zeichenspeicher bzw. Zeichen-ROM in einen freien Speicherbereich (RAM) umkopiert werden.

Um die kompletten Zeichensätze 1 und 2 zu nutzen, werden 4 KByte (2×2048 Byte) benötigt. Dafür kann der Speicherbereich 12288/$3000 bis 16383/$3FFF genutzt werden. Dieser Speicherbereich wird auch für BASIC-Programme genutzt, es kann also bei längeren Programmen bzw. vielen genutzten Variablen dazu kommen, dass der eigene Zeichensatz überschrieben wird.

Beim Umkopieren mit BASIC kommt noch hinzu, dass vorübergehend störende Interrupts unterbunden werden müssen (indirekt durch Stoppen des IRQ-auslösenden Timer A am CIA 1), da der Ein-/Ausgabe-Bereich (siehe Speicherbelegungsplan, I/O-Bereich) ausgeblendet bzw. das Zeichensatz-ROM eingeblendet werden muss und die normalen Interrupt-Routine erwartet, dass der I/O-Bereich eingeblendet ist.

POKE 56334, PEEK(56334) AND 254                      (Interrupts abstellen)
POKE 1, PEEK(1) AND 251                              (E/A-Bereich aus-, Zeichensatz-ROM einblenden)
FOR A=53248 TO 57343: POKE A-40960, PEEK(A): NEXT A  (das Umkopieren von $D000 nach $3000)
POKE 1, PEEK(1) OR 4                                 (E/A-Bereich wieder einblenden)
POKE 56334, PEEK(56334) OR 1                         (Interrupts aktivieren)

In unserem BASIC-Beispiel unten erledigt dies eine schnelle Assemblerroutine.

Die Kopie des Zeichenspeichers liegen danach im Adressbereich von 12288 bis 16383, wobei das Zeichen "@" an der Speicheradresse 12288-12295 liegt, gefolgt vom Zeichen "A" im Bereich von 12296 bis 12303 und so fort.

Um nun eigene Zeichen zu erzeugen, muss man wissen, wie ein Zeichen aufgebaut ist. Da ein Zeichen je 8 Bytes des Speichers belegt und aus einer 8×8 Punktmatrix (Pixeln) besteht, sieht das Zeichen "A" wie folgt aus, wobei zur Übersicht nur die gesetzten Bits (1) eingezeichnet wurden:

Reihe 128 064 032 016 008 004 002 001 Summe
1. 0 0 0 1 1 0 0 0 24
2. 0 0 1 1 1 1 0 0 60
3. 0 1 1 0 0 1 1 0 102
4. 0 1 1 1 1 1 1 0 126
5. 0 1 1 0 0 1 1 0 102
6. 0 1 1 0 0 1 1 0 102
7. 0 1 1 0 0 1 1 0 102
8. 0 0 0 0 0 0 0 0 000
Dieses "A" stellt sich dar als
A-non-mc.png
0 schwarz
1 grün

Um eigene Zeichen zu erschaffen, wird eine leere Tabelle benötigt und in jeder Spalte eine "1" eingetragen, an dem ein Pixel angezeigt werden soll. Die gesetzten Bits jeder Reihe werden addiert, der entsprechende Wert steht im Tabellenkopf. (Vergleiche hierzu die Punktmatrix vom Zeichen "A" in der oberen Tabelle.)

Reihe 128 064 032 016 008 004 002 001 Summe
1.
2.
3.
4.
5.
6.
7.
8.

Anschließend werden die Summen mit POKE in die entsprechenden Speicheradressen geschrieben, z.B.

FOR X=12288 TO 12295: POKE X,0: NEXT X

löscht das Zeichen "@" (macht es unsichtbar)

FOR X=12288 TO 12295: POKE X,255: NEXT X

erzeugt ein gefülltes Rechteck (Cursorzeichen an)

Auch Multicolor-Zeichen lassen sich so selbst erstellen. Dabei würde ein unmodifiziertes Zeichen "A" mit den 4 Multicolor-Farben dargestellt werden, wobei 00 die Hintergrundfarbe (53281) ist, 01=1 die Multicolor-Farbe 1 (53282), 10=2 die Multicolor-Farbe 2 (53283), 11=3 die Multicolor-Farbe 3, die aus dem Farbspeicher (55296-56295) kommt.

Reihe 128 064 032 016 008 004 002 001 Bedeutung
1. 0 0 0 1 1 0 0 0 Bits
0 1 2 0 Farben
2. 0 0 1 1 1 1 0 0 Bits
0 3 3 0 Farben
3. 0 1 1 0 0 1 1 0 Bits
1 2 1 2 Farben
4. 0 1 1 1 1 1 1 0 Bits
1 3 3 2 Farben
5. 0 1 1 0 0 1 1 0 Bits
1 2 1 2 Farben
6. 0 1 1 0 0 1 1 0 Bits
1 2 1 2 Farben
7. 0 1 1 0 0 1 1 0 Bits
1 2 1 2 Farben
8. 0 0 0 0 0 0 0 0 Bits
0 0 0 0 Farben
Dieses Multicolor-"A" stellt sich dar als
A-multicolor.png
00 schwarz
01 violett
10 gelb
11 grün

Das Erstellen von Zeichen ist mit Hilfe der Tabelle recht einfach, aber es existieren auch eine Vielzahl von Zeichensatz-Editoren, mit denen die Zeichenerstellung - nach ein wenig Einarbeitungszeit - viel schneller und bequemer von Hand geht. BASIC-Erweiterungen wie z.B. Simons' BASIC bieten BASIC-Befehle (z.B. DESIGN) für den Umgang und die Manipulation von Zeichen an.

Beispiel[Bearbeiten | Quelltext bearbeiten]

Selbstdefinierte Zeichen auf den Commodore 64 (deutsche Umlaute)

Dieses Listing bzw. Programmbeispiel besteht aus 2 Abschnitten: Zuerst die Routine, um das Zeichensatz-ROM ins RAM zu kopieren (Zeilen 10-26) und dann die Modifizierung (ab Zeile 60) der Zeichen bzw. Tasten [ , £ , ]  und   zu den deutschen Umlauten Ä, Ö, Ü, ß. Diese lassen sich dann z.B. mit POKE 1024,X (mit 27, 28, 29, 30) oder mit PRINT CHR$(X) (mit 91, 92, 93, 94) auf dem Bildschirm darstellen (können aber nicht ausgedruckt werden!).

10 REM KOPIERROUTINE
11 FOR I=0 TO 26: READ X: POKE 828+I,X: NEXT I
12 DATA 169,000,160,208,133,095,132,096 : REM LDA #0; LDY #$D0; STA 95, STY 96
13 DATA 169,000,160,224,133,090,132,091 : REM LDA #0; LDY #$E0; STA 90; STY 91
14 DATA 169,000,160,064,133,088,132,089 : REM LDA #0; LDY #$40; STA 88; STY 89
15 DATA 076,191,163 : REM JMP $A3BF
16 REM KOPIERT $D000-$DFFF -> $3000-$3FFF
20 REM ZEICHENSATZ INS RAM TRANSFERIEREN
21 POKE 56334,PEEK(56334) AND 254 : REM INTERRUPT AUS
22 POKE 1,PEEK(1) AND 251 : REM ZS ROM EINBLENDEN
23 SYS 828 : REM KOPIEREN
24 POKE 1,PEEK(1) OR 4 : REM ZS ROM AUSBLENDEN
25 POKE 56334,PEEK(56334) OR 1 : REM INTERRUPT EIN
26 POKE 53272,PEEK(53272) AND 240 OR 12 : REM $D018 SETZEN, ZEICHENSATZ IM RAM BEI $3000
60 REM DEUTSCHE UMLAUTE SETZEN
61 FOR A=12504 TO 12535: READ ZE: POKE A,ZE: POKE A+1024,255-ZE: NEXT A
62 DATA 195,024,102,126,102,102,102,000: REM AE-Ä
63 DATA 102,060,102,102,102,102,060,000: REM OE-Ö
64 DATA 102,000,102,102,102,102,060,000: REM UE-Ü
65 DATA 126,102,102,126,102,126,096,096: REM SS-ß

Speichernutzung[Bearbeiten | Quelltext bearbeiten]

In den Beispielen wird der Zeichensatz im RAM bei $3000 gespeichert, was mit dem für BASIC-Programme bzw. -Variablen genutzten Speicher kollidiert (siehe Speicherbelegungsplan). Soll der komplette BASIC-Speicher weiterhin zur Verfügung stehen, bietet es sich an, den Zeichensatz z.B. nach $C800-$CFFF zu legen. Da der VIC-II den Bildschirmspeicher im gleichen 16kByte-Segment wie den Zeichensatz erwartet, muss dann allerdings auch der Bildschirmspeicher von $0400 nach z.B. $C400 verlegt werden.

Das geht in folgenden Schritten:

  • Zeichensatz nach $C800 umkopieren
  • VIC-Segment auf $C000-$FFFF umstellen per $DD00 (CIA2): POKE 56576,148
  • Startadresse des Bildschirmspeichers (für VIC-II) umstellen und Adresse Zeichensatz setzen per $D018: POKE 53272,18
  • Startadresse des Bildschirmspeichers (für den KERNAL/BASIC) umstellen per $0288: POKE 648,196

Auch andere Bereiche können für den Bildschirmspeicher genutzt werden.

  • An $A000-$BFFF und $E000-$FFFF sind normalerweise das BASIC-ROM bzw. das KERNAL-ROM für die CPU sichtbar. Da Schreibzugriffe zum RAM durchgeleitet werden und der VIC immer das RAM sieht, können diese Bereiche trotzdem für den Bildschirmspeicher genutzt werden, solange nicht gescrollt wird oder auf andere Weise Lesezugriffe auf den Bildschirmspeicher nötig werden (in dem Fall würden plötzlich Teile der ROMs auf dem Bildschirm erscheinen).
  • Prinzipiell ist sogar der Bereich von $D000-$DFFF (I/O-Bereich) als Bildschirmspeicher nutzbar, allerdings müsste dann für Schreib- und Lesezugriffe der I/O-Bereich ausgeblendet werden, was insbesondere von BASIC aus wenig praktikabel ist.

Verwandte Themen[Bearbeiten | Quelltext bearbeiten]

Weblinks[Bearbeiten | Quelltext bearbeiten]