1. Einführung in BASIC

 

BASIC (Beginners Allpurpose Simple Instruction Code) ist als Lernsprache für Studenten und Schüler entwickelt worden. BASIC steht dabei auch für „grundlegend“, das englische Wort hierfür „basic“. Dies bedeutet: BASIC ist schnell und einfach zu lernen, weil es nur die Dinge beinhaltet, die ein Programmierer unbedingt benötigt, wie z.B. Variablen, Zeichenketten (Strings), Datenfelder (Arrays), einfache Schleifen (FORNEXT) und einige Sprungbefehle (GOTO, GOSUB). Konstrukte, die von C her bekannt sind, wie z.B. do...while, switchcase, aber auch Zeiger (wie z.B. char*) gibt es in BASIC genau so wenig, wie z.B. dynamische Speicherreservierung mittels malloc(). Diese Einschränkungen gibt es in einigen modernen BASIC-Versionen nicht mehr, der Vorteil des Ur-BASIC ist jedoch, dass der BASIC-Interpreter so wenig Speicher benötigt, dass er quasi auf jedem System lauffähig ist. Und genau deshalb wurde auch auf den ersten Heimcomputern oder später sogar auf Taschenrechnern stets ein BASIC-Interpreter integriert.

Der C64 ist so ein Heimcomputer, der BASIC mit dem sogenannten BASIC-ROM gleich mitliefert. Im Endeffekt ist das BASIC-ROM einfach ein Baustein auf der C64-Platine, der ein ausführbares Maschinenprogramm enthält. Dieses Programm steht gleich beim Start des C64 zur Verfügung und enthält eben den BASIC-Interpreter, der es dem Benutzer erlaubt, Programme auszuführen. Das BASIC-ROM alleine wäre aber ziemlich hilflos, denn zunächst muss der Benutzer seine Programme ja eintippen. Hierfür bietet der C64 einen grundlegenden Texteditor an, der gleich nach dem Start ausgeführt wird, und das Kernal-ROM. Auch das Kernal-ROM ist ein Baustein auf der Platine des C64, der das Betriebssystem enthält, das dann auch die Hardware verwaltet. Ohne das Kernal-ROM funktioniert übrigens auch BASIC nicht, das ausgiebig auf das Kernal und dessen Funktionen zugreift. So funktioniert z.B. der LOAD-Befehl und auch der SAVE-Befehl zum Laden und Speichern von BASIC-Programmen nur zusammen mit dem Kernal, das dann auch die Floppy verwaltet.

 

1.1 Die ersten Befehle

 

Geben wir nun unser erstes BASIC-Programm ein. Dies soll erstens möglichst einfach gestrickt sein, aber zweitens auch alles das leisten, was Programme im Allgemeinen leisten: Es sollte

 

·       eine Benutzereingabe (=E) einlesen

·       eine Verarbeitung (=V) der Daten vornehmen

·       eine Ausgabe (=A) auf dem Bildschirm machen

 

Diese drei Punkte nennt man dann auch das EVA-Prinzip.

Und schwupp, sind wir schon bei unserem ersten BASIC-Befehl, nämlich PRINT.

 

1.1.1 Der Befehl PRINT

 

PRINT (BASIC-Befehle werden stets großgeschrieben, und werden in diesem Text generell fett dargestellt) gibt es in vielen Varianten, die einfachste Variante ist aber die folgende:

 

PRINT [Text]“ bzw. PRINT“[Text]“;

 

PRINT kann also einen Text, der zwischen Anführungszeichen steht, auf dem Bildschirm ausgeben. Tippen Sie nun die folgende Zeile ein:

 

PRINT WILLKOMMEN ZUM BASIC-KURS

 

Nun drücken Sie die RETURN-Taste (auch Tasten werden hier groß und fett geschrieben) und führen damit den BASIC-Befehl PRINT aus. Auf dem Bildschirm erscheint nun:

 

WILLKOMMEN ZUM BASIC-KURS

READY.

 

Wie Sie unschwer erkennen können, schreibt der C64 im Standard-Modus alle Texte groß und in hellblauer Farbe. Der Cursor (das ist das blinkende Kästchen, das sich stets bei jeder Ein- und Ausgabe ein Stückchen weiterbewegt) steht nach Drücken der RETURN-Taste hinter dem Wort READY. Hieran können Sie nun ein paar Dinge erkennen. Wenn z.B. READY erscheint, dann hat der C64 sämtliche Befehle verarbeitet, die ihm übergeben wurden. In Ihrem Fall war dies genau einer, nämlich eine einfache PRINT-Anweisung. Der C64 befindet sich also im Editor-Modus, und nicht im Programmmodus. Es wird also hier noch kein Programm ausgeführt, sondern jede Zeile, die Sie eingeben (und diese muss auch stets eine BASIC-Anweisung sein), wird sofort ausgeführt. Natürlich ist dieser Zustand sehr unbefriedigend, auch, weil nach jeder PRINT-Anweisung immer READY erscheint. Das stört ungemein, denn wie soll man in dieser Weise einen mehrzeiligen Text ausgeben? Sie müssen also ein Programm eingeben, und dies tun Sie, indem Sie eine Zahl vor Ihre BASIC-Zeile schreiben, z.B. so:

 

10 PRINT“WILLKOMMEN ZUM BASIC-KURS“

(in Programm-Listings hebe ich übrigens die Befehle nicht noch einmal fett hervor, denn so könnte man sie nur noch sehr schwer lesen)

 

Was nun passiert, nachdem Sie RETURN drücken, ist anscheinend: Schlicht gar nichts! Auch READY wird nicht mehr ausgegeben. Aber hier geschieht nur scheinbar nichts, denn im Endeffekt geschieht hier sogar sehr viel, nur eben im Verborgenen: Die Zeile, die Sie eingegeben haben, wird an einer geeigneten Stelle in Ihrem BASIC-Programm eingefügt, und zwar unter der Nummer, die Sie am Anfang der Zeile benutzt haben (nämlich 10). Und mehr noch: Die Zeilen werden sortiert eingefügt. Wenn Sie also nun z.B. schreiben

 

5 PRINT“HALLO, LIEBER BENUTZER“

 

dann enthält Ihr Programm nun eine neue Zeile vor der alten Zeile 10. Wenn Sie dann die folgende Zeile eingeben

 

15 PRINT“IST PROGRAMMIEREN MIT BASIC NICHT TOLL?“

 

dann wird Zeile 15 nach Zeile 10 eingefügt. Das Listing können Sie sich nun mit dem LIST-Befehl wie folgt anzeigen lassen:

 

LIST

5 PRINT“HALLO, LIEBER BENUTZER“

10 PRINT“WILLKOMMEN ZUM BASIC-KURS“

15 PRINT“IST PROGRAMMIEREN MIT BASIC NICHT TOLL?“

 

Und schon sind wir beim zweiten BASIC-Befehl LIST.

 

1.1.2 Der Befehl LIST

 

LIST hat das folgende Format:

 

LIST [Startzeile]-[Endzeile] bzw. LIST [Startzeile]-

 

LIST kann also ohne Parameter aufgerufen werden, dann wird das gesamte Programm aufgelistet. LIST mit einem Parameter, aber einem Minuszeichen am Ende listet das gesamte Programm auf, aber nicht ab Anfang, sondern ab der angegebenen Startzeile. Mit zwei Parametern geben Sie die Start- und Endzeile an. Fehlt nur noch die Definition, was ein Parameter ist:

 

Parameter sind Zahlen, Variablen oder Konstanten, die durch Kommata oder das Minuszeichen voneinander getrennt werden, und die vor der Ausführung an eine Funktion oder einen BASIC-Befehl weitergereicht werden.

 

Ein weiteres Beispiel für Parameter ist z.B. der POKE-Befehl.

 

1.1.3 Die Befehle PEEK und POKE

 

POKE besitzt zwei Parameter in der folgenden Form:

 

POKE [Speicheradresse],[Wert]

 

POKE ist zusammen mit PEEK der wichtigste Befehl beim C64, denn POKE schreibt einen bestimmten Wert in den Speicher. Aber der arme C64 muss natürlich wissen, an welcher Stelle der Wert stehen soll. Dazu wird nun der Speicher eingeteilt, nämlich in einzelne sogenannte Worte. Ein Wort ist beim C64 eine Zahl, die der Prozessor (das ist der Baustein, der die Programme ausführt) am Stück lesen kann, und diese Zahl kann Werte zwischen 0 und 255 beinhalten. Der Speicher des C64 kann 65.536 Worte speichern, und diese Worte werden auch von 0 bis 65.535 durchnummeriert. Die Speicheradresse ist nun in BASIC die Nummer des Wortes, das Sie ansprechen wollen. Dass dies wirklich funktioniert, können Sie sehr einfach feststellen, z.B. durch die BASIC-Zeile

 

POKE 1024,1

 

Wenn Sie diese POKE-Anweisung eingeben, erscheint ein A in der linken oben Ecke des Bildschirms. Dies liegt einfach daran, dass der Bildschirmspeicher, der die einzelnen Zeichen enthält, an der Speicheradresse 1024 beginnt. Mit

 

POKE 1025,1

 

erscheint also das A an der zweiten Position von links oben aus gesehen - ein Beweis dafür, dass das mit den Speicheradressen wirklich funktioniert, und eben kein Hokuspokus ist. Mit PEEK kann man den Speicher in ebenso einfacher Weise auslesen:

 

[Variable]=PEEK([Speicheradresse])

 

Dabei ist eine Variable ein Platzhalter für eine Zahl, genau wie in der Mathematik z.B. beim x. Wenn Sie also nach den POKE-Befehlen nun

 

X=PEEK(1024)

 

eingeben, dann liefert

 

PRINT X

 

Den Wert 1 zurück. Beim C64-BASIC kann für Variablen aber nur ein Name mit 1 oder 2 Zeichen verwendet werden, der Rest wird ignoriert. So ist z.B.

 

AB=1

 

dasselbe wie

 

ABC=1

 

Übrigens: PEEK ist eine Funktion, dies erkennen Sie daran, dass PEEK stets einen Wert zurückgibt. Deshalb wird der Parameter für PEEK, der die Speicheradresse angibt, in Klammern geschrieben - wenn Sie dies vergessen, wird kein Wert zurückgegeben, sondern die Meldung

 

?SYNTAX  ERROR

 

ausgegeben.

 

1.1.4 Zeichenketten (Strings) definieren

 

Selbst das Ur-BASIC wäre aber zu sehr beschränkt, wenn man mit diesem nicht auch Zeichenketten in Variablen ablegen könnte. Allerdings müssten Sie dann auch stets mit angeben, ob Sie in der Variablen A eine Zahl oder eine Zeichenkette ablegen wollen- und kämen wahrscheinlich irgendwann durcheinander. Deshalb gibt es in BASIC spezielle separate Variablen für Zeichenketten, die Sie immer dann benutzen, wenn Sie an den Variablennamen ein Dollarzeichen anhängen. A ist also etwas Anderes, als A$ (sprich: A-String). Auch die Zuweisung von Zeichenketten an String-Variablen funktioniert anders, nämlich so:

 

[Variablenname$]=“[Text]“ bzw. [Variablenname$]=[Quellstring]

 

Die einfachste Variante ist wahrscheinlich sowas wie

 

A$=“HALLO LEUTE“

 

aber auch kompliziertere Konstrukte wie

 

A$=B$+C$+D$

 

sind möglich. Hier hängt das Plus-Zeichen die einzelnen Zeichenketten aneinander und speichert das Ergebnis wieder im String A$. Es gibt zahlreiche auch komplexe String-Funktionen, die aber nicht in das Einführungskapitel gehören.

 

1.2 Das erste Programm eingeben und mit RUN starten

 

Am besten, Sie tippen erst einmal das nun folgende Listing ab. Obwohl ich Ihnen unter „Tipps und Tricks“ auch zeige, wie Sie mit einfachen Mitteln fertige Programme auf den C64 übertragen können, halte ich das Abtippen von Listings zumindest am Anfang für eine gute Übung. Beachten Sie an dieser Stelle bitte, dass die erste unterstrichene Zeile nur der Dateiname ist, unter dem Sie Ihr Listing später abspeichern sollten- und keine Zeilennummer.

 

01-NAMENSABFRAGE

10 PRINT"[CTRL/WHT][SHIFT+CLR/HOME]";

20 PRINT"WIE HEISST DU";

30 INPUT NA$

40 PRINT"HALLO "+NA$+"!"

50 PRINT"WILLKOMMEN ZUM BASIC-KURS"

 

Was Sie nun tun müssen, ist den BASIC-Interpreter in den Programm-Modus zu versetzten. Im Programm-Modus wird das Programm, das sich zurzeit im Speicher befindet (weil Sie dies ja zuvor abgetippt haben) Zeile für Zeile ausgeführt. Dies erreichen Sie, indem Sie den folgenden Befehl verwenden:

 

RUN bzw. RUN [Startzeile]

 

Wenn Sie also nun RUN eingeben, gefolgt natürlich von der RETURN-Taste, wird das erste Programmbeispiel ab Zeile 10 ausgeführt. Zeile 10 macht nichts Anderes, als den Bildschirm zu löschen. Wenn Sie allerdings RUN 20 eingeben, startet das Programm ab Zeile 20, und der Bildschirm wird nicht nach dem Start gelöscht. Immer, wenn das Programm durchgelaufen ist (dies geschieht dann, wenn entweder die letzte Zeile ausgeführt wurde, oder BASIC auf eine END-Anweisung trifft), wird der C64 wieder in den Editor-Modus zurückversetzt, und natürlich wird dann auch wieder READY angezeigt.

Kommen wir nun zur Erklärung des Listings 01-NAMENSABFRAGE.

Zeile 10 löscht den Bildschirm, das wurde ja oben schon angedeutet. Dies geschieht beim C64 jedoch nicht durch Kommandos wie cls() oder clearscreen() in C, sondern mittels PRINT. Beim C64 gibt es dazu neben Textzeichen auch Steuerzeichen, die den Cursor und auch den Bildschirm direkt beeinflussen können. Auch die Farbe kann mit Steuerzeichen geändert werden. Dazu muss Zeile 10 jedoch genau so abgetippt werden, wie sie im Listing steht: Erst die Zeilennummer, dann ein Leerzeichen, dann PRINT, dann Anführungszeichen. Nach Eingabe von Anführungszeichen wechselt der Editor in einen Modus, in dem auch Steuerzeichen angezeigt werden. Das erste Steuerzeichen wird durch gleichzeitiges Drücken von CTRL und 2 angezeigt - ein inverses E. Wenn Sie die Taste 2 genau betrachten, dann werden Sie feststellen, dass unter der Taste noch WHT steht. Dies ist die Abkürzung für „white“ und bedeutet „weiße Textfarbe“. CTRL ist dann die Abkürzung für „control key“, was bedeutet, dass mit CTRL+2 nicht SHIFT+2 gemeint ist (dies würde ein Anführungszeichen setzen), sondern das Steuerzeichen für „Weiß“. Das Steuerzeichen für das Löschen des Bildschirms muss danach mit SHIFT+CLR/HOME erzeugt werden - ein inverses Herzsymbol.

Zeile 20 gibt nur mit PRINT einen Text aus, der den Benutzer dazu auffordert, seinen Namen einzugeben, der anschließend im String NA$ landet. Allerdings soll die Eingabe des Namens direkt hinter diesem Text erfolgen, deshalb schließt hier PRINT mit einem Semikolon ab, das BASIC davon abhält, den Cursor nach Abarbeiten von Zeile 20 in die nächste Bildschirmzeile zu setzen. Zeile 30 liest nun den Namen ein, indem hier die INPUT-Anweisung benutzt wird, die das folgende Format hat:

 

INPUT [Variable oder Stringvariable]

 

Die Zeile

 

30 INPUT NA$

 

liest also den Namen des Benutzers so lange von der Tastatur ein, bis dieser RETURN drückt. Allerdings hat INPUT die Eigenschaft, vor der eigentlichen Benutzereingabe noch ein Fragezeichen anzuzeigen, und genau deshalb wurde Zeile 20 mit einem Semikolon abgeschlossen. In Zeile 40 wird nun ein Begrüßungstext ausgegeben, der aber ein zusammengesetzter Text ist: Erst folgt „HALLO“ in Textform, dann der String NA$, der durch das +-Zeichen direkt angehängt wird, und dann das Ausrufezeichen. An dieser Stelle sieht man ganz gut, wie PRINT arbeitet: Es interpretiert sämtliche Parameter als Strings, auch Texte, die in Anführungszeichen stehen. Und nicht nur das: Zahlen werden intern in Strings umgewandelt, allerdings mit einer unangenehmen Eigenschaft: Vor und nach der in eine Zechenkette umgewandelten Zahl steht jeweils ein Leerzeichen. Außerdem können Zahlen nur als Parameterliste (also durch ein Komma oder ein Semikolon getrennt) übergeben werden, und nicht durch das +-Zeichen verkettet werden wie Strings. Es ist auch nicht in einer einfachen Weise möglich, dieses Verhalten abzustellen.

Zeile 50 entspricht nun unserem Text ganz zu Anfang der Einführung, nämlich:

 

50 PRINT"WILLKOMMEN ZUM BASIC-KURS"

 

1.3 Mehr über den PRINT-Befehl

 

Der PRINT-Befehl ist viel flexibler, als man oft denkt, denn PRINT kann nicht nur Text ausgeben, sondern auch den Cursor steuern. Im Endeffekt ist PRINT auf dem C64 sogar flexibler, als die printf()-Funktion in C, zumindest auf eine gewisse Weise. So kann mit speziellen Steuerzeichen z.B. der Cursor positioniert werden - allerdings nur, nachdem Sie bei PRINT die ersten Anführungszeichen eingegeben haben. Wenn Sie PRINT“ eingeben, und danach die Taste CURSOR OBEN drücken, erscheint ein inverses Bällchen. Dies ist das Steuersymbol für „Cursor oben“. Genauso verhält es sich mit den Tasten CURSOR UNTEN, CURSOR LINKS und CURSOR RECHTS, hier wird auch nach Eingabe des ersten Anführungszeichens das entsprechende Steuersymbol angezeigt. Die Bedienung der Cursortasten (Sie müssen z.B., um den Cursor nach oben zu steuern, SHIFT+CURSOR OBEN drücken) und die Belegung der Steuerzeichen mit inversen Zeichen ist allerdings beim C64 etwas gewöhnungsbedürftig. Dies hat vor Allem etwas damit zu tun, dass die Tastatur des C64 maximal 64 Tastencodes besitzen darf. Deshalb muss man sich wohl oder übel an die etwas kryptischen Steuerzeichen gewöhnen.

Was man allerdings davon hat, ist klar: Steuerzeichen gibt es fast für alles. So kann auch das inverse Q als Text dargestellt werden, Sie müssen nur (natürlich innerhalb des PRINT-Textes nach dem ersten Anführungszeichen) die Taste CTRL und die Taste RVS ON zusammen drücken (die Taste für die Zahl 9 ist zusätzlich mit RVS ON beschriftet). Wenn Sie nun den Buchstaben Q eingeben, wird dieser zwar im Listing normal angezeigt, später bei der Ausgabe aber invers dargestellt. Auch alle folgenden Buchstaben werden invers angezeigt, aber nur so lange, bis Sie mit CTRL+RVS OFF diesen Modus wieder beenden. Auch hier ist die Taste für die Zahl 0 wieder zusätzlich beschriftet, nämlich mit RVS OFF.

Die Textfarbe kann wieder mit CTRL verändert werden, Sie müssen aber zusätzlich nachher noch eine Farbtaste drücken. Die Farben stehen wieder unter den Nummerntasten als Abkürzungen, die folgende Bedeutung haben:

 

·       BLK: Black (schwarz)

·       WHT: White (weiß)

·       RED: Red (rot)

·       CYN: Cyan (eine Art Türkis)

·       PUR: Purple (purpurrot, im Endeffekt ist es aber die Farbe Magenta)

·       GRN: Green (grün)

·       BLU: Blue(blau)

·       YEL: Yellow(gelb)

 

Auch hier erscheint ein bestimmtes Steuersymbol, das etwas kryptisch wirken kann. Deshalb habe ich auch in den folgenden Listings immer die Tastenkombination angegeben, und nicht die Symbole selbst. Der Vorgänger des C64, der VC20, hatte nur einen sehr beschränkten Grafikchip mit 7 Farben. Er hatte aber fast das gleiche BASIC und fast den gleichen Prozessor (6502 statt 6510). Der VICII des C64 kann aber 16 Farben darstellen, deswegen benötigt man für die Farben 8-15 eine zusätzliche Steuertaste. Dies ist die COMMODORE-Taste, die auch zusammen mit einer Zahlentaste gedrückt werden kann, um folgende Farben auszuwählen:

 

·       Die BLK-Taste wird zu orange (orange)

·       Die WHT-Taste wird zu brown (braun)

·       Die RED-Taste wird zu light red (hellrot)

·       Die CYN-Taste wird zu gray 1 (hellgrau)

·       Die PUR-Taste wird zu gray 2 (normales Grau)

·       Die GRN-Taste wird zu light green (hellgrün)

·       Die BLU-Taste wird zu light blue(hellblau)

·       Die YEL-Taste wird zu gray 3 (dunkelgrau)

 

Die normale Textfarbe ist Hellblau auf blauem Grund

 

Tippen Sie nun das nächste Listing ab bzw. transferieren dies auf den C64 (wie dies geht erkläre ich am Ende der Einführung)

 

02-FARBDEMO 1

(Die Punkte sind Leerzeichen und dienen nur der Übersicht beim Abtippen)

10 PRINT"[SHIFT+CLR/HOME]";

20 PRINT"[RVS ON][CTRL+BLK]SCHWARZE FARBE...[RVS OFF]"

30 PRINT"[RVS ON][CTRL+WHT]WEISSE FARBE.....[RVS OFF]"

40 PRINT"[RVS ON][CTRL+RED]ROTE FARBE.......[RVS OFF]"

50 PRINT"[RVS ON][CTRL+CYN]CYANE FARBE......[RVS OFF]"

60 PRINT"[RVS ON][CTRL+PUR]PURPURNE FARBE...[RVS OFF]"

70 PRINT"[RVS ON][CTRL+GRN]GRUENE FARBE.....[RVS OFF]"

80 PRINT"[RVS ON][CTRL+YEL]GELBE FARBE......[RVS OFF]"

90 PRINT"[RVS ON][COMMODORE+BLK]ORANGENE FARBE...[RVS OFF]"

100 PRINT"[RVS ON][COMMODORE+WHT]BRAUNE FARBE.....[RVS OFF]"

110 PRINT"[RVS ON][COMMODORE+RED]HELLROTE FARBE...[RVS OFF]"

120 PRINT"[RVS ON][COMMODORE+CYN]DUNKELGRAUE FARBE[RVS OFF]"

130 PRINT"[RVS ON][COMMODORE+PUR]GRAUE FARBE......[RVS OFF]"

140 PRINT"[RVS ON][COMMODORE+GRN]HELLGRUENE FARBE.[RVS OFF]"

150 PRINT"[RVS ON][COMMODORE+YEL]HELLGRAUE FARBE..[RVS OFF]"

160 PRINT

170 PRINT"[COMMODORE+BLU]UND DAS IST WIEDER DIE NORMALE UND"

180 PRINT"HELLBLAUE FARBE"

 

1.4. Farben mit POKE ändern

 

Das nächste Beispiel ist so berühmt, dass ich nun etwas vorgreifen möchte. Es gibt sogar eine Retro-Internetseite, die sich nach der BASIC-Zeile

 

POKE 53280,0: POKE 53281,0

 

benannt hat. Deshalb füge ich an dieser Stelle schon einmal ein Programm ein, das sehr viel Berühmtheit erlangt hat, weil es so eindrucksvoll den Umgang mit Farben demonstriert.

Es wurde ja schon angedeutet, dass mit POKE Speicherinhalte geändert werden können. Aber warum ist dies so enorm wichtig, und warum gibt es über „peeks und pokes“ ganze Bücher? Ganz einfach: Sämtliche Geräte blenden ihren Konfigurationsbereich in den Speicher ein - man nennt diese Technik auch Memory-Mapped I/O, auf Deutsch „in den Speicher eingeblendete Ein/Ausgabe“. Deshalb kann man sämtliche Geräte (also auch den Videochip VIC) durch PEEK und POKE steuern. Und natürlich liegen auch die sogenannten Kontrollregister des VIC (also des Videochips) im Speicher. Beim VIC beginnen diese Register an der Adresse 53248. Register sind fest in den einzelnen Chips verdrahtet und speichern einzelne Zahlen im Bereich 0-255. Der VIC-Chip hat 40 Register, und da die Register ab der Adresse 53248 eingeblendet werden, wird Register 0 auf die Adresse 53248 und Register 39 auf die Adresse 53248+39=53287 abgebildet. Es ist nun so, dass Register Nr. 32 einen Farbwert für die Rahmenfarbe, und Register Nr. 33 einen Farbwert für die Hintergrundfarbe enthält, der auch beim Bildaufbau mit beachtet wird. Das heißt nun, dass der berühmte Befehl

 

POKE 53280,0: POKE 53281,0

 

Rahmen- und Hintergrundfarbe auf Schwarz setzt - eine Kombination, die oft bei Spielen eingesetzt wird, und einen sehr guten Kontrast zu weiteren Objekten wie Sprites bewirkt. Aber auch Effekte, wie z.B. ein Bildschirmflimmern nach einer Explosion des eigenen Raumschiffes werden oft durch POKE-Befehle realisiert. Bitte ergänzen Sie nun Ihr Listing 02-FARBDEMO durch folgende Zeilen:

 

03-FARBDEMO 2

… Listing aus Farbdemo 1 …

190 FOR I=0 TO 255

200 POKE 53280,I:POKE 53281,I

210 NEXT I

220 POKE 53280,14:POKE 53281,6

 

Zusätzlich zur Zeichen-Farbdemo flimmert der Bildschirm einige Zeit lang und wird anschließend wieder auf normale Farben gestellt. Dieses Verhalten wird durch die Variable I realisiert, die nacheinander die Werte 0-255 erhält. I kann nun als Parameter an POKE weitergereicht und anstatt einer konkreten Zahl in die Adressen 53280 und 53281 geschrieben werden. POKE wertet nun die Variable I aus und benutzt auch die korrekten Werte. Diese Werte werden allerdings nicht durch Anweisungen wie

 

I=1

 

angegeben, sondern durch eine FOR-Schleife, die 256-mal durchlaufen wird. Um dies zu erreichen, definieren Sie zunächst den Schleifenkopf mit dem folgenden Befehl:

 

FOR [Variable]=[Startwert] TO [Endwert] STEP [Schrittweite]

(wird STEP weggelassen, ist die Schrittweite 1.0)

 

In dem Schleifenkörper stehen nun sämtliche Befehle, die die Schleife durchlaufen soll (dies können auch mehrere BASIC-Zeilen sein). In dem letzten Beispiel ist dies nur Zeile 200. Das Schleifenende wird mit NEXT definiert, gefolgt von dem Namen der Variable, die den Schleifenzähler enthält (hier I). Wird der Variablenname weggelassen, wird die aktuell verwendete Zählvariable (also hier I) benutzt. NEXT springt stets direkt zu der Zeile hinter dem letzten FOR zurück, und erhöht die Zählvariable um den STEP-Wert (hier 1.0, weil STEP fehlt). Dies geschieht aber nur solange, wie der Wert der Zählvariable kleiner ist, als der Endwert, der bei FOR definiert wurde.

Auf Schleifen und andere Sprünge innerhalb des Programms wird später noch ausführlich eingegangen, nachdem in Kapitel 2 die Arrays behandelt wurden. Wenn dies dann geschehen ist, und Sie sich die BASIC-Befehlsreferenz in Ruhe angesehen haben, dann besitzen Sie quasi schon solide BASIC-Grundlagen. Vielleicht fragen Sie sich an dieser Stelle vielleicht, ob und wenn ja, wo die Farben der einzelnen Zeichen im Speicher stehen. Die Antwort ist: Natürlich stehen die Farben der einzelnen Zeichen im Speicher an den Adressen 55296-56295. Dazu wird im weiteren Verlauf noch viel mehr erzählt. Vorab nur so viel, dass Sie mit der nächsten Zeile die Farbe des ersten Zeichens auf dem Bildschirm im Weiß ändern können:

 

POKE 55296,1

 

1.5 Rechnen mit Variablen

 

Was eine Variable ist, wissen Sie schon: Eine Variable ist ein Platzhalter für einen Wert oder einen Text in Form eines Strings. Strings und Zahlen werden in BASIC strikt getrennt, und eine BASIC-Zeile wie

 

A=B+C$

 

sind nicht erlaubt und führen zu der Meldung

 

?TYPE MISMATCH  ERROR

 

1.5.1 Rechnen mit Operatoren

 

Allerdings können reine Zahlen-Variablen durchaus in Rechnungen benutzt werden. Die einfachste Art, mit BASIC zu rechnen, ist die Verwendung von Operatoren. Operatoren sind die mathematischen Operationen +, -, * und : (in BASIC wird aber statt einem Doppelpunkt das Zeichen / benutzt), sowie der Pfeil nach oben (Exponentialfunktion ab, die in diesem Text durch ^ dargestellt wird), für den es auch eine extra Taste gibt. Operatoren verknüpfen also die Variablen (aber auch „nackte“ Zahlen) miteinander in der folgenden Weise:

 

[Variable/Zahl][Operator][Variable/Zahl]

 

Natürlich gelten hierbei die mathematischen Regeln, und die Punktrechnung (Operator * und /) hat auch Vorrang vor der Strichrechnung (Operatoren + und -). Es gibt aber in BASIC auch logische Operatoren, nämlich OR (oder), AND (und) und NOT(nicht), und diese Operatoren werden ganz zum Schluss ausgewertet, wobei OR Vorrang vor AND hat. Man spricht an dieser Stelle auch von Prioritäten, die bei BASIC wie folgt verteilt sind:

 

NOT, OR, AND, + , - , * , / ,^ (Operatoren mit niedriger Priorität stehen weiter links)

 

Operatoren mit einer höheren Priorität werden stets vor Operatoren mit einer niedrigen Priorität ausgeführt. Deshalb hat auch ein negatives Vorzeichen, das bei der Berechnung vor eine Zahl gezogen werden könnte, immer Vorrang vor der Addition, die dann auch mit negativen Zahlen rechnen muss. Die normale Priorität kann allerdings auch durch Klammern geändert werden, z.B. so:

 

X=1*(2+3)*(4+5*6)

 

Aber auch andere Variablen können durch Operatoren verknüpft werden, z.B. so:

 

Y=10*X^2-16*X+2

 

Wenn Sie nun den Wert des hier definierten Polynoms an der Stelle x=1 ausrechnen wollen, dann müssen sie die folgenden Zeilen benutzen:

 

X=1

Y=10*X^2-16*X+2

PRINT X

(Ausgabe: -4)

 

Die andere Alternative ist, eine BASIC-Funktion mit DEF FN zu definieren:

 

DEF FN F(X)=10*X^2-16*X+2

PRINT F(1)

(Ausgabe: -4)

 

1.5.2 Fest verdrahtete Funktionen

 

BASIC besitzt einige Funktionen, die fest verdrahtet sind, und die Sie nicht abschalten können.

Für Zahlen sind dies die folgenden Funktionen:

 

·       PEEK(X) gibt den Speicherinhalt der Adresse X zurück

·       VAL(X$) gibt den in einen numerischen Wert umgewandelten String X$ als Zahl zurück

·       ASC(X$) gibt den ASCII-Wert des ersten Zeichens in X$ als Zahl zurück

·       SIN(X) berechnet den Sinus von X (X im Bogenmaß)

·       COS(X) berechnet den Cosinus von X (X im Bogenmaß)

·       TAN(X) berechnet den Tangens von X (X im Bogenmaß)

·       ATN(X) berechnet den Arcus-Tangens von X (X im Bogenmaß)

·       INT(X) liefert den Ganzzahl-Anteil von X zurück

·       ABS(X) liefert den Absolutwert zurück

·       SGN(X) liefert das Vorzeichen zurück, also ist SGN(-10)=-1, SGN(10)=+1 und SGN(0)=0

·       RND(X) liefert eine Zufallszahl zwischen 0 und 1 zurück. Wird als Parameter 0 übergeben, wird der Zufallsgenerator neu initialisiert.

 

Hinzu kommen die folgenden Spezial-Funktionen, die Strings zurückgeben können:

 

·       CHR$(X) ist die Umkehrfunktion von ASC, verwandelt also einen ASCII-Wert in ein Zeichen

·       STR$(X) ist die Umkehrfunktion von VAL, verwandelt also eine Zahl in einen String

·       LEFT$(X$,A) gibt A Zeichen von X$ zurück, und zwar von links aus betrachtet

·       RIGHT$(X$,A) gibt A Zeichen von X$ zurück, und zwar von rechts aus betrachtet

·       MID$(X$,A,B) gibt X$ ab der Zeichenposition A zurück, die Anzahl der Zeichen ist B

 

Beispiele für String-Funktionen sind z.B.:

 

PRINT CHR$(65) gibt ein großes A aus

PRINT ASC(“A“) gibt die Zahl 65 aus

PRINT STR$(1234) gibt die Zahl 1234 aus, und zwar ohne zusätzliche Leerzeichen

LEFT$(“HALLO WELT“,5)=“HALLO“

RIGHT$(“HALLO WELT“,4)=“WELT“

“G“+MID$(“HALLO WELT“,8,2)+“D“=“GELD“

 

1.6 Der ASCII-Code

 

ASCII ist die Abkürzung für „American Standard Code for Information Interchange), das heißt der ASCII-Standard definiert eine Zeichentabelle, die für sämtliche Computer systemübergreifend gültig sein soll, damit Texte unter Umständen auch auf anderen Computern als dem C64 gelesen werden können. Der ASCII-Standard ordnet jeder Zahl einen Buchstaben zu, z.B. dem großen A den Wert 65. Die ASCII-Tabelle ist inzwischen sehr gut im Internet auffindbar, aber auch mit BASIC können Sie sich mittels der ASC-Funktion den ASCII-Wert für bestimmte Zeichen ausgeben lassen.

Nun kommen aber zu dem ASCII-Code, den auch BASIC verwendet, Besonderheiten des C64 hinzu: Hier gibt es neben den Buchstaben auch Grafik-Zeichen. Wenn Sie z.B. SHIFT+Q drücken, dann erscheint kein kleines Q oder ein großes Q anstatt eines kleinen Q, sondern ein Bällchen, das dann auch auf der Taste Q auf der rechten Seite unterhalb des Buchstabens Q aufgedruckt ist. Wenn Sie stattdessen COMMODORE+Q drücken, dann erscheint das Zeichen, das auf der linken Seite unterhalb des Buchstabens Q aufgedruckt ist. Man spricht in diesem Fall auch oft von PRINT-Grafik. Mit PRINT-Grafik können Sie z.B. in einfacher Weise Karten zeichnen, weil das Symbol für Kreuz, Herz, Pik oder Karo im C64-Standard-Zeichensatz vorhanden ist. Aber auch andere Dinge wie Textkästen auf dem Bildschirm können durch PRINT-Grafik erstellt werden. Leider entspricht diese Vorgehensweise nun in keiner Weise mehr dem ASCII-Standard, deswegen enthält der C64 auch zwei Zeichentabellen. Die zweite Tabelle enthält dann auch Kleinbuchstaben und ist ASCII-Kompatibel. Leider muss diese zweite Zeichentabelle explizit ausgewählt werden, entweder durch das Drücken von SHIFT und COMMODORE gleichzeitig, oder durch

 

POKE 53272,22

 

Mit dem letzten POKE-Befehl sagen Sie dem VIC-Grafikchip, dass er die zweite ROM-Speicherbank auswählen soll, in der die Zeichentabelle mit den ASCII-kompatiblen Zeichen steht. Rückgängig machen können sie dies durch

 

POKE 53272,21

 

1.6.1 ASCII vs. PETSCII

Der Vorgänger des VC16, des VC20 und des C64 war der Commodore PET, der auch schon Print-Grafik benutzte, um z.B. ein Poker-Spiel zu erstellen. Beim PET wurden jedoch noch die Zeichen direkt in den Bildschirmspeicher „gepoked“, und es gab keinen ASCII-Standard - auch nicht in dem sehr rudimentären BASIC, das damals noch von Kassette nachgeladen werden musste. Allerdings blieb der Zeichensatz auch beim C64 bestehen, und schimpfte sich später PETSCII. PETSCII ist kein ASCII-Standard, dies sehen Sie z.B. daran, dass

 

POKE 1024,65

 

kein großes A, sondern ein Grafikzeichen an die Position (0,0) des Bildschirms schreibt. Stattdessen wird bei PETSCII das große A auf die Zahl 1 abgebildet. Allerdings folgen andere Zeichen dem ASCII-Standard, z.B. die Zahlen (ASCII-Wert 48-57), und auch ein paar Zeichen mit dem ASCII-Code 59-63. PETSCII müssen Sie genau dann verwenden, wenn Sie sich außerhalb von BASIC befinden, z.B. in einem Assembler-Programm, mit dem Sie Maschinensprache erstellen können.

 

1.7 Die Behandlung von Fehlern

 

Wer programmiert, der macht Fehler. Dies ist nun mal so, und kann auch nicht umgangen werden. Einmal nicht aufgepasst, und schon wird aus „PRINT“ „PINT“, und BASIC meldet sich mit

 

?SYNTAX  ERROR

 

Bis jetzt wurde nicht erläutert, was es mit dieser kryptischen Meldung auf sich hat, aber wenn Sie richtig programmieren wollen, kommen Sie nicht drum herum, sich die Error-Meldungen zu merken, und was diese bedeuten. Da dies hier immer noch eine Einführung ist, möchte ich Ihnen an dieser Stelle einfach sämtliche Error-Meldungen und ihre Bedeutung auflisten.

 

SYNTAX ERROR

Es wurde ein syntaktischer Fehler entdeckt. Dies heißt, dass ein Befehl nicht erkannt werden konnte, oder aber ein Ausdruck nicht nur logisch, sondern auch mathematisch falsch ist. Sie haben dann z.B. eine Klammer vergessen, oder aber einen BASIC-Befehl falsch geschrieben.

 

TYPE MISMATCH ERROR

Ein zugewiesener Wert stimmt nicht mit dem Variablentyp überein, den BASIC eigentlich erwartet. Sie können z.B. einer Zahlenvariable keinen String zuweisen.

 

ILLEGAL QUANTITY ERROR

Der zugewiesene Wert hat die zulässige Grenze überschritten, die BASIC eigentlich erwartet, und konnte deswegen nicht zugewiesen werden. Meistens tritt dieser Fehler auf, wenn Sie versehentlich versuchen, mit POKE einen Wert in den Speicher zu schreiben, der negativ oder größer, als 255 ist.

 

BAD SUBSCRIPT ERROR

Der verwendete Array-Index (mehr dazu in Kapitel 2) hat die zulässige Grenze überschritten, die Sie zuvor mit der DIM-Anweisung (siehe auch dort in Kapitel 4) festgelegt haben. Meistens tritt dieser Fehler auf, wenn Sie versehentlich versuchen, ein Array-Element einzulesen, das außerhalb der Dimensionsgrenzen liegt, oder auch, wenn der angegebene Index negativ ist.

 

FORMULA TOO COMPLEX ERROR

Die eingegebene Formel enthält zu viele Klammern oder mehr als 20 Verschachtelungen. Auch Ausdrücke, die mehr als 88 Zeichen enthalten, kann BASIC nicht mehr auflösen. Dieser Fehler wird oft nicht richtig behandelt, und oft erscheint diese Meldung immer und immer wieder. Dies ist dann ein Zeichen für einen Stack Overflow, der immer dann auftritt, wenn der Stapelspeicher des Prozessors aufgebraucht wurde. Ein Stack Overflow ist ein sehr kritischer Zustand und sollte möglichst vermieden werden.

 

STRING TOO LONG ERROR

Der Zielstring ist zu lang, um durch BASIC korrekt verarbeitet zu werden. Strings können in BASIC maximal 255 Zeichen enthalten, und Strings, die Sie mit INPUT bzw. INPUT# von der Tastatur oder aus einer Datei einlesen, dürfen eine Länge von 88 Zeichen nicht überschreiten. Auch bei Strings, die Sie mit dem +-Operator verknüpfen, darf der Zielstring eine Länge von 255 Zeichen nicht überschreiten.

 

NEXT WITHOUT FOR ERROR

Es wurde ein NEXT-Befehl für eine Variable angegeben, für die vorher kein FOR angegeben wurde. Schleifen können zwar durchaus innerhalb von anderen Schleifen stehen, jedoch dürfen sich die Schleifen nicht überschneiden. Auch dann wird dieser Fehler ausgelöst.

 

RETURN WITHOUT GOSUB ERROR

Wie Sie später im Kapitel „Schleifen und Sprünge“ noch sehen werden, können Sie mit GOSUB Unterprogramme aufrufen. GOSUB springt wie GOTO zu einer bestimmten Programmzeile. Jedoch kann später mit RETURN zur aufrufenden Zeile zurückgesprungen werden. Wird RETURN ohne GOSUB verwendet, wird dieser Fehler angezeigt

 

OUT OF MEMORY ERROR

Dies ist ein sehr kritischer Fehler, der immer dann auftritt, wenn Sie den gesamten Speicher aufgebraucht haben. Dies kann mehrere Gründe haben, z.B. den Grund, dass Sie sehr viele Strings verwenden, ohne diese irgendwann wieder aus dem Speicher zu entfernen. Auch sehr große Datenfelder können den Speicher aufbrauchen. Die einzige Chance, die Sie an dieser Stelle haben, ist die Optimierung Ihres Programmcodes (falls es dann noch gelingt, das Programm vorher erfolgreich zu sichern).

 

REDIM’D ARRAY ERROR

Dies ist ein kritischer Fehler, der immer dann auftritt, wenn Sie versuchen, ein Array erneut mit DIM anzulegen. In BASIC der Version 2.0 können Sie dies nicht, und es gibt auch keinen REDIM-Befehl, mit dem Sie ein Array explizit neu definieren können - und es gibt auch kein malloc() oder realloc() wie in C. Sie müssen sich also beim C64 von vorn herein im Klaren darüber sein, wie groß Ihre Arrays maximal werden können, oder gegebenenfalls eine alternative Methode verwenden, um Ihre Daten zu sichern (z.B. in einer separaten Datei). Sie können natürlich an dieser Stelle auch alternative Datenstrukturen verwenden, wie z.B. verkettete Listen, dies kann dann aber auch bedeuten, dass Sie einen Teil Ihres Programms in Maschinensprache programmieren müssen.

 

REDO FROM START

Diese Meldung, eingeleitet von einem Fragezeichen, ist eigentlich kein Fehler im eigentlichen Sinne. Jedoch rechne ich selbst diese Meldung zu den Eingabefehlern, weil REDO FROM START immer dann erscheint, wenn der INPUT-Befehl etwas anderes erhält, als er erwartet. Dies ist z.B. der Fall, wenn Sie in Ihrem Programm eine Zahl einlesen wollen, der Benutzer aber stattdessen eine Zeichenkette eingibt.

 

FILE NOT OPEN

Eigentlich ist dies kein Fehler, sondern der Versuch, auf eine Datei mit einer Dateinummer zuzugreifen (z.B. mit INPUT#), die noch nicht mit OPEN geöffnet wurde. Wie auch die Meldung DEVICE NOT PRESENT (Gerät nicht vorhanden) wird die Fehlernummer für FILE NOT OPEN im Endeffekt vom Kernal generiert und anschließend von BASIC im Klartext ausgegeben. Dies gilt dann auch für die Meldung FILE NOT FOUND (Datei nicht gefunden) oder INPUT PAST END (Versuch, Daten über das Dateiende hinaus zu lesen). Allerdings kann es auch Fehlermeldungen der Floppy geben, die BASIC nicht erkennt, z.B. BLOCK READ ERROR, CORRUPTED BLOCK DATA oder TRACK SYNC ERROR, die eigentlich darauf hindeuten, dass etwas mit der Diskette nicht stimmt.

 

1.8 Speichern und Laden von Programmen mit LOAD und SAVE

 

Ich möchte nun voraussetzen, dass Sie mindestens eine Floppy besitzen, und dass diese Floppy so konfiguriert ist, dass sie die Gerätenummer 8 besitzt. In einem Emulator wie VICE können Sie die Nummern entsprechend aus einem Menü auswählen, im Fall von Original-Floppys müssen Sie unter Umständen entsprechende DIP-Schalter umstellen. Ich empfehle auch, bei einem Emulator wie VICE die „true floppy emulation“ zu benutzen, denn auch, wenn diese sehr langsam ist (eben wie die Original-Floppy), so unterstützt diese Emulation auch die Funktionen, die eventuell nicht richtig laufen, wenn die Option „true floppy emulation“ abgeschaltet ist. Wenn Sie nur einen Emulator benutzen, um den BASIC-Kurs zu absolvieren, dann können Sie sich einfach die Datei BASIC-Kurs.D64 herunterladen, wenn Sie stattdessen auf einem Original-C64 arbeiten, dann müssen Sie weitere Dinge beachten, die hier aber zusätzlich im 9. Kapitel (Tipps und Tricks) erklärt werden müssen.

Zunächst nun die einfache Variante, die auf dem Emulator und dem Original-C64 identisch ist: Die BASIC-Kommandos LOAD und SAVE. LOAD lädt ein BASIC-Programm in den Speicher, SAVE speichert ein Programm auf Diskette. Um also Ihre Arbeit zu sichern, benutzen Sie SAVE:

 

SAVE “[Dateiname]“,[Laufwerknummer] (meistens ist die Laufwerknummer 8)

 

Im Falle des letzten Beispiel ist dies also

 

SAVE "03-FARBDEMO 2“,8

 

Um das letzte Beispiel erneut in den Speicher zu laden (z.B. nach dreitägiger C64-Abstinenz) benutzen Sie LOAD:

 

LOAD “[Dateiname]“,[Laufwerknummer] (meistens ist die Laufwerknummer 8)

 

Im Falle des letzten Beispiel ist dies also

 

LOAD "03-FARBDEMO 2“,8

 

Wenn Sie mehrere Floppys haben, dann sollten Sie diese per DIP-Schalter so konfigurieren, dass das zweite Laufwerk die Nummer 9, das dritte Laufwerk die Nummer 10, usw. bekommt. BASIC kann damit am besten umgehen. Nicht benutzen sollten Sie stattdessen Nummern <7, da diese z.B. für andere Geräte wie Tastatur (0), Modem (1), Scanner (2), Drucker (3,4) oder Festplatten (5,6) reserviert sind.

BASIC-Programme starten nun stets ab Adresse 2049. Das bedeutet, dass LOAD und SAVE alle Daten stets an die Adresse 2049 laden. Dies wird dadurch erreicht, dass alle BASIC-Dateien mit den beiden Zahlen 01,08 beginnen. Das heißt dann auch, dass Dateien stets als eine Folge von Zahlen abgelegt werden, die im Bereich von 0-255 liegen. Diese Zahlen nennt man auch Bytes, weil der Wert (0-255) in 8 Bits Platz findet, und 8 Bits zusammengenommen bezeichnet man als Byte. In Dateien beschreiben nun die ersten Bytes die Startadresse, und diese ist bei BASIC-Programmen 2049=8*256+1. Dies ist so, weil in das erste Byte nur Zahlen von 0-255 passen, und alle Adressen von über 255 ein zusätzliches Byte benötigen, das auch die Bits 8-15 der Adresse (0-65.535) aufnimmt. Genau deshalb werden Adressen beim C64 in ein Lo-Byte und ein Hi-Byte aufgeteilt - anders kann es der 8-Bit-Prozessor auch gar nicht verarbeiten.

Maschinenprogramme können aber auch an ganz andere Adressen geladen werden, z.B. an die Adresse 49152 (erste zwei Bytes=0,192). Damit LOAD erkennen kann, dass die ersten zwei Bytes der zu ladenden Datei explizit ausgewertet werden müssen, wird ein separater Unterkanal, nämlich Kanal 1 der Floppy benutzt (raw data channel). Deshalb laden Sie Maschinenprogramme auch mit

 

LOAD“[Dateiname]“,8,1

 

Allerdings irren Sie, wenn Sie denken, dass Sie das soeben geladene Programm mit

 

SAVE“[Dateiname]“,8,1

 

wieder abspeichern können, denn SAVE besitzt keinen vierten und fünften Parameter für die Start- und Endadresse. Stattdessen verwendet SAVE hier den Start- und Endzeiger für BASIC-Programme, und BASStart ist dann auch stets 2049. Für dieses Problem gibt es mehrere Lösungen (z.B. Schreiben einer separaten Datei durch PRINT# in einem separaten Programm, „umbiegen“ der BASIC-Programmzeiger, etc.), jedoch ist es an dieser Stelle noch zu früh, um Ihnen die ganzen Tricks zu zeigen, die es hier gibt. Ein Listing, das ich selbst entwickelt habe, möchte ich Ihnen jedoch nicht mehr vorenthalten, nämlich den Saver, ein Maschinenprogramm, mit dem Sie beliebige Speicherinhalte auf Diskette sichern können:

 

SAVER

0 REM LOAD: SYS 53176 “[NAME]”

1 REM SAVE: SYS 53176 “[NAME]”,[START],[END]

10 FOR I=53176 TO 53176+73: READ A: POKE I,A:NEXT I

20 DATA 32,87,226,162,8,134,186,32,121

30 DATA 0,240,44,32,253,174,32,138,173

40 DATA 32,247,183,72,32,121,0,240,21,104,132,193,133,194,32,253,174,32

50 DATA 138,173,32,247,183,132,174,133,175,76,237,245,104,132,195,133

60 DATA 196,160,0,44,160,1,132,185,169

70 DATA 0,76,165,244,60,54,52,39,69,82,62,0,0