Tips und Tricks zum C 128

Wir haben Ihnen wieder neue und nützliche Tips, Tricks und Befehle zu bieten. Einen kleinen Kurs, OLD- und Spritebefehle sowie eine bessere INPUT-Routine.

Wieder einmal bieten wir Ihnen kleine Kniffe und Routinen, die Ihnen helfen werden, leichter mit Ihrem C 128 umzugehen.

Die Floppy 1571 und Originalprogramme

Es häufen sich die Anfragen von Lesern, wonach sich ein Teil ihrer gekauften Programme nicht in den Computer laden lassen. Diesen Lesern möchten wir nun Antwort geben. Die in den Floppylaufwerken VC 1541 und VC 1571 eingebauten DOS-Versionen (Floppy-Betriebssystem) sind untereinander leider nicht voll kompatibel. Originalprogramme sind jedoch in der Regel mit einem Kopierschutz versehen. Wenn dieser Schutz einer der besseren Art ist, so benutzt er das FloppyDOS für seine Routinen. Diese Routinen sind jedoch auf das DOS der VC 1541 zugeschnitten. Versucht der Kopierschutz nun, eine Routine in der VC 1571 auszuführen, die von der der VC 1541 abweicht, so kann die Kopierschutzabfrage nicht mehr richtig ausgeführt werden und das Programm läßt sich nicht weiter laden. Dagegen ist leider kein Kraut gewachsen. Hier sind die Benutzer von Raubkopien leider in der besseren Lage, da aus einem »gecrackten« Programm eben diese Abfragen entfernt wurden.

(dm)

Die Variablen-Behandlung beim C 128

Das Format der Integer- und Gleitkommavariablen im C 128-Modus ist identisch mit denen im C 64-Modus. Nur bei den Stringvariablen hat sich das Format geändert. Es wird genau wie beim C 64 ein Stringdeskriptor angelegt, der die Adresse, an der der String tatsächlich abgelegt wurde und die Länge des Strings beinhaltet. An den Inhalt des Strings, also an seine ASCII-Zeichen, wird wie beim CBM 8032 ein Zwei-Byte-Zeiger angehängt. Dieser zeigt auf das Längenbyte im Stringdeskriptor. Zwar wird dadurch mehr Platz im Speicher benötigt, der Vorteil ist jedoch unschätzbar — die berühmt gefürchtete »Garbage Collection« schlägt nicht mehr in dem vom C 64 gewohnten Ausmaß zu. Es wird nur noch höchstens eine Sekunde zur »Stringmüllbeseitigung« gebraucht.

Die Variablenformate

In der folgenden Aufstellung steht »NAME« für den ASC-Wert eines Zeichens.

Integer-Variable

Die ganzzahligen Integer-Variablen werden in zwei Speicherzellen mit dem höchstwertigen Byte (MSB) an erster Stelle abgelegt. Es sind vorzeichenbehaftete Zahlen im Bereich von -32768 bis + 32767. Ist das höchstwertige Bit in einer Zahl gesetzt, so ist sie negativ. Im Commodore-Basic werden Integer-Variablen durch ein nachgestelltes Prozentzeichen dargestellt (zum Beispiel AA% oder Z%). Für die interne Kennzeichnung werden in den beiden Namen-Bytes die höchstwertigen Bits gesetzt.

Einzelvariable

Jede Einzelvariable belegt 7 Byte. Den Aufbau ersehen Sie aus Bild 1:

Name 1 + 126 Name 2 + 128 MSB LSB 00 00 00
Bild 1. Aufbau einer Integer-Variable

Felder

Ein Feld belegt 5 + 2 x Dimension + (Dimension n x Dimension (n-1) x Dimension (n-2)…) x 2 Byte.

Aufbau des Deskriptorblockes

  1. Byte Name + 128
  2. Byte Name + 128
  3. Byte Gesamtlänge Array (Lowbyte)
  4. Byte Gesamtlänge Array (Highbyte)
  5. Byte Anzahl der Dimensionen
  6. Byte Anzahl Elemente Dimension n, Low
  7. Byte Anzahl Elemente Dimension n, High
  8. Byte Anzahl Elemente Dimension n-1, Low
  9. Byte Anzahl Elemente Dimension n-1, High und so weiter für die restlichen Dimensionen.

Die Feldelemente werden direkt hinter dem Deskriptorblock in je 2 Byte (MSB-LSB) gespeichert (siehe Bild 2).

MSB 1 LSB 1 MSB 2 LSB 2 etc.
Bild 2. So liegen die Feldelemente hintereinander

Bei mehrdimensionalen Feldern wird die letzte Dimension als erste angelegt.

Gleitkomma-Variable

Die Gleitkommazahlen sind in 5 Byte abgelegt. Im ersten Byte wird der Exponent gespeichert. Die Mantisse liegt in den folgenden 4 Byte als 32-Bit vorzeichenbehaftete Zahl. Die Gleitkommazahlen werden im Commodore-Basic nur durch die ASC-Werte der ersten beiden Zeichen dargestellt (zum Beispiel AA oder B).

Intern wird die Gleitkommazahl mit ihrem Namen in 2 Byte mit den ASC-Werten gekennzeichnet. Besteht der Name nur aus einem Zeichen, so lautet das zweite Byte Null.

Einzelvariable

Jede Einzelvariable belegt 7 Byte, wie Sie aus Bild 3 ersehen können.

Name 1 Name 2 + 128 Exponent Mantisse 32-Bit
Bild 3. Aufbau einer Gleitkomma-Variable

Felder

Ein Feld belegt 5 + 2 x Dimension + (Dimension n x Dimension (n-1) x Dimension (n-2)…) x 2 Byte.

Aufbau des Deskriptorblockes

  1. Byte Name + 128
  2. Byte Name + 128
  3. Byte Gesamtlänge Array (Lowbyte)
  4. Byte Gesamtlänge Array (Highbyte)
  5. Byte Anzahl der Dimensionen
  6. Byte Anzahl Elemente Dimension n, Low
  7. Byte Anzahl Elemente Dimension n, High
  8. Byte Anzahl Elemente Dimension n-1, Low
  9. Byte Anzahl Elemente Dimension n-1, High und so weiter für die restlichen Dimensionen.

Die Feldelemente werden direkt hinter dem Deskriptorblock in je fünf Speicherzellen gespeichert. (Siehe Bild 4)/

Expon 1 Mantisse 1 Expon 2 Mantisse 2 usw.
Bild 4. Und auf diese Weise liegen die Feldelemente im Speicher

Bei mehrdimensionalen Feldern wird die letzte Dimension als erste angelegt.

Stringvariable

Stringvariablen werden in zwei Teilen gespeichert. In einem Deskriptorblock finden sichdie für die Verwaltung notwendigen Angaben. Im oberen RAM-Bereichwird der String selbst als Folge von ASC-Werten abgelegt. Im Deskriptorblock zeigt ein Zeiger auf eine Adresse im oberen RAM-Bereich, an der der String abgelegt ist. Jeder String wird von einem Zwei-Byte-Zeiger, der auf das Längen-Byte im Deskriptor zeigt, abgeschlossen.

Aufbau der ASCII-Zeichenformate

Text-String Zeiger
Lowbyte Highbyte

Im Commodore-Basic werden Stringvariable mit einem nachgestellten Dollarzeichen dargestellt (zum Beispiel A$ oder AB$). Intern werden Strings mit 2 Byte gekennzeichnet, wobei das höchstwertige Bit im zweiten Namen-Byte gesetzt ist. Besteht der Name nur aus einem Byte, so hat das zweite Namen-Byte den ASC-Wert 128.

Einzelvariable

Jede Einzelvariable belegt 7 Byte und im oberen RAM-Bereich zwei Byte + Länge des Strings. Der Aufbau wird aus Bild 5 ersichtlich.

Name 1 Name 2 + 128 String-länge Zeiger in RAM 00 00
low high
Bild 5. Aufbau einer einzelnen Stringvariable

Felder

Jedes Feld belegt 5 + 2 x Dimension-Byte + (Dimension n x Dimension (n-1) x Dimension (n-2)…) x 3 und im oberen RAM-Bereich (Länge aller Strings + (2 x Anzahl aller Strings)). Es müssen nur Strings, deren Länge größer Null ist, berücksichtigt werden.

Aufbau des Deskriptorblockes

  1. Byte Name + 128
  2. Byte Name + 128
  3. Byte Gesamtlänge Array (Lowbyte)
  4. Byte Gesamtlänge Array (Highbyte)
  5. Byte Anzahl der Dimensionen
  6. Byte Anzahl Elemente Dimension n, Low
  7. Byte Anzahl Elemente Dimension n, High
  8. Byte Anzahl Elemente Dimension n-1, Low
  9. Byte Anzahl Elemente Dimension n-1, High und so weiter für die restlichen Dimensionen.

Die Feldelemente werden direkt hinter dem Deskriptorblock in je 3 Byte gespeichert (Bild 6).

String 1 länge Zeiger 1 low/high String 2 länge Zeiger 2 low/high usw.
Bild 6. Lage der Feldelemente hinter dem Deskriptorblock

Bei mehrdimensionalen Feldern wird die letzte Dimension als erste angelegt.

Funktionsvariable

Funktionen, die man mit der Anweisung
DEF FN name(var) = ausdr.
definiert, werden von Basic ebenfalls als Variable mit dem Namen »name« im RAM abgelegt.

Intern wird das höchstwertige Bit im ersten Namen-Byte gesetzt. Hat der Variablenname nur ein Zeichen, so ist das zweite Namen-Byte Null. Im Gegensatz zu den anderen Variablen gibt es aber hier keine Felder.

Jede Funktionsvariable belegt 7 Byte und im oberen RAM-Bereich 2 + Länge der Funktionsvariablen. Ansonsten entspricht die Ablage der einen einfachen Stringvariablen (Bild 7).

Name 1 + 128 Name 2 String-länge Zeiger in RAM 00 00
low high
Bild 7. Anordnung einer Funktionsvariablen

Damit sind alle Variablentypen, die der C 128 kennt, dargestellt.

Im Normalzustand werden die Variablen in Bank 1 ab Adresse $0400 (dezimal 1024) aufwärts und die Inhalte der Strings und Funktionsvariablen ab Adresse $FEFF (dezimal 65279) abwärts gelegt.

In Tabelle 1 sind die Adressen einiger Zeiger aus der erweiterten Zeropage, die für die Verwaltung der Variablen wichtig sind, aufgeführt. Die aktuellen Adressen in der jeweiligen Bank kann man leicht nach folgender Formel berechnen:
Adresse = PEEK(Zeigeradresse) +
PEEK(Zeigeradresse +1) * 256

Label Adresse Funktion
Dez Hex
TXTTAB 45 002D Zeiger auf Start BASIC B0
VARTAB 47 002F Zeiger auf Start Variablen B1
ARYTAB 49 0031 Zeiger auf Start Variablenfelder B1
STREND 51 0033 Zeiger auf Ende der Variablenfelder + 1 B1
FRETOP 53 0035 Zeiger auf Start String B1
FRESPC 55 0037 Hilfszeiger für Stringverwaltung
MAXME1 57 0039 Höchste verfügbare Variablenadresse B1
BASTOP 4624 1210 Zeiger auf BASIC-Text Ende B0
MAXME0 4626 1212 Höchste verfügbare BASIC-Text-Adresse B0
Tabelle 1. Wichtige Adressen (B0/B1 entspricht Bank 0/1)

Doch Achtung: Zum Nachschauen muß man dann noch die richtige Bank angeben.

(Michael Bauer/dm)

Anti-C 128-POKE

Wer seinen C 128 häufiger im C 64-Modus benutzt, wird feststellen, daß dies der Commodore-Taste nicht unbedingt gut tut. Und das Umschalten mit GO 64 wird mit der Zeit auch lästig.

Gibt man im C 128-Modus folgende Zeile im Direkt- oder Programmodus ein, so springt der C 128 in den C 64-Modus und ist auch durch einen Reset nicht mehr in den C 128-Modus zu bringen.
BANK1:POKE 65528,77:POKE 65529,255:GO 64

(M. Güthling/dm)

Neue Befehle und Tri<ks für den C 128

Das Handbuch des Commodore 128 ist zwar etwas besser geraten als beim C 64, trotzdem lassen sich noch einige Fehler finden. So wurde beschrieben, daß die Umschaltung auf die DIN-Tastatur mit POKE 1,PEEK(1) AND 191 im Programm erfolgen kann. Vor diesem POKE ist aber noch das Datenrichtungsregister auf Ausgabe zu setzen. Dies erfolgt mit POKE 0, PEEK (0) OR 64. Mit POKE 1, PEEK(1) OR 64 wird die ASCII-Tastatur wieder aktiviert. Weiterhin wurde behauptet, daß mit POKE 2757,129 die Umschaltmöglichkeit auf die DIN-Tastatur verhindert werden kann und nur ein Druck auf den Reset-Knopf dies rückgängig macht. POKE 2757,0 tut es auch.

ESC 0 schaltet den Einfüge-, Anführungs- und Invers-Modus aus. Wenn Sie die ESC-Taste zweimal kurz hintereinander drücken, erreichen Sie den gleichen Effekt, nur schneller.

Der USR-Vektor wurde nur für den C 64-Modus beschrieben und das auch noch falsch. Im C 64-Modus liegt der USR-Vektor an den Speicherstellen 785 und 786 und im C 128-Modus bei 4633 und 4634.

Im C 128-Modus hat der Basic-Interpreter eine Verbesserung aufzuweisen. Während beim C 64 die Abfrage auf einen Leerstring beim ASC-Befehl die Fehlermeldung ILLEGAL QUANTITY hervorruft, erhalten Sie beim C 128 als Ergebnis den Wert 0.

Um Zahlen in andere Zahlensysteme umzurechnen, gibt es beim C 128 die Befehle DEC und HEX$. Mit dem eingebauten Maschinensprachenmonitor haben Sie eine sehr komfortable Möglichkeit zur Zahlenumrechnung. Sie rufen mit dem Befehl MONITOR den Maschinensprachenmonitor auf und geben die umzurechnende Zahl mit vorangestelltem Umrechnungssymbol ein ($ = hexadezimal, + = dezimal, & = oktal und °/o = binär). Wenn Sie nun die RETURN-Taste drücken, so wird die Zahl in allen vier Zahlensystemen ausgegeben.

Zum Spritehandling gibt es beim C 128 komfortable Befehle. So können Sprites unabhängig vom laufenden Programm bewegt werden. Dieses geschieht in der Interruptroutine. In der Speicherstelle 4861 steht ein Flag, welches angibt, ob die Interruptroutine für die Spritesteuerung ausgeführt werden soll. Wenn Sie in diese Speicherstelle einen Wert ungleich Null schreiben, so bleiben alle Sprites sofort stehen. Aber Achtung! Der PLAY-Befehl funktioniert dann nicht mehr. Mit POKE 4861,0 bewegen sich die Sprites weiter. Für die Geschwindigkeit können beim MOVSPR-Befehl Werte bis 15 angegeben werden. Wenn Sie aber direkt die Register für die Spritegeschwindigkeit mit POKE ansprechen, so sind auch höhere Geschwindigkeiten möglich. Errechnen läßt sich die Speicherstelle durch 4478+(SN-1)*11. Hierbei steht SN für die Spritenummer (1 bis 8). Wollen Sie die Spritegeschwindigkeit drosseln, so können Sie dies mit dem Programm SPRITES-LOW (Listing 1) tun. Mit
BANK 15: SYS DEC("1300"),X
wird das Programm aufgerufen. Für X setzen Sie den Wert der Verzögerung ein. Die Spritegeschwindigkeit, die mit dem Befehl MOVSPR eingegeben wurde, sollte aber nicht größer als 1 sein. Experimentieren Sie ruhig ein bißchen!

Kommen wir gleich zum zweiten Maschinenprogramm (Listing 2). Dies Programm rekonstruiert ein mit NEW gelöschtes Programm. Solange noch keine neuen Programmzeilen eingegeben wurden, kann mit
BANK 0: SYS DEC("1300")
ein mit NEW oder nach einem RESET gelöschtes Programm gerettet werden.

Das Basic V 7.0 wurde zwar um etliche Befehle erweitert, trotzdem gibt es immer noch keinen vernünftigen INPUT-Befehl. Die Eingaberoutine aus Listing 3 können Sie als Unterprogramm in Ihren eigenen Programmen benutzen.

Es erlaubt, nur bestimmte Zeichen einzugeben. Außerdem kann eine maximale Eingabelänge festgelegt werden. Zu diesem Programm nun noch einige Erklärungen:

In Zeile 45 werden die erlaubten Zeichen der Stringvariablen EZ$ übergeben. In Zeile 50 wird in der Variablen Ql die maximale Eingabelänge festgelegt und das Unterprogramm mit GOSUB 100 aufgerufen. Nach der Rückkehr aus dem Unterprogramm steht die Eingabe in der Stringvariablen Y2$. In der Eingaberoutine wird in Zeile 110 der aktuelle Cursormodus der Variablen Q9 übergeben und mit POKE 2598,0 der blinkende Cursormodus eingeschaltet. POKE 2599,01äßt den Cursor auch bei dem Befehl GET oder GETKEY blinken. Zeile 150 prüft auf die maximale Eingabelänge und Zeile 160 auf die erlaubten Zeichen. Wird versucht, unerlaubte oder zuviele Zeichen einzugeben, so wird dies durch ein akustisches Signal angezeigt. Zeile 180wartet darauf, daß der Cursor sich nicht in der Blinkphase befindet. Wurde Return gedrückt, so wird mit POKE 2599,1 das Cursorblinken bei GET wieder ausgeschaltet und der vorher in Q9 festgehaltene Cursormodus in Speicherstelle 2598 eingetragen.

PROGRAMM : SPRITESLOW C128 1300 132D
-----------------------------------
1300 : 78 85 FA 85 FB A9 11 8D   16
1308 : 14 03 A9 13 8D 15 03 58   A9
1310 : 60 C6 FA A5 FA D0 0C A9   00
1318 : 00 8D FD 12 A5 FB 85 FA   E7
1320 : 4C 65 FA A9 01 8D FD 12   AB
1328 : 4C 65 FA 00 13            E3
Listing 1. Das Monitorlisting der Routine »Spriteslow«
PROGRAMM : OLD C128       1300 134C
-----------------------------------
1300 : A5 2D A4 2E 85 FA 84 FB   65
1308 : A0 03 C8 B1 FA D0 FB C8   4A
1310 : 98 18 65 FA A0 00 91 2D   18
1318 : A5 FB 69 00 C8 91 2D A5   2E
1320 : 2D 85 FA A5 2E 85 FB A0   C3
1328 : 01 B1 FA F0 0B AA 88 B1   6A
1330 : FA 85 FA 86 FB 4C 27 13   61
1338 : A5 FA 18 69 02 8D 10 12   7F
1340 : 90 02 E6 FB A5 FB 8D 11   9D
1348 : 12 60 01 1C               E5
Listing 2. Monitor-Auszug des neuen OLD-Befehls
10 :rem  eingaberoutine mit getkey
20 :
30 :
40 :rem beispiel einer eingabe
45 ez$="1234567890+-."
50 print"eingabe : ";:q1=5:gosub100:eg$=y2$:end
60 :
100 rem  beginn der eingaberoutine
110 q9=peek(2598):poke2598,0:q4=0:y2$="":poke2599,0
120 getkeyy1$
130 ify1$=chr$(13)then220
140 ify1$=chr$(20)then270
150 ifq4=q1thenprintchr$(7);:goto120
160 q5=instr(ez$,y1$):ifq5=0thenprintchr$(7);:goto120
170 poke2600,2
180 ifpeek(2598)then180
190 printy1$;:y2$=y2$+y1$:q4=q4+1:goto120
200 :
210 : rem return gedrueckt
220 poke2600,2
230 ifpeek(2598)then230
240 poke2599,1:poke2598,q9:return
250 :
260 : rem del taste gedrueckt
270 ifq4=0thenprintchr$(7);:goto120
280 poke2600,2
290 ifpeek(2598)then290
300 printchr$(20);:q4=q4-1:y2$=left$(y2$,q4):goto120
Listing 3. Eine verbesserte Eingaberoutine für den C 128
(Herbert Kunz/dm)

Eine Grafik-Spielerei

Mit dieser kleinen Routine können Sie bezaubernde Grafik-Bilder erzeugen. Durch Verändern des Wertes X können die Steigungen der Kurven variiert werden. Ebenfalls kann man einen verkleinernden oder vergrößernden Faktor wählen (Zeile 30).
10 GRAPHIC 1,1
20 FOR A = 200 T0 0 STEP-3
30 B=B+3
40 CIRCLE, 160, 100, A, A, 0, 0, B, X
50 NEXT

(Guido Ädolphs/dm)
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →