Make your own free website on Tripod.com

Spiele-Kurs für Assemblerprogrammierer
(Teil 6)

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.

Speicherformat

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:

  1. Absolute Adresse des linken oberen Zeichens des Ausschnittes. Sie wird in den Speicherzellen SRAM und SRAM+1 (683 und 684) abgelegt.
  2. Absolute Adresse der ersten Bildschirmzeile des Video-RAMs, in die der Spielinhalt hineinkopiert werden soll. In unserem Fall ist dies immer 1224 (1024+5 x 40), da die oberen fünf Zeilen ja nicht gescrollt werden sollen. Diese Adresse wird der Flexibilität halber in den Speicherzellen VRAM und VRAM+1 (679 und 680) abgelegt.
  3. Breite des Spielfeldes im Registerpaar SBREITE und SBREITE+1 (685 und 686).

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 !):

  1. Pixelposition auf 0 setzen.
  2. Pixelposition auf 1 setzen.
    usw.
  1. Pixelposition auf 7 setzen.
  2. Bildschirmspeicher um 1 Zeichen nach rechts kopieren, danach nach Punkt 1 springen.

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:

0
Scrolling nach rechts (Herauszählen der Pixelposition)
64
Scrolling nach links (Herunterzählen der Pixelposition)
128
Scrolling stoppen

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:

  1. »CHAR-SET«
  2. »SCROLL-SCREEN«

»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