C 64
Zeichen-Editor

Zeichen-Editor

Bei vielen Anwendungen ist es sinnvoll mit zwei verschiedenen Zeichensätzen zu arbeiten. Dieses Programm ermöglicht Ihnen, einen eigenen Zeichensatz zu erstellen, ohne den Original-Zeichensatz zu zerstören.

Programmiert man ein Videospiel, ein Textverarbeitungsprogramm oder will man einfach nur die üblichen Bildschirmzeichen etwas interessanter gestalten, bleibt einem nichts anderes übrig, als den normalen Zeichensatz aus dem ROM herauszuholen, ins RAM zu kopieren und dann in diesem kopierten Zeichensatz »herumzuPOKEn«.

Diese Tätigkeit ist aber — ähnlich wie bei der Konstruktion von Sprites — immer wieder eine mühsame Rechnerei. Deshalb habe ich mit einen komfortablen Zeichen-Editor zusammengestellt, der jede Rechnerei abnimmt. Mit seiner Hilfe ist das Definieren eigener Grafik-Zeichen ein Kinderspiel.

Nach dem Eintippen (und Abspeichern!) läßt man das Programm mit RUN starten. Nach einer kurzen Wartezeit, während der Großbuchstaben-Zeichensatz aus dem ROM ins RAM kopiert wird (und zwar in die Speicherzellen 51200 bis 53248, der Bildschirm beginnt dann bei Adresse 50176), erscheint das Menü mit einem Zeichenfeld links unten. (Wen es interessiert: das Maschinenprogramm, das den Zeichensatz ins RAM kopiert, beginnt bei der Adresse 828, also dem Anfang des Kassettenpuffers).

In diesem Zeichenfeld kann man nun mit den Cursortasten herumwandern, Sternchen (*) malen und gegebenenfalls mit der Space-Taste wieder löschen. Ein Sternchen im Zeichenfeld bedeutet einfach, daß hier ein Bit gesetzt wird, das dann später zur Berechnung des Zeichens dient. Jedes Graphik-Zeichen besteht ja aus 8 Bytes — und genau diese 8 Bytes stellt das Zeichenfeld symbolisch dar.

Taste 1: Berechnung des selbsterstellten Zeichens

Sobald man sein Zeichen gemalt hat, muß es berechnet werden. Hierfür ist im Menü der Programmpunkt 1 vorgesehen. Drückt man diese Taste, so wird gefragt: »Welche Taste?« Man drückt nun die Taste, der man das soeben erstellte Zeichen zuordnen möchte, und genau das Zeichen, das zu der gedrückten Taste gehört, wird nun durch das im Zeichenfeld definierte Zeichen ersetzt.

Ein Beispiel: Füllt man das Zeichenfeld ganz mit Sternchen aus, läßt das Feld berechnen und drückt dann die Taste »A«, so wird überall auf dem Bildschirm dort, wo eben noch ein »A« gestanden hat, ein reverses Quadrat erscheinen. Nette Spielchen kann man zum Beispiel mit der Space-Taste machen: dann wird nämlich überall da, wo ein Space auf dem Bildschirm ist (und das sind ja üblicherweise eine ganze Menge), das eben definierte Zeichen gedruckt. Auf diese Weise kann man den Bildschirm etwas interessanter gestalten.

Taste 2:

Sobald das neue Zeichen berechnet und ausgedruckt ist, kann man wieder beliebig im Zeichenfeld herumhantieren. Will man jedoch ein ganz anderes Zeichen konstruieren, so drückt man einfach Taste 2, und flugs ist das Zeichenfeld wieder »sauber« — das gerade definierte Zeichen wird dabei natürlich nicht gelöscht. Zusätzlich zum reinen Konstruieren von Grafik-Zeichen gibt es jedoch auch noch andere Programmfunktionen:

Taste 3: ROM-Zeichen auslesen

Mit Hilfe dieses Programmpunktes kann man sich ein beliebiges Zeichen aus dem ROM-Zeichensatz herholen. Hierbei wird das gewünschte Zeichen in das Zeichenfeld hineingePOKEt und die Daten dieses Zeichens rechts daneben ausgegeben. Selbst wenn Sie also den Buchstaben »A« als ein reverses Quadrat definiert haben sollten, so erscheint — sofern Sie Taste 3 und danach »A« drücken — auf dem Zeichenfeld das gute, alte »A« wieder (denn im ROM-Zeichensatz bleibt natürlich alles beim alten).

Taste 4: Eigene Zeichen auslesen

Natürlich können Sie nicht nur Zeichen aus dem ROM holen, sondern auch aus dem kopierten Zeichensatz, in dem Sie bisher munter herummanipuliert haben. Sie haben zum Beispiel aus dem »O« ein Smiley-Gesicht gemacht und wollen er gerne in vergrößerte Form wiedersehen, um etwa Korrekturen oder ähnliches vorzunehmen — bitte sehr! Drücken Sie die Taste 4, dann ein »O« und Ihr eigenes Zeichen steht im Zeichenfeld — samt den dazugehörigen Daten rechts nebenan.

Taste 8: Restore

Nun kann es vorkommen, daß Sie genug haben von Ihren eigenen Zeichen. Eigentlich wollten Sie jetzt ganz gern wieder die alten, »normalen« Zeichen anstelle der vielen Smiley-Gesichter und reversen Quadrate sehen.

Wenn Sie Taste 8 drücken, wird einfach der ROM-Zeichensatz wieder ins RAM kopiert; und da dieser Teil in Maschinensprache geschrieben ist, geht das ziemlich schnell vonstatten.

Will man übrigens nur ein einziges Zeichen wieder in den Ursprungszustand versetzen, so geht man am besten so vor: Man holt sich das (alte) Zeichen aus dem ROM (mit Taste 3) und läßt es mit Taste 1 wieder in den neuen Zeichensatz hineinkopieren. Mit dieser Methode kann man zum Beispiel auch einen Art Geheimcode entwickeln: Man tauscht einfach die Zeichen im ROM untereinander aus (statt eines A ein B, statt eines U ein X und so weiter). Nach einigem Umdefinieren bekommt man einen ganz eigenartigen Buchstabensalat auf dem Bildschirm.

Taste 9: Bild zeichnen

Nehmen wir an, Sie haben aus den etwas eintönigen Grafikzeichen des C 64 interessantere Zeichen zusammengebastelt: Leitern, Mauerwerke, Treppen und ähnliches. Sie würden aber ganz gerne sehen, wie diese Zeichen im Zusammenhang wirken; wie es etwa aussieht, wenn ein Leiterstück unter dem anderen steht, daneben ein Mauerwerk und so weiter. Dazu drücken Sie Taste 9 und können jetzt mit Ihren selbsterstellten Zeichen den ganzen Bildschirm vollmalen. Wenn Sie wieder ins Menü zurückwollen, drücken Sie einfach »Cursor Home« (steht auch auf dem Bildschirm).

Ein Hinweis zu diesem Programmpunkt: Der Cursor ist beim Bildmalen aus Gründen der Programmiervereinfachung nicht immer sehr gut sichtbar, manchmal »legt« er sich sogar ab, wenn er schnell über den Bildschirm bewegt wird. Das sollte Sie aber nicht weiter stören, schließlich ist diese Programmfunktion nur als Hilfe gedacht für einen schnellen Überblick.

Tasten 6 und 7: Abspeichern und Laden

Wenn Sie eigene Zeichen definiert haben, möchten Sie diesen Zeichensatz vielleicht abspeichern, um ihn später noch einmal verwenden zu können. Drücken Sie einfach Taste 6 und geben einen Dateinamen ein — der kopierte Zeichensatz mit Ihren selbsterstellten Zeichen wird nun auf Diskette gespeichert (nur der Großbuchstaben-Zeichensatz). Er nimmt dabei genau 44 Blöcke auf der Diskette ein. Mit Taste 7 können Sie schließlich einen abgespeicherten Zeichensatz wieder laden (der aktuelle Zeichensatz wird dabei überschrieben).

Sollten Sie einmal versehentlich 6 oder 7 gedrückt haben, so kommen Sie wieder ins Menü zurück, wenn Sie »N« + »RETURN« eingeben!

Taste 5: Daten eingeben

Eine letzte Programmfunktion bietet die Eingabe von Daten, die ein Zeichen definieren. Dies ist eine Alternative zum Konstruieren eines Zeichens im Zeichenfeld. Zu beachten ist, daß nur Zahlen von 0 bis 255 eingegeben werden können (dies wird allerdings vom Programm sichergestellt; negative und Zahlen größer als 255 werden vom Programm nicht angenommen). Nach Eingabe des 8. Bytes erscheint dann die übliche Frage »Welche Taste!« und nach Eingabe dieser Taste das bekannte Sternchenbild auf dem Zeichenfeld.

Die Erklärung der Taste 0 (Programmende) erübrigt sich wohl. Zu erwähnen ist hierbei nur, daß der kopierte Zeichensatz auch nach Beendigung des Programms weiterhin zur Bildschirmgestaltung benutzt wird; auch der Bildschirm selbst sitzt weiterhin an der Adresse 50176 (und nicht wie üblich, bei 1024). Wollen Sie also wieder einen ganz gewöhnlichen Bildschirm mit ganz gewöhnlichen Grafik-Zeichen haben, so geht das am einfachsten nur durch Aus- und Anschalten des Computers (auch die Run/Stop-Restore-Taste wurde im Programm blockiert).

Eine kleine Bemerkung am Rande zum eigenen Programmieren: Sehr oft kommt es ja vor, daß man einen Satz von einem Programm aus mitten in dem Bildschirm hineinschreiben will. Üblicherweise geht man so vor, daß man die Cursor-Steuerzeichen in die Print-Zeile so oft einfügt, bis der gesuchte Platz gefunden ist. Für Programmlistings ist das etwas unübersichtlich. Es gibt aber noch eine andere Methode, die ich in diesem Programm benutzt habe (und zwar am Anfang fast jedes Programmpunktes): will man zum Beispiel einen Buchstaben in die 14. Zeile, 5. Spalte schreiben, so gibt man zunächst POKE 214,13
ein, danach ein PRINT-Kommando und dann PRINTTAB(4)»X«.

In Adresse 214 steht nämlich die Zeilenposition des Cursors. Um diese richtig einzusetzen, muß man allerdings noch einen PRINT-Befehl nachschicken: Cursor in Zeile 13 + PRINT-Befehl ergibt dann Zeile 14!

(Volker Bühn / gk)

Programmablauf-Plan:

Zeile Beschreibung
1-7 Programmname und Adresse des Autors
10-30 Einlesen und Aufruf der Maschinenroutine, die den Zeichensatz vom ROM ins RAM an die Adresse 51200 kopiert
40-140 Menü und Zeichenfeld werden gezeichnet
300-460 Abfrage der Tastatur:
1. Zeichnen im Zeichenfeld
2. Aufruf der einzelnen Programmfunktionen
500-520 Unterprogramm zum Printen des Zeichenfeldes
1000-1530 Die einzelnen Unterprogramme zur Steuerung des Cursors, der Space-Taste und des Sternchens, um im Zeichenfeld ein Zeichen zu erzeugen.
2000-8040 Einzelne Programmfunktionen:
2000-2120 Berechnung eines erstellten Zeichens; Zuordnung dieses neuen Zeichens in den Zeichensatz; Printen der Daten des Zeichens
3000-3150 Ausgabe eines Zeichens aus dem ROM- Zeichensatz; Printen der Daten dieses Zeichens
4000-4150 Ausgabe eines Zeichens aus dem kopierten Zeichensatz, Printen der Daten dieses Zeichens
5000-5050 Neuer Bildschirm zum Zeichen mit dem selbsterstellten Zeichensatz
Die Zeile 5050 dient zur Cursor- Steuerung und Ausdrucken eines Zeichens auf dem Bildschirm
6000-6120 Abspeichern eines selbsterstellten Zeichensatzes auf Diskette
7000-7120 Laden eines Zeichensatzes von Diskette
8000-8040 Eingabe von 8 Bytes zur Definition eines Zeichens
In 8030 wird sichergestellt, daß keine Zahl größer als 8 Bit ist
10000-10040 POKEn des Maschinenprogramms nach 828
10100-10150 DATA-Zeilen des Maschinenprogramms (in Hexcodes)

Wichtige Programmzeilen:

Erstellung eines eigenen Zeichens:

2050-2070 Hier werden die Bytes des selbsterstellten Zeichens aus dem Zeichenfeld gelesen, berechnet und in B(1) bis B(8) abgelegt.
2080 Die Bytes des Zeichens werden nun in die Stelle des Zeichensatzes gePOKEt, die der Benutzer durch die Tastenabfrage definiert hat.
ROM-Zeichen:
3050 Verhindern von Interrupts
3060-3070 lm ROM-Zeichensatz wird das vom Benutzer festgelegte Zeichen in B(1) bis B(8) sowie C(1) bis C(8) abgelegt
3080 Zulassen von Interrupts
3090-3110 Die Bytes B(1) bis B(8) werden in das Zeichenfeld in Form von Sternchen (*) hinein gePOKEt
Eigenes Zeichen holen:
4060-4070 wie 3060-3070, nur daß im kopierten Zei chensatz gesucht wird
4080-4100 wie 3090-3110
Bild zeichnen:
5050 In den Adressen 209,210 und 211 steht die aktuelle Cursorposition. Dies verhindert, daß der Cursur auf den Bildschirm wie ein normales Zeichen gePRINTet wird.

Liste der wichtigsten Variablen

Z Position des anfänglichen Cursors im Zeichenfeld (ist immer 50776)
PU$
NO$
Strings, um Punkte beziehungsweise Leerstellen zu PRINTen
A Variable, die die aktuelle Cursorposition im Zeichenfeld angibt
G$ Stringvariable zur Tastaturabfrage
B(1) bis B(8)
C(1) bis C(8)
Arrays, die die 8 Bytes eines Zeichens enthalten
G Bildschirmcode eines Zeichens
C Cursorposition beim Bildzeichnen
N$ Name einer einzulesenden beziehungsweise abzuspeichernden Datei
A$ Hexcode aus den DATA-Zeilen
HN,LN Hi-Nibble beziehungsweise Lo-Nibble von A$
I,J,K Schleifenvariable
1 rem ************************
2 rem * zeichen-editor/c64   *
3 rem * von    volker buehn  *
4 rem *        b2,14         *
5 rem *        6800 mannheim *
6 rem * am     6.7.1984      *
7 rem ************************
10 print"{clr}":print:print"  bitte warten!":restore:poke657,128:poke792,134:poke793,234
20 gosub10000:rem einlesen der                            maschinenroutine
30 sys828    :rem aufruf derselben
40 poke53280,0:poke53281,0:print"{clr}        {rvon}selbsterstellte zeichen{rvof}"
50 print:print"1 zeichen berechnen 6 abspeichern"
60 print"2 neues zeichen     7 laden"
70 print"3 rom-zeichen       8 restore"
80 print"4 zeichen holen     9 bild zeichnen"
90 print"5 datas eingeben    0 programmende"
100 z=50776
110 pu$="........                               "
120 no$="                            "
130 gosub510:iffl=1thenreturn
140 a=z:pokea,peek(a)or128
300 getg$:ifg$=""then300
310 ifg$="{up}"thengosub1020
320 ifg$="{down}"thengosub1120
330 ifg$="{rght}"thengosub1220
340 ifg$="{left}"thengosub1320
350 ifg$=" "thengosub1420
360 ifg$="*"thengosub1520
370 ifg$="1"thenpokea,peek(a)and127:goto2000
380 ifg$="2"thenrun100
390 ifg$="3"then3000
400 ifg$="4"then4000
405 ifg$="5"then8000
410 ifg$="6"then6000
420 ifg$="7"then7000
430 ifg$="8"then30
440 ifg$="9"then5000
450 ifg$="0"thenprint"{clr}":end
460 goto300
500 rem feld zeichnen
510 print"{home}":fori=1to14:print:next
520 fori=1to8:printpu$:next:return
1000 :
1010 rem cursor nach oben
1020 ifpeek(a-40)=32thenreturn
1030 pokea,peek(a)and127:a=a-40:pokea,peek(a)or128:return
1100 :
1110 rem cursor nach unten
1120 ifpeek(a+40)=32thenreturn
1130 pokea,peek(a)and127:a=a+40:pokea,peek(a)or128:return
1200 :
1210 rem cursor nach rechts
1220 ifpeek(a+1)=32thenreturn
1230 pokea,peek(a)and127:a=a+1:pokea,peek(a)or128:return
1300 :
1310 rem cursor nach links
1320 ifpeek(a-1)=32thenreturn
1330 pokea,peek(a)and127:a=a-1:pokea,peek(a)or128:return
1400 :
1410 rem space-taste im zeichenfeld
1420 ifpeek(a+1)=32thenpokea,174:return
1430 pokea,46:a=a+1:pokea,peek(a)or128:return
1500 :
1510 rem "*" im zeichenfeld
1520 pokea,42:ifpeek(a+1)=32thenpokea,peek(a)or128:return
1530 a=a+1:pokea,peek(a)or128:return
2000 rem *******************
2001 rem *zeichen berechnen*
2002 rem *******************
2010 poke214,14:print:printtab(14)"welche taste? ";
2020 getg$:ifg$=""then2020
2030 printg$:g=peek(z+28)*8:k=0:a=z
2040 printtab(10);no$:printtab(10);no$:print"{up}{up}{up}{up}"
2050 forj=1to8:fori=a+7toastep-1
2060 ifpeek(i)=42thenb(j)=b(j)+2^k
2070 k=k+1:nexti:a=a+40:k=0:nextj
2080 fori=51200+gto51207+g:k=k+1:pokei,b(k):next
2090 printtab(10);no$
2100 printtab(15);b(1);b(2);b(3);b(4)
2110 printtab(15);b(5);b(6);b(7);b(8)
2120 poke(z+11),g/8:fori=1to8:b(i)=0:next:fl=0:goto140
3000 rem **************
3001 rem * rom-zeichen*
3002 rem **************
3010 gosub510
3020 poke214,14:print:printtab(14)"welche taste? ";
3030 getg$:ifg$=""then3030
3040 k=0:a=z:printg$:g=peek(z+28)*8
3050 poke56334,peek(56334)and254:poke1,peek(1)and251
3060 fori=53248+gto53255+g
3070 k=k+1:b(k)=peek(i):c(k)=b(k):next:k=0
3080 poke1,peek(1)or4:poke56334,peek(56334)or1
3090 forj=1to8:fori=7to0step-1
3100 ifb(j)>=2^ithenb(j)=b(j)-2^i:poke(a+7-i),42
3110 nexti:a=a+40:nextj
3120 print"{up}"tab(10);no$
3130 printtab(15);c(1);c(2);c(3);c(4)
3140 printtab(15);c(5);c(6);c(7);c(8)
3150 fori=1to8:b(i)=0:next:goto140
4000 rem *************************
4001 rem * eigenes zeichen holen *
4002 rem *************************
4010 gosub510
4020 poke214,14:print:printtab(14)"welche taste? ";
4030 getg$:ifg$=""then4030
4040 printg$:g=peek(z+28)*8:k=0:a=z
4050 iffl=1then4080
4060 fori=51200+gto51207+g
4070 k=k+1:b(k)=peek(i):c(k)=b(k):next:k=0
4080 forj=1to8:fori=7to0step-1
4090 ifc(j)>=2^ithenc(j)=c(j)-2^i:poke(a+7-i),42
4100 nexti:a=a+40:nextj
4110 print"{up}"tab(10);no$
4120 iffl=1then2080
4130 printtab(15);b(1);b(2);b(3);b(4)
4140 printtab(15);b(5);b(6);b(7);b(8)
4150 poke(z+11),g/8:fori=1to8:b(i)=0:next:goto140
5000 rem ****************
5001 rem *  bild malen  *
5002 rem ****************
5010 print"{clr}";:poke53280,0:poke53281,1:poke646,0:poke650,128
5020 print"[home=zurueck]"
5030 poke204,0:getg$:ifg$=""then5030
5040 ifg$="{home}"thenpoke204,1:poke646,6:poke650,0:goto40
5050 c=peek(209)+peek(210)*256+peek(211):pokec,peek(c)and127:printg$;:goto5030
6000 rem *************
6001 rem * speichern *
6002 rem *************
6010 print"{clr}":print:print"       speichern des zeichensatzes"
6020 print:print"(input 'n' , wenn zurueck)"
6030 print:print:print"  name der datei?"
6040 inputn$
6050 ifn$="n"then40
6060 open2,8,2,n$+",s,w"
6070 close1:open1,8,15:input#1,oa:ifoa<>0then6010
6080 fori=51200to53248
6090 s%=peek(i)
6100 print#2,s%
6110 nexti
6120 close2:goto40
7000 rem *********
7001 rem * laden *
7002 rem *********
7010 print"{clr}":print:print"       laden eins zeichensatzes"
7020 print:print"(input 'n', wenn zurueck)"
7030 print:print:print"  name der datei?"
7040 inputn$
7050 ifn$="n"then40
7060 open2,8,2,n$+",s,r"
7070 close1:open1,8,15:input#1,oa:ifoa<>0then7010
7080 fori=51200to53248
7090 input#2,s%
7100 pokei,s%
7110 nexti
7120 close2:goto40
8000 rem ******************
8001 rem * datas eingeben *
8002 rem ******************
8010 print"{clr}":print:print" daten fuer ein zeichen eingeben"
8020 fori=1to8:printi". byte":inputb(i):c(i)=b(i)
8030 ifb(i)>255orb(i)<0theni=i-1
8040 next:fl=1:gosub40:goto4010
10000 rem ****************************
10001 rem * maschinenroutine-eingabe *
10002 rem ****************************
10010 fori=0to58:reada$
10020 hn=(asc(left$(a$,1))-48)*16:ifhn>144thenhn=hn-112
10030 ln=asc(right$(a$,1))-48:ifln>9thenln=ln-7
10040 hn=hn+ln:poke(828+i),hn:next:return
10100 data78,a9,31,85,01,a9,00,85,64,a9
10110 datad0,85,63,a9,c8,85,65,a2,10,a0
10120 data00,b1,62,91,64,c8,d0,f9,e6,63
10130 datae6,65,ca,d0,f2,a9,37,85,01,58
10140 dataa9,12,8d,18,d0,a9,94,8d,00,dd
10150 dataa9,c4,8d,88,02,20,44,e5,60
Listing »Zeichen-Editor«
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →