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:

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 blau zu einem eindeutigen Violett. Das liegt daran, dass auf der großen violetten Fläche die beiden ausgewählten Farben (2, rot, und 6, blau) 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. Dieser wie ein Rasterbar aussehende Streifen wird mit den folgenden Befehlen erzeugt (Ausgabe in Z. 25 und 30):
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.

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: (Laden mit Zieladress-Angabe)
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: (SCRLD mit Adress-Patch)
POKE $b21c,$e8: POKE $b218,$ec: SCRLD 1,dr,2,"zeichen": POKE $b21c,$04: POKE $b218,$d8
Die beiden 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 (8 Pages, ergibt 9 Blöcke auf Disk). Hier werden durch die POKEs 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 TSB-MEM-Position des Groß-Klein-Zeichensatzes geladen (der durch CSET 1 eingestellt wird).
3. Möglichkeit: (SCRLD mit Sekundäradresse für fortlaufende Daten)
POKE $b1c1,8: SCRLD 1,dr,3,"zeichen": POKE $b1c1,32 (hier an Standard-Zieladresse $E000)
In diesem Fall wirkt sich der POKE nur 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 bereits vorhandene 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:
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:

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". Hier ein Link auf den Ausschnitt aus dem TSB-Programm, das die Vorlage für beiden Nachladedateien (".fnt" und ".scr") erzeugt hat. Eingebunden werden sie so:
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
POKE $b21c,$68: POKE $b218,$6c: SCRSV 1,dr,2,"mayhem.fnt,p,w": POKE $b21c,4: POKE $b218,$d8
POKE $b21c,$cc: SCRSV 1,dr,2,"mayhem.scr,p,w": POKE $b21c,4
In diesem Fall haben wir den Zeichensatz mit einem nach Möglichkeit 2 gepatchten SCRSV abgespeichert. Der Bildschirminhalt wurde schließlich mit einem ebenso gepatchten SCRSV gesichert. Diese beiden Zeilen reichten dafür aus. Oben für den Zeichensatz (lag hier an $6800) und die zweite Zeile für den Bildschirminhalt (an $cc00) wie im Bild zu sehen.
Man kann also in TSB Zeichensätze sehr flexibel handhaben.