C 64
Tips und Tricks

Tips & Tricks für Profis

Nachdem die Anfänger unter den C 64-Fans nun ihre eigene Rubrik haben, sollen natürlich die Profis auch nicht zu kurz kommen. Sicher wird auch für diese Lesergruppe noch der eine oder andere unbekannte Trick dabei sein.

Wer sich als echter Profi bezeichnet, wird bei der Durchsicht unserer Tips & Tricks-Sammlung sicher ab und zu in ein leichtes Schmunzeln verfallen. Es ist bei manchen Beiträgen nämlich gar nicht so leicht, sie eindeutig den Anfängern beziehungsweise den Profis zuzuordnen. Wir hoffen aber trotzdem, eine gute Auswahl getroffen zu haben.

Nun unsere Bitte an Sie: Helfen Sie den vielen Anfängern unter unseren Lesern mit kleinen, leicht verständlichen Tricks, die vielleicht für Sie schon ein »alter Hut« sein mögen, den Einsteigern jedoch eine große Hilfe sein werden. Jeder Beitrag, ob Einzeiler, Programmiertrick oder sonstiges, ist willkommen. Achten Sie auch bitte auf eine leicht verständliche, einfach geschriebene Anleitung.

(tr)

OLD-Funktion für Variablen

Dieses Programm (Listing 1) holt nicht nur ein Basic-Programm nach NEW, CLR oder einem Reset zurück, sondern auch sämtliche Variablen, Strings und Felder.

Da arbeitet man an einem phänomenalen Basic-Programm und tippt »CLR« statt »CLOSE« oder »NEW« statt NEXT in seinen Computer ein, oder dieser hängt sich selbst auf — und die Variablen sind weg, die womöglich den Grund für den Absturz in sich bergen!

Oder: Man lädt ein Maschinenprogramm in den $C000-Bereich, und nach »RUN« erfolgt ein »?OUT OF MEMORY ERROR«, weil die Basic-Ende-Zeiger verstellt wurden.

Das Maschinenprogramm, welches dabei entstand, steht ab $C000 im Speicher (kann verschoben werden), benötigt 115 Byte Speicherplatz und wird einfach mit »SYS 49152« aufgerufen.

Es können, wie gesagt, alle Werte und sogar definierte Funktionen und Felder zurückgeholt werden. Allerdings bestehen da noch drei kleine Bedingungen:

  1. Es muß vorher bereits ein Basic-Programm im Speicher gestanden haben (mindestens: »10 :«).
  2. Es darf vor Aufrufen der Routine kein Variablen-Programm eingegeben oder ein Feld abgefragt worden sein.
  3. Die erste Dimensionierung eines Feldes muß ein Stringfeld sein. Beispiele:
    • »DIM DE(20),DE$(20)« muß umgestellt werden zu »DIM DE$(20),DE(20)«
    • »DIM E(34)« muß ergänzt werden zu »DIM A$(0),E(34)« (A$(0) genügt schon!!)

Diese Ergänzung braucht der Computer nämlich, um zu erkennen, daß in die Array-Behandlung gesprungen werden muß, sonst entsteht ein Fehler.

Funktionsweise

Der Computer untersucht das erste Byte nach dem Basic-Programm-Ende. Wenn dieses ein Buchstabe ist, prüft er es auf Stringvariable. Wenn nicht, wird der Zähler einfach um 7 Byte (zwei Namensbyte und fünf Informationsbyte) erhöht und diese übergangen.

Wenn aber eine Stringvariable gefunden wurde, untersucht er Byte 6 und 7. Diese sind bei einem String nämlich immer Null, weil sie hier nicht gebraucht werden; bei einem Feldkopf hingegen ist die Anzahl der Elemente der Dimensionierung des folgenden Feldes darin abgelegt: Wenn der Computer also eine numerische als erste Dimensionierung findet, hält er sie für eine normale numerische Variable (denn eine andere Erkennung ist hier leider nicht möglich!) und nicht für den ersten Feldkopf der Arrays, gibt einen falschen und unsinnigen Wert für die meist nicht vorhandene einfache Variable und findet auch die restlichen Felder nicht mehr!

Wenn keine Buchstaben mehr gefunden werden, wird noch eine Garbage-Collection durchgeführt, um die Stringzeiger wieder nachzustellen.

Beachten Sie bitte:

Falls Sie zum Beispiel eingeben
10DIM A$(30),B$(10)
20CLR
30DIM A$(30)
40SYS 49152
wird automatisch A$(30), aber auch B$(10) zurückgeholt!!

Tip: Das Programm kann auch nach einem »NEW«, »CLR« oder »Reset« eingeladen werden. Sie können das Programm auch auf anderen Speicherbereichen laufen lassen (zum Beispiel im Kassettenpuffer). Dazu müssen Sie die beiden Sprungbefehle C04B JMP C018 C06A JMP C04E jeweils anpassen (und die SYS-Adresse). Mit dem SMON ist das Verschieben ja kein Problem.

Übrigens: Bild 1 zeigt das dokumentierte Assemblerlisting von »RE-CLR«.

(Andreas Blödow/tr)
LABEL         LOC         CODE                STATEMENT

STPRG         0000                        *=        $C000
Old           C000      A0    01          LDY       #01
              C002      98                TYA
              C003      91    2B          STA       (2B),Y        eine "NEW-Null" löschen (mit 1 überschreiben)
              C005      20    33    A5    JSR       A533          Basic-Zeilen neu binden
              C008      18                CLC
              C009      A5    22          LDA       22
              C00B      69    02          ADC       #02
              C00D      85    2D          STA       2D
              C00F      A5    23          LDA       23            Programmende (= Zeiger + 2 Nullen) überlesen
              C011      69    00          ADC       #00
              C013      85    2E          STA       2E
              C015      20    60    A6    JSR       A660          zum CLR-Befehl
-----------------------------------------------------------------------------------------------------------------------------
Variablen     C018      A0    00          LDY       #00
              C01A      B1    2F          LDA       (2F),Y        1.Byte nach Programmende
              C01C      AA                TAX                     retten
              C01D      29    7F          AND       #7F           Bit 7 löschen
              C01F      20    13    B1    JSR       B113          Buchstabe?
              C022      90    49          BCC       C06D          nein, denn fertig
              C024      8A                TXA
              C025      0A                ASL                     war Bit 7 gesetzt?
              C026      B0    10          BCS       C038          ja, kein String (sondern Integervariable oder Funktion),
              C028      C8                INY                     Arrayerkennungsschleife überspringen
              C029      B1    2F          LDA       (2F),Y        2. Namensbyte
              C02B      10    0B          BPL       C038          kleiner als $80, also REAL-Variable, kein String
              C02D      A0    05          LDY       #05
              C02F      B1    2F          LDA       (2F),Y        6. Byte des Strings
              C031      D0    1B          BNE       C04E          ungleich Null => Array-Feldkopf, kein String
              C033      C8                INY
              C034      B1    2F          LDA       (2F),Y        7. Byte des Strings
              C036      D0    16          BNE       C04E          ungleich Null => Array-Feldkopf, kein String
              C038      A0    07          LDY       #07
              C03A      E6    2F          INC       2F
              C03C      D0    02          BNE       C040
              C03E      E6    30          INC       30            7 Bytes überlesen
              C040      88                DEY
              C041      D0    F7          BNE       C03A
              C043      A5    2F          LDA       2F
              C045      85    31          STA       31
              C047      A5    30          LDA       30            Array-Ende = Variablen-Ende
              C049      85    32          STA       32
              C04B      4C    18    C0    JMP       C018          und weitermachen, nächstes Element prüfen
-----------------------------------------------------------------------------------------------------------------------------
ARRAY         C04E      A0    00          LDY       #00
              C050      B1    31          LDA       (31),Y        1.Byte nach Variablenende
              C052      29    7F          AND       #7F           Bit 7 löschen
              C054      20    13    B1    JSR       B113          Buchstabe?
              C057      90    14          BCC       C06D          nein, dann fertig, keine Felder mehr
              C059      C8                INY
              C05A      C8                INY
              C05B      18                CLC
              C05C      B1    31          LDA       (31),Y        Feldlänge Low-Byte
              C05E      65    31          ADC       31            zu Array-Ende-Zeiger addieren und merken
              C060      AA                TAX
              C061      C8                INY
              C062      B1    31          LDA       (31),Y        Feldlänge High-Byte
              C064      65    32          ADC       32            zu Array-Zeiger addieren
              C066      85    32          STA       32            Feld überlesen und
              C068      86    31          STX       31            Array-Zeiger auf Feld-Ende positionieren
              C06A      4C    4E    C0    JMP       C04E          und weitermachen
-----------------------------------------------------------------------------------------------------------------------------
Ende          C06D      20    26    B5    JSR       B526          Garbage-Collection: Stringzeiger nachstellen
              C070      4C    AE    A7    JMP       A7AE          zurück zur Interpreterschleife
Bild 1. Das dokumentierte Assembler-Listing zu »RE-CLR«
PROGRAMM : RE-CLR         C000 C073
-----------------------------------
C000 : A0 01 98 91 2B 20 33 A5   45
C008 : 18 A5 22 69 02 85 2D A5   F5
C010 : 23 69 00 85 2E 20 60 A6   4B
C018 : A0 00 B1 2F AA 29 7F 20   3D
C020 : 13 B1 90 49 8A 0A B0 10   35
C028 : C8 B1 2F 10 0B A0 05 B1   C4
C030 : 2F D0 1B C8 B1 2F D0 16   AB
C038 : A0 07 E6 2F D0 02 E6 30   14
C040 : 88 D0 F7 A5 2F 85 31 A5   12
C048 : 30 85 32 4C 18 C0 A0 00   5B
C050 : B1 31 29 7F 20 13 B1 90   57
C058 : 14 C8 C8 18 B1 31 65 31   A2
C060 : AA C8 B1 31 65 32 85 32   63
C068 : 86 31 4C 4E C0 20 26 B5   75
C070 : 4C AE A7                  F0
Listing 1. »RE-CLR«. Verwenden Sie zur Eingabe bitte den MSE.

Wersiboard und Sound-Editor

Das Programm »Sound-Editor« aus der 64’er ist eines der besten (oder sogar das beste) Synthesizerprogramm, das es für den C 64 gibt.

Einzigstes Manko ist, daß man sich jedes Mal die Finger verknotet, wenn man versucht, eine Melodie zu spielen. Überdies muß man eine Ewigkeit (verglichen mit anderen Programmen) warten, ehe eine angeschlagene Note auch tatsächlich erklingt. So erkannte ich also, daß zwei Dinge fehlten:

  1. ein Programm, welches die gespielten Noten schneller zu Gehör bringt, und
  2. eine professionelle Klaviatur.

Das kurze Maschinenprogramm (Listing 2) übernimmt die Abfrage des Wersiboards und ahmt im wesentlichen die Arbeitsweise der originalen Basic-Routine in Ausgabe 7/85 (Zeilen 2025 bis 2160) nach. Der größte Unterschied besteht darin, daß die Maschinenroutine eine Tabelle mit Frequenzwerten ab Speicherstelle dezimal 52948 erwartet, aus der sie die aktuelle Frequenz holt. Im Basic-Programm wird dies mit »f*bf(sn)« gelöst. Meine Vorgehensweise hat den Nachteil, daß die Frequenztabelle bei jedem Wechsel der Frequenz (Untermenü »Stimmen-Parameter« Punkt »F«) neu angelegt werden muß.

Die Basic-Zeilen 20000 bis 20080 im Listing 3 erfüllen diese Aufgabe. Dieses Basic-Listing ist übrigens für sich als Programm nicht lauffähig und nur in Verbindung mit dem Sound-Editor (Ausgabe 7/85) sinnvoll!

Die Bedienung des wersiboardfähigen Sound-Editors ist denkbar einfach: Die normale Computertastaturabfrage bleibt erhalten. Ändern Sie die Frequenzwerte, ist die Änderung zunächst nur über diese zu bemerken; das Wersiboard ist noch auf die alten Frequenzwerte gestimmt.

Dies können Sie jedoch ändern, indem Sie die Tastenkombination »Shift-W« betätigen. Die oben erwähnte Frequenztabelle wird sodann erneuert.

Viel mehr ist beim erweiterten Sound-Editor nicht zu beachten, alle übrigen Parameter des erweiterten Sound-Editors sind direkt nach einer Änderung ohne zusätzliche Maßnahmen auch über das Wersiboard spielbar.

Sie sollten jedoch darauf achten, daß Sie keine Oktave über vier einstellen; denn der C 64 kann nur acht Oktaven darstellen. Das Wersiboard reicht aber über vier Oktaven, und rechnen Sie mal 5+4… Achten Sie also im Untermenü »Stimmen-Parameter« auf eine entsprechende Einstellung.

Ein Tip zum Sound-Editor: Schalten Sie im Untermenü Filter/Laut. immer »FiltEx« ein. Das Hintergrundrauschen wird dadurch beträchtlich vermindert.

Und nun zur Vorgehensweise bei der Eingabe der Erweiterung:

  1. Laden Sie den Sound-Editor und geben Sie die zusätzlichen Basic-Zeilen ein. Diese enthalten alle neuen Zeilen sowiejene, die nur geändert werden.
  2. Speichern Sie den erweiterten Sound-Editor wieder (zum Beispiel unter dem Namen »Sound-Editor +«).
  3. Laden Sie den MSE und geben Sie mit ihm die wenigen Hexazeilen ein; »SAVEn« Sie das Programm unter dem Namen »Wersi« auf der Diskette, auf der sich auch die anderen zum Sound-Editor gehörenden Routinen befinden.
  4. Fertig!

Laden Sie nun ganz normal den erweiterten Sound-Editor und starten Sie ihn mit »RUN«.

Und nun viel Spaß mit dem Wersiboard plus Sound-Editor!

(Helge Kautz/tr)
PROGRAMM : WERSI          C864 C922
-----------------------------------
C864 : A9 72 8D E0 03 A2 07 A0   68
C86C : 08 BD FF DE CE E0 03 CE   CC
C874 : E0 03 2A 90 07 88 D0 F4   54
C87C : CA D0 EC 60 AE E0 03 AD   4F
C884 : D5 03 C9 01 D0 12 BD D4   AC
C88C : CE 8D 00 C0 BD D5 CE 8D   1A
C894 : 01 C0 AD DB 03 8D 04 D4   32
C89C : AD D6 03 C9 01 D0 12 BD   09
C8A4 : 36 CF 8D 07 C0 BD 37 CF   7D
C8AC : 8D 08 C0 AD DC 03 8D 0B   55
C8B4 : D4 AD D7 03 C9 01 D0 12   C1
C8BC : BD 98 CF 8D 0E C0 BD 99   7C
C8C4 : CF 8D 0F C0 AD DD 03 8D   27
C8CC : 12 D4 AD DE 03 C9 01 D0   B4
C8D4 : 08 AD 48 C0 09 01 8D 48   3C
C8DC : C0 AD DF 03 C9 01 F0 3C   AC
C8E4 : 4C EE C8 AD E0 03 C5 0A   E0
C8EC : D0 18 A9 72 85 0A A2 07   C2
C8F4 : A0 08 BD FF DE C6 0A C6   E1
C8FC : 0A 2A 90 E7 88 D0 F6 CA   BD
C904 : D0 EE AD 48 C0 29 FE 8D   2C
C90C : 48 C0 AD D8 03 AE D9 03   4E
C914 : AC DA 03 8D 04 D4 8E 0B   D7
C91C : D4 8C 12 D4 60 FF         17
Listing 2. »WERSI«. Verwenden Sie zur Eingabe bitte den MSE.
1060 ifw=0thenw=1:load"wersi",8,1

1160 dimv%(8,255),tn%(255),th(49)

1530 sys51300:geta$:ifa$=""then1530
1535 ifa$="W"thengosub20000:goto1530

3362 poke984+sn,c(sn):poke987+sn,c1(sn)

3565 poke981+i,abs(s(i))

3735 poke990,abs(eg)

3835 poke991,abs(su)

4295 syspr,18,1,;"{wht}sh w{grn}     wersiboard stimmen"

7425 poke981+i,abs(s(i))

7429 poke50334+i,c(i):poke984+i,c(i)

7431 poke987+i,c1(i)

7441 poke990,abs(eg)

7443 poke991,abs(su)
7444 gosub20000:return

8035 print"bitte 40 sekunden warten"

8460 fori=0to48:th(i)=2^(i/12):next

8484 f1$=chr$(30):f1=5

8576 poke984+sn,c(sn):poke987+sn,c1(sn)

8582 poke981+sn,abs(s(sn))

8631 poke990,abs(eg):poke991,abs(su)

8666 gosub20000:w=1

8880 poke53280,0:poke53281,0

20000 ifw=1thensyspr,18,1,;"{wht}sh w     {rvon}wersiboard stimmen{rvof}"
20010 forxx=0to2:zz=-2
20020 foryy=0to48
20025 zz=zz+2
20030 ww=th(yy)*bf(xx)
20040 ifww>65535thenww=0
20050 sys do,52950+(98*xx)+zz,ww
20060 nextyy,xx
20070 ifw=1thensyspr,18,1,;"{wht}sh w{grn}     wersiboard stimmen"
20080 return
Listing 3. »Sound-Editor-Zusatz«. Diese Zeilen müssen Sie zusätzlich zum Sound-Editor eintippen

Paint Magic und Basic-Programme

Um Paint Magic-Bilder in einem Basic-Programm aufrufen zu können, geht man wie folgt vor:

Das Bild kann jetzt, wenn es zuvor absolut geladen wurde, in einem Basic-Programm mit »SYS 24513« aufgerufen werden.

Verschwinden des Bildes: POKE 53272,21 POKE 56576,151 POKE 53265,27 POKE 53270,200

(Frank Hoffmann/tr)

Zerstörtes Directory retten

Jedem eifrigen Benutzer der Floppy, der nicht gleichzeitig ein Übermensch ist, wird es wohl schon mindestens einmal passiert sein, daß er das Directory einer Diskette (vielleicht auch nur teilweise) »vermurkst« hat.

Sei es nun durch Formatieren (ohne ID) oder eine sonstige Unachtsamkeit. Der arme Mensch wird wohl alles daransetzen, das oder die Programme wiederzubekommen. Eine mögliche Vorgehensweise besteht darin, die einzelnen Blöcke der Diskette nach den Zahlen für die Anfangsadresse des Programms abzusuchen.

Diese steht im dritten und vierten Byte des ersten Blocks jedes Programms in der Form Low-Byte/High-Byte. Dies ist notwendig, damit der Computer bei absolutem Laden (mit LOAD "Name",8,1) weiß, wo er das Programm im Speicher ablegen soll.

Nun kann man natürlich jeden Block einzeln »per Hand« absuchen. Dies ist aber in Anbetracht der Tatsache, daß es dero 664 gibt, nicht ratsam. Deshalb wird man sich für diesen Zweck wohl ein Programm schreiben. Hierbei wird wohl der erste Versuch eine Basic-Version sein. So auch bei mir. Ich mußte aber leider feststellen, daß es zwar gut funktionierte (kein Wunder, es war ja auch von mir!), aber auch einen sehr großen Zeitbedarf hatte.

Also mußte ein schnelleres Programm her. Denn man wartet schließlich nicht gerne, und schon gar nicht, wenn man um ein geliebtes Programm bangen muß.

Und so kam ich auf die Idee, das Problem dadurch zu lösen, daß man ein Maschinenprogramm im Floppyspeicher ablegt. Durch diese Methode läßt sich das umgehen, was beim Basic-Programm den größten Teil des Geschwindigkeitsverlustes ausmacht:

Denn da muß man jeden Block vollständig einlesen. Und bis die Zahlen mit GET verarbeitet sind und der nächste Block gelesen werden soll, ist der Lesekopf schon weiter. Mit dieser Methode braucht man zirka eine Umdrehung.

Der Programmsucher (Listing 4) geht hier, wie schon angedeutet, einen etwas anderen Weg: Es wird nicht der ganze Block, sondern nur die zur Bestimmung der benötigten Zahlen notwendigen GCR-Byte eingelesen (siehe dazu auch 64’er 6/85, Seite 116-119).

Soviel zu den programmtechnischen Dingen. Wer sich mit Maschinensprache und insbesondere der Floppy-Programmierung auskennt, wird das Programm wohl ohnehin verstehen. Wer nicht, sollte sich den Floppy-Kurs im 64’er durchlesen.

Nun zur Bedienung des Programms:

Diese ist zum Glück sehr einfach. Das Programm wird mit »RUN« gestartet und fragt dann nach der Startadresse des zu suchenden Programms. Hier nicht die Zahl eingeben, mit der das Programm eventuell über »SYS« gestartet wird, sondern die, an der es im Speicher beginnt. Diese sind aber in den meisten Fällen identisch. Bei Programmen, die am Basic-Start stehen (dies trifft für alle zu, die mit »LOAD "Name",8« geladen werden), braucht nur »RETURN« gedrückt zu werden. Danach startet das Programm die Suche auf der Diskette. Nach etwa 14 Sekunden beginnt das Programm, wenn kein Fehler aufgetreten ist, mit der Ausgabe der (möglichen) Startblocks.

Wenn man die Startadresse(n) hat, trägt man diese am besten mit einem Disk-Monitor, zusammen mit irgendwelchen Pseudonamen (zum Beispiel X1, X2, …), in das Directory ein und probiert dann aus, welches das richtige Programm ist. Danach kann man dann mit »SCRATCH« und »RENAME« die anderen wieder löschen und dem gesuchten den richtigen Namen geben. Validate nicht vergessen!

(Martin Thierer/tr)
PROGRAMM : PROGRAMMSUCHER 0801 0CDA
-----------------------------------
0801 : 0D 08 C1 07 9E 28 32 30   B8
0809 : 36 33 29 00 00 00 A9 0E   E6
0811 : 8D 20 D0 A9 0B 8D 21 D0   5B
0819 : A9 A1 A0 0A 20 1E AB 20   DE
0821 : E1 09 A9 07 8D 86 02 A2   2C
0829 : 09 A0 1E 18 20 F0 FF A0   D8
0831 : FF 20 CF FF C9 0D F0 0A   11
0839 : C8 29 0F 99 00 02 C0 04   A8
0841 : D0 EF A2 00 86 F7 86 F8   E6
0849 : 98 48 B9 00 02 A8 F0 15   C7
0851 : 18 A5 F7 7D 80 0B 85 F7   50
0859 : E8 A5 F8 7D 80 0B 85 F8   6A
0861 : CA 88 4C 4F 08 E8 E8 68   A9
0869 : A8 88 10 DC A5 F7 8D D4   EF
0871 : 0C A5 F8 8D D5 0C A9 00   A4
0879 : 48 A9 6F A2 0B A0 05 20   D0
0881 : 03 0A 68 AA A0 20 BD 0A   0F
0889 : 0C 20 A8 FF E8 88 D0 F6   D3
0891 : 20 1A 0A 8A F0 07 48 8E   18
0899 : 71 0B 4C 7A 08 A9 00 8D   DB
08A1 : 71 0B A9 7B A2 0B A0 04   7F
08A9 : 20 03 0A 20 1A 0A 20 20   84
08B1 : 0A A2 00 86 90 20 A5 FF   7E
08B9 : C9 30 F0 2A 9D DA 0C 20   3D
08C1 : A5 FF E8 24 90 50 F5 20   C8
08C9 : 2B 0A A9 00 9D DA 0C 86   52
08D1 : FD 38 A9 27 E5 FD 4A 85   BC
08D9 : FD A9 DA A0 0C 20 31 0A   10
08E1 : 20 64 0A 4C 0F 08 20 2B   48
08E9 : 0A A9 75 A2 0B A0 05 20   84
08F1 : 03 0A 20 1A 0A 20 20 0A   7B
08F9 : A0 00 20 A5 FF 99 DA 0C   A6
0901 : C8 C0 66 D0 F5 20 2B 0A   FE
0909 : 20 86 0A A9 00 85 F7 85   3B
0911 : FC A9 0C 85 F8 A9 01 85   81
0919 : F9 A9 00 85 FB A4 F7 B9   D0
0921 : DA 0C 8D 3C 03 C8 B9 DA   FF
0929 : 0C 8D 3D 03 C8 B9 DA 0C   89
0931 : 8D 3E 03 C8 84 F7 A5 F9   4A
0939 : 20 74 0A 85 FA 2E 3E 03   E7
0941 : 2E 3D 03 2E 3C 03 88 D0   34
0949 : F4 2E 3E 03 2E 3D 03 2E   7A
0951 : 3C 03 90 38 C6 F8 D0 05   BB
0959 : 20 83 0A E6 FC A0 00 B9   E2
0961 : 8A 0B F0 07 20 D2 FF C8   B8
0969 : 4C 60 09 A6 F9 A9 00 20   2A
0971 : CD BD A0 00 B9 97 0B F0   AB
0979 : 07 20 D2 FF C8 4C 75 09   1C
0981 : A6 FB A9 00 20 CD BD A9   4A
0989 : 0D 20 D2 FF C6 FA F0 05   6D
0991 : E6 FB 4C 4A 09 A6 F9 E8   51
0999 : E0 12 F0 FB E0 24 F0 05   3B
09A1 : 86 F9 4C 1A 09 A5 FC F0   0E
09A9 : 1A A9 D2 A0 0B A2 06 86   4B
09B1 : FD 20 31 0A 20 64 0A 48   2A
09B9 : 20 E1 09 68 C9 4A D0 03   51
09C1 : 4C 09 09 A9 EF A0 0B A2   7F
09C9 : 07 86 FD 20 31 0A 20 64   43
09D1 : 0A 48 20 E1 09 68 C9 4A   D3
09D9 : D0 03 4C 0F 08 4C 66 FE   9A
09E1 : 18 A2 0B A0 00 20 F0 FF   E6
09E9 : A9 12 20 D2 FF A9 9A 20   F6
09F1 : D2 FF A2 28 A9 20 20 D2   32
09F9 : FF CA D0 FA A9 92 20 D2   46
0A01 : FF 60 85 F7 86 F8 A9 08   77
0A09 : 20 B1 FF A9 6F 20 93 FF   7D
0A11 : B1 F7 20 A8 FF 88 10 F8   51
0A19 : 60 A9 08 20 AE FF 60 A9   14
0A21 : 08 20 B4 FF A9 6F 20 96   2A
0A29 : FF 60 A9 08 20 AB FF 60   E4
0A31 : 48 98 48 A2 0B A4 FD 18   2A
0A39 : 20 F0 FF A9 12 20 D2 FF   74
0A41 : A9 05 20 D2 FF 68 A8 68   86
0A49 : 20 1E AB A9 92 20 D2 FF   0E
0A51 : 60 A9 04 85 FD A9 A6 A0   41
0A59 : 0B 20 31 0A 20 64 0A 20   90
0A61 : E1 09 60 A9 00 85 C6 A5   A7
0A69 : C6 F0 FC A9 00 85 C6 AD   BE
0A71 : 77 02 60 A2 04 DD C5 0B   B2
0A79 : CA B0 FA BD CA 0B BC CE   A7
0A81 : 0B 60 20 52 0A A2 0C 8A   0A
0A89 : 48 20 FF E9 68 AA E8 E0   60
0A91 : 19 D0 F4 A9 0B 85 F8 A2   8B
0A99 : 0D A0 00 18 20 F0 FF 60   44
0AA1 : 93 96 11 11 20 20 20 20   AA
0AA9 : 20 20 20 20 D5 C0 C0 C0   CD
0AB1 : C0 C0 C0 C0 C0 C0 C0 C0   B0
0AB9 : C0 C0 C0 C0 C0 C0 C0 C0   B8
0AC1 : C0 C0 C0 C9 0D 20 20 20   DD
0AC9 : 20 20 20 20 20 DD 20 50   18
0AD1 : 52 4F 47 52 41 4D 4D 53   41
0AD9 : 55 43 48 45 52 20 56 20   4A
0AE1 : 32 2E 30 20 DD 0D 20 20   41
0AE9 : 20 20 20 20 20 20 AD B2   45
0AF1 : C0 C0 C0 C0 C0 C0 C0 C0   F0
0AF9 : C0 C0 C0 C0 C0 C0 C0 C0   F8
0B01 : C0 C0 C0 C0 B2 BD 0D 20   F7
0B09 : 20 20 20 20 20 20 20 20   09
0B11 : DD 20 31 39 38 35 20 56   CC
0B19 : 4F 4E 20 4D 2E 54 48 49   7A
0B21 : 45 52 45 52 20 DD 0D 20   90
0B29 : 20 20 20 20 20 20 20 20   29
0B31 : CA C0 C0 C0 C0 C0 C0 C0   3A
0B39 : C0 C0 C0 C0 C0 C0 C0 C0   38
0B41 : C0 C0 C0 C0 C0 CB 0D 11   6A
0B49 : 11 9E 20 20 20 20 20 20   79
0B51 : 50 52 4F 47 52 41 4D 4D   86
0B59 : 2D 53 54 41 52 54 41 44   C2
0B61 : 52 45 53 53 45 20 3A 20   14
0B69 : 32 30 34 39 0D 00 20 03   3F
0B71 : 00 57 2D 4D 66 04 00 52   3D
0B79 : 2D 4D 03 93 45 2D 4D 01   75
0B81 : 00 0A 00 64 00 E8 03 10   86
0B89 : 27 9F 20 20 54 52 41 43   EF
0B91 : 4B 20 3A 20 90 00 9F 20   47
0B99 : 20 20 53 45 4B 54 4F 52   80
0BA1 : 20 3A 20 90 00 57 45 49   5B
0BA9 : 54 45 52 20 3A 20 42 49   79
0BB1 : 54 54 45 20 54 41 53 54   CA
0BB9 : 45 20 44 52 55 45 43 4B   8D
0BC1 : 45 4E 20 21 00 24 1F 19   29
0BC9 : 12 11 12 13 15 07 06 05   F7
0BD1 : 03 4E 4F 43 48 20 45 49   65
0BD9 : 4E 4D 41 4C 20 41 4E 5A   A2
0BE1 : 45 49 47 45 4E 20 3F 20   68
0BE9 : 28 4A 2F 4E 29 00 4E 4F   36
0BF1 : 43 48 20 45 49 4E 20 44   19
0BF9 : 55 52 43 48 47 41 4E 47   97
0C01 : 20 3F 20 28 4A 2F 4E 29   78
0C09 : 00 A5 06 20 4B F2 85 46   50
0C11 : A9 00 85 07 20 7F 03 A2   4C
0C19 : 03 20 56 F5 50 FE B8 CA   F6
0C21 : D0 FA 50 FE B8 AD 01 1C   97
0C29 : 9D CC 03 E8 E0 04 D0 F2   62
0C31 : 6E CC 03 6E CD 03 6E CE   E0
0C39 : 03 6E CF 03 6E CC 03 6E   FE
0C41 : CD 03 6E CE 03 6E CF 03   EE
0C49 : A9 00 85 30 A9 03 85 31   85
0C51 : A9 CD 85 34 20 E6 F7 A2   27
0C59 : 02 A5 52 CD CA 03 D0 09   96
0C61 : A5 53 CD CB 03 D0 02 38   CC
0C69 : 04 18 3E 00 04 CA 10 FA   D6
0C71 : A6 07 E8 E4 46 F0 05 86   7F
0C79 : 07 4C 0B 03 EE 62 03 EE   B5
0C81 : 62 03 EE 62 03 4C 9E FD   76
0C89 : A5 12 85 16 A5 13 85 17   93
0C91 : A5 06 85 18 A5 07 85 19   79
0C99 : 20 27 F5 60 20 18 C1 20   E0
0CA1 : 42 D0 A9 0F 8D 05 1C A9   5C
0CA9 : 00 A8 99 00 04 C8 D0 FA   23
0CB1 : A2 01 86 06 A9 E0 85 00   EE
0CB9 : A5 00 30 FC C9 02 B0 0D   93
0CC1 : E8 E0 12 F0 FB E0 24 D0   B5
0CC9 : E9 20 23 C1 60 A2 00 20   1F
0CD1 : 0A E6 60 00 00 55 55 55   11
0CD9 : 55                        5F
Listing 4. »Programmsucher«. Verwenden Sie zur Eingabe bitte den MSE.

59 390 Bytes free

Mit Double-Basic (Listing 5) können Sie zwei unabhängige Basic-Programme im Speicher halten, die zusammen 59 390 Byte (!) lang sein können. Die Programme können 38 911 (PRG 1) und 20 480 Byte (PRG 2) belegen.

Durch CTRL + F1 werden beide Programme gegeneinander ausgetauscht, während alle Variablen des jeweiligen Programmes erhalten bleiben. Wenn Sie also erst Programm 1 bearbeitet haben, können Sie nach CTRL + F1 mit Programm 2 fortfahren und umgekehrt. Zusätzlich besitzt Double-Basic zwei andere, ungewöhnliche Funktionen:

  1. CTRL + Pfeil links verlangsamt die Ausführungszeiten des Computers. Der Grad der Verzögerung kann durch »POKE 53024,…« eingestellt werden (255 = größte Verzögerung).
  2. CTRL + RUN/STOP hält den Computer an, bis SPACE gedrückt wird. Sehr praktisch für das Listen eines Programmes: CTRL + STOP gedrückt halten und für jede nächste Zeile zusätzlich kurz SPACE drücken.

Wenn Sie Double-Basic mit dem MSE abgetippt haben, speichern Sie es. Nach dem Laden mit »,8,1« und NEW können Sie Double-Basic mit SYS 52992 initialisieren (SYS 52992 ist nach jedem RUN/STOP-RESTORE notwendig!). Es stehen nun die beschriebenen Funktionen zur Verfügung.

Hinweise: CTRL + F1 ist nur möglich, wenn sich der Computer im Direktmodus befindet. Während des Listens führt der Druck dieser Tastenkombination zum Absturz! Also: erst STOP, dann CTRL + F1. Da alle Variablen erhalten bleiben, kann ein Programm nach einem Tausch mit CONT fortgeführt werden, wenn es vorher unterbrochen wurde. Es sei denn, das System hat seit dem letzten Tausch eine FOR-, NEXT- oder GOSUB-RETURN-Struktur bearbeitet. In diesem Fall reagiert der Computer, wenn er auf NEXT oder RETURN stößt, mit Unsinn, Fehlermeldungen oder gar Absturz.

Einige Daten zu Double-Basic. Double-Basic ist in den System-Interrupt eingebunden und belegt den Speicherbereich von $CF00 bis $D000, ist also verwendbar mit Turbo-Tape und SMON (ohne Diskmonitor).

In der Interrupt-Routine (ab $CF0B) wird auf die Betätigung einer der drei Tasten-Kombinationen geprüft. Wird der Programmtausch aufgerufen, erfolgt zuerst noch ein Test, ob sich der Computer auch im Direktmodus befindet. Daraufhin wird der Inhalt des Speichers von 2049 bis 22528 mit dem des RAM-Bereichs unter dem ROM vertauscht. Genauso wird mit den Basic-Vektoren in den Zellen 43 bis 66 (die unter anderem die Programmlänge und den freien Speicherplatz angeben) und einer Tabelle ab $CFD9 verfahren. Bevor in die normale Interrupt-Routine gesprungen wird, wird noch die Nummer des aktuellen Programmes angezeigt.

(Julian Ziersch/tr)
PROGRAMM : DBASIC         CF00 D000
-----------------------------------
CF00 : A9 0B 8D 14 03 A9 CF 8D   ED
CF08 : 15 03 60 AD 8D 02 C9 04   85
CF10 : F0 03 4C 31 EA A5 CB C9   5A
CF18 : 04 F0 29 C9 39 D0 13 A0   BF
CF20 : 1E A2 FF CA EA EA EA EA   70
CF28 : EA EA EA D0 F6 88 D0 F1   37
CF30 : F0 E0 C9 3F D0 DC A9 7F   84
CF38 : 8D 00 DC A9 10 2D 01 DC   5A
CF40 : D0 FB F0 CE A5 9D C9 80   93
CF48 : D0 C8 AD FA CF C9 31 F0   39
CF50 : 08 A9 31 8D FA CF 4C 5E   47
CF58 : CF A9 32 8D FA CF 78 A9   9D
CF60 : 34 85 01 A9 01 85 FB A9   4C
CF68 : 08 85 FC A9 00 85 FD A9   1F
CF70 : A0 85 FE A2 20 20 88 CF   AB
CF78 : A0 00 84 FD A9 D0 85 FE   2E
CF80 : A2 30 20 88 CF 4C A6 CF   ED
CF88 : A0 00 B1 FB 85 02 B1 FD   3F
CF90 : 91 FB A5 02 91 FD E6 FB   65
CF98 : D0 02 E6 FC E6 FD D0 EA   3A
CFA0 : E6 FE CA D0 E5 60 A2 37   2C
CFA8 : 86 01 A2 18 B5 2B BC D9   B6
CFB0 : CF 9D D9 CF 94 2B CA 10   AC
CFB8 : F3 AC 21 D0 C8 A2 28 A9   F9
CFC0 : 20 9D FF 03 CA D0 FA A2   73
CFC8 : 0D BD F1 CF 9D 01 04 98   4D
CFD0 : 9D 01 D8 CA D0 F3 4C 31   BD
CFD8 : EA 01 08 03 08 03 08 03   64
CFE0 : 08 00 58 00 58 00 58 30   46
CFE8 : FF 00 2A 2A 2A 20 10 12   BF
CFF0 : 07 00 2A 2A 2A 20 10 12   CF
CFF8 : 07 2D 31 20 2A 2A 2A DF   43
Listing 5. »Double Basic«. Verwenden Sie zur Eingabe bitte den MSE.

Tips für Schreibmaschinen-Profis

Jeder, der einmal einen Schreibmaschinenkurs absolviert hat, hat sich auch schon über die Vertauschung der Tasten »Y« und »Z« auf der Tastatur des C 64 geärgert. Vor allem, wenn man in einem Basic-Programm in PRINT-Zeilen einen kleinen Text schreiben möchte, ist dieser Umstand sehr störend. Eine naheliegende, wenn auch sehr umständliche Methode ist, das Betriebssystem zu ändern. Es empfiehlt sich, diese Änderung dann in ein EPROM zu »brennen«.

Um die genannten Tasten in die deutsche Norm zu bringen, ist zuerst das Betriebssystem ins RAM zu kopieren (zum Beispiel mit einem Monitor), dann sind die folgenden POKEs einzugeben: POKE 60301,89 POKE 60314,90 POKE 60366,217 POKE 60379,218 POKE 60431,183 POKE 60444,173

Übrigens: Wenn das Betriebssystem ins RAM kopiert wurde, besteht im allgemeinen das Problem, diese Kopie dauerhaft eingeschaltet zu lassen. Wenn man nämlich RUN/STOP-RESTORE drückt, wird das RAM aus- und das ROM wieder eingeblendet. Durch einen POKE 64982,53 wird dies verhindert.

(Stefan Zellin/tr)

Tips zum Gedichtgenerator

Das Programm »Lyrik« aus der Ausgabe 11/85 istja wirklich sehr schön, vor allem ist die Programmstruktur so gewählt, daß problemlos eigene Erweiterungen eingebaut werden können. Im Programm sind jedoch keine Bereichskontrollen für die Anzahl der Verse vorgesehen. Hier muß man selbst aufpassen. Auch sollte im Wortschatz wegen Zeile 371 kein »Ei« vorkommen! Nebenbei: Die Satzstrukturen passen großenteils nicht zu den angegebenen Mnemonic-Strukturen. Ein richtiger Fehler ist jedoch in Zeile 196, dort muß es heißen: fora=1toaz-1 ….

Geben Sie mal folgende Struktur ein: 2 Strophen, 1. Strophe 10 Verse, 2. Strophe 2 Verse, und geben Sie eigene Mnemonics ein. Es klappt nicht! Die Verse der zweiten Strophe erscheinen auch in der ersten Strophe. Der Grund ist die Codierung der Indizes von mn$. Zur Abhilfe muß ein eigener Verszähler vz eingeführt werden:

107vz=-1:….
181vz=vz+1:inputmn$(vz):….
192vz=vz+1:inputmn$(vz):…
196fora=1toaz4:forb=0tova%(0)-1:vz=vz+1:mn$(vz)=mn$(b): nextb,a:goto300
242vz=vz+1:mn$(vz)=pm$(….
301….:vz=-1
305….:vz=vz+1:w$=mn$(vz):….
816fora=0tor-1:b=int(rnd(1)*q0):vz=vz+1:mn$(vz)=co$(b):next 818 goto196

Durch eine weitere sehr kleine Änderung kann mit VRB10 beziehungsweise VRB20 ein Imperativ wie »höre« eingebaut werden:

418ifepthen….
419e$(z2)=left$(vb$(wa,1),len(vb$(wa,1))-1)
420ifright$(e$(z2),1)o"e"thene$(z2) = e$(z2)+"e"
421z1=z1+6:goto710

Folgende kleine Änderung ergibt ein neues Mnemonic, das einen sehr viel lebendigeren Versaufbau erlaubt. ADV erzeugt ein Adverb, somit sind Verse wie »Der Blitz lächelt schrecklich« (sub2001 vrb11 adv) möglich.

462rem — adv —
464ifm$ <> "adv"then468
466wa=int(rnd(1)*q4):e$(z2)=left$(no$(wa,2),len(no$(wa,2))-1)
467z1=z1+4:goto710
468:

Wie das Listing zeigt, werden die Adverben aus den Adjektiven erzeugt, das schränkt die Wahl der Adjektive geringfügig ein: »größte« oder »dunkle« kann nicht mehr verwendet werden. Noch zwei Vorschläge für neue Mnemonics: FIX setzt einen vorher eingegebenen String ein, so lassen sich Gedichte für »unsere Oma« erzeugen! KMP setzt eine Vergleichsstruktur wie »so sehr wie« oder »größer als« ein. Strukturen wie »schöner als« oder »so blutrünstig wie« erzeugt das Programm selbst unter Verwendung der Adjektive. Deshalb dürfen dort zum Beispiel »große« »gute« »viele« und ähnliche nicht auftreten. Auch »scharfe« oder »fromme« sind nicht möglich. Eine Einschränkung zwar, aber der Gewinn ist größer!

468rem — fix 469ifm$ = -fix-thene$(z2)=fi$:z1=z1 + 4: goto710
470rem — vergleich —
471ifm$<>"kmP"—then700
472wa=int(rnd(1)*(q9 + 4)):ifwa> =q9then475
473e$(z2)=v9$(wa)
474z1=z1+4:goto710
475w1=int(rnd(1)*q4)
476if wa>q9 + 1thene$(z2) = no$(w1,2)+"r als ":goto474
477e$(z2)="so "+left$(no$(w1,2),len(no$(w1,2))-1)+" wie":goto474

Für das Mnemonic »FIX« sind noch folgende Zeilen im Programm nötig:

99fi$="der C 64"
150Print:Print:inPut"String für FIX";fi$

Das Mnemonic KMP benötigt noch folgende Zeilen:

11q9=xx Für xx müssen Sie die Anzahl der von Ihnen ab Zeile 9000 eingegebenen Vergleiche einsetzen.
26….,v9$(q9-1)
65fora=0toq9-1:readv9$(a):next:rem vergleich
9000 data besser als, so gut wie, und so weiter.

Wichtig: Um auch beim automatischen Dichten in den Genuß der eigenen Mnemonics zu kommen, sollten die Satzstrukturen ab Zeile 1001 überarbeitet beziehungsweise ergänzt und mit Strukturen, die die neuen Mnemonics enthalten, versehen werden.

Wenn es Sie stört, daß Komma und Leerzeichen vertauscht gedruckt werden, daß am Versende auch nach einem Komma ein Punkt gesetzt wird und daß bei mehr als 80 Zeichen pro Vers der Ausdruck falsch formatiert wird, dann helfen Ihnen folgende Zeilen:

712forx=0toz2-1:p$ = p$+e$(x) 4-"":ife$(x)", "then714
713iflen(p$)>3thenp$=left$(p$, len(p$)-4)+e$(x)
715ifright$(p$,2)=", "thenp$ = left$(p$, len(p$)-1):goto722
716p$=left$(p$, len(p$)-1)+"."
722printp$
723ifdr$<>jthen739
724x=len(p$):y=y:ifx<81then738
725x=x-1:ifmid$(p$,x,1)< >""orx>80then725
726print#1, left$(p$,x-1)
727print#1, spc(78+x-y);mid$(p$,x+1,y-x)
730goto739
738print#1,p$
739p$="":nextb:print:ifdr$="j"thenprint # 1

Haben Sie sich auch schon geärgert, wenn Sie lange Mnemonic-Ketten eingegeben haben und das Programm lapidar mit »UNKNOWN MNEMONIC« aussteigt? Dann helfen Ihnen die folgenden Zeilen. Nach Erkennen eines Fehlers wird die fehlerhafte Versstruktur ausgegeben, nach Berichtigung wird das Gedicht neu erzeugt.

700print"ERROR…UNKNOWN MNEMONIC:"m$:goto13000
13000close1:gosub13100
13010forx=0toz2:e$(x)="":next:goto300
13100print"{home,11 Cursordown,2Spaces}"mn$(vz)
13101input"{home,11 Cursordown}";mn$(vz)
13102return

Wenn Sie zusätzlich noch Groß- und Kleinschrift einführen wollen, müssen Sie sämtliche DATA-Zeilen ab 2060 anpassen! Die DATA-Elemente müssen dabei in Anführungszeichen stehen, da sonst Großbuchstaben nicht übernommen werden. Dieser Aufwand lohnt sich wohl nur, wenn Sie sowieso den Wortschatz ändern wollen. Folgende Zeilen müssen dann zusätzlich geändert werden:

304…. open1,4,7
714nextx:x=asc(left$(p$,1)):x$=chr$(xor128):p$=x$+mid$(p$,2)

Man könnte nun daran denken, eine Korrekturmöglichkeit der Mnemoniczeilen vorzusehen. Weiter wäre es sicher reizvoll, von gelungenen Gedichten die Struktur speichern beziehungsweise laden zu können. Auch wäre daran zu denken, bei der Struktureingabe eine Abfrage des Stringzählers einzubauen, um einen »illegal quantity error« zu vermeiden. Wollen Sie obiges nicht alles selbst machen, so können Sie eine leere Diskette mit Rückporto an Uli Beyenbach, Gluckstr. 12, 75 Karlsruhe-21 schicken. Ich schicke Ihnen dann das verbesserte Programm zu.

(Uli Beyenbach/tr)
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →