Aufgewickelt
Die LIST-Funktion des VC 20 hat bekanntlich eine Reihe von Nachteilen. Das hier vorgestellte Programm ermöglicht Endloslistings vorwärts und rückwärts und soll als Anregung zur eigenen Beschäftigung mit Betriebssystemroutinen dienen.
Wie unendlich langwierig kann es doch sein, wenn man im Listing eine Stelle sucht, von der man nur ungefähr weiß, wo sie liegt! Manche Basic-Erweiterungen bieten die Möglichkeit, das LISTing per Cursor hin- und herzuschieben. Das gleich zu beschreibende Programm leistet ähnliches. Mehr noch! Es läßt sich durch leichte Ergänzung des einbettenden Basic-Programms beliebig komfortabel gestalten. Im einzelnen bewirkt das Programm nach Listing 1 folgendes:
- Ansprung per GOSUB 500. Nach Drücken der Return-Taste Rücksprung ins Ausgangsprogramm oder, falls der Ansprung vom Direktmodus aus erfolgte, in den Direktmodus. Solange das in den Kassettenpuffer gelegte Maschinenprogramm nicht durch andere Operationen (LOAD, SAVE, VERIFY) zerstört wurde, kann jeder weitere Ansprung per GOSUB 580 vorgenommen werden, was eine Einlesezeit von 2,5sec einspart.
- Das LISTing läuft mit der von LIST her bekannten Geschwindigkeit über den Bildschirm (Anfang zufällig), und zwar endlos: Nach Erscheinen der letzten Basic-Zeile erscheint wieder die erste und so weiter. (Die CTRL- und Run/Stop-Taste haben die üblichen Funktionen, sind hier aber überflüssig.)
- Das LISTing stoppt nach Drücken der * -Taste und nimmt seinen Lauf nach abermaligem Drücken der * -Taste wieder auf. Alle weiteren Operationen (einschließlich Rückkehr per Return-Taste) können nur am gestoppten LISTing vorgenommen werden.
- Drücken der Cursor-Down-Taste läßt die jeweils nächste Basic-Zeile erscheinen (mit der üblichen Repeat-Funktion der Cursor-Taste und dem Bildschirm-Scrollen nach oben bei vollem Bildschirm).
- Drücken der Cursor-Right-Taste sucht diejenige Basic-Zeile auf, die auf die letzte auf dem Bildschirm befindliche Zeile folgt, addiert zur Zeilennummer den Wert 4 x 256 und läßt, angefangen bei der sich so ergebenden Zeile, nach Löschung des Bildschirms, fünf aufeinanderfolgende Basic-Zeilen erscheinen. (Der Wert 4 in 256 kann im Programm nach Listing 1 in Zeile 630 abgeändert werden.) Das Ganze bewirkt also, grob gesagt, ein schnelles Durchsuchen des Listings in Sprüngen von 1024 (oder einem vom Benutzer abgeänderten Vielfachen von 256). Ist die Zeile mit der um den Wert 1024 erhöhten Nummer gar nicht vorhanden, was den Normalfall darstellt, da ja 1024 für das Listing als willkürlich gewählter Wert erscheint, wird die darauffolgende Zeile als erste der fünf auszugebenden Zeilen genommen. Genauer gesagt, werden nur vier ausgegeben, da die Suchschleife in diesem Fall einen Leerlaufschritt macht.
- Drücken der Cursor-Up-Taste (Cursor mit Shift) löscht den Bildschirm und läßt, ausgehend von der jeweils letzten Basic-Zeile auf dem Bildschirm (genauer: von der auf diese folgenden Zeile), fünf aufeinanderfolgende Basic-Zeilen erscheinen. (Die Zahl 5 kann im Programm nach Listing 1 in Zeile 770 abgeändert werden.) Jedes weitere Drücken der Cursor-Up-Taste nimmt die zur ersten auf dem Bildschirm befindlichen Basic-Zeile vorhergehende Zeile und läßt fünf aufeinanderfolgende Zeilen erscheinen (mit der üblichen Repeat-Funktion der Cursor-Up-Taste). Bei Erreichen der absolut ersten Zeile des LISTings wird dieser Vorgang mit der absolut letzten Zeile fortgesetzt und so weiter. (Rückwärtsverschieben des LISTings über die Anfangszeile hinaus).
Alle verwendeten Cursor-Tasten behalten ihre Repeat-Funktion bei. Das Rückwärtslisten ist dreimal langsamer als das Vorwärtslisten über die * - oder Cursor-Down-Taste und nur zum Einpendeln gedacht: Überblick mit *, Grobabstimmung mit Cursor right, Feinabstimmung mit Cursor down, Korrektur mit Cursor up, endgültige Feinabstimmung mit Cursor down.
Will man das LISTing mit einer vorgegebenen Zeilennummer Y*256+X beginnen lassen, was wegen der oben erwähnten schnellen Durchsuchungsmöglichkeit in Schritten von 1024 an sich nicht nötig ist, so ersetze man den Aufruf GOSUB 500, beziehungsweise GOSUB 580, durch POKE 780, Y:POKE 781, X:GOSUB 500, beziehungsweise POKE 780, Y: POKE 781, X: GOSUB 580.
Für das Maschinenprogramm wird der Trick verwendet, geeignete Teile des Betriebssystems in den Kassettenpuffer zu kopieren und dort durch einige wenige POKE-Anweisungen abzuändern und miteinander zu verbinden. Es werden keine DATA-Zeilen benötigt, wodurch die bekannten Schwierigkeiten mit dem im VC 20-Basic nicht vorhandenen »RESTOREn« umgangen werden.
Neben der eben beschriebenen langen Form des Programms zum Endloslisten nach Listing 1 schlagen wir in Listing 2 noch eine kurze Form vor. Für diese gelten die oben beschriebenen Punkte 1 bis 5 (* -Taste: Lauf, *-Taste: Stillstand, Cursor-Down-Taste: Zeile für Zeile — endlos, Cursor-Right-Taste: Schrittweite 1024, Return-Taste: Rückkehr). Sowohl das Maschinenprogramm als auch das einbettende Basic-Programm sind wesentlich kürzer. Der Hauptaufand wurde im Programm nach Listing 1 für die Organisation des Rückwärtslaufes benötigt.
(Fred Behringer/ev)Zeile | |
510-570 | Aufbau des Maschinenprogramms im Kassettenpuffer durch Aneinanderreihung von Teilen des Betriebssystems und leichte Ergänzungen und Abänderungen. |
510 | Übergabe der X/A-Register (dort steht die Nummer der zu listenden Basic-Zeile) an $0014/$0015 (20/21). |
520 | $C163-$C636 (50707-50742). Startadresse einer Basic-Programmzeile berechnen. Zeilennummer in $0014/$0015 (20/21). |
530 | $X708-$C711 (50952-50961). Festhalten der jeweils erreichten Zeilennummer in der Suchschleife und Ablegen nach $00FD/$00FE (6253/254). Nach Erreichen der Adresse der gesuchten Zeilennummer in $0014/$0015 (20/21) steht in $00FD/$00FE (253/254) die Nummer der vorhergehenden Zeile. Ist die Nummer in $0014/$0015 (20/21) nicht größer als die erste Zeile des zu listenden Programms, dann wird $C708-$C711 übersprungen und $00FD/$00FE (253/254) behält seinen alten Wert bei. |
540 | $C637-$C63F (50743-50751). Weiter in der Suchschleife zur Berechnung der Adresse derjenigen Zeile, deren Nummer in $0014/$0015 (20/21) steht. Die Adresse wird an $005F/$0060 (95/96) ausgegeben. Existiert diese Zeile nicht, dann erscheint die Adresse der nächstfolgenden Zeile. In den X5A-Registern steht jeweils die Nummer (Low-Byte, High-Byte) derjenigen Zeile, welche auf die Zeile folgt, deren Adresse in $005F/$0060 (95/96) gelegt wurde. Ist die in $0014/$0015 (20/21) eingegebene Zeilennummer nicht kleiner als die Nummer der größten Zeile des zu listenden Programms, dann werden X/A mit (für unsere Zwecke) unbrauchbaren Werten belegt; jedoch erhält dann (und nur dann) das Y-Register den Wert 1 (siehe unten Zeile 780). Das Basic-Rahmenprogramm erhält die jeweiligen A-, X-, Y-werte über $030C-$030E (780-782). |
550 | $C6C9-$C741 (50896-51009). Eigentliches Programm zum Auflisten der gewünschten Zeile. Normalerweise Zeilenvorschub, der in 790 (siehe unten) korrigiert wird. Bei Erreichen der letzten Zeile Austritt ohne Zeilenvorschub, was in Zeile 780 (siehe unten) steht. |
560 | Abänderungen von Sprungadressen und Korrektur der Zeilennummer, so daß bei der letzten Zeile in $00FD/$00FE (253/254) abgelegt wird (siehe unten Zeile 530). |
570 | Ergänzung um einen DEY-Befehl $0088 (136). Abänderung zweier Sprungadressen. Sorge dafür, daß nach LISTen der betreffenden Zeile nicht zum Basic-Warmstart gesprungen wird, sondern an die SYS-Rücksprungadresse des aufrufenden Basic-Programms. Das wird durch Überschreiben des Inhalts von $C714 (50964) (natürlich in der Kassettenpuffer-Kopie) mit dem RTS-Befehl $0060 (96) erreicht. |
580 | Listen, solange nicht *. |
590-600 | Sonst: Wenn {Cursor down}, dann eine Zeile listen. |
610 | Wenn wieder *, dann listen, solange nicht abermals *. |
620-630 | Wenn {Cursor right}, dann Sprung um 1024. |
640 | Wenn {Return}, dann zurück. |
650 | Wenn nicht {Cursor up}, dann Neubeginn der Eingabeschleife. |
660 | Nummer der vorhergehenden Zeile in X/Y. |
670-680 | Wenn größer, dann Korrektur für Null und fünf Zeilen listen. |
690 | Neubeginn der Eingabeschleife. |
700-720 | Wenn nicht {Cursor up}, dann Korrektur für Nulldurchgang und fünf Zeilen listen. |
740 | Abermaliger Beginn der Eingabeschleife. |
750-760 | Wenn {Cursor up}, dann Vorgänger der Zeile, deren Nummer in X/Y liegt (Anfangszeile des angegebenen Fünferblocks) als Anfangszeile des neuen Fünferblocks nehmen und fünf Zeilen ausgeben. |
770 | Ausgabe von fünf aufeinanderfolgenden Zeilen. |
780-800 | Ausgabe einer Zeile |
790 | und Korrektur für Programme. |
500 rem endloslisting 501 rem (lange fassung) 502 rem 503 rem 510 poke 828,134:poke 829,20:poke 830,133:poke 831,21 520 for i=0 to 35:poke 832+i,peek(50707+i):next 530 for i=0 to 9:poke 868+i,peek(50952+i):next 540 for i=0 to 8:poke 879+i,peek(50743+i):next 550 for i=0 to 120:poke 888+i,peek(50889+i):next 560 poke 845,42:poke 853,34:poke 865,22:poke 867,20:poke 875,253:poke 877,254 570 poke 878,136:poke 887,204:poke 949,19:poke 963,96 580 gosub 780:get x$:if x$<>"*"then 580 590 get x$:if x$=""then 590 600 if x$=chr$(17)then gosub 780:goto 590 610 if x$="*"then 580 620 if x$<>chr$(29)then 640 630 poke 780,peek(780)+4:gosub 770 640 if x$=chr$(13)then 800 650 if x$<>chr$(145)then 590 660 x=peek(253):y=peek(254) 670 if x+256*y<=peek(781)+256*peek(780)then 730 680 poke 780,0:poke 781,0:gosub 770 690 get x$:if x$=""then 690 700 ifx$<>chr$(145)then 600 710 poke 781,255:poke 780,249 720 for i=0 to 3:sys 828:x=peek(253):y=peek(254):poke 781,x:poke 780,y:next 730 gosub 770 740 get x$:if x$=""then 740 750 if x$<>chr$(145)then 600 760 poke 781,x:poke 780,y:gosub 780:goto 660 770 print chr$(147);:for i=1 to 5:gosub 780:next:return 780 sys 828:if peek(782)=1 then poke 781,0:poke 780,0:goto 800 790 print chr$(145); 800 return
900 rem endloslisting 901 rem (kurze fassung) 902 rem 903 rem 910 poke 828,134:poke 829,20:poke 830,133:poke 831,21 920 for i=0 to 45:poke 832+i,peek(50707+i):next 930 for i=0 to 120:poke 878+i,peek(50889+i):next 940 poke 939,19:poke 953,96 950 gosub 1020:get x$:if x$<>"*"then 950 960 get x$:if x$=""then 960 970 if x$=chr$(17)then gosub 1020:goto 960 980 if x$=chr$(13)then 1040 990 if x$="*"then 950 1000 if x$<>chr$(29)then 960 1010 poke 780,peek(780)+4:print chr$(147);:for i=1 to 5:gosub 1020:next:goto 960 1020 sys 828:if peek(782)=1 then poke 781,0:poke 780,0:goto 1040 1030 print chr$(145); 1040 return