64'er, Ausgabe 11/November 1989
»Ruckelhaftes« Scrolling kann den Spielspaß erheblich mindern. In dieser Folge lernen Sie, wie man ein »butterweiches« Scrolling programmiert.
Dieser Kursteil ist einem der gefürchtesten Themen der Spieleprogrammierung gewidmet: dem Softscrolling. Man hat quasi einen riesigen Hintergrund, von dem aber immer nur ein Ausschnit auf dem Bildschirm zu sehen ist.
Bild 1. Ein Spielfeld mit drei nebeneinanderliegenden Bildschirmen. |
Zunächst muß man sich über das Format Gedanken machen, in dem die Daten eines Spielfeldes im Speicher abzulegen sind. Man teilt das Spielfeld dazu in Zeilen und Spalten ein (Bild 1). Dieses Spielfeld ist 120 Zeichen breit und 20 Zeilen hoch. Ferner muß man sich überlegen, welcher Speicherbereich sich für die Ablage der Spielfelddaten gut eignet. Ich schlage der Einfachkeit halber die Organisation gemäß Bild 2 vor. Wie Sie dort sehen können, sind für das Spielfeld zwei Speicherbereiche vorgesehen. Dies muß je nach Spielbedarf des Spielfeldes entschieden werden. Unseres belegt 2400 Byte, es paßt also bequem in den 4-KByte-Bereich $1000 bis $1FFF. Die Maschinenroutinen legen wir nach $C000, den Basic-Start legen wir nach $4000, so daß man auch noch Testprogramme in Basic schreiben kann.
Bild 2. Die Speicherbelegung |
Unser Ziel ist es nun, eine Routine zu schreiben, die diesen Bereich flimmerfrei, mit verschiedenen Geschwindigkeiten und in verschiedene Richtungen über den Bildschirm schiebt. Hierbei sollen die oberen fünf Zeilen nicht gescrollt werden. Dort kann z.B. die Punktzahl angezeigt werden. Vorgesehen sind nur die Richtungen links und rechts, da die Routine andernfalls den Rahmen dieses Kursteil sprengen würde.
Man underscheidet zwischen zwei Arten von Scrolling: dem Softscrolling und dem Hardscrolling. Beim Softscrollling handelt es sich um ein pixelweises Verschieben des Bildschirminhaltes. Bei einem Hardscrolling wird der Bildschirmeinhalt um ein ganzes Zeichen verschoben. Dies wird duch Umkopieren der Zeichen im Video-RAM erreicht. Um eine Softscroll-Routine zu realisieren, ist es zunächst einmal notwendig, eine schnelle Hardscroll-Routine zu schreiben. Dies geschah in Listing 1.
Bild 4. Das Flußdiagramm der Softscroll- IRQ-Routine. |
Tippen Sie das Listing ein, speichern Sie den Quelltext auf Diskette und assemblieren Sie ihn, anschließend lösen Sie einen Reset aus. Geben Sie nun als Basic-Testprogramm Listing 1.1 ein. Starten Sie dieses Programm mit »RUN«.
WICHTIG: Jede Programmzeile im Basic Listing ist mit einer Prüfsumme versehen. Zum Generieren dieser Prüfsumme brauchen Sie das Programm »CHECKSUMMER V3« (Laden und starten Sie dieses Programm und fangen Sie dann an die Programmzeilen zu übernehmen; die Prüfsumme erscheint in der linken oberen Ecke). Andernfalls können Sie das betreffende Basic-Programm über den Link in der Beschreibung des Listings downloaden. |
Wie Sie sehen, bewegen sich Zeichen flimmernd und ruckelnd über den Bildschirm. Sehen wir uns nun das Listing an. In Zeile 10000 beginnt die Routine HSCROLL. Sie kopiert einen Ausschnitt aus einem Spielfeld in die untersten 20 Zeilen des Video-RAMs. Dafür werden folgende Parameter benötigt:
Um ein Maximum an Geschwindigkeit zu erreichen, wurde die Routine selbstmodifizierend geschrieben, denn ein Hardscrollvorgang muß innerhalb eines Bildschirmaufbaus (1/50 Sekunde = 20 ms) vorstatten gehen. Immer wenn eine Bildschirmzeile kopiert wurde, wird die Adresse zum Lesen einer Zeile aus dem Spielfeld (MODI1) um die Spielfeldbreite »SBREITE« aufaddiert, um die nächste Zeile zu erreichen. Parallel dazu wird die Adresse des STA-Befehls in Zeile 10140 um 40 erhöht, so daß die nächste Bildschirmzeile erreicht wird. Dies geschieht zwanzig mal.
Der VIC des C64 erlaubt es, den gesamten Bildschirm pixelweise zu verschieben. Es existieren zwei Register, in denen jeweils 3 Bit für diese Funktion reserviert sind. Die unteren 3 Bit des Registers 53265 (VIC+17) sind für das Verschieben in Y-Richtung vorgesehen und die unteren 3 Bit des Registers 53270 (VIC+22) für das Verschieben in X-Richtung. Probieren Sie es mit folgender Befehlsfolge aus:
POKE 53270,(PEEK(53270) AND 248) OR X
<X> darf hier von 0 bis 7 laufen. Setzen Sie beispielsweise eine 5 ein, rückt der Bildschirm um 5 Pixel nach rechts. Wir nennen diese Zahl »Pixelposition«. Der Bildschirm hat also Pixelposition 5.
Setzen Sie statt 53270 das Register 53265 ein, so rückt der Bildschirm nach unten. Wir werden allerdings, wie schon erwähnt, nur in die X-Richtung scrollen.
Wählen Sie eine Pixelposition von 7, so rückt der Bildschirm um fast eine Zeichenbreite nach rechts bzw. nach unten. Der freiwerdende Raum wird durch die Hintergrundfarbe ausgefüllt. Um nun den Effekt zu erzielen, daß Bildschirmteile hinter dem Rahmen hervortreten, läßt sich der Bildschirm horizontal auf 38 Spalten und vertikal auf 24 Zeilen verkleinern:
POKE 53270,PEEK(53270) AND 247:REM 38 SPALTEN EIN POKE 53270,PEEK(53270) OR 8:REM 38 SPALTEN AUS POKE 53265,PEEK(53265) AND 247:REM 24 ZEILEN EIN POKE 53265,PEEK(53265) OR 8:REM 24 ZEILEN AUS
Der Bildschirm läßt sich auf diese Weise nur um maximal 7 Pixel bewegen. Das Softscrolling wird aus diesem Grund mit dem Hardscrolling kombiniert.
Ein Softscrolling nach rechts gliedert sich also in folgende Schritte (wenn von Scrollregister die Rede ist, so sind stets die unteren 3 Bit des Registers 53270 gemeint !):
Um ein fließendes und flimmerfreies Softscrolling zu erreichen, muß dieser Vorgang mit dem Rasterstrahl synchronisiert werden, d.h. der Bildschirm muß bei jedem Bildschirmaufbau um 1 Pixel verschoben werden. Man erreicht dies, indem man den System-IRQ nicht über den Timer, wie sonst, von CIA #1 auslöst, sondern wieder einmal über den Raster-IRQ (vlg. Teil 2, 3 und 4).
Die Tatsache, daß bei jedem Bildschirmaufbau (alle 1/50 Sekunde) um einen Schritt gescrollt werden muß, wirft spätestens bei Punkt 9 ein Problem auf. Man muß hier in einer 1/50 Sekunde 1 KByte umkopieren.
Da es aber oft erwünscht ist, einige Zeilen nicht zu scrollen, habe ich es bei 20 Zeilen belassen. So bleibt nach einem Hardscroll-Vorgang ein wenig Zeit für andere IRQ-Routinen, bevor der nächste Raster-IRQ ausgelöst wird.
Ergänzen Sie Listing 1 durch die Zeilen von Listing 2. Speichern Sie den neuen Quelltext auf Diskette ab und assemblieren Sie ihn. Die Softscroll-Routine läßt sich sich nun mit SYS 49152 starten. Sie ermöglicht ein Softscrolling nach links oder rechts in 8 Geschwindigkeiten.
Als Voreinstellung wurde ein langsames Scrolling nach links gewählt.
Um ein Softscrolling der unteren 20 Zeilen zu erreichen, muß zunächst der Bildschirm gesplittet werden. Hierzu benötigt man, wie in den Kursteil 2 und 3 beschrieben, zwei Rasterstrahlpositionen, an dessen ein IRQ ausgelöst werden soll. Die obere Grenze ist die Rasterzeile 49. Das ist genau der Übergang vom Rahmen zum Textbildschirm. Die untere Grenze liegt bei Rasterzeile 89. Das ist die Grenze zwischen Bildschirmzeile 5 und 6.
Da die Scrollregister des VIC auf den ganzen Bildschirm wirken, die oberen 5 Zeilen aber nicht verschoben werden sollen, muß bei Rasterzeile 49 die Pixelposition 0 eingestellt werden (durch Löschen der unteren 3 Bit des Registers 53270). In Rasterzeile 89, bei der der Scrollbereich beginnt, muß dann die aktuellen Pixelposition eingestellt werden. Wir haben nun eine Speicherzelle definiert (PIXPOS), in der die aktuelle Pixelposition des Scrollbereiches gespeichert wird. Die oberen fünf Zeilen erscheinen nun in jedem Fall mit der Pixelposition 0 und die restlichen Bildschirmzeilen mit der Pixelposition, die in PIXPOS steht.
Ein Teil des Softscrollings läßt sich, wie schon erwähnt, durch Verändern der Pixelposition erreichen. Die Teilroutine, die zur Rasterzeile 49 gehört, kümmert sich um dieses Herunter- bzw. Heraufzählen.
Da das Programm in beide Richtungen scrollen kann, muß es ein Flag geben, welches die Richtung anzeigt. Diese Aufgabe übernimmt die Speicherzelle DIRECT:
Sehen wir uns nun das Heraufzählen der Pixelposition an (DIRECT = 0). Der Programmteil beginnt ab Zeile 2240. Wie Sie sehen, wird PIXPOS um STEP aufaddiert. Es sind also verschiedene Schrittweiten möglich. Wozu dies gut ist, wird später erläutert. Wir nehmen zunächst an, STEP enthalte den Wert 1.
PIXPOS startet mit 0 und wird schrittweise um 1 inkrementiert. Da PIXPOS nur Werte zwischen 0 und 7 annehmen darf, wird es bei Erreichen des Wertes 7 kritisch, da PIXPOS nun den Wert 8 annimmt. Dies ist nicht erlaubt, denn der richtige Wert wäre 0 (Siehe Tabelle im Kapittel »Softscrolling mit Tücken«). Man könnte jetzt stets mit einem CMP-Befehl auf Bereichsüberschreitung prüfen und das Register dann entsprechend auf 0 zurücksetzen, dies ist allerdings sehr umständlich, da man auf diese Weise zwei getrennte Routinen für Auf- und Abwärtszählen benötigte. Außerdem müßte man sich um verschiedene Schrittweiten kümmern. Mit STEP = 3 muß PIXPOS beispielsweise die Werte 0, 3, 6, 1, 4, 7 usw. annehmen. Man hilft sich nun mit einem Trick: Man führt eine AND #7-Verknüpfung durch. So enthält das Register PIXPOS im obigen Beispiel nach einer 6 den Wert 9, binär 00001001. Nach Abtrennen der unteren 3 Bit mit AND #7 enthält es eine 1. Dies funktioniert auch beim Abwärtszählen!
Wie schon erwähnt, muß unsere Hardscroll-Routine innerhalb von 20 ms ein komplettes Hardscrolling zustande bringen. Die vorgestellte Routine erfüllt diese Bedingung. Sollten Sie später selber eine Hardscroll-Routine schreiben, so denken Sie an folgenden Tip: Testen Sie Ihr Programm zunächst mit fünf Zeilen. Wenn dies funktioniert, so können Sie (ziemlich) sicher sein, daß Sie alles richtig programmiert haben. Erhöhen Sie jetzt die Anzahl der gescrollten Zeilen auf den gewünschten Wert. Fängt das Bild jetzt an zu ruckeln und zu flimmern, so ist ihre Routine höchstwahrscheinlich zu langsam.
Es stellt sich nun die Frage, wann das Hardscrolling erfolgen muß. Gewöhnlich geht man davon aus, daß der Inhalt des Video-RAMs »momentan« auf dem Bildschirm erscheint, - tatsächlich werden die Speicherzeilen nur alle 20 ms ausgelesen und auf dem Schirm »dargestellt«, - Veränderungen des Speicherinhaltes erscheinen somit zeitverzögert auf dem Bildschirm, und man kann, ohne das Bild zu beeinflussen, ganz gewaltig im Video-RAM »herumwuseln«, sofern man nur fertig ist, bevor der jeweilige Speicherbereich erneut ausgelesen und dargestellt wird.
Wird nun der Scrollbereich bereits mit der Pixelposition 0 dargestellt, d.h. tastet die Rasterstrahl bereits die Rasterzeilen größer 89 ab, ist es zu spät, denn der Bildschirm wäre schon »zurückgeschnappt« bevor er duch Hardscrolling die richtige Position erreicht. Das Hardscrolling muß also vorher erfolgen. Naheliegend wäre nun, das Hardscrolling »anzuwerfen«, wenn der Rasterstrahl den Scrollbereich mit den Pixelposition 7 vollständig dargestellt hat, also nach Erreichen von Rasterzeile 250. Die Routine hätte dann aber nur soviel Zeit, wie der Rasterstrahl benötigt, um vom unteren Bildschirmrand zum oberen zu kommen, und dies ist mit Sicherheit zuwenig.
Wir lösen das Problem mit einem Trick: Der Rasterstrahl hat gerade die Darstellung der Zeile 6 (erste zum Scrollbereich gehörende Bildschirmzeile) mit der Pixelposition 7 beendet und beginnt nun mit Zeile 7. Zeile 6 wurde also jetzt vollständig dargestellt. Verändern wir jetzt ihren Inhalt, so wird dieser erst 20 ms später dargestellt. Wir können also jetzt schon mit dem Hardscrollen dieser Zeile beginnen. Da unsere Hardscroll-Routine langsamer als der Rasterstrahl ist, kopieren wir quasi »hinter dem Rasterstrahl her«.
Im Programm ist dies folgendermaßen verwirklicht: Der Programmteil, der zur Rasterzeile 49 (obere Splitgrenze) gehört (im Listing Zeile 2170), kümmert sich nur um das Herauf- bzw. Herunterzählen von PIXPOS und darum, daß die Werte nur zwischen 0 und 7 liegen (s.o.). Ferner sorgt er dafür, daß PIXPOS bei Überschreiten der erlaubten Grenzen entsprechend der Schrittweite zurückgesetzt wird. Der Programmteil für Rasterzeile 89 (untere Splitgrenze, im Listing Zeile 2410) setzt die Pixelposition auf den Wert von PIXPOS. Nun kontrolliert das Programm, ob beim nächsten Additions- bzw. Subtraktionsvorgang ein Übertrag erfolgt, beispielsweise von 7 auf 0 gesprungen wird. Ist dies der Fall, sorgt es dafür, daß die nächste Raster-IRQ nicht bei Zeile 49, sondern bei Zeile 98 erfolgt. Dies ist diejenige Rasterzeile, die genau hinter Bildschirmzeile 6 liegt. Außerdem sorgt es dafür, daß die Position innerhalb des Scrollbildschirmes SCRPOS (in unserem Fall liegt dieser ab $1000 = 4096) herauf- bzw. heruntergezählt wird und kümmert sich um das Überschreiten der Grenzen. Anschließend wird die absolute Adresse des ersten Bytes, das vom Scrollbildschirm ins Video-RAM kopiert werden soll, in den Übergaberegistern SRAM und SRAM+1 an die Hardscrollroutine übergeben.
Ist der Rasterstrahl nun an der Bildschirmzeile 6 vorbeigelaufen, wird ein IRQ ausgelöst. Die dazugehörige Routine (Zeile 2120) tut nichts weiter als die Hardscrollroutine auf zu rufen und anschließend den nächsten Raster-IRQ auf Rasterzeile 49 zu legen. Die Hardscrollroutine kopiert nun den Teil aus dem Scrollbildschirm ins Video-RAM, der bei der Speicherzelle beginnt, auf den die Speicherzellen SRAM und SRAM+1 zeigen, wobei dieser Vorgang »unsichtbar« bleibt. Erreicht der Rasterstrahl nun Rasterzeile 89, wird der verschobene Bildschirm mit PIXPOS = 0 dargestellt - das Bild ruckt nicht!
Bild 3. Die Initialisierungsroutine. |
In Bild 3 und 4 sehen Sie die Flußdiagramme sowohl zu der Initialisierungsroutine als auch zu der IRQ-Routine. Bild 5 soll Ihnen den Hardscrollvorgang verdeutlichen.
Bild 5. Das Hardscrolling. |
Die vorgestellte Scrollroutine bietet die Möglichkeit, sowohl in zwei Richtungen als auch mit verschiedenen Geschwindigkeiten zu scrollen.
Die Richtung wird durch die Speicherzelle DIRECT, wie oben beschrieben, festgelegt. Die Richtung darf nur zu einem bestimmten Zeitpunkt verändert werden, und zwar nachdem der Wert von PIXPOS in den VIC übertragen wurde und bevor das Programm nachschaut, ob der nächste Wert von PIXPOS ein Hardscrolling erfordert. Hierzu bedienen wir uns eines Pseudoregisters PDIRECT, dessen Inhalt genau zu diesem Zeitpunkt in das Register DIRECT übertragen wird (Zeile 2450). Somit ist sichergestellt, daß das Register DIRECT nur in diesem Moment verändert wird. Andernfalls gäbe es ein unschönen Flackern des Bildschirmes.
Verschieden Geschwindigkeiten werden dadurch erreicht, daß man die Pixelposition nicht um 1 verändert, sondern um größere Beträge.
Die Speicherzelle STEP darf Werte bis 8 annehmen. In diesem Fall wird allerdings permanent »hardgescrollt«, so daß nur noch wenig Zeit für das Hauptprogramm überbleibt.
Für den Parameter STEP gilt übrigens das gleiche wie für DIRECT. Er darf nur zu einem bestimmten Zeitpunkt (Zeile 2470) verändert werden. Möchten Sie die Geschwindigkeit ändern, so müssen Sie stets PSTEP (Pseudostep) beschreiben.
Die Scrollroutine, die aus Listing 1, ergänzt durch Listing 2, besteht, speichern Sie bitte auf Diskette ab. Fertigen Sie jetzt durch Hinzufügen der Zeile:
5.OB "SCROLL.OBJ,P,W"
und anschließenden RUN ein Objektfile an. Sie benötigen dies später für Listing 3.1.
Nach Start von Listing 4 durch
LOAD "FILE-GEN.CRU",8<return> RUN<return>
erzeugt dieses zwei Dateien:
»CHAR-SET« ist ein selbstdefinierter Zeichensatz und »SCROLL-SCREEN« ein Scrollbildschirm. Er ist 120 Zeichen, also drei Bildschirme breit. Der letzte Bildschirm enthält das gleiche wie der erste Bildschirm. Das vereinfacht die Reaktion auf das Überschreiten der Scrollbildschirmgrenzen beim Hardscrolling.
Die Scrollroutine ist so geschrieben, daß sie nach Erreichen von Position 79 wieder auf 0 umschaltet. Das gleiche geschieht beim Scrollen nach rechts, die Routine springt dann von 0 auf 79. Beide Files wurden übrigens mit den Editoren von Master-Tool erstellt (64'er Ausgabe 1/89).
Sowohl der Quelltext der Scrollroutine als auch die beiden genannten Files werden im Teil 8 für das dort vorgestellte Spiel benötigt.
Speichern Sie Listing 3.1 under dem Namen »SCROLLTEST« auf Diskette, starten Sie es jedoch noch nicht. Tippen Sie nun den Lader in Listing 3 ab und speichern Sie ihn unter dem Namen »SCROLLTEST-BOOT« ab.
Starten Sie jetzt den Lader, so wird wieder einmal der Basicstartvektor auf $4000 (16384) verbogen und anschließend Listing 3.1 sowohl nachgeladen als auch gestartet. Listing 3.1 erlaubt es, den vorher generierten Zeichensatz und den Scrollbildschirm zu verbinden.
Nächstes Mal beschäftigen wir uns mit der Soundprogrammierung.
(H. Rosenfeld/af)
Listing 1. Eine Hard-Scroll-Routine als Quellcode (download Quellcode in Hypra-Ass Format, oder assembliertes Binary von »HARD SCROLL«) |
||
10 -.BA 49152 100 -;******************************** 110 -;** VARIABELEN ** 120 -;******************************** 200 -.GL VIDEORAM =1024+5*40 210 -.GL SCROLLSCR =4096 220 -.GL SCROLLBREITE=120 230 -.GL ROBEN =49 240 -.GL RUNTEN =89 250 -.GL RHARD =98 399 -; 400 -.GL IRQVEC =$0314 410 -.GL IRQALT =$EA31 420 -.GL IRQEND =$EA81 430 -.GL VIC =$D000 440 -.GL IRQMASK=VIC+26 450 -.GL IRQFLAG=VIC+25 460 -.GL RASTER =VIC+18 470 -.GL HIBIT =VIC+17 480 -.GL XSCROLL=VIC+22 490 -.GL CIATIME=$DC0E 699 -; 700 -.GL VRAM =679 710 -.GL SCRSTART=VRAM+2 720 -.GL SRAM =SCRSTART+2 730 -.GL SBREITE =SRAM+2 740 -.GL GRENZE =SBREITE+2 750 -.GL SCRPOS =GRENZE+2 760 -.GL PIXPOS =SCRPOS+2 770 -.GL STEP =PIXPOS+1 780 -.GL DIRECT =STEP+1 790 -.GL PSTEP =DIRECT+1 800 -.GL PDIRECT =PSTEP+1 810 -; 10000-;******************************** 10010-;** HARD-SCROLL-ROUTINE ** 10020-;******************************** 10030-HSCROLL LDX #20 10040- LDA SRAM 10050- STA MODI1+1 10060- LDA SRAM+1 10070- STA MODI1+2 10080- LDA VRAM 10090- STA MODI2+1 10100- LDA VRAM+1 10110- STA MODI2+2 10120-LINELOOP LDY #39 10130-MODI1 LDA 65535,Y 10140-MODI2 STA 65535,Y 10150- DEY 10160- BPL MODI1 10170- CLC 10180- LDA MODI1+1 10190- ADC SBREITE 10200- STA MODI1+1 10210- LDA MODI1+2 10220- ADC SBREITE+1 10230- STA MODI1+2 10240- CLC 10250- LDA MODI2+1 10260- ADC #40 10270- STA MODI2+1 10280- LDA MODI2+2 10290- ADC #0 10300- STA MODI2+2 10310- DEX 10320- BNE LINELOOP 10330- RTS 60000-.EN READY. | ||
Listing 1.1. Das Basic-Programm der Hard-Scroll-Routine (Sie können dieses Programm »TEST HARD SCROLL« auch downloaden) |
||
10 VRAM=679 :REM VIDEORAM <041> 20 SRAM=683 :REM SCROLLBILDSCHIRM <214> 30 SBREITE=685:REM BREITE <158> 40 POKE VRAM ,200:POKE VRAM+1 ,4 <146> 50 POKE SBREITE,120:POKE SBREITE+1,0 <125> 60 : <036> 70 FOR X=4096 TO 4096+80 <134> 80 POKE SRAM ,X-INT(X/256)*256 <008> 90 POKE SRAM+1,X/256 <244> 100 SYS 49152 <158> 110 NEXT X:GOTO 20 <178> | ||
Listing 2. Eine Ergänzung zu Listing 1 (Sie können sowohl den separaten Quellcode, den ergänzten Quellcode in Hypra-Ass Format, als auch den lauffähigen Objektcode downloaden.) |
||
1000 -;******************************** 1010 -;** INITIALISIERUNG ** 1020 -;******************************** 1030 -INIT SEI 1040 - LDA #<(VIDEORAM) 1050 - LDX #>(VIDEORAM) 1060 - STA VRAM 1070 - STX VRAM+1 1080 - LDA #<(SCROLLSCR) 1090 - LDX #>(SCROLLSCR) 1100 - STA SCRSTART 1110 - STX SCRSTART+1 1120 - LDA #<(SCROLLBREITE) 1130 - LDX #>(SCROLLBREITE) 1140 - STA SBREITE 1150 - STX SBREITE+1 1160 - LDA #<(SCROLLBREITE-40) 1170 - LDX #>(SCROLLBREITE-40) 1180 - STA GRENZE 1190 - STX GRENZE+1 1200 - LDA #0 1210 - STA SCRPOS 1220 - STA SCRPOS+1 1230 - STA PIXPOS 1240 - STA DIRECT 1250 - STA PDIRECT 1260 - LDA #1 1270 - STA STEP 1280 - STA PSTEP 1290 - LDA #ROBEN 1300 - STA RASTER 1310 - LDA HIBIT 1320 - AND #127 1330 - STA HIBIT 1340 - LDA #129 1350 - STA IRQMASK 1360 - LDA #<(IRQNEU) 1370 - LDX #>(IRQNEU) 1380 - STA IRQVEC 1390 - STX IRQVEC+1 1400 - LDA CIATIME 1410 - AND #254 1420 - STA CIATIME 1430 - CLI 1440 - RTS 2000 -;******************************** 2010 -;** IRQ-ROUTINE ** 2020 -;******************************** 2030 -IRQNEU LDA IRQFLAG 2040 - STA IRQFLAG 2050 - LDA RASTER 2060 - CMP #RHARD 2070 - BCS IRQHARD 2080 - CMP #RUNTEN 2090 - BCS IRQUNTEN 2100 - JMP IRQOBEN 2110 -; 2120 -IRQHARD JSR HSCROLL 2130 - LDA #ROBEN 2140 - STA RASTER 2150 - JMP IRQEND 2160 -; 2170 -IRQOBEN LDA XSCROLL 2180 - AND #255-7 2190 - STA XSCROLL 2200 - BIT DIRECT 2210 - BMI CONT1 2220 - BVS SLINKS1 2230 -; 2240 -SRECHTS1 CLC 2250 - LDA PIXPOS 2260 - ADC STEP 2270 - AND #7 2280 - STA PIXPOS 2290 - JMP CONT1 2300 -; 2310 -SLINKS1 SEC 2320 - LDA PIXPOS 2330 - SBC STEP 2340 - AND #7 2350 - STA PIXPOS 2360 -; 2370 -CONT1 LDA #RUNTEN 2380 - STA RASTER 2390 - JMP IRQALT 2400 -; 2410 -IRQUNTEN LDA XSCROLL 2420 - AND #255-7 2430 - ORA PIXPOS 2440 - STA XSCROLL 2450 - LDA PDIRECT 2460 - STA DIRECT 2470 - LDA PSTEP 2480 - STA STEP 2490 - BIT DIRECT 2500 - BMI CONT2 2510 - BVS SLINKS2 2520 -; 2530 -SRECHTS2 CLC 2540 - LDA PIXPOS 2550 - ADC STEP 2560 - AND #255-7 2570 - BNE SETHARD 2580 - JMP CONT2 2590 -; 2600 -SLINKS2 SEC 2610 - LDA PIXPOS 2620 - SBC STEP 2630 - BCC SETHARD 2640 -; 2650 -CONT2 LDA #ROBEN 2660 - STA RASTER 2670 - JMP IRQEND 2680 -; 2690 -SETHARD BIT DIRECT 2700 - BVS SLINKS3 2710 -; 2720 -SRECHTS3 DEC SCRPOS 2730 - LDA SCRPOS 2740 - CMP #255 2750 - BNE CONT4 2760 - DEC SCRPOS+1 2770 -CONT4 LDA SCRPOS+1 2780 - CMP #255 2790 - BNE CONT5 2800 - LDA SCRPOS 2810 - CMP #255 2820 - BNE CONT5 2830 - LDA GRENZE 2840 - STA SCRPOS 2850 - LDA GRENZE+1 2860 - STA SCRPOS+1 2870 - JMP SRECHTS3 2880 -; 2890 -SLINKS3 INC SCRPOS 2900 - BNE CONT3 2910 - INC SCRPOS+1 2920 -CONT3 LDA SCRPOS+1 2930 - CMP GRENZE+1 2940 - BNE CONT5 2950 - LDA SCRPOS 2960 - CMP GRENZE 2970 - BNE CONT5 2980 - LDA #0 2990 - STA SCRPOS 3000 - STA SCRPOS+1 3010 -; 3020 -CONT5 CLC 3030 - LDA SCRSTART 3040 - ADC SCRPOS 3050 - STA SRAM 3060 - LDA SCRSTART+1 3070 - ADC SCRPOS+1 3080 - STA SRAM+1 3090 - LDA #RHARD 3100 - STA RASTER 3110 - JMP IRQEND READY. | ||
Listing 3. Der Lader zu Listing 3.1 (Sie können dieses Programm »SCROLLTEST-BOOT« auch downloaden) |
||
10 REM LADER FUER 'SCROLLTEST' <076> 20 POKE 43,1:POKE 44,64:REM BASIC-START NA CH $4000 <241> 30 POKE 16384,0 <130> 40 PRINT"{CLR,2DOWN}NEW" <224> 50 PRINT"{2DOWN}LOAD";CHR$(34);"SCROLLTEST ";CHR$(34);",8{HOME}"; <068> 60 POKE 631,13 :REM TASTENPUFFER RETURN <249> 70 POKE 632,131:REM TASTENPUFFER SHIFT+RUN /STOP <002> 80 POKE 198,2 :REM 2 ZEICHEN IM TASTENPUF FER <166> 90 END <092> | ||
Listing 3.1. Ein Programm zum Einbinden der Files von Listing 4 in die Scrollroutine (Sie können dieses Programm »SCROLLTEST« auch downloaden) |
||
10 REM TESTPROGRAMM FUER "SCROLL.OBJ" <211> 20 : <252> 30 REM ** NACHLADEN ** <204> 40 A$="SCROLL.OBJ" :GOSUB 10000:REM MASC HINENROUTINE <116> 50 A$="CHAR-SET" :GOSUB 10000:REM ZEIC HENSATZ <220> 60 A$="SCROLL-SCREEN":GOSUB 10000:REM SCRO LLBILDSCHIRM <170> 70 : <046> 100 REM ** BILDSCHIRMFARBEN ** <173> 110 POKE 53281,12:POKE 53280,12:REM BILDSC HIRM- UND RAHMENFARBE <132> 120 POKE 53282,0 :POKE 53283,11:REM MEHRFA RBEN <005> 130 POKE 646,9 : REM CURSOR FARBE <083> 140 : <116> 150 REM ** SELBSTDEFINIERTE ZEICHEN ** <042> 160 POKE 53272,(PEEK(53272) AND 240)OR 2:R EM NEUER ZEICHENSATZ EIN <158> 170 POKE 53270,PEEK(53270)OR 16: R EM MEHRFARBENMODUS EIN <223> 180 POKE 53270,PEEK(53270)AND 247: R EM 38 SPALTEN <135> 190 : <166> 200 REM ** BESCHRIFTUNG ** <078> 210 PRINT"{CLR,BLACK,SPACE}CURSOR LEFT{3SP ACE}= SCROLLING LEFT" <095> 220 PRINT" CURSOR RIGHT{2SPACE}= SCROLLING RIGHT" <102> 230 PRINT" CURSOR UP{5SPACE}= SPEED UP" <251> 240 PRINT" CURSOR DOWN{3SPACE}= SPEED DOWN " <146> 250 PRINT" SPACE{9SPACE}= SCROLLING STOP" <253> 260 : <238> 270 REM ** SCROLLING ** <113> 280 SYS 49152:S=1 <135> 290 GET A$:IF A$="" GOTO 290 <037> 300 IF A$="{LEFT}" THEN POKE 695,0 <048> 310 IF A$="{RIGHT}" THEN POKE 695,64 <049> 320 IF A$=" " THEN POKE 695,128 <151> 330 IF A$="{UP}" THEN S=S+1:IF S>8 THEN S= 8 <022> 340 IF A$="{DOWN}" THEN S=S-1:IF S<1 THEN S=1 <076> 350 POKE 694,S <060> 360 GOTO 290 <186> 9000 : <086> 9999 REM ** FILES NACHLADEN ** <230> 10000 SYS 57812A$,8,1:POKE 780,0:SYS 65493 <137> 10010 RETURN <162> | ||
Listing 4. Ein gepacktes Programm, das einen Zeichensatz und einen Scrollbildschirm enthält (Sie können dieses Programm auch downloaden) |
||
Name : file-gen.cru 0801 0c34 ---------------------------------- 0801 : 17 08 c5 07 9e 32 30 37 19 0809 : 33 20 46 49 4c 45 2d 47 39 0811 : 45 4e 20 20 20 00 00 00 8c 0819 : a9 36 85 01 4c 54 0b a9 46 0821 : 00 85 fb a9 d0 85 fc a9 98 0829 : 00 85 fd a9 fc 85 fe 20 d9 0831 : e2 08 a9 1a 85 fb a9 09 b6 0839 : 85 fc a9 c8 85 fd a9 ff af 0841 : 85 fe 20 e2 08 a9 38 85 63 0849 : fb a9 d4 85 fc a9 38 85 08 0851 : fd a9 fc 85 fe 20 e2 08 9f 0859 : 20 da 08 a9 0d a2 0b a0 71 0861 : 09 20 c6 08 a9 00 20 d2 ee 0869 : ff a9 10 20 d2 ff a9 52 bd 0871 : 8d 18 09 a9 09 8d 19 09 f5 0879 : a2 14 ad 18 09 85 fb ad 9c 0881 : 19 09 85 fc a9 b0 85 fd 52 0889 : a9 ff 85 fe 20 e2 08 ad 08 0891 : 18 09 85 fb ad 19 09 85 e1 0899 : fc a9 d8 85 fd a9 ff 85 89 08a1 : fe 20 e2 08 18 ad 18 09 ca 08a9 : 69 50 8d 18 09 ad 19 09 15 08b1 : 69 00 8d 19 09 ca d0 c2 51 08b9 : a9 00 20 d2 ff a9 78 20 34 08c1 : d2 ff 4c da 08 20 bd ff 7a 08c9 : a9 01 a2 08 a0 01 20 ba a4 08d1 : ff 20 c0 ff a2 01 4c c9 07 08d9 : ff 20 cc ff a9 01 4c c3 77 08e1 : ff a0 00 78 a9 33 85 01 8c 08e9 : b1 fb 48 a9 37 85 01 58 33 08f1 : 68 20 d2 ff c8 d0 02 e6 07 08f9 : fc e6 fd d0 e6 e6 fe d0 45 0901 : e2 60 43 48 41 52 2d 53 ef 0909 : 45 54 53 43 52 4f 4c 4c 1f 0911 : 2d 53 43 52 45 45 4e 00 bb 0919 : 00 ea ea fa fa fe fe ff 4c 0921 : ff aa 08 f9 ff 08 f9 ea b5 0929 : ea fa fa fe fe ff ff bf 9e 0931 : bf af af ab ab aa aa 00 e4 0939 : 00 28 38 38 3c 00 04 f9 2a 0941 : 28 38 38 3c 00 00 20 7a 90 0949 : f9 80 81 04 f9 20 1d f9 6c 0951 : 80 81 81 20 06 f9 80 81 2b 0959 : 06 f9 20 1e f9 82 85 03 f7 0961 : f9 81 20 1d f9 82 20 81 fe 0969 : 20 06 f9 82 86 20 20 60 06 0971 : 86 81 20 1e f9 82 85 03 53 0979 : f9 81 20 16 f9 80 81 06 b3 0981 : f9 84 20 81 20 06 f9 82 14 0989 : 20 03 f9 60 20 81 20 1e 80 0991 : f9 82 85 03 f9 81 20 16 e5 0999 : f9 82 20 08 f9 81 20 06 15 09a1 : f9 82 86 20 20 60 86 81 a3 09a9 : 20 0a f9 83 81 06 f9 20 2e 09b1 : 0d f9 82 85 03 f9 81 20 52 09b9 : 16 f9 82 07 f9 20 20 81 71 09c1 : 20 06 f9 82 06 f9 83 20 31 09c9 : 0a f9 82 86 20 03 f9 86 50 09d1 : 81 20 0d f9 82 85 03 f9 39 09d9 : 81 20 1c f9 82 20 20 81 5d 09e1 : 20 17 f9 82 20 05 f9 81 71 09e9 : 20 0d f9 82 85 03 f9 81 ba 09f1 : 20 1c f9 82 20 20 81 20 37 09f9 : 17 f9 82 20 05 f9 81 20 18 0a01 : 0d f9 82 85 03 f9 81 20 a2 0a09 : 1c f9 82 20 20 81 20 17 83 0a11 : f9 82 20 05 f9 81 20 0d 3a 0a19 : f9 82 85 03 f9 81 20 07 4f 0a21 : f9 80 81 06 f9 20 0e f9 48 0a29 : 82 20 20 81 20 17 f9 82 9b 0a31 : 86 20 03 f9 86 81 20 0d d6 0a39 : f9 82 85 03 f9 81 20 07 6f 0a41 : f9 82 80 81 05 f9 20 0e 88 0a49 : f9 82 20 20 81 20 17 f9 f9 0a51 : 82 20 05 f9 81 20 0d f9 a5 0a59 : 82 04 f9 83 20 07 f9 82 f3 0a61 : 82 86 20 86 81 81 20 0e c0 0a69 : f9 82 20 20 81 20 17 f9 19 0a71 : 82 20 05 f9 81 20 19 f9 f5 0a79 : 82 82 20 03 f9 81 81 20 97 0a81 : 0e f9 82 03 f9 83 20 06 d5 0a89 : f9 80 81 10 f9 84 20 05 73 0a91 : f9 81 20 19 f9 82 82 20 74 0a99 : 03 f9 81 81 20 04 f9 80 34 0aa1 : 81 03 f9 20 10 f9 82 86 0e 0aa9 : 20 04 f9 86 20 04 f9 86 32 0ab1 : 20 04 f9 86 20 05 f9 86 42 0ab9 : 81 20 19 f9 82 82 86 20 66 0ac1 : 86 81 81 20 04 f9 82 20 c7 0ac9 : 20 81 20 10 f9 82 20 16 14 0ad1 : f9 81 20 19 f9 82 82 20 b4 0ad9 : 03 f9 81 81 20 04 f9 82 78 0ae1 : 20 20 81 20 10 f9 82 20 91 0ae9 : 16 f9 81 20 0d f9 80 81 06 0af1 : 0b f9 84 82 20 03 f9 81 6f 0af9 : 81 20 04 f9 82 20 20 81 77 0b01 : 20 10 f9 82 86 20 04 f9 65 0b09 : 86 20 04 f9 86 20 04 f9 4d 0b11 : 86 20 05 f9 86 81 20 0d 37 0b19 : f9 82 80 81 0b f9 84 86 43 0b21 : 20 86 81 81 20 04 f9 82 24 0b29 : 20 20 81 0b f9 20 06 f9 c8 0b31 : 82 17 f9 83 20 0d f9 82 85 0b39 : 11 f9 83 81 20 04 f9 82 67 0b41 : 20 0c f9 81 20 2b f9 82 5e 0b49 : 12 f9 83 20 04 f9 82 0d 71 0b51 : f9 83 20 a2 00 bd 96 0b c7 0b59 : 9d 10 01 e8 d0 f7 a2 34 1b 0b61 : bd fd 0b 9d 00 03 e8 d0 f1 0b69 : f7 ea ea a2 ff 9a a9 92 85 0b71 : 85 2d 38 e9 01 85 fe a9 64 0b79 : 0f 85 2e e9 00 85 ff a9 93 0b81 : 53 85 fc a9 0b 85 fd ad 3b 0b89 : 20 d0 85 fb 4c 52 01 00 4d 0b91 : 00 00 00 00 00 00 0b 08 ce 0b99 : 0a 00 9e 32 30 36 31 00 0b 0ba1 : 00 00 a9 08 a2 03 a0 09 e4 0ba9 : 20 c6 08 a9 00 20 d2 ff b0 0bb1 : a9 08 20 d2 ff 48 c6 fc 18 0bb9 : a5 fc c9 ff d0 02 c6 fd 83 0bc1 : 68 60 48 ad 20 d0 49 01 d1 0bc9 : 8d 20 d0 c6 fe a5 fe c9 20 0bd1 : ff d0 02 c6 ff 68 60 a0 98 0bd9 : 00 b1 fc c9 f9 d0 18 ee 8e 0be1 : 20 d0 20 30 01 b1 fc aa 5e 0be9 : 20 30 01 b1 fc 91 fe 20 30 0bf1 : 3d 01 ca d0 f8 f0 05 91 ca 0bf9 : fe 20 3d 01 a6 fc ca 86 01 0c01 : fc e0 ff d0 02 c6 fd a5 21 0c09 : fe c9 1f a5 ff e9 08 b0 39 0c11 : c8 a5 fb 8d 20 d0 a9 37 fa 0c19 : 85 01 20 60 a6 20 8e a6 26 0c21 : a2 1f bd 10 01 9d 00 08 d1 0c29 : ca d0 f7 a9 f9 4c 34 03 67 0c31 : 4c ae a7 50 52 4f 47 52 2a | ||