Tips & Tricks für Anfänger und Fortgeschrittene
Hier wieder einige interessante Hinweise zum Programmieren des C 64.
Kopieren von Bildschirmzeilen
Der Kern des Einzeilers (Listing 1) besteht aus dem Aufruf einer Betriebssystemroutine, die das Kopieren von Bildschirmzeilen ermöglicht. Mit dieser Routine wird ein Scrollen des Bildschirms erreicht, indem die erste Zeile in die letzte Bildschirmzeile kopiert und anschließend durch den Print-Befehl ein Zeilenvorschub ausgelöst wird. Somit erscheint die am oberen Bildschirmrand verdrängte Zeile wieder unten. Um den Einzeiler komfortabler zu gestalten, wird das zum Starten nötige »RUN« zuerst gelöscht, um ein Mitscrollen zu verhindern; mit Druck auf eine beliebige Taste wird der Scroll-Vorgang angehalten und nach loslassen wieder fortgesetzt. Nach dem Eingeben des Einzeilers sollte der Bildschirm gelöscht werden und anschließend der zu scrollende Text oder die Grafik erstellt werden. Es ist lediglich darauf zu achten, daß die 39. Bildschirmzeile nicht benutzt wird. Das Starten erfolgt am Anfang der letzten Bildschirmzeile mit »RUN«, gefolgt von einem Doppelpunkt (um eventuell folgende Zeichen auszuschalten). Die Routine eignet sich besonders gut für Spiele, die mit bewegtem Hintergrund arbeiten, da sie relativ schnell ist.
Dank dieser Routine ist es zum Beispiel möglich gewesen, ein grafisches Froggerspiel (Listing 2) in nur 23 Basic-Zeilen zu erstellen.
(Stefan Moll/tr)1 print"{up} ":fort=0to1:poke172,peek(60656):poke780,peek(216):sys59848:print:wait203,64:t=0:next
0 v=53248:poke2042,13:poke2043,14
1 print"{clr}@@@?{rvon}{$a0}{rvof}@{CBM-B}{rvon}c{SHIFT-*}{CBM-B}O{rvof}@{rvon}{CBM-A}{rvof}_{rvon}{SHIFT-*}{CBM-M}{CBM-C}{rvof}@{rvon}{CBM-B}{CBM-B}{rvof}@{CBM-B}{rvon}{CBM-B}@{CBM-B}{CBM-O}{SHIFT-*}{CBM-B}{CBM-O} {$a0}{rvof}?{rvon} {CBM-B}{CBM-O} {CBM-B}{CBM-O}{SHIFT-*}{rvof}{CBM-B}{rvon}{CBM-B}@{CBM-B}{CBM-B}{rvof}@{rvon}{CBM-M}{CBM-U}{rvof}@{rvon}{CBM-A}";
2 print"_{rvon}{SHIFT-*}{CBM-B}O@{CBM-B}{rvon}c{SHIFT-*}{rvof}_{rvon}{$a0}{rvof}@@@@{rvon}{CBM-B}{rvof}@{rvon}{CBM-V}{rvof}@g{rvon}{CBM-B}{$a0}{rvof}?{rvon}{CBM-B}{CBM-U}{rvof}{CBM-B}{rvon}{CBM-B}{CBM-U}{CBM-B}{CBM-B}{CBM-U}{CBM-B}{CBM-B}{CBM-C}{CBM-B}{CBM-B}{CBM-V}{rvof}{CBM-B}{rvon}{CBM-B}{CBM-B}{rvof}?{rvon}{CBM-B}{CBM-B}{rvof}_{rvon}{CBM-B}{CBM-B}{rvof}o";
3 print"{rvon}{CBM-B}{CBM-B}{rvof}o{rvon}{CBM-B}{CBM-V}{rvof}o{rvon}{CBM-B}{CBM-U}{rvof}_{rvon}{CBM-B}{CBM-U}{rvof}_{rvon}{CBM-B}{CBM-C}{rvof}?{rvon}{CBM-B}{CBM-V}{rvof}?{rvon}{CBM-B}{CBM-B}{rvof}?{rvon}{CBM-B}{CBM-V}{rvof}_{rvon}{CBM-B}{CBM-U}{rvof}g{rvon}{CBM-B}{SHIFT-*}{rvof}a{CBM-C}@"
4 fort=0to126:poke832+t,peek(1024+t):next:pokev+41,13:pokev+42,6:pokev+27,12
5 poke650,128:poke649,2:pokev+32,0:pokev+33,5:pokev+23,8:pokev+29,8:s=300:g=0
6 pokev+16,8:pokev+6,30:pokev+7,120:y=100:x=40:pokev+4,x:pokev+5,y:pokev+21,12
7 pokev+30,peek(v+30)and251:pokev+31,peek(v+31)and243
8 x$="{rvon} {down}{left} {down}{left} {down}{down}{down}{down}{left} {down}{left} {down}{left} {down}{down}{down}{down}{left} {down}{left} {down}{left} {down}{down}{down}{down}{left} {down}{left} {down}{left} "
9 print"{clr}{red}";tab(10);x$:print"{home}{blk}{down}{down}";tab(17);x$:print"{home}{wht}";tab(24);x$:print"{home}{gry2}{down}{down}";tab(31);x$
10 poke56322,224:j=peek(56321):if(jand1)=0theny=y-15:goto17
11 ifpeek(v+31)and4=4thenprint"{blk}{clr}tot";g;"froesche gerettet":wait145,16,16:goto5
12 ifpeek(v+30)=12thenprint"{clr}{blk}gerettet !":s=s-50:g=g+1:wait145,16,16:goto6
13 if(jand2)=0theny=y+15:goto17
14 if(jand4)=0thenx=x-15:goto17
15 if(jand8)=0thenx=x+15:goto17
16 poke172,peek(60656):poke780,peek(216):sys59848:print:forl=1tos:next:goto10
17 ify>230theny=230
18 ify< 40theny= 40
19 ifx>63and(peek(v+16)and4)=4thenx=63
20 ifx<25and(peek(v+16)and4)<>4thenx=25
21 ifx<0and(peek(v+16)and4)=4thenpokev+16,8:x=255+x
22 ifx>255thenpokev+16,peek(v+16)or4:x=x-255
23 pokev+4,x:pokev+5,y:goto10
Scrolling nach unten in Basic
Die Idee ist folgende: Wen man auf dem Bildschirm eine Zeile schreibt, die länger als 40 Zeichen ist, so wird alles, was unterhalb dieser Zeile steht, nach unten weggescrollt. Der folgende Einzeiler bewirkt, daß nachfolgende PRINT-Anweisungen auf dieselbe Weise den Bildschirm nach unten wegschieben:
1 PRINT CHR$(19)CHR$(17)CHR$(157)CHR$(148):POKE 218,152
Disketten von verstellten Laufwerken lesen
10 OPEN1,8,15,"M-W"+CHR$(105)+CHR$(0)+ CHR$(X):CLOSE1
Dieses »Programm« schreibt in die Speicherzelle $69 des Laufwerks-Speichers den Wert X. Diese Speicherzelle enthält die Konstante, die bestimmt, wieviele Leseversuche gemacht werden, bevor eine Fehlermeldung ausgegeben wird. Wird diese Konstante (der Standardwert ist 5) größer gewählt, so kann man auch Disketten lesen, bei denen das Laufwerk vorher Probleme hatte. Die Zugriffszeit erhöht sich natürlich entsprechend der Konstanten und der Anzahl der auftretenden Leseschwierigkeiten. Man hat aber somit die Möglichkeit, Disketten von schlecht justierten Laufwerken zu lesen.
(Alex Haderer/tr)Reset ohne Datenverlust
Wirkung: Folgender Einzeiler wirkt (fast) wie ein Reset; das Programm wird jedoch ohne Datenverlust fortgeführt:
1 POKE 648,4:SYS 64789:SYS 58451:SYS 58784
Anwendungsbeispiele:
Sie wollen in einem Basic-Programm sämtliche Erweiterungen (Toolkits etc.) abschalten sowie den regulären Zeichensatz darstellen.
Ein Programm mit hochauflösender Grafik, verändertem Zeichensatz und/oder Schutz-POKEs (gegen Listen, Run/Stop, Save etc.) ist beendet (Fehlermeldung, Abbruch). Wenn Sie Eingaben machen, erscheinen diese nicht auf dem Bildschirm, nur die Farbe ändert sich. In einem solchen Fall geben Sie den Einzeiler ohne Zeilennummer blind ein.
(Florian Müller/tr)Bildschirmcode in ASCII-Code umwandeln
1 X=X+(X>127)*128:W=X-(X>-1ANDX<32ORX>95) * 64-(X > 63ANDX < 96) * 32
In der Variablen X wird der Bildschirmcode (PEEK(…)) abgelegt. In der Variablen W befindet sich dann der zugehörige ASCII-Code. Es muß allerdings berücksichtigt werden, daß nach Einsetzen eines Codes für inverse Zeichen der Inhalt der Variablen W nachher dem Code für das »normale Zeichen« entspricht. Will man diese Routine aber auch dazu benutzen, inverse Zeichen zu drucken, so muß man vorher überprüfen, ob der Bildschirminhalt größer als 127 ist, denn dann handelt es sich ja um ein inverses Zeichen. Wäre das der Fall, könnte man zum Beispiel durch Setzen des Reversflags (Adresse 199) auf 1 einen inversen Ausdruck bewirken.
(Knut Smoczyk/tr)Langsame Bildschirmausgaben
Dieses kleine Maschinenprogramm (Listing 3) verlangsamt sämtliche Bildschirmausgaben des C 64 um ein Vielfaches. Es läßt sich ohne Probleme in eigene Programme einbinden.
Abschalten läßt sich die kleine Erweiterung mit RUN/STOP-RESTORE oder mit »POKE 806,202:POKE 807,241«. Mit POKE 53232,Zahl kann man die Ausgabegeschwindigkeit regulieren (1=normal).
Nach dem Starten verschiebt sich das Maschinenprogramm, das zuerst in den Bildschirmspeicher geschrieben wird, selbst nach 53228. Dann werden sämtliche Ausgabevektoren auf diese Adresse gerichtet, die nichts weiter als zwei ineinandergeschachtelte Verzögerungsschleifen beinhaltet.
(Dominik Irion/tr)10 print"{clr}":fori=0to43:readx:poke1024+i,x:next:sys1024
11 data160,0,185,24,4,153,236,207,200,192,20,208,245,160,236,140,38,3,160
12 data207,140,39,3,96
13 data72,152,72,160,100,169,255,233,1,208,252,136,208,247,104,168,104,76
14 data202,241
Direkter Programmodus
Jedem Floppy-Besitzer ist das schon oft passiert: die rote Leuchtdiode blinkt und zeigt einen Fehler an. Was tun?
- Ein Programm zum Auslesen des Fehlerkanals eingeben oder einladen ist nicht möglich, da das im Computer befindliche Programm nicht gelöscht oder verändert werden soll.
- Ein Programm im Direktmodus eingeben? Der Computer reagiert auf diesen Versuch mit einem »ILLEGAL DIRECT ERROR«.
Die Lösung:
Wir simulieren mit POKE 58,1 einen Programmablauf-Modus und verhindern so die oben genannte Fehlermeldung:
OPEN1,8,15:POKE58,1:FORI = 1TO50:GET#1,A$: PRINTA$;:CLOSE-(ST=64):IFST< >64THENNEXT
Auto-Befehl in Basic
Mit diesem Mini-Programm lassen sich Zeilennummern automatisch vorgeben. Gestartet wird das Programm mit A=Anfangszeilennummer: GOTO 1. Nun wird der Bildschirm gelöscht und die in A definierte Zeilennummer ausgegeben. Mit POKE 19,1 wird die Tastatur zum aktuellen Eingabegerät. Dadurch wird bei der nachfolgenden INPUT-Anweisung das Fragezeichen nicht mit ausgegeben. Nach der Eingabe der Zeile wird darunter ausgegeben: »A = nächste Zeilennummer: GOTO 1«. In den Tastaturpuffer wird »Cursor Home« und »RETURN« geschrieben, so daß die Zeile nach dem END-Befehl automatisch ins Programm übernommen wird.
1 PRINT"{CLR}"A;:POKE 19,1:INPUT A$:POKE 19,0:PRINT
2 PRINT"A="A+10":GOTO1":POKE 198,3:POKE 631,19:POKE 632,13:POKE 633,13:END
Das Programm wird mit RUN/STOP-RESTORE wieder verlassen.
(Herbert Kunz/tr)Einzeiler zur Eingabe von Einzeilern
Es lassen sich Basic-Zeilen bis zu 88 Zeichen Länge eingeben. Man startet also den Einzeiler: Es wird dabei der Bildschirm gelöscht, der Cursor auf die dritte Bildschirmzeile gebracht, und in der vierten Zeile, Spalte 8, ein »↑« ausgedruckt. Nun gibt man eine Zeile, beginnend bei der Cursorposition, ein, bis der Pfeil auf das letzte Zeichen der Eingabezeile zeigt. Auf dem Bildschirm ist nun also eine zweizeilige Basic-Zeile zu sehen und in der dritten Basic-Zeile noch acht weitere Zeichen. Das macht zusammen 2 x 40 + 8 = 88 Zeichen, welche auch nach einem RETURN angenommen werden. Warum steht der Cursor aber erst in der dritten Bildschirmzeile? Ganz einfach: Denn nun kann man in der ersten Bildschirmzeile ein LIST (Zeilennummer) eingeben. Die gelistete Basic-Zeile geht dann genau in dem 88-Zeichenbereich. Aber am besten, man probiert den Einzeiler einfach selber mal aus.
Nun zum Programm selbst:
SYS 59749 erzeugt die wichtige Fortsetzungszeile, welche der C 64 selbständig nach 40 Eingabezeilen ausdruckt (Scrollen nach unten, nächste Zeile löschen). SYS 42112 ein Basic-Ende ohne »READY«. Der Vektor hierfür steht in den Speicherstellen 770 und 771.
1 PRINT"{CLR,2DOWN}";: SYS 59749:SYS 59749: PRINT"{HOME,2DOWN}": PRINTTAB(7)"↑": PRINT" {HOME,DOWN}":SYS 42112
Einzeiliger Taschenrechner
1 PRINT"{LIG.BLUE,CLR}"A$"="A:INPUTA$.:PRINT "{HOME,BLUE}A="A$":GOTO1":POKE631,19:POKE632,13: POKE198,2
Mit diesem Einzeiler kann jede beliebige Rechenoperation innerhalb eines Programms durchgeführt werden.
Zum Programm: Beim ersten Start erscheint in der oberen Ecke ein »=0«, das ignoriert werden kann. In den INPUT-Befehl wird nun eine beliebige Rechenoperation eingegeben. Jetzt folgt der eigentliche Trick: Zuerst wird die Variable A, dahinter die Rechenoperation, die im String vorhanden ist und schließlich der Befehl »GOTO 1« (zum späteren Wiederstarten des Programms) in die erste Bildschirmzeile geschrieben. Um zu verhindern, daß es ein kurzes Auftauchen der Variablenzuweisung gibt, ist der PRINT-Befehl der Bildschirmfarbe angepaßt. Nun wird zuerst ein »HOME«, gefolgt von einem »RETURN« in den Tastaturpuffer geschrieben und dieser auf die Länge von zwei Eingaben gebracht. Ist das Programm beendet, nimmt der Computer die Variablenzuweisung auf, startet das Programm erneut und gibt das Ergebnis aus.
(Thorsten Wanschura/tr)Auto-DATA-Routine
Das Maschinenprogramm (Listing 4) muß mit dem MSE eingegeben werden. Es belegt keinen Basic-Speicher, sondern liegt im Speicherbereich von $C000-$C0CF. Nach dem Laden mit LOAD »Name«, Gerätenummer,1 muß »NEW« eingegeben werden. Die Erweiterung wird mit SYS 49152 initialisiert und stellt dann folgende neue Befehle zur Verfügung:
- @A Startzeilennummer, Schrittweite und
- @D Startzeilennummer, Schrittweite.
Dabei darf die Startzeilennummer Werte von 0 bis 63999 annehmen und die Schrittweite darf 255 nicht überschreiten. Wird die Zeilennummer 63999 überschritten, so hat dies einen »ILLEGAL QUANTITY ERROR« zur Folge.
Der @A-Befehl gibt bei der Eingabe eines Basic-Programms die jeweils folgende Zeilennummer aus. Allerdings ist dieser Befehl wesentlich komfortabler als zum Beispiel der Befehl, der in der 64’er-Ausgabe 12/84 veröffentlicht wurde.
Es ist möglich, die zuletzt eingegebene Zeile zu korrigieren und danach das Abtippen fortzusetzen, ohne den Auto-Befehl zu verlassen. Die Zeilennummer wird dabei nicht stur weiter nach oben gezählt und die Zeile wird korrekt angenommen. Wer einmal mit der Routine von Frank Siedel oder auch mit der Auto-Routine von Hypra-Ass gearbeitet hat, wird diesen Vorteil sehr zu schätzen wissen.
Der @A-Befehl kann zum Beispiel durch Drücken der Return-Taste verlassen werden.
Der @D-Befehl gibt zusätzlich zu der Zeilennummer am Anfang jeder Zeile noch ein »DATA« aus. Er kann verlassen werden, indem man vor dem Drücken der Return-Taste das »DATA« mit der INST/DEL-Taste löscht oder die Cursor-down-Taste betätigt. In Verbindung mit dem Checksummer stellt diese Erweiterung eine große Hilfe beim Abtippen von Programmen dar.
(Florian Gallwitz/tr)PROGRAMM : AUTO.OBJ C000 C0D1 ----------------------------------- C000 : A9 20 A0 C0 8D 02 03 8C 08 C008 : 03 03 A9 9A A0 C0 8D 08 A1 C010 : 03 8C 09 03 A9 00 85 02 B1 C018 : 60 A9 00 85 02 4C 48 B2 07 C020 : A6 02 F0 3B A5 FB A4 FC 32 C028 : C0 FA B0 ED 85 63 84 62 99 C030 : A2 90 38 20 49 BC 20 DF E7 C038 : BD A2 00 BD 00 01 F0 06 D6 C040 : 9D 77 02 E8 D0 F5 A9 20 DA C048 : 9D 77 02 A4 02 88 F0 0C F6 C050 : E8 A9 44 9D 77 02 E8 A9 50 C058 : C1 9D 77 02 E8 86 C6 20 24 C060 : 60 A5 86 7A 84 7B 20 73 0F C068 : 00 AA F0 29 A2 FF 86 3A D7 C070 : 90 06 E8 86 02 4C 96 A4 34 C078 : 20 6B A9 A5 14 A4 15 18 58 C080 : 65 FD 85 FB 90 01 C8 84 02 C088 : FC A6 7A BD 00 02 D0 02 85 C090 : 85 02 4C 9F A4 85 02 4C 34 C098 : 5F C0 20 73 00 08 C9 40 B6 C0A0 : F0 04 28 4C E7 A7 20 73 49 C0A8 : 00 C9 41 F0 07 C9 44 F0 AD C0B0 : 07 4C A2 C0 A2 01 D0 02 17 C0B8 : A2 02 86 02 20 73 00 20 1B C0C0 : EB B7 86 FD A5 14 A4 15 A0 C0C8 : 85 FB 84 FC 4C 20 C0 00 D4 C0D0 : 00 A2
Zahlenratespiel
Die Zahlenobergrenze ist veränderbar, indem man die Zahl 108 (=100.000.000) variiert. Durch Verändern der ersten FOR…NEXT-Schleife kann man die Anzahl der Rateversuche erhöhen beziehungsweise erniedrigen. Das eigentliche Herz des Programms ist die SGN-Funktion. Durch sie wird die Variable D definiert. Nach jedem Rateversuch wird der derzeitige Wert dieser Variable am linken Bildschirmrand ausgegeben: »-1« bedeutet, daß die zu erratende Zahl kleiner ist als die eben eingetippte. »1« bedeutet, daß die Zahl größer ist. Bei »0« hat man die gesuchte Zahl erraten, und der Computer denkt sich automatisch eine neue aus. Die bisherige Anzahl der Versuche wird immer rechts des D-Wertes ausgegeben.
7PRINT"NEUEZAHL":A=INT(RND(1)*10↑8):FORB=1TO99: INPUTC:D=SGN(A-C):PRINTD,B:OND+1GOTO7:NEXT
Alle Befehle müssen abgekürzt werden!
Der Hypra-POKE
POKE 57818,8. Nachdem man Hypra-Load geladen und gestartet hat, braucht man nach Eingabe dieses POKEs bei den Befehlen LOAD und SAVE nie wieder das »,8« am Schluß anghängen. Die Defaultnummer (das ist die Nummer, die genommen wird, wenn keine angegeben wird) für die Geräteadresse wird von vormals 1 (Datastette) auf 8 (Diskette) gestellt.
(Ernst Hofler/tr)Tips zum Apfelmännchen
Aufgrund der großen Resonanz und vieler Anfragen, bringen wir hier die Daten der in Ausgabe 11/85 auf Seite 169 veröffentlichten Bilder.
- Bild 1: -0.7; 2.1; -1; 1; 30
- Bild 2. 1.67; 1.86; -.75; 0.75; 40
- Bild 3. 0.1429; 0.1802; 1.02; 1.0477: 100
- Bild 4. 0.5665; 0.5737; 0.5602; 0.5665: 85
- Bild 5. 0.7425; 0.74825; 0.09621; 0.10067; 150
- Bild 6: -0.103; 0.379; 0,618; 0.929; 50
Doch damit nicht genug, wir haben noch ein paar mehr:
- 0.7654; 0,76722; 0.10021; 0.10151; 200
- -0.0171; -9.44e-3; 0.6534; 0.658; 150
- 0.22223; 0.2545; 0.7089; 0.7421; 150
- 0.76461; 0.76498; 0.10056; 0.10082; 254
Anpassung des Apfelmännchen an Datasette
Folgende Änderungen sind zur Anpassung mit Turbo-Tape notwendig:
300 ?"{down}"tab(10)"(5){2space} Effekt"
310 entfällt
315 entfällt
340 get a$:if a$<"1" or a$>"5"then 340
360 on val (a$)gosub 1000,2000,3000,4000,70003
4020 ←s nb$
4030 return
Die Zeilen 4040 bis 5720 entfallen. Will man ein Bild sofort nach dem Berechnen speichern, so antwortet man im Programm mit »j«, und drückt, nachdem der Computer zu zeichnen begonnen hat, Record und Play.
(Dirk Trossen/og)Literaturhinweise zu Apfelmännchen:
In den Zeitschriften »Spektrum der Wissenschaft«, Ausgabe 10/85 und »geo« sind ausführliche Berichte zur Mandelbrotmenge (Apfelmännchen) enhalten.
(Dietmar Horst/og)