----------------------------------------------------
Kapitel
6
Scrolling
----------------------------------------------------
Sehr
oft übersteigt der Informationsbetrag, den ein Programmierer anzeigen möchte,
dem, der auf den Bildschirm paßt. Eine Möglichkeit, um dieses Problem
zu lösen, besteht im "Scrollen" (= Rollen) der Information über
den Schirm. So scrollen BASIC-Programm Listings z.B. über die Mattscheibe. Alle
Personal Computer besitzen diesen Typ des Scrollens. Zusätzlich besitzt der
ATARI-Personal Computer aber noch zwei weitere Scroll-Möglichkeiten. Es sind
grobes Scrolling (über die LMS-Anweisung) und feines Scrolling.
Andere
Computer benutzen außchließlich grobes Scrolling. Bei dieser Art sind
allerdings die Pixel, welche die Zeichen beinhalten, auf der Bildschirmposition fixiert.
Der Text wird dabei gescrollt, indem die Bytes durch den Bildschirmspeicher bewegt
werden. Die Auflösung bei dieser Methode beträgt ein Zeichen, das sehr
grob ist, wie man sicherlich zugeben muß. Das erzeugte Scrolling ist springend
und nicht sehr augenfreundlich. Außerdem kann es nur dadurch erreicht werden,
daß jeweils bis zu tausend Bytes im RAM herumgeschoben werden. Dieses ist auch
für einen Computer eine sehr mühselige Arbeit. Das System muß also
die Daten bewegen, um ein Scrollen der Information zu erzeugen.
Einige
Personal Computer produzieren ein etwas feineres Scrolling, indem die Bilder in einem
Graphik-Modus mit höherer Auflösung gezeichnet und dann erst gescrollt
werden. Obwohl hierbei eine bessere Auflösung beim Scrolling erreicht wird,
müßen noch mehr Daten als beim groben Scrolling bewegt werden, wodurch
das Programm natürlich sehr stark verlangsamt wird. Das grundsätzliche
Problem ist also, daß Daten durch den Bildschirmbereich des Speichers bewegt
werden müßen, damit ein Scrollen erreicht wird.
Auf
dem ATARI Computer gibt es eine bessere Möglichkeit, um ein grobes Scrolling
zu erreichen: der Bildschirmbereich wird über den anzuzeigenden Datenbereich
bewegt, was mit Hilfe der LMS-Anweisung geschieht. Der Load-Memory-Scan-Befehl wurde
zum ersten Mal in Kapitel 2 behandelt. Er teilt dem ANTIC-Prozessor mit, wo sich
das Bildschirm-RAM befindet. Eine normale Display List besitzt nur eine LMS-Anweisung
am Anfang; der angewählte RAM-Bereich enthält die anzuzeigenden Daten in
linearer Reihenfolge. Durch Manipulation der Bytes des LMS-Operanden kann ein einfaches
Scrolling erreicht werden; das Playfield-Fenster wird über die Daten bewegt.
Das heißt durch Ändern von lediglich zwei Adress-Bytes kann ein Effekt
erzielt werden, der dem Bewegen der gesamten Bildschirmdaten gleichkommt. Das folgende
Programm realisiert die oben beschriebene Methode:
10 DLIST=PEEK(560)+256*PEEK(561):REM
Display-List finden
20 LMSLOW=DLIST+4:REM
Adresse des niederwertigen Operanden
30 LMSHIGH=DLIST+5:REM
Adresse des höherwertigen Operanden
40 FOR
I=0 TO 255:REM Äußere Schleife
50 POKE
LMSHIGH,I
60 FOR
J=0 TO 255:REM Innere Schleife
70 POKE
LMSLOW,J
80 FOR
Y=l TO 50:NEXT Y:REM Verzögerungs-Schleife
90 NEXT
J
100 NEXT I
Dieses
Programm bewegt das Display-List über den gesamten Adressbereich des Computers.
Die Inhalte aller Speicherstellen werden auf dem Bildschirm ausgegeben. Das Scrolling
ist ein einfaches serielles Scrolling, das durch Kombination von waagerechtem und
senkrechtem Scrolling erreicht wird. Ein reines senkrechtes Scrolling kann erzielt
werden, indem ein festgelegter Betrag (die Zeilenlänge in Bytes) zum LMS-Operanden
addiert oder subtrahiert wird. Das folgende Programm tut dies:
10
GRAPHICS 0
20 DLIST=PEEK(560)+256*PEEK(561)
30 LMSLOW=DLIST+4
40 LMSHIGH=DLIST+5
50 SCREENLOW=0
60 SCREENHIGH=0
70 SCREENLOW=SCREENLOW+40:REM
Nächste Zeile
80 IF
SCREENLOW<256 THEN GOTO 120:REM übertrag?
90
SCREENLOW=SCREENLOW-256:REM Ja, Zeiger korrigieren
100 SCREENHIGH=SCREENHIGH+l
110 IF SCREENHIGH=256
THEN END
120 POKE LMSLOW,SCREENLOW
130 POKE LMSHIGH,SCREENHIGH
140 GOTO 70
Ein
reines waagerechtes Scrolling ist nicht ganz so leicht zu erreichen wie ein reines
senkrechtes. Das Problem hierbei ist, daß das Bildschirm-RAM für eine
einfache Display-List sequentiell organisiert ist. Die Bildschirm-Bytes für
die einzelnen Zeilen folgen direkt aufeinander, wobei das erste Byte einer Zeile
genau dem letzten der vorangehenden folgt. Es könnte gescrollt werden, indem
alle Bytes nach links oder rechts geschoben werden; dieses kann durch de- bzw. inkrementieren
des LMS-Operanden geschehen. Bei dieser Methode wird aber das Byte am Rand einer
Zeile eine Zeile höher bzw. tiefer an den linken bzw. rechten Rand gebracht.
Das erste Beispielprogramm zeigte dieses.
Die
Lösung ist, den Bereich der Bildschirmdaten zu erweitern und in eine Folge von
unabhängigen waagerechten Datenzeilen aufzuspalten. Abbildung 6.1 illustriert
diese Idee schematisch:
Normale Datenanordnung Datenanordnung
für
waagerechtes Scrolling
Abbildung
6.1.
Anordnung
der Daten im Bildschirmspeicher
Die
in obiger Abbildung auf der linken Seite befindliche Anordnung stellt die normale
Aufteilung der Bildschirmdaten dar. Das eindimensionale, serielle RAM wird zu einer
linearen Folge gestapelt. Das rechte Bild zeigt die Datenanordnung für ein wagerechtes
Scrolling. Das RAM ist hierbei natürlich immer noch eindimensional und seriell,
wird aber jetzt anders benutzt. Das RAM für jede einzelne Zeile ist größer
als eine Bildschirmbreite. Dieses ist kein Fehler; die grundliegende Absicht beim
Scrolling ist ja, mehr Information anzuzeigen, als auf den Bildschirm paßt.
Ist kein RAM-Bereich vorhanden, der diese zusätzliche Information fassen kann,
wird sie auch nicht angezeigt. Mit dieser Datenanordnung kann ein echtes waagerechtes
Scrolling erreicht werden. Das Bildschirmfenster kann über den gesamten Datenbereich
bewegt werden, ohne daß ein senkrechtes Rollen wie bei den früheren Versuchen
auftritt.
Der
erste Schritt bei der Erzeugung waagerechten Scrollings ist die Festlegung der Länge
einer Zeile, wobei der zugehörige RAM-Bereich entsprechend angelegt werden muß.
Als nächstes muß eine neue Display-List geschrieben werden, die für
jede Mode-Line eine LMS-Anweisung besitzt. Hierdurch wird die Display-List natürlich
länger als gewöhnlich (wofür es allerdings auch keinen Hinderungsgrund
gibt). Welche Werte sollen nun für die LMS-Operanden verwendet werden? Es könnten
z.B. die Adressen der ersten Bytes jeder Datenzeile sein. Für jede Mode-Line,
d.h. LMS-Operanden, gibt es dann eine solche Adresse.
Sobald
die neue Display-List geschrieben und im Speicher plaziert wurde, muß der ANTIC-Prozessor
auf sie umgeschaltet werden. Ebenso müßen die Bildschirmdaten in den entsprechenden
RAM-Bereich geschrieben werden, damit der Schirm gefüllt wird. Soll nun ein
Scrolling durchgeführt werden, müßen die LMS-Operanden de- bzw. inkrementiert
werden, wodurch ein Scrolling nach links bzw. nach rechts erfolgt. Das Programm für
diese Aktion muß darauf achten, daß nicht über die Ränder des
angelegten Bildschirm-RAMs hinaus gescrollt wird. Andernfalls erscheint ein falsches
Bild auf der Mattscheibe. Der LMS-Operand muß beim Aufbau des Programms auf
das linksseitigste Byte der angezeigten Zeile deuten. Das Maximum für den Wert
dieses LMS-Operanden ist die Adresse des letzten Bytes der Speicherzeile minus der
Anzahl der Bytes, die in einer Bildschirmzeile angezeigt werden.
Da
waagerechtes Scrolling ein etwas komplizierter Prozeß ist, soll es hier an
einem Beispiel verdeutlicht werden. Als erstes muß die Länge der Speicherzeilen
bestimmt werden. Im Beispiel werden Zeilen mit einer Länge von 256 Bytes verwendet,
weil dadurch die Berechnungen vereinfacht werden. Jede Zeile verbraucht hierdurch
eine Page des Speichers. Im Beispiel wird der BASIC-Modus 2 verwendet, d.h. der Bildschirm
besteht aus 12 Zeilen. Dieses wiederum bedeutet einen Speicherbereich von 12 Pages,
was 3K-RAM entspricht. Der Einfachheit halber (und um zu garantieren, daß der
Bildschirm nicht leer ist) werden die untersten 3K des Speichers benutzt. Dieser
Bereich wird vom OS und vom DOS belegt und ist daher mit interessanten Daten gefüllt.
Damit das Ganze noch interessanter wird, wird die Display-List auf Page 6 abgelegt.
So erscheint sie mit auf dem Schirm, wenn gescrollt wird.
Die
Anfangswerte der LMS-Operanden sind leicht zu berechnen; die niederwertigen Bytes
haben alle den Wart 0, wogegen die höherwertigen Bytes die Werte 0, 1, 2, 3
usw. annehmen. Das folgende Programm führt alle oben genannten Aktionen aus
und scrollt dann den Bildschirm horizontal.
10
REM Als erstes wird die Display-List
aufgebaut
20
POKE 1536,112:REM Blank-8-Line
30
POKE 1537,112:REM Blank-8-Line
40
POKE 1539,112:REM Blamk-8-Line
50
FOR I=1 TO 12:REM Schleife
zum Einlesen der DL
60
POKE 1536+3*I,71:REM
BASIC-Modus 2 mit gesetztem LMS
70
POKE 1536+3*I+1,0:REM Niederwertiges
LMS-Operanden Byte
80
POKE 1536+3*I+2,I:REM Höherwertiges
LMS-Oparanden Byte
90
NEXT I
100
POKE 1575,65:REM JVB-Anweisung für
ANTIC
110
POKE 1576,0:REM
DL fängt bei $600 an
120
POKE 1577,6
130
REM ANTIC wird mitgeteilt, wo
sich die DL befindet
140
POKE 560,0
150
POKE 561,6
160
REM Nun wird waagerecht gescrollt
170
FOR I=l TO 235:REM Schleife
für niederwertige LMS-Bytes
180
REM 235 anstatt 256, da eine Zeile aus 20 Zeichen besteht
190
FOR J=l TO 12:REM Für jede Mode-Line
200
POKE 1536+3*J+1,I:REM Niederwertiges LMS-Byte
210
NEXT J
neuschreiben
220
NEXT I
230
GOTO 170:REM Endlos-Schleife
Dieses
Programm scrollt die Daten von rechts nach links. Wird das Ende einer Page erreicht,
beginnt einfach wieder alles von vorn. Die Display-List kann in der 6. Reihe von
oben gefunden werden (Page 6). Sie erscheint als eine Folge von Anführungszeichen.
Der
nächste Schritt wäre das Mischen von senkrechtem und waagerechtem Scrolling.
Senkrechtes Scrolling wird durch Addition oder Subtraktion einer 1 am LMS-Operanden
erzielt; senkrechtes entsprechend durch Addition bzw. Subtraktion der Zeilenlänge.
Diagonales Scrolling kann demnach erreicht werden, wenn diese beiden gemischt werden,
d.h. gleichzeitig ausgeführt werden.
Es
gibt 4 mögliche Richtungen des diagonalen Scrollings. Beträgt die Zeilenlänge
z.B. 256 Bytes und es soll nach rechts unten gescrollt werden, so muß ein Wert
von 256+(-1)=255 zum LMS-Operanden addiert werden. Dieses ist eine 2-Byte Addition;
das obere Programm umgeht die Schwierigkeiten bei der Manipulation von 2-Byte Adressen,
was bei den meisten Programmen aber nicht möglich ist. Für schnelles Scrollen
in 2 Richtungen ist ein Maschinensprachen-Programm erforderlich.
Alle
Anordnungen sind möglich, wenn die LMS-Bytes unterschiedlich manipuliert werden.
Die Zeilen können gleichmäßig scrollen oder sich gegenseitig überholen.
Vieles könnte natürlich mit einem normalen Display gemacht werden, wobei
allerdings mehr Daten zur Durchführung notwendig wären. Der wirkliche Vorteil
des LMS-Scrollings ist die Geschwindigkeit. Anstatt einen gesamten Bildschirm mit
Daten zu bewegen, werden vom Programm nur 2 bzw. etwas mehr Bytes manipuliert.
FEINES
SCROLLING
Die
zweite wichtige Möglichkeit auf dem ATARI 400/800 "TM" ist die des
Fein-Scrollings. Feines Scrolling bedeutet, daß die Zeichen in Schritten, die
der Größe eines Bildschirmpixels entsprechen, gescrollt werden. Beim groben
Scrolling beträgt diese Größe jeweils nur ein Zeichen; das waagerechte
Scrolling hat eine waagerechte Auflösung von einem Color Clock, sowie eine senkrechte
von einer Scan-Line. Das feine Scrolling kann allerdings nicht über diese Werte
hinaus kleiner werden. Soll feines Scrolling über eine längere Strecke
durchgeführt werden, so müßen grobes und feines Scrolling kombiniert
werden.
Zum
Durchführen des feinen Scrollings sind lediglich zwei Schritte erforderlich.
Als erstes muß das entsprechende Bit der Mode-Line-Anweisung, die zu der zu
scrollenden Zeile gehört, gesetzt werden (in den meisten Fällen gilt dieses
für den gesamten Bildschirm, d.h. in sämtlichen Mode-Line-Anweisungen werden
die "Fein-Scrolling"-Bits gesetzt). Bit D5 der DL-Anweisung ist das Einschalt-Bit
für feines Scrolling in senkrechter Richtung, Bit D4 für das in waagerechter
Richtung. Die Werte für die senkrechte und waagerechte Verschiebung werden in
zwei Registern gespeichert. Das Register für feines Scrolling in waagerechter
Richtung (HSCROL) liegt bei $D404, das für feines senkrechtes Scrolling (VSCROL)
liegt bei $D405.
Für
feines horizontales Scrolling wird die Anzahl der Color Clocks, um die gescrollt
werden soll, in HSCROL gespeichert. Beim feinen senkrechten Scrolling wird die Anzahl
der Scan-Lines, um die gescrollt werden soll, nach VSCROL gebracht. Die in diesen
Registern gespeicherten Werte gelten dann für alle Mode-Lines, deren entsprechende
Bits gesetzt sind.
Es
gibt zwei Faktoren, durch die der Einsatz von feinem Scrolling verkompliziert wird.
Beide liegen in der Tatsache begründet, daß ein gescrolltes Display mehr
Information als ein nicht gescrolltes anzeigt. Was geschieht z.B., wenn eine Zeile
waagerecht um ein halbes Zeichen nach links gescrollt wird? Die Hälfte des ersten
Zeichens befindet sich außerhalb des linken Bildschirmrandes und das 40. Zeichen
der Zeile wird ebenfalls nach links verschoben. Was nimmt nun diesen rechts freigewordenen
ein? Das entsprechende Zeichen wäre das 41. Es gibt aber nur 40 Zeichen in einer
Zeile; was geschieht also? Wird grobes Scrolling verwendet, dann erscheint das 41.
Zeichen plötzlich auf dem Schirm, sobald das erste Zeichen am linken Rand aus
dem Bild verschwunden ist. Dieses plötzliche Erscheinen irritiert das Auge sehr,
aber es wurde bereits eine hardwaremäßige Lösung in das Gerät
eingebaut: es gibt drei Anzeige-Optionen, welche die Zeilenbreite bestimmen. Es sind
folgende: das "Narrow-Playfield" (narrow = eng) mit einer Breite von 128
Color Clocks, das "Normal-Playfield" mit einer Breite von 160 Color Clocks,
und das "Wide-Playfield" (wide = ausgedehnt), welches eine Breite von 192
Color Clock besitzt. Diese Optionen werden durch Setzen des zugehörigen Bits
im DMACTL-Register ausgewählt.
Wird
feines waagerechtes Srolling benutzt, dann holt ANTIC mehr Daten aus dem RAM, als
vom Display angezeigt werden. Wird DMACTL z.B. auf ein normales Playfield eingestellt,
das im BASIC-Modus 0 vierzig Bytes pro Zeile besitzt, dann holt ANTIC in Wirklichkeit
Daten, die denen eines Wide-Playfield entsprechen. (In diesem Falle wären es
49 Bytes pro Zeile.) Hierdurch werden die Zeilen waagerecht verschoben, sofern diese
Länge nicht berücksichtigt wird. Dieses Problem taucht allerdings nicht
auf, wenn das RAM vom Programmierer bereits in lange waagerechte Zeilen aufgeteilt
wurde, wie in Abbildung 6.1 dargestellt.
Das
entsprechende Problem beim senkrechten Scrolling kann auf zwei Arten gelöst
werden. Die erste Möglichkeit wäre, es einfach zu ignorieren. In diesem
Fall ergeben sich an den Bildschirmrändern keine Halbbilder. Statt dessen werden
die Bilder am unteren bzw. am oberen Rand nicht sauber gescrollt; sie springen plötzlich
ins Bild. Der richtige Weg erfordert wenig Arbeit. Um ordentliches feines Scrolling
zu erhalten (in und aus dem Bildschirm), muß eine Mode-Line als Buffer eingesetzt
werden. Dieses geschieht, indem bei dieser (der letzten Mode-Line des zu scrollenden
Bereiches) das Bit für horizontales Scrolling nicht gesetzt wird. Das Fenster
wird zwar um eine Mode-Line gekürzt, scrollt dann aber ohne das irritierende
Springen.
Es
ist möglich, Bilder für den Schirm zu entwerfen, die eine Höhe von
mehr als 192 Scan-Lines besitzen. Bei "festen" Displays würde dies
störend wirken. Mit scrollenden Displays aber können Bilder, die sich ober-
oder unterhalb der angezeigten Region befinden, immer in den sichtbaren Bereich gescrollt
werden.
Feines
Scrolling besitzt eine senkrechte Begrenzung von 16 Scan-Lines; das waagerechte Limit
beträgt 16 Color Clocks. Wird versucht, über diese Begrenzungen hinauszugehen,
ignoriert ANTIC einfach die höherwertigen Bits der Scrolling-Register. Um den
gesamten Bildschirm fein zu scrollen (und zwar über eine beliebige Entfernung),
muß feines mit grobem Scrolling gekoppelt werden. Als erstes wird das Bild
fein gescrollt, wobei auf die gescrollte Entfernung geachtet wird. Entspricht der
Betrag des feinen Scrollings der Größe eines Zeichens, wird das Feinscrolling-Register
auf Null gesetzt und eine grobes Scrolling durchgeführt. Abbildung 6.2 veranschaulicht
diesen Vorgang:
Abbildung
6.2.
Verbinden
von feinem und grobem Scrolling
Das
folgende Programm ist ein Beispiel für einfaches feines Scrolling:
1
HSCROL=54276
2
VSCROL=54277
10
GRAPHICS 0:LIST
20
DLIST=PEEK(560)+256*PEEK(561)
30
POKE DLIST+10,50:REM Für zwei Mode-Lines werden beide
40
POKE DLIST+11,50:REM Scrolling-Möglichkeiten
50
FOR Y=0 TO 7:REM eingeschaltet
60
POKE VSCROL,Y:REM Senkrecht scrollen
70
GOSUB 200:REM Verzögerung
80
NEXT Y
90
FOR X=0 TO 3
100
POKE HSCROL,X:REM Waagerecht scrollen
110
GOSUB 200:REM Verzögerung
120
NEXT X
130
GOTO 40
200
FOR J=l TO 200
210
NEXT J:RETURN
Dieses
Programm zeigt feines Scrolling in sehr langsamem Tempo und demonstriert einige Probleme,
die beim Benutzen dieser Möglichkeit auftreten. Als erstes sind die Zeilen unter
dem gescrollten nach rechts verschoben. Grund hierfür ist ANTIC, der sich mehr
Daten holt (48 statt 40 Bytes pro Zeile). Dieses Problem taucht allerdings nur in
unrealistischen Programmen auf; bei richtiger Verwendung des feinen Scrollings schließt
eine ordnungsgemäße Aufteilung der Daten (wie in Abbildung 6.1. gezeigt)
dieses aus. Das zweite und ernstzunehmendere Problem taucht auf, wenn ein Scrolling-Register
geändert wird, während ANTIC sich in der Mitte seines Anzeigeprozesses
befindet. Diese Änderung "verwirrt" den ANTIC-Prozessor, und hat zur
Folge, daß der Schirm zittert. Die Scrolling-Register sollten also nur während
des Vertical-Blanks geändert werden. Dieses kann allerdings nur mit Assembler-Routinen
geschehen. Folglich kann feines Scrolling nur mit Programmen in Maschinensprache
erreicht werden.
ANWENDUNGEN
Die
Anwendungen für feines Scrolling mit Graphiken sind zahllos. Die offensichtlichste
Anwendung ist bei großen Karten gegeben, die mit Zeichensatzgraphiken aufgebaut
wurden. Im Programm "Eastern Front" wurde mit dem BASIC-Modus 2 eine Karte
von Rußland aufgebaut, die sich über 10 Bildschirme erstreckt. Der Fernsehschirm
ist ein Ausschnitt dieser Karte. Der Benutzer ist durch Betätigen des Steuerknüppels
in der Lage, über die gesamte Fläche zu scrollen. Dieses System ist sehr
effizient: das gesamte Kartenprogramm mit Daten, Display-List und Zeichensatz-Definition
benötigt einen Speicherbereich von ca. 4K-RAM.
Es
gibt viele Verwendungen für diese Technik. Jedes mit Zeichensatz erstellte Bild
kann mit diesem System verwendet werden. (Scrolling benötigt nicht unbedingt
Zeichensatz-Graphiken. Map-Modi-Graphiken sind allerdings ungünstiger, da sie
sehr viel Speicherplatz benötigen.) Auf diese Weise könnten große
Schaltpläne gezeigt werden, wobei der Joystick zum Scrollen und zum Anzeigen
spezieller Dinge auf dem Schirm benutzt werden könnte. Mit dieser Technik kann
jedes Bild dargestellt werden, daß nicht ganz auf den Schirm paßt (Z.B.
Baupläne).
Auch
für große Textblöcke könnte dieses System verwendet werden.
Da es aber nicht sehr praktisch ist, fortgesetzte Textteile durch Scrolling über
das Display zu bewegen und dann zu lesen, ist es für unabhängige Textpassagen
besser geeignet.
Eine
andere Verwendung dieser Technik besteht im Anzeigen spezieller Menüs. Der Benutzer
arbeitet mit dem Menü, indem er den Joystick zum Angeben der Operation verwendet.
Hat er sich für etwas entschieden, plaziert er einfach über den Steuerknüppel
ein Fadenkreuz an der zugehörigen Stelle und drückt den Feuerknopf. Obwohl
dieses System nicht für alle Programme verwertbar ist, mag es für einige
von um so größerem Nutzen sein.
Es
gibt noch zwei weitere Anwendungen für das feine Scrolling. Die erste ist das
selektive Feinscrolling. Hierbei werden verschiedene Scrolling-Bits unterschiedlicher
Mode-Lines eingeschaltet. Normalerweise wird der gesamte Schirm gescrollt, dieses
ist aber nicht unbedingt erforderlich. Ein Beispiel hierfür ist das ATARI™ DOS
2.0S.
Die
zweite Möglichkeit ist, die Scrolling-Register mit Hilfe von Display-List-Interrupts
zu ändern. Die Änderung des VSCROL-Registers ist ein schwieriges Unterfangen;
ANTIC könnte durch diese verwirrt werden und unerwünschte Resultate anzeigen.
Das Ändern des HSCROL-Registers mit dieser Methode ist zwar auch nicht ganz
leicht, aber einfacher als das des VSCROL-Registers.