home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.uni-stuttgart.de/pub/systems/acorn/
/
Acorn.tar
/
Acorn
/
acornet
/
fun
/
mags
/
hl-01-93.arc
/
!HL-01_93_Text_Text40
< prev
next >
Wrap
Text File
|
1993-03-24
|
15KB
|
331 lines
ÿÿÿÿÿÿÿÿÿÿ Tips'n'Trix ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
- Von einem, der auszog, um das Scrollen zu lernen -
Fⁿr schnelle Actiongames oder saubere Textausgaben ist sie einfach unerlΣ▀lich.
Und auch in so manchem Demo kann man sie gut gebrauchen.
Die Rede ist natⁿrlich von der ultimativen...
...Vertikalscroll-Routine !!!
Herk÷mmliche Scrollroutinen gibt es wie Sand am Meer. Die gebrΣuchlichsten
sind folgende:
1) Hardwarescrolling.
Dies ist die Scrollmethode, die am allerwenigsten Rechenzeit beansprucht.
Das Scrollen erledigt hier nΣmlich der gute, alte Memorychip MemC(1a),
indem er ein wenig mit seinen drei beschreibbaren Videoregistern (Vinit,
Vstart und Vend) herumspielt.
Vstart und Vend markieren dabei das gesamte screen memory. Vinit zeigt
auf die aktuelle Screen-Basisadresse; die Adresse also, ab der der MemC
den Bildschirmspeicher ausliest.
M÷chte man nun den Bildschirm nach oben scrollen, erh÷ht man einfach den
Wert in Vinit um die jeweilige Zeilenbreite in Bytes (in Mode 15 wΣren
das also 640 Bytes). Im nΣchsten Framefly liest nun der MemC diesen
modifizierten Wert aus Vinit aus und beginnt, das neue Bild aufzubauen.
Dieses erscheint um eine Zeile nach oben gescrollt, weil ja die erste
"Original"-Bildzeile geflissentlich vom MemC ⁿbergangen wird.
Der MemC hat noch ein weiteres Videoregister, das allerdings vom User
weder gelesen noch beschrieben werden kann: Vptr.
Vptr zeigt auf das aktuelle quadword (4 W÷rter = 16 Bytes), das gerade vom
MemC ausgelesen und per DMA an den VidC weitergeleitet wird. Was passiert
nun, wenn Vptr den Wert von Vend (Ende des Bildschirmspeichers) erreicht ?
Irgendwas mu▀ ja passieren, denn sonst wⁿrde der MemC flei▀ig
Speicherbereiche auslesen, die nix mit Video & Screen zu tun haben !!
Des RΣtsels L÷sung liegt im Vstart-Register. Um es mit BASIC-Befehlen
auszudrⁿcken:
...
Vptr=Vptr+16
IF Vptr>Vend THEN Vptr=Vstart
So lΣuft das natⁿrlich in der RealitΣt nicht ab. WΣre ja noch sch÷ner, wenn
die Chips fortan in BASIC programmiert wΣren...
Nun, es dⁿrfte jetzt jedem klar sein, da▀ Vptr beim ▄berschreiten des Vend-
Registers mit dem Inhalt von Vstart geladen wird.
Dies bedeutet aber auch, da▀ Vptr den Bereich zwischen Vstart und Vend
nicht verlassen kann, sondern stΣndig dazwischen ZIRKULIERT. Deshalb
spricht man im Zusammenhang mit dem Screenmemory auch von einem ZIRKULAREN
Buffer.
Um den ganzen Kram mit der Hardware zu synchronisieren, wird Vptr mit dem
Wert aus Vinit geladen, sobald der Elektronenstrahl das untere Ende des
angezeigten Bildes erreicht.
Angenommen, wir befinden uns in Mode 15 bei einen Bildschirmspeicher der
Gr÷▀e 160K und erh÷hen Vinit in jedem Vsync um 640 Bytes, ergibt sich ein
superweiches Hardwarescrolling nach oben. Zur Veranschaulichung befindet
sich innerhalb der !Hardliner-Applikation im "Examples"-Verzeichnis ein
kleines Demoprogramm dazu.
Der Vorteil dieser Scrollmethode liegt also auf der Hand: Chipscrolling
verbraucht (fast) keine Prozessorzeit und erm÷glicht sogar in einem
hochaufl÷senden Modus wie z.B. Mode 28 noch Framerates von 50 oder 60
Hertz.
Es gibt aber auch einen gravierenden Nachteil: M÷chte man ⁿber der zu
scrollenden FlΣche noch etwas bewegen lassen (beispielsweise Sprites),
kann das ziemlich kompliziert werden, da ja bei jedem Scroll der GESAMTE
Bildschirm nach oben bewegt wird; also rutschen auch die Sprites beim
nΣchste Bildschirmaufbau nach oben. Au▀erdem wird der Hintergrund (also
die ScrollflΣche) nicht "upgedatet", soda▀ bewegte Sprites auf dem Screen
unsch÷ne Spuren hinterlassen. Letztlich kann man den Hardwarescroll nicht
- wie auf anderen Computersystemem - auf beliebige Bildschirmbereiche
beschrΣnken, gescrollt wird immer der gesamte Screen.
Bis auf den letzten Einwand kann man natⁿrlich alle Negativ-Punkte durch
einigerma▀en geschickte Programmierung abwenden. Und wer beispielsweise
(wie ich) von einem CPC kommt, wird wissen, wie eifrig Hardscrolling dort
genutzt wird. Aber wird besitzen schlie▀lich alle einen Archimedes, und
auf einem solchen 32-Bitter sollte man versuchen, m÷glichst alles ⁿber die
Software zu erledigen.
Wir kommen also zur nΣchsten Scrollm÷glichkeit, und die nennt sich...
2.) Softwarescrolling.
Hier gibt es zwei verschiedene Scrollarten.
Die erste bietet sich besonders dann an, wenn man nur einen Screen
reserviert hat. In einem Mode 13-Bild wⁿrde man dann mittels LDM/STM-
Kommandos die zweite Bildschirmzeile in die erste, die dritte in die
zweite, die vierte in die dritte, usw. kopieren. Das Resultat wΣre, da▀
der Bildschirm nach oben gescrollt wⁿrde. Hier gibt es jedoch den gleichen
Nachteil wie beim Hardwarescrolling: Alles, was sich auf dem Screen
befindet, wird nach oben geschoben, also auch Sprites, Lines, usw.
Allerdings kann man hier die ScrollflΣche nach eigenen Belieben bestimmen,
was eigentlich die Grundvoraussetzung fⁿr eine Scrollroutine ist.
Die zweite Softscroll-Variante bietet schon eher eine L÷sung unseres
Problems. Man arbeitet hier mit einem internen Buffer, der so gro▀
(manchmal etwas gr÷▀er) als die FlΣche ist, die gescrollt werden soll.
Verschoben wird nur der Buffer, und zwar nach dem Schema, wie man den
Bildschirm mit der ersten Softscroll-Routine verschiebt. Nachdem man den
Buffer gescrollt hat, kann man ihn wie eine Grafik behandeln und per
LDM/STM auf den Bildschirm bringen.
Diese Routine ist sehr flexibel und programmiererfreundlich, hat aber einen
Σu▀erst st÷renden Nachteil: Sie kostet Unmengen an kostbarer Prozessorzeit:
Das Scrollen eines kompletten Mode 13-Screens kann durchaus 80-90% der
Leistung eines ARM2s ben÷tigen, was fⁿr den 50 Hertz-Fetischisten ganz
einfach nicht akzeptabel ist.
Um es noch einmal zusammenzufassen, hier die Vor- und Nachteile der bisher
vorgestellten Scrollroutinen:
Hardwarescrolling: -zeitgⁿnstig (wenige Promille der Rechenzeit)
-schwierig mit Sprites zu verbinden
-gescrollt wird nur kompletter Screen
dir. Softscrolling: -zeitgⁿnstig (2.5-2.7 Taktzyklen pro word)
-gescrollt wird beliebiger Ausschnitt
-schwierig mit Sprites zu verbinden
indir. Softscrolling: -zeitintensiv (s.o. !!!)
-spritefreundlich
-gescrollt wird beliebiger Ausschnitt
-beansprucht einen (manchmal gro▀en) Buffer
Hm !
Sinnvoll wΣre also eine Routine, die die Vorteile der bisherigen Routinen
vereint. Die Routine sollte also
- schnell
- flexibel
- und spritefreundlich
sein. Aber das sind ja gleich drei Dinge auf einmal ! Nein, nein, das geht
nun wirklich nicht...
DOCH !
Und zwar mit dem...
3.) Zirkularen Softwarescroll.
H÷rt sich bombastisch an, ist aber im Grund ganz einfach.
Die Idee dahinter ist nΣmlich, da▀ wir beim Scrollen gar nicht Scrollen.
Oder, mit anderen Worten: Das eigentliche Scrollen kostet nur sehr, sehr
wenige Taktzyklen. Bei einem vollstΣndigen Screenscroll handelt es sich
um vielleicht 500 oder 600 Zyklen, die aber kaum ins Gewicht fallen.
Der Haken an der Sache ist nur, da▀ wir die zu scrollende FlΣche in jedem
Frame neu auf den Bildschirm bringen mⁿssen. Bei gro▀en ScrollflΣchen
kann das recht arg werden; aber fⁿr normale Zwecke ist die Scrollroutine
einfach grandios ! Wie gesagt, sie verbraucht ungefΣhr genausoviel Zeit,
wie das Plotten einer gleichgro▀en FlΣche erfordern wⁿrde (plus die
erwΣhnten 500 Zyklen). Dafⁿr haben wir haben auch die Garantie, da▀ jede
beliebige Spriteroutine mit der Scrollroutine zusammenarbeitet, falls man
so etwas mal brauchen sollte.
Um die Routine zu verstehen, solltet Ihr Euch jetzt am besten in die Lage
des MemC versetzen. Stellt Euch vor, Ihr wΣrd eine Memorycontroller, der
tagein-tagaus nichts Besseres zu tun hat, als interne Register zu
verwalten !! Dann dⁿrfte das Folgende absolut kein Problem fⁿr Euch
darstellen...
Also:
Prinzipiell Σhnelt der zirkulare Softwarescroll (ZISS) dem oben
besprochenen Hardwarescrolling. Das Wort "Software" deutet es schon an:
Wir ben÷tigen diesmal einen internen Buffer.
Um alles etwas zu vereinfachen, m÷chte ich den ZISS anhand eines konkreten
Beispiels erlΣutern: Wir m÷chten einen Bereich scrollen, der so gro▀ wie
ein normaler Mode 13-Screen ist und aus lauter Spritebl÷cken (wie im
ArcAngels-Megademo) besteht. Die Spritebl÷cke haben die Gr÷▀e 32x32 Pixel.
ZunΣchst legen wir im Memory einen Buffer an, der 320 Bytes breit und
(256+32)=288 Bytes lang, also 90 KByte gro▀ ist. In ihn passen der
komplette Bildschirm plus die nΣchste anzuzeigende Spriteblockzeile
(10 Sprites zu je 32x32 Pixel).
Der Bildschirm soll bei jedem Vsync um eine Zeile nach oben gescrollt
werden. Gleichzeitig soll unten eine Zeile eingefⁿgt werden, um eine
kontinuierliche Grafikbewegung zu simulieren.
Wer beim Hardscroll gut aufgepa▀t hat, dem dⁿrften folgende Vereinbarungen
gut verstΣndlich sein:
"start" bezeichnet die Startadresse des Buffers
"ende" bezeichnet die Adresse des auf den Buffer folgenden Bytes
"offset" Σhnelt dem Vinit-Register im MemC. offset=0 gibt den Zustand zu
Beginn des Scrolls an. Nach zehn DurchlΣufen hat offset den
Wert 10x320(Bufferbreite)=3200, usw.
"length" gibt die LΣnge des Buffers an, hier also 90 KByte.
Schematisch hat die Routine folgenden Aufbau
;.schleife
;
;Warte auf Vsync
;
;erh÷he offset um 320
;wenn offset>=length, dann offset=offset-length
;
;fⁿge nach jeweils 32 Vsyncs 10 neue Sprites in den Buffer ein
;
;plotte den Buffer auf den Screen; als Bufferbeginn zΣhlt start+offset
;
;B schleife
Das Wichtigste an der Routine dⁿrfte klar sein: offset wird bei jedem
Durchlauf um 320 erh÷ht. Sobald offset aber length ⁿberschreitet, wird
die Operation offset=offset-length durchgefⁿhrt, was quasi eine
Zurⁿckstellung von offset auf den Ausgangszustand bedeutet.
Herzstⁿck der Scrollroutine ist das Plotten. Wie man vielleicht schon
jetzt absehen kann, wird das mit "normalen" Mitteln nicht zu machen sein,
denn der Beginn des Buffers ergibt sich ja aus start+offset. Wⁿrde man
jetzt einfach 256 Bytezeilen linear aus dem Buffer in den Screen kopieren,
wΣre ein Gro▀teil der Ausgabe Grafikschrott.
Deshalb mu▀ man einen Ausweg finden. Und der ist simpel: Man fragt einfach
zu Beginn einer jeden Zeile ab, ob die nun auszulesende Adresse gr÷▀er
als ende ist. Wenn ja, kann man sicher sein, da▀ die Zeile keine Grafik
mehr enthΣlt, da man ja den Buffer bereits verlassen hat. In diesem Fall
setzt man die Leseadresse auf den Wert von start und macht ganz cool
weiter. Irgendwann hat man dann 256 Zeile kopiert und das Ende des
Screens erreicht.
Wⁿrde man immer nur denselben Buffer durchscrollen lassen wollen, wΣre
die Arbeit jetzt schon getan. Das Bild wⁿrde bis in alle Ewigkeit oben
aus dem Screen heraus- und von unten wieder in den Screen hineinscrollen.
Aber wir wollen ja noch verschiedene Spritebl÷cke einbauen und machen
deshalb munter weiter.
Wenn wir den Buffer im ungescrollten Zustand betrachten, befinden sich
unsere Spritebl÷cke ab start+256*320. An diese Adresse mⁿssen wir bei
Bedarf den Grafiknachschub hinplotten.
Dies ist bei Berⁿcksichtigung des Scroll-Offsets praktisch genau gleich.
Wir ermitteln zunΣchst, ob die Adresse start+offset+256*320 gr÷▀er als
ende ist, sich also au▀erhalb des Buffers befindet. Wenn ja, mⁿssen wir
von dieser Adresse nur noch length abziehen, und die Welt ist wieder in
Ordnung. Warum ?
Nun, unsere Plot-Routine wird wie ⁿblich beginnen, den Buffer ab
start+offset auszulesen. Sobald sie ende erreicht, wird sie auf den Wert
von start restauriert, von ihr wird also length abgezogen. Die erste
Zeile, die sie nicht mehr auf den Screen bringt, ist also genau die Zeile,
an die wir die Spritebl÷cke kopieren.
Im nΣchsten Durchlauf ist offset um 320 gr÷▀er. Die letzte geplottete Zeile
entspricht dann der ersten "neuen" Grafikzeile.
Beim Kopieren der neuen Spritebl÷cke in den Scrollbuffer mⁿssen wird
natⁿrlich genau wie beim Plotten verfahren: Zu Beginn einer jeden Zeile
wird geprⁿft, ob sich die Ablegeadresse noch innerhalb des Buffers
befindet. Wenn nicht, wird - wie ⁿblich - length angezogen.
---------------------------------------------------------------------------
Das ist sie also schon, unsere ultimative Vertikalscroll-Routine. Man
k÷nnte sie im Nachhinein mit einer unbeweglichen Druckerrolle vergleichen.
Die OberflΣche dieser Walze wⁿrde dann unseren Scrollbuffer darstellen,
und der Beginn des Buffer wⁿrde quasi bis in alle Ewigkeit um die Walze
herumwandern. Die Position, an die wir die Sprites kopieren wⁿrden,
wΣre dem Bufferbeginn immer ein Stⁿck voraus (dieses "Stⁿck" entsprΣche
natⁿrlich der LΣnge des Buffers).
Soweit ich wei▀, handelt es sich beim ZISS um die schnellste Scrollroutine
ⁿberhaupt. Mit gewissen EinschrΣnkungen kann man sie auch auf typische
Horizontalscroll-Probleme portieren; sie bietet sich beispielsweise bei
Sinusscrollern an.
Damit das Ganze theoretische Gelabere ein bi▀chen verstΣndlicher wird,
befindet sich innerhalb der !Hardliner-Applikation im Verzeichnis
"Examples" ein kleines Beispiel zum ZISS. Schaut es Euch in Ruhe an !
Auch wenn sich momentan alles noch ein bi▀chen schwammig anh÷rt: ▄bung
macht den Meister...
- Tim Juretzky -
PS: Wollt Ihr wissen, warum diesmal ausgerechnet eine Scrollroutine durch-
gesprochen wurde ? Tja, dann schaut Euch mal den Textscroll an, den Ihr
da vor Euch seht ! Supersmooth, isn't it ? Waschechter ZISS, wⁿrde ich
sagen... Die Entwicklungsversionen des "Hardliners" hatten noch eine
andere Scrollroutine. Da diese aber ohne Ende ruckelte, zuckelte und
flackerte, mu▀te Abhilfe geschaffen werden. Das Ergebnis seht Ihr hier...