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:
- Es muß vorher bereits ein Basic-Programm im Speicher gestanden haben (mindestens: »10 :«).
- Es darf vor Aufrufen der Routine kein Variablen-Programm eingegeben oder ein Feld abgefragt worden sein.
- 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 | |
| 10 | DIM A$(30),B$(10) |
| 20 | CLR |
| 30 | DIM A$(30) |
| 40 | SYS 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
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
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:
- ein Programm, welches die gespielten Noten schneller zu Gehör bringt, und
- 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:
- 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.
- Speichern Sie den erweiterten Sound-Editor wieder (zum Beispiel unter dem Namen »Sound-Editor +«).
- 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.
- 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
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
Paint Magic und Basic-Programme
Um Paint Magic-Bilder in einem Basic-Programm aufrufen zu können, geht man wie folgt vor:
- Laden des Bildes
- Starten des Bildes mit »RUN«
- RUN-STOP/RESTORE drücken
- Im Direktmodus »POKE 24565,96« eingeben
- Speichern mit einem Monitor (zum Beispiel SMON) von Hex $4000 bis $6400
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
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
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:
- 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).
- 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
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:
| 107 | vz=-1:…. |
| 181 | vz=vz+1:inputmn$(vz):…. |
| 192 | vz=vz+1:inputmn$(vz):… |
| 196 | fora=1toaz4:forb=0tova%(0)-1:vz=vz+1:mn$(vz)=mn$(b): nextb,a:goto300 |
| 242 | vz=vz+1:mn$(vz)=pm$(…. |
| 301 | ….:vz=-1 |
| 305 | ….:vz=vz+1:w$=mn$(vz):…. |
| 816 | fora=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:
| 418 | ifepthen…. |
| 419 | e$(z2)=left$(vb$(wa,1),len(vb$(wa,1))-1) |
| 420 | ifright$(e$(z2),1)o"e"thene$(z2) = e$(z2)+"e" |
| 421 | z1=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.
| 462 | rem — adv — |
| 464 | ifm$ <> "adv"then468 |
| 466 | wa=int(rnd(1)*q4):e$(z2)=left$(no$(wa,2),len(no$(wa,2))-1) |
| 467 | z1=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!
| 468 | rem — fix 469ifm$ = -fix-thene$(z2)=fi$:z1=z1 + 4: goto710 |
| 470 | rem — vergleich — |
| 471 | ifm$<>"kmP"—then700 |
| 472 | wa=int(rnd(1)*(q9 + 4)):ifwa> =q9then475 |
| 473 | e$(z2)=v9$(wa) |
| 474 | z1=z1+4:goto710 |
| 475 | w1=int(rnd(1)*q4) |
| 476 | if wa>q9 + 1thene$(z2) = no$(w1,2)+"r als ":goto474 |
| 477 | e$(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:
| 99 | fi$="der C 64" |
| 150 | Print:Print:inPut"String für FIX";fi$ |
Das Mnemonic KMP benötigt noch folgende Zeilen:
| 11 | q9=xx Für xx müssen Sie die Anzahl der von Ihnen ab Zeile 9000 eingegebenen Vergleiche einsetzen. |
| 26 | ….,v9$(q9-1) |
| 65 | fora=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:
| 712 | forx=0toz2-1:p$ = p$+e$(x) 4-"":ife$(x)", "then714 |
| 713 | iflen(p$)>3thenp$=left$(p$, len(p$)-4)+e$(x) |
| 715 | ifright$(p$,2)=", "thenp$ = left$(p$, len(p$)-1):goto722 |
| 716 | p$=left$(p$, len(p$)-1)+"." |
| 722 | printp$ |
| 723 | ifdr$<>jthen739 |
| 724 | x=len(p$):y=y:ifx<81then738 |
| 725 | x=x-1:ifmid$(p$,x,1)< >""orx>80then725 |
| 726 | print#1, left$(p$,x-1) |
| 727 | print#1, spc(78+x-y);mid$(p$,x+1,y-x) |
| 730 | goto739 |
| 738 | print#1,p$ |
| 739 | p$="":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.
| 700 | print"ERROR…UNKNOWN MNEMONIC:"m$:goto13000 |
| 13000 | close1:gosub13100 |
| 13010 | forx=0toz2:e$(x)="":next:goto300 |
| 13100 | print"{home,11 Cursordown,2Spaces}"mn$(vz) |
| 13101 | input"{home,11 Cursordown}";mn$(vz) |
| 13102 | return |
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 |
| 714 | nextx: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)