Sokoban-Zeichensatz
Umgang mit Zeichensätzen
Umgang mit Zeichensätzen

Neue Zeichensätze erstellt man am besten mit einem Zeichensatz-Editor (zum Beispiel mit dem C64 Studio), das ist bequemer und man kann bei vielen zu ändernden Zeichen leichter den Überblick bewahren. Der Erfolg vieler C64-Spiele beruht auf speziellen Zeichensätzen, nachvollziehbar z.B. beim Spiel "Uridium", wie es auf dieser Seite sehr schön beschrieben steht.

Für manche Zwecke reicht es aber, nur einige wenige Zeichen zu verändern. So etwas kann man dann ganz leicht auch mit TSB und den Befehlen MEM und DESIGN erledigen. Hier ein Beispiel, in dem nur ein einziges verändertes Zeichen verwendet wird, um einen bestimmten Effekt zu erzeugen:

Color Combiner

Das Programm (auf der TSB-Disk enthalten) zeigt, wie man zwei Farben so miteinander kombinieren kann, dass im Auge des Betrachters scheinbar eine neue Farbe entsteht. In diesem Bild vermischen sich rot und braun zu einem schönen Rotbraun. Das liegt daran, dass auf der großen rotbraunen Fläche die beiden ausgewählten Farben (2, rot, und 9, braun) durch das Muster des zur Anzeige verwendeten Zeichens ganz dicht beieinander liegen.

Hier der entsprechende Definitionsabschnitt im Code des Programms "colorcombi.dmo":


1020 design 2,$e800+8*96
1021 @b.b.b.b.
1022 @.b.b.b.b
1023 @b.b.b.b.
1024 @.b.b.b.b
1025 @b.b.b.b.
1026 @.b.b.b.b
1027 @b.b.b.b.
1028 @.b.b.b.b
Das Zeichen mit dem Bildschirm-Code 96 (ein nicht
von der Tastatur aus erreichbares Leerzeichen)
erhält hiermit ein ganz enges Schachbrettmuster
mit Ein-Pixel-Abstand.

Die Zeilennummerierung wie sie hier zu sehen ist,
ist empfehlenswert: Die @-Definitionszeilen gehen
von xxx1 bis xxx8, weshalb man nicht mal eben
eine Zeile vergisst oder falsch einordnet.

Die Startadresse $E800 ist die Adresse des Groß-
Klein-Zeichensatzes (CSET 1).

Kommen wir zu TSB-spezifischeren Tipps: Es gibt den Multicolor-Modus auch für Textzeichen, worauf die meisten der oben angesprochenen Spiele beruhen. Mit dem Text-Multi-Modus teilt man seinen Zeichensatz in zwei unabhängige Abteilungen: normal gefärbte Chars (zwei Farben pro Zeichen, eine davon generell für den ganzen Screen) und vierfarbige Chars (drei Farben davon für den ganzen Screen, eine individuell, ganz ähnlich wie bei den Sprites). Die individuelle Farbe wird aber im folgenden "Rasterbar"-Beispiel auch erst einmal nur da gesetzt, wo eine Ausgabe überhaupt erfolgt (verändert das Color-Ram ab $D800 nur an den Stellen, wo die Ausgabe stattfindet).

Für Multicolor-Zeichen brauchen wir in TSB nur drei weitere Befehle neben DESIGN. Für die Aktivierung des Multi-Modus den Befehl MULTI ON und für die Einfärbung der Zeichen BCKGNDS f0,f1,f2,x sowie COLOUR,f3. Folgende Zuordnung tritt nach MULTI inkraft:

Farbe : Bitmap-Muster : Befehl  : Hinweis
      :               :
f0    :      %00      : BCKGNDS : $D021, Hintergrundfarbe (plus 128 als Flag für MULTI)
f1    :      %01      :         : $D022, generelle Farbe 1
f2    :      %10      :         : $D023, generelle Farbe 2
f3    :      %11      : COLOUR  : dies ist die "individuelle" Farbe (aus dem Color-Ram).

Die individuelle Farbe beeinflusst schließlich den Multi-Modus. Ist sie in den Farben 0 bis 7 kodiert, werden die zugehörigen Zeichen im normalen Text-Zweifarbmodus angezeigt, die verschiedenen Graus, Braun und die hellen Farben bleiben dann außen vor. Liegt ihr Wert zwischen 8 und 15, "verwandeln" sich die Zeichen in vielfarbige Chars, allerdings beim Bitmuster %11 auch nur in den Farben von 0 bis 7 (die Farben werden dargestellt wie tatsächliche Farbe = Farbwert AND 7). Die mit BCKGNDS gewählten Farben für die genannten Bitmuster %01 und %10 werden aktiviert.

Beispiel. Der folgende, wie ein Rasterbar aussehende Streifen wird mit den darunter stehenden Befehlen erzeugt (Ausgabe in Z. 25 und 30):

Rasterbar
1100 proc rasterbar

1120 design 3,$e000+8*27:" key [
1121 @....
1122 @bbbb
1123 @bbbb
1124 @....
1125 @cccc
1126 @cccc
1127 @....
1128 @dddd

1140 design 3,$e000+8*29:" key ]
1141 @dddd
1142 @....
1143 @cccc
1144 @cccc
1145 @....
1146 @bbbb
1147 @bbbb
1148 @....

1185 end proc
10 mem: cset 0: bckgnds 128+12,9,8,x: colour,10
15 multi on
20 rasterbar
25 print at(0,4) dup("[",40);
30 print dup("]",40): colour,0
35 do null
40 end

In PROC rasterbar werden die beiden Zeichen "[" und "]" umdefiniert zu vierfarbigen Multicolor-Zeichen. In der Aufrufroutine (Z. 10) lautet die Color-Ram-Farbe hier f3=10. Das ist mehr als 7, also tritt der Multicolor-Modus in Kraft und es wird auf dem Bildschirm an allen Stellen mit dem Buchstaben D in den Definitionszeilen rot angezeigt (10 AND 7 = 2, rot). Der Buchstabe B erhält f1 zugewiesen (9, braun) und Buchstabe C ist f2 (8, orange). Die Punkte in der Definition erhalten die generelle Hintergrundfarbe f0, hier 12 (mittelgrau). Ändert man aber f3 auf einen Wert kleiner als 8, z.B. zu 6, ist der ganze Zauber vorbei und alle gesetzten Pixel sind (in dem Fall) nur noch blau (Farbe 6).


Solange es um nur wenige Zeichen geht, ist gegen das Vorgehen per MEM und DESIGN nichts einzuwenden, denn vom so wertvollen freien Basic-Speicher geht dann nicht viel verloren.

Sokoban-Zeichensatz

Sollten es aber mehr Zeichen werden (und damit kommen wir zum Eingangsbild dieses Tipps-Abschnitts, dem Sokoban-Zeichensatz), dann fressen die DESIGN-Zeilen den Basic-Speicher auf und eine Zeichensatzdefinition auf diesem Wege lohnt sich nicht mehr.

Also besser einen Zeichenssatzeditor verwenden? Nicht unbedingt. Man ändert nur die Vorbereitungen zu so einem Programm wie dem "Sokoban". Es reicht ja, wenn im eigentlichen Programm die geänderten Zeichen irgendwie zur Verfügung gestellt werden können. Geht das?

Ja, da haben wir gleich mehrere Möglichkeiten. Vorausgesetzt, uns stehen die geänderten Zeichen als Datei zur Verfügung, können wir sie auch zu unserem Programm hinzuladen.

1. Möglichkeit:

LOAD "Zeichen",dr,0,Zieladresse

Der Wert von DR (DR für "Drivenummer") ist egal und wird von USE bestimmt. Der Umfang eines Datensatzes ist bei LOAD beliebig.

2. Möglichkeit:

POKE $b21c,$e8: POKE $b218,$ec: SCRLD 1,dr,2,"zeichen": POKE $b21c,$04: POKE $b218,$d8

Die POKEs patchen die TSB-Befehle SCRLD und SCRSV, um beliebige Quell- bzw. Zieladressen für zweimal 1 KB große Datensätze verwenden zu können (9 Blöcke auf Disk). Hier werden die Adressen $E800 und $EC00 angepeilt (und nach dem Laden wieder auf ihre Defaultwerte zurückgesetzt, $0400 und $D800). Die Zeichendaten werden also an die Position des Groß-Klein-Zeichensatzes geladen (der durch CSET 1 eingestellt wird).

3. Möglichkeit:

POKE $b1c1,8: SCRLD 1,dr,3,"zeichen": POKE $b1c1,32 (Zieladresse: $E000)

In diesem Fall wirkt sich der POKE auf die Anzahl der einzulesenden Bytes aus. Der Wert 8 lädt acht Pages, das sind 2 KB, also der Umfang z.B. des Groß-Klein-Zeichensatzes (9 Blöcke auf Disk). Im Unterschied zu Möglichkeit 2 müssen die Daten hier nicht extra mit SCRSV vorbereitet werden, man kann direkt beliebige Zeichensätze benutzen. Der Standardwert an Speicherstelle $B1C1 ist 32.

Da der Umfang der Zeichensatzdaten beim Sokoban-Projekt nicht so riesig war, haben wir dort die erste Alternative eingesetzt, um den geänderten Zeichensatz einzubinden.

90 if display=$0400 then mem: cset 1:
   print "wait...":
   load "sokoban.chr",0,0,$ec00

DISPLAY liefert die aktuelle Adressse des Textbildschirms. Lautet sie anders als $0400 (dezimal 1024), ist der veränderte Zeichensatz bereits geladen und aktiviert und der Rest der Zeile braucht nicht noch einmal ausgeführt zu werden. Beim ersten Mal allerdings kopiert TSB mit MEM den ROM- (Doppel-) Zeichensatz nach Position $E000 (Länge: 4 KB von $E000 bis $EFFF), wo er jetzt frei verändert werden kann. Der LOAD-Befehl lädt hier die veränderten 26 Zeichen - das sind 208 Bytes - nach $EC00, das liegt im Bereich des Groß-Klein-Zeichensatzes an der Position der invertierten Kleinbuchstaben. Im Sokoban-Programm werden also die invertierten Kleinbuchstaben dazu verwendet, den Spielplan und die Spielfiguren darzustellen (siehe Bild).

Erstellt wurden die Zeichen dennoch mit TSB-Befehlen, wie oben beschrieben, allerdings in einem Extraprogramm, das nur dazu da war, die Zeichen zu definieren und abzuspeichern. Sie wurden dabei nicht an ihre eigentliche Position gelegt ($E000), sondern an eine zum Abspeichern mit PRINT# leichter zugängliche Stelle, nach $6000. Das geht ganz einfach, indem man beim DESIGN-Befehl die Basisadresse entsprechend anpasst: b=$6000: DESIGN 2,b+8*Bildschirm-Code.

Hier als Beispiel der Code für das letzte veränderte Zeichen darin: "y", Bildschirm-Code (128+) 25. (Die 128 haben wir hier in der Beschreibung addiert, weil die Basisadresse des Groß-Klein-Zeichensatzes bei $6800 liegt, wir hier aber die ersten 128 Zeichen überspringen und erst ab $6C00 zählen, wo die invertierten Kleinbuchstaben liegen. Das kleine invertierte "y" ist tatsächlich Bildschirm-Code 128+25=153.)

900 B=$6C00
999 :
1250 DESIGN 2,B+8*25
1251 @........
1252 @.BB..BB.
1253 @.B.BBBB.
1254 @.BB..BB.
1255 @.BBBB.B.
1256 @.BBBB.B.
1257 @.B...BB.
1258 @........
1259 : 

Das ganze Ergebnis der Definitionszeilen landete hier also an der Adresse $6C00 und reichte bei 26 Zeichen bis $6CCF (208 Bytes, 1 Diskblock). Mit einer kleinen FOR..NEXT-Schleife waren die Bytes schnell abgespeichert. In "Sokoban" reichte dann die oben wiedergegebene Zeile 90 zum Einbinden der neuen Zeichen, wie hier noch einmal zu sehen:

Sokoban-Chars

So ein Vorgehen kann man natürlich auch auf einen ganzen Zeichensatz ausdehnen und dann damit auch solche atemberaubenden Szenen wie die folgende aus dem Spiel "Mayhem in Monsterland" präsentieren.

Den Zeichensatz von "Mayhem in Monsterland" haben wir in den Beispieldateien zum PC-Programm CharPad gefunden. Alles andere in unserem Bild hat TSB erledigt:

Mayhem in Monsterland

Im Folgenden der dazugehörige Programmabschnitt, wobei der Zeichensatz und der Bildschirm- und Farbram-Inhalt in den Zeilen 1130 und 1140 nachgeladen werden. Im Color-Ram-Bereich liegen hier tatsächlich individuelle Farben, die den Multi-Modus je nach Bedarf aktivieren (die Wolken und Sterne sind z.B. im Standard-Textmodus). Eine generelle $D800-Farbe gibt es nicht. Das Programm befindet sich auf der TSB-Disk unter dem Namen "mayhem.dmo". Bei Interesse können wir auch das TSB-Programm, das die beiden Nachladedateien erzeugt hat, zum Download anbieten.

1100 proc mayhem
1110 mem: cset 1: bckgnds $83,10,9,x
1120 multi on
1125 poke $b21c,$e8:poke $b218,$ec
1130 scrld 1,dr,2,"mayhem3a90.fnt"
1135 poke $b21c,$cc:poke $b218,$d8
1140 scrld 1,dr,2,"mayhem.scr"
1145 poke $b21c,$04
1150 do null
1160 nrm
1170 end proc

In diesem Fall haben wir sowohl den Zeichensatz als auch den Bildschirminhalt mit SCRSV abgespeichert. Diese beiden Zeilen reichten dafür aus:

POKE $b21c,$68: POKE $b218,$6c: SCRSV 1,dr,2,"mayhem.fnt,p,w": POKE $b21c,4: POKE $b218,$d8

für den Zeichensatz an Adresse $6800 und

POKE $b21c,$cc: SCRSV 1,dr,2,"mayhem.scr,p,w": POKE $b21c,4

für den Bildschirminhalt wie im Bild zu sehen.

Man kann also in TSB Zeichensätze sehr flexibel handhaben.