C 64
Tips & Tricks

Die große Software-Vielfalt der CBMs für den C 64 ausnützen

Den meisten Anwendern wird sich schon einmal das Problem gestellt haben, wie sie Programme von anderen Computersystemen auf ihr eigenes übertragen können. Dieser Artikel sollte es jedem ermöglichen, auch komplexe Basicprogramme der weitverbreiteten Commodore-Systeme CBM 30XX, CBM 40XX (hier kurz als CBMs bezeichnet) und C 64 füreinander umzuschreiben.

Hat man das Programm fertig eingegeben und auf Kassette oder Diskette abgespeichert, so ist das Laden von CBM-Programmen in den C 64 kein Problem: Disketten- und Kassettenformat sind identisch (zumindest bei den Doppellaufwerken 2031 und 4040 mit dem Einzellaufwerk VC 1541). Der Basic-Benutzerspeicher beginnt beim C 64 mit der Speicherstelle 2048 und endet bei 40959. Ein spezielles »Verschiebeprogramm« im C 64 sorgt dafür, daß CBM-Programme in den richtigen Speicherbereich geladen werden. Wer jedoch schon einmal versucht hat, C 64-Programme in einen CBM zu laden, wird damit keinen Erfolg gehabt haben, denn die CBMs besitzen kein solches Programm. Dort beginnt der Speicher für Basic-Programme bei 1024 und endet, je nach RAM-Ausbaustufe (8 KByte, 16 KByte oder 32 KByte) bei spätestens 32767. In einen CBM geladene C 64-Programme sind ohne Verbiegung von Zeigern weder zu listen noch zu starten. Man könnte bei den CBMs nach dem Laden den Zeiger für den Programmanfang verändern (durch den Befehl »POKE 40,0:POKE 41,8«), aber man müßte diesjedesmal nach dem Laden tun, ein auf die Dauer sehr umständliches Verfahren. Ein entsprechendes »Verschiebeprogramm«, welches diesen Aufwand vermeidet, finden Sie unter der Überschrift »Von den Kleinen auf die Großen« in dieser Ausgabe. Nun zur eigentlichen Arbeit, dem Umschreiben: Alle Computer haben die gleichen Basic-Anweisungen (bis auf die CBMs der Serie 4000, welche zusätzlich komfortable Diskettenbefehle besitzen). Sie unterscheiden sich im wesentlichen nur durch die Speicherbelegung und die Farbe, die Sprites und die hochauflösende Grafik des C 64.

Der Bildschirmbereich:

Die meisten Basicprogramme erstellen bewegte Grafiken mit Hilfe der Befehle PEEK und POKE. Im Bildschirmbereich wird durch den Befehl »POKE X, Y« an der Stelle mit der Adresse X das Zeichen mit dem Bildschirm-Code Y gesetzt. Gelöscht wird es dann durch den Befehl »POKE X, 32«, denn die Zahl 32 entspricht dem Leerzeichen (Blank). Durch PRINT PEEK(X) kann man abfragen, welches Zeichen sich an der Stelle X befindet. Der Bildschirmcode ist bei allen drei Systemen identisch. Jedoch liegt der Bildschirmspeicher an unterschiedlichen Stellen: Bei den CBMs zwischen 32768 und 33767, beim C 64 zwischen 1024 und 2023. Wenn man ein CBM-Programm auf den C 64 überträgt, muß man also von allen Bildschirmadressen 31744 subtrahieren, umgekehrt 31744 addieren.

Jedoch kommt da noch ein kleines Problem hinzu: Der C 64 kann 16 Farben darstellen. Dazu besitzt er einen Farbenspeicher, welcher ganz analog zum Bildschirmspeicher zu behandeln ist. Er beginnt bei 55296 und endet bei 56295; die Differenz zwischen Bildschirmadresse und Farbadresse beträgt 54272. Wenn man also ein CBM-Programm für den C 64 umschreibt, muß man hinter jedem POKE-Befehl für den Bildschirm einen entsprechenden für die Farbe anhängen, also zum Beispiel hinter POKE 1024,64 anfügen: POKE 1024 + 54272,X ,wobei X eine Zahl zwischen 0 und 15 ist, welche dann die Farbe des Zeichens bestimmt. Dieser Befehl kann weggelassen werden, wenn ein Zeichen gelöscht wird, also im Befehl der Bildschirmcode 32 (= Leerzeichen) eingesetzt wird. Die Farbcodes haben folgende Bedeutung:

0 schwarz
1 weiß
2 rot
3 türkis
4 violett
5 grün
6 blau
7 gelb
8 orange
9 braun
10 hellrot
11 grau 1
12 grau2
13 hellgrün
14 hellblau
15 grau 3

Umgekehrt müssen die POKE-Befehle für den Farbenspeicher bei einer Übertragung auf die CBMs gestrichen werden. Sprites und hochauflösende Grafik können nicht auf die CBM-Serie übertragen werden.

Tastatur und Joystick

Viele Programme fragen durch PEEK die gerade gedrückte Taste ab. Dazu existiert in der Zero-Page eine Speicherstelle, in welcher sich die Matrixkoordinate der gerade gedrückten Taste befindet. Bei den CBMs ist dies die 151, beim C 64 die 203. Die Wirkungsweise kann man sich leicht durch folgendes kleines Programm verdeutlichen:

10 PRINT PEEK (203)
20 GOTO 10

(Bei den CBMs muß die 203 in Zeile 10 durch 151 ersetzt werden). Nach dem Starten durch RUN erscheint eine Reihe von Zahlen, beim C 64 die 64, bei den CBMs die 255. Drückt man nun irgendeine Taste, so erscheint eine gerade Zahl, je nachdem, welche Taste gerade gedrückt ist. In Tabelle 1 ist ein Vergleich der Tastaturcodes dargestellt.

gedrückte Taste CBM 30XX CBM 40XX Commodore 64
75 95 57
1 26 49 56
2 18 50 59
3 25 51 8
4 42 52 11
5 34 53 16
6 41 54 19
7 58 55 24
8 50 56 27
9 57 57 32
0 10 48 35
+ 17 43 40
9 45 43
£ 48
HOME 7 19 51
INS/DEL ? ? 0
Q 64 81 62
W 56 87 9
E 63 69 14
R 55 82 17
T 62 84 22
Y 54 89 25
U 23 86 30
I 53 73 33
O 60 79 38
P 52 80 41
@ 15 64 46
* 33 42 49
59 94 54
A 48 65 10
S 40 83 13
D 47 68 18
F 39 70 21
G 46 71 26
H 38 72 29
J 45 74 34
K 37 75 37
L 44 76 42
= 1 61 53
RETURN 27 13 1
Z 32 90 12
X 24 88 23
C 31 67 20
V 23 86 31
B 30 66 28
N 22 78 39
M 29 77 36
, 70 44 47
. 2 46 44
/ 49 47 55
CRS↑ ? ? 7
CRS← ? ? 2
SPACE 6 32 60
Tabelle 1. Vergleich der Tastaturcodes

Es gilt, einige besondere Adressen zu beachten:

CBM: In 152 steht 1 (anstatt 0), wenn die Taste SHIFT gedrückt ist.
C 64: Adresse 653:
0: wenn nichts gedrückt
1: SHIFT gedrückt
2: Commodore-Taste gedrückt
4: CTRL gedrückt

Dazu noch ein Tip für eigene Programme: Meistens benötigt man für ein Spiel eine Unterscheidung zwischen verschiedenen Tastendrücken (zum Beispiel bis zu neun verschiedene Tasten für die Richtungssteuerung eines Raumschiffes). Am schnellsten funktioniert die Abfrage, wenn man ein Feld mit 256 (Ganzzahl-)Variablen definiert (zum Beispiel A%(255)), und die Richtung als Wert des entsprechenden Indexes darin speichert.

Beispiel (hier für C 64): Wir wollen für ein Spielprogramm eine Kanone (↑haben, die man am unteren Bildschirmrand mit Taste ”1” nach links und mit Taste ”2” nach rechts steuern kann. In unserem Beispiel würde das Programm entsprechend Listing 1 aussehen.

 1 REM KANONE
 5 ZA = 1984:ZE = 2023:OP = 2004
10 DIM A%(255)
20 A%(56) = –1:A%(59) = 1
:
1000 REM ABFRAGE – ZEICHEN SETZEN, SUBROUTINE
1010 NP = OP + A%(PEEK(203)):REM NEUE POSITION
1020 IF NP >ZE OR NP<ZA THEN NP = OP: REM ZEILENBEGRENZUNG
1030 POKE OP, 32:REM ALTE POSITION LÖSCHEN
1040 POKE NP, 30:REM NEUE POSITION SETZEN
1050 POKE NP+54272,1:REM FARBE SETZEN
1060 OP = NP
1070 RETURN
Listing 1. Ein kleines Beispielprogramm für den C 64.

A% (255) ist das Variablenfeld. Der Tastaturcode von ”1” ist beim C 64 die 56, von ”2” die 59. Die Tastaturadresse ist 203. Variablen:
OP die alte Position der Kanone
NP die neue Position der Kanone
ZE Bildschirmadresse am Ende der Zeile, in der sich die bewegt
ZA Bildschirmadresse am Zeilenanfang

CBM-Besitzer können nach Studium des Artikels an diesem Beispielprogramm ihr neugelerntes Wissen ausprobieren. Die Lösung steht am Ende des Artikels (aber nicht vorher nachschauen!).

Diese Methode ist auch bei der Verwendung eines Joysticks nützlich, denn dieser muß ähnlich wie die Tastatur mit PEEK abgefragt werden. Seine Adresse ist 56321 (Port 1) beziehungsweise 56320 (Port 2), wobei Port 1 weniger geeignet ist, da der Inhalt seines Speichers auch von der Tastatur beeinflußt wird. Die Codierung ist der Tabelle 2 zu entnehmen.

Bewegung Port 1 Port 2
Feuer-Taste 239 111
nach oben 254 126
nach unten 253 125
nach rechts 247 119
nach links 251 123
nach links oben 250 122
nach rechts unten 245 117
nach rechts oben 246 118
nach links unten 249 121
keine Taste gedrückt 255 127
Tabelle 2. Die Codierung der Joystick-Ports

Die CBMs besitzen keinen Anschluß für Joysticks, es gibt jedoch diverse Konstruktionen zum Anschluß an den User-Port. Daher empfiehlt es sich, beim Übertragen von C 64-Programmen auf die CBMs auf den Joystick zu verzichten und diese Programmteile durch Tastaturabfragen zu ersetzen.

PRINT-Befehle

Die ASCII-Codes sind bei allen drei Systemen größtenteils identisch, sie unterscheiden sich praktisch nur in den Farbsteuerzeichen und der Umschaltung von Grafik auf Groß/Kleinschreibung. Die Umschaltung auf Groß/Kleinschreibung erfolgt bei den CBMs durch den Befehl ”POKE 59468,14” und zurück auf die Blockgrafik durch ”POKE 59468,12”. C 64-Besitzer benutzen hier den Befehl ”PRINT CHR$(14)" (Kleinschreibung) beziehungsweise den Befehl ”PRINT CHR$(142)" (Grafik). Beim Übertragen von Programmen auf den C 64 kann man nach Belieben Farbsteuerzeichen einfügen, umgekehrt sind diese zu löschen.

Der Ton

Wichtig für das Übertragen von Programmen mit Ton ist vor allem die Tonhöhe und ihre Adresse. Beim C 64 stehen drei Tongeneratoren zur Verfügung. Ihre Tonhöhe wird dabei durch je zwei Adressen bestimmt, wobei die erste Adresse (das Low-Byte) die Tonhöhe nur sehr wenig, die zweite Adresse (das High-Byte) die Tonhöhe hingegen wesentlich stärker (nämlich genau 255 mal so stark wie das Low-Byte) beeinflußt. In der Tabelle 3 sind die wichtigsten Tonadressen des Commodore 64 zusammengefaßt.
(Adresse = 54272 + Register)

REGISTER INHALT
Stimme 2 2 3
0 7 14 Frequenz Low-Byte (0-255)
1 8 15 Frequenz High-Byte (0-255)
2 9 16 Tastverhältnis Low-Byte (0-255)
3 10 17 Tastverhältnis High-Byte (0-255)
4 11 18 Wellenform: Rauschen = 129
Rechteck = 65
Sägezahn = 33
Dreieck = 17
5 12 19 Anschlag
0 (hart) – 15*16 (weich)
+ Abschwellen
0 (hart) – 15 (weich)
6 13 20 Halten
0 (stumm) – 15*16 (laut)
+ Ausklingen
0 (schnell) – 15 (langsam)
24 24 24 Lautstärke: 0 (stumm) – 15 (volle Lautstärke)
Tabelle 3. Die wichtigsten Tonadressen von C 64.

Bei den CBMs steht jedoch nur ein Tongenerator zur Verfügung, auch können dort weder Wellenform, noch Lautstärke, noch Hüllenkurve programmiert werden. Daher ist es bei der Übertragung von C 64-Programmen auf die CBMs bei komplexen Klängen und Geräuschen meist am einfachsten, den Ton selbst neu zu gestalten. Wenn man den Ton beim Übertragen auf den C 64 direkt übernehmen will, ist das Umschreiben nicht schwierig. Bei den CBMs gibt es drei Tonadressen, welche wie üblich durch PEEK und POKE angesprochen werden: 59464, 59466 und 59467. Der Tongenerator wird dort eingeschaltet durch POKE 59466,16:POKE 59467,20: POKE 59464,0. Nun kann man die Tonhöhe einfach festsetzen, indem man eine Zahl zwischen 0 und 255 in die Adresse 59646 schreibt (durch POKE 59464,X, wobei X eine Zahl zwischen 0 und 255 ist). Dabei ist 255 ein relativ tiefer Ton und 0 ein sehr hoher Ton (Ultraschall, daher unhörbar und mit »Ton ausgeschaltet« zu vergleichen). Die Tonhöhe kann man für den C 64 als High-Byte übernehmen, jedoch bedeutet dort 0 einen sehr tiefen Ton und 255 einen sehr hohen, also genau umgekehrt. Daher muß man wie folgt vorgehen. Wenn im CBM-Programm steht: POKE TA, TH, wobei TA die Adresse der Tonhöhe 59464 und TH die Tonhöhe ist, muß es nun im C 64-Programm heißen: POKE FH, 255 — TH. Es kommt aber dazu, daß der Tonumfang des C 64 etwas kleiner ist als der der CBMs. Daher empfiehlt es sich, den Wert für die Tonhöhe mit 2 oder 3 zu multiplizieren, wobei darauf zu achten ist, daß der Bereich von 0 bis 255 nicht überschritten wird. Der Befehl muß also lauten: POKE FH, 255 — 2 * TH.

Diskettenbefehle

Die komfortablen Diskettenbefehle des CBM 40 XX können nicht übernommen werden, jedoch kann man die überall möglichen Kommando-String-Befehle verwenden. Allerdings muß dafür für die Monofloppy 1541 (beziehungsweise 1540) die Laufwerksnummer gestrichen werden. Tabelle 4 stellt eine Vergleichsliste der beiden Laufwerke dar.

Doppelfloppy 4040
(die neuen 4er Befehle stehen in Klammern)
Monofloppy 1541
Diskette neu formatieren:
OPEN 1,8,15,"N0:Name,XX"
(HEADER"Name,",IXX
I = Laufwerksnummer)
OPEN 1,8,15,"N:Name,XX"
Inhaltsverzeichnis lesen:
LOAD"$1",8 bzw. LOAD"$",8
(DIRECTORY)
LOAD"$",8
Beliebiges Programm laden:
LOAD"Name",8 bzw. LOAD"Name1’,8
(DLOAD"Name" bzw.
DLOAD"Name"D1)
LOAD"Name",8
Beliebiges Programm sichern:
SAVE"Name",8 bzw. SAVE"NameT",8
(DSAVE"Name" bzw. DSAVE"Name",D1)
SAVE"Name",8
Datei löschen:
OPEN 1,8,15,"S0:Name" bzw. OPEN 1,8,15,"S1:Name"
(SCRATCH"Name",DO bzw. SCRATCH"Name",D1)
OPEN 1,8,15,"S:Name"
Datei umbenennen:
OPEN 15,8,15:
PRINT15,"R0:Neu=0:Alt" bzw. OPEN 15,8,15:PRINT15,"R1:Neu=1:Alt"
(RENAME D1, "Alt"TO"Neu" bzw. RENAME DO,"Alt"TO"Neu")
OPEN 15,8,15:
PRINT15,"R:Neu=Alt"
Tabelle 4. Vergleich der Befehle für die Laufwerke 4040 und 1541

Zum Schluß noch einige wichtige Zero-Page-Adressen zum Vergleich in Tabelle 5 (aus urheberrechtlichen Gründen dürfen die vollständigen Listen leider nicht abgedruckt werden).

CBM C64 Bedeutung
Hex Dezimal Hex Dezimal
0028-0029 40-41 002B-002C 43-44 Zeiger auf Basic-Anfang
002A-002B 42-43 002D-002E 45-46 Zeiger auf Variablen Anfang
002C-002D 44-45 s.u. Zeiger auf Ende der Variablentabelle
s.o. 002F-0030 47-48 Zeiger auf Beginn der Felder
002E-002F 46-47 0031-0032 49-50 Zeiger auf Ende der Felder
0030-0031 48-49 0033-0034 51-52 Zeiger auf Beginn der Strings (rückwärts)
0032-0033 50-51 0037-0038 55-56 Zeiger auf Ende der Strings (= Speichergrenze)
0036-0037 54-55 0039-003A 57-58 laufende Zeilennummer
0038-0039 56-57 003B-003C 59-60 vorhergehende Zeilennummer
003A-0038 58-59 003D-003E 61-62 nächster Befehl (für CONT)
003C-003D 60-61 003F-0040 63-64 aktuelle DATA-Zeile
003E-003F 62-63 0041-0042 65-66 aktuelles DATA-Element (Adresse)
0042-0043 66-67 0045-0046 69-70 aktueller Variablenname
0044-0045 68-69 0047-0048 71-72 Zeiger auf aktuelle Variable
0046-0047 70-71 0049-004A 73-74 Variablenzeiger für FOR...NEXT
0070-0087 112-135 0073-008A 115-138 diese Routine holt nächstes Basic-Zeichen
0088-008C 136-140 008B-008F 139-143 Zufallszahl
008D-008F 141-143 00A0-00A2 160-162 interne Uhr
0097 151 00CB 203 gedrückte Taste
00A7 167 00CC 204 Cursor an/aus (0=an,1=aus)
00C6 198 00CA 202 Spaltenposition des Eingabecursors
00D8 216 00C9 201 Zeilenposition des Eingabecursors
00FD-00FF 253-255 00FB-00FE 251-254 freier Platz für Zeiger in Page 0
026F-0278 623-632 0277-0280 631-640 Tastaturpuffer
Tabelle 5. Die wichtigsten Zero-Page Adressen

Lösung des Beispielprogramms »Kanone« für CBM:

1 REM KANONE
5 ZA = 33728:ZE = 33767:OP = 33748
10 DIM A%(255)
20 A%(26) = -1:A%(18) = 1:REM (Für CBM 30XX)
oder
20 A%(49) = 1:A%(50) = 1:REM (Für CBM 40XX)
1000 REM Abfrage und Zeichen setzen, Subroutine
1010 NP = OP + A%(PEEK(151)):REM neue Position
1020 IF NP>ZE OR NP<ZA THEN NP = OP: REM Zeilenbegrenzung
1030 POKE OP, 32:REM alte Position löschen
1040 POKE NP,30:REM neue Position setzen
1050:
1060 OP = NP
1070 RETURN

Und nun viel Erfolg beim Umschreiben!

(M. und J. Heinz/rg)
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →