Die Bitmaphöhe hängt hier wie beim Scroller_XLimited Algorithmus von der Levelbreite ab. In den allermeisten Fällen ergibt sich aber eine sehr vertretbare Extrahöhe (zusätzlich zu den 288 Zeilen (256 + BLOCKHÖHE * 2)) , sodaß das kein großer Nachteil ist. Bei einer Levelbreite von 16000 Pixeln (50 Screens) kommt man z. B. mit weniger als 15 Extrazeilen aus. Die Vertikal-Nachfüllreihe besteht jetzt aus 22 Blöcken (22 * 16 = 352), weil die Bitmap wegen dem horizontalen Scrolling breiter sein muß. Die Horizontal-Nachfüllspalte müßte analog jetzt aus 18 Blöcken (18 * 16 = 288) bestehen, weil die Bitmap wegen vertikalen Scrolling jetzt höher sein muß. Da sich dann aber beide Nachfüllbereiche überschneiden würden, verwenden wir für die Horizontal-Nachfüllspalte nur 17 Blöcke und verschieben sie einen Block nach unten. Das kann man sich so vorstellen:
Die einzelnen Scroll-Routinen sind jetzt um einiges komplizierter. Das ist deshalb so, weil sich die Nachfüllspalte und die Nachfüllreihe beim Scrollen verschieben und beide voneinander abhängen. Die Verschiebung geschieht nur alle BLOCKBREITE bzw. BLOCKHÖHE Pixel, und wenn das geschieht, muß der jeweils andere Nachfüllbereich mit verschoben werden. Das sehen wir uns jetzt bei allen Scrollfunktionen genauer an.
Nach-Rechts-Scrollen: Ausgangsposition (A) ist (0,3). Zielposition (B) ist (16,3). Da wir uns vertikal nicht an einer durch 16 (BLOCKHÖHE) teilbaren Position befinden, sind in der Vertikal-Nachfüllreihe ein paar 'Nachfüllblöcke' ('Unten-Blöcke') vorhanden:
Die grünen Blöcke zeigen die Position der Horizontal-Nachfüllspalte. In dieser Spalte befinden sich keine Nachfüllblöcke, da das Verschieben der Nachfüllspalte nur an durch 16 (BLOCKBREITE) teilbaren Levelpositionen passiert. Die grünen Blöcke sind also zu den normalen (grauen) zu zählen.
Nach den normalen Scroll-Routinen befinden wir uns in Situation (B). Die Vertikal-Nachfüllreihe muß offensichtlich korrigiert werden, damit sie wieder richtig, d. h. wie in (C) ist. Der Block ganz links oben (1. Pfeil) ist ein Nachfüllblock (rot), muß aber zu einem normalen Block (grau) werden. Dadurch befindet sich in der Vertikal-Nachfüllreihe aber ein Nachfüllblock (rot) zu wenig. Wir blitten also auch den jetzt(!) ganz rechten Nachfüllblock (2. Pfeil). Das machen wir natürlich nur, wenn die Vertikal-Nachfüllreihe Nachfüllblöcke (= rote Blöcke) enthält, d. h. LevelPositionY nicht durch 16 (BLOCKHÖHE) teilbar ist, d. h. der aktuelle vertikale Schritt ungleich 0 ist.
Nach-Links-Scrollen: Ausgangsposition (A) ist (16,3). Zielposition (B) ist (0,3). Da wir uns vertikal nicht an einer durch 16 (BLOCKHÖHE) teilbaren Position befinden, sind in der Vertikal-Nachfüllreihe ein paar 'Nachfüllblöcke' ('Unten-Blöcke') vorhanden:
Auch hier ist die Vertikal-Nachfüllreihe nach den normalen Scrollroutinen nicht ganz in Ordnung. Um aus (B) (C) zu machen, gehen wir wie folgt vor. Der Block ganz links oben (1. Pfeil) muß neu geblittet werden. Da sich in der Vertikal-Nachfüllreihe einige Nachfüllblöcke befinden, muß aus dem normalen (grauen) Block ein Nachfüllblock (rot) werden. Wären da keine Nachfüllblöcke in der Vertikal-Nachfüllreihe, müßten wir den Block trotzdem blitten, aber als normalen (grauen) Block, nämlich deshalb, weil die normalen horizontalen Scrollfunktionen den Bereich der Vertikal-Nachfüllreihe ignorieren. Deshalb ist der Block ganz links oben der Block (22,0) des Levels. Das war richtig für die LevelPositionX 16, aber nicht für LevelPositionX 0. Dort muß der Block entweder der Block (0,0) des Levels sein, d. h. ein normaler Block, oder der Block (0,18), d. h. ein Nachfüllblock der Vertikal-Nachfüllreihe. Wenn die Nachfüllreihe Nachfüllblöcke enthält, dann haben wir jetzt einen Nachfüllblock (rot) geblittet, und dadurch befinden sich dort jetzt zu viele Nachfüllblöcke. Deshalb müssen wir dann, und nur dann(!), den vormals(!) ganz rechten Nachfüllblock (2. Pfeil) mit dem entsprechenden normalen (grauen) Levelblock überblitten.
Nach-Unten-Scrollen: Ausgangsposition (A) ist (3,0). Zielposition (B) ist (3,16). Da wir uns horizontal nicht an einer durch 16 (BLOCKBREITE) teilbaren Position befinden, sind in der Horizontal-Nachfüllspalte ein paar 'Nachfüllblöcke' ('Rechts-Blöcke') vorhanden:
Die roten Blöcke zeigen die Position der Vertikal-Nachfüllreihe. In dieser Reihe befinden sich keine Nachfüllblöcke, da das Verschieben der Nachfüllreihe nur an durch 16 (BLOCKHÖHE) teilbaren Levelpositionen passiert. Die roten Blöcke sind also zu den normalen (grauen) zu zählen.
Nach den normalen Scroll-Routinen haben wir das Problem, daß sich die Horizontal-Nachfüllspalte nicht dort befindet, wo sie es eigentlich sollte, es sei denn, es befinden sich keine Nachfüllblöcke in der Horizontal-Nachfüllspalte - dann brauchen wir hier im Gegensatz zur Korriegierung der Vertikal-Nachfüllreihe beim Nach-Links/Rechts-Scrollen, wo mindestens ein Block immer geblittet werden muß, gar nichts machen. Wenn wir nicht soviel Glück haben, müssen wir zwei Blöcke blitten. Zum einen ist das der Block ganz links (1. Pfeil) in der neuen Vertikal-Nachfüllreihe, (2. Block von oben ganz links), der zu einem Normal-Block (grau bzw. rot) werden muß, weil Nachfüllblöcke der Horizontal-Nachfüllspalte nichts in der Vertikal-Nachfüllreihe zu suchen haben. Zum anderen ist das der jetzt(!) ganz-unten-liegende Nachfüllblock (2. Pfeil). Dieser Block ist zur Zeit ein normaler (grauer) Block, muß aber zu einem Nachfüllblock (grün) werden. Hier ist zu beachten, daß das Aussehen der Horizontal-Nachfüllspalte davon abhängt, in welche Richtung wir zuletzt horizontal gescrollt sind, egal wie lange das her ist. Wenn wir zuletzt nach rechts gescrollt sind, dann sieht sie wie in (A) aus, wenn wir zuletzt nach links gescrollt sind, dann sieht sie wie in (B) aus:
Wir müssen einen Nachfüllblock ('Rechts-Block') blitten, d. h. wir haben keinerlei Probleme, wenn die letzte Horizontal-Scroll-Richtung rechts (A) war. War die letzte Horizontal-Scroll-Richtung aber links (B), dann wurde durch sie die letzte Planeline jenes Nachfüllblockes zerstört, der über dem liegt, den wir überblitten, d. h. den vorher(!) ganz-unten-liegenden Nachfüllblock. Beim Nach-Links-Scrollen wurde zum Glück ein Backup von dieser Planeline gemacht, sodaß wir sie jetzt restaurieren. Danach können wir unseren Nachfüllblock - ein 'Rechts-Block' blitten, natürlich nachdem wir von jener Planeline ein Backup gemacht haben, die der Blit vom darunterliegenden normalen Block zerstören wird. Wir müssen die Letzte-Scroll-Richtung-Variable schließlich noch auf RECHTS setzen, um den 'Zustand' (A oder B) der Nachfüllspalte auch später und an anderen Stellen richtig bestimmen zu können.
Nach-Oben-Scrollen: Ausgangsposition (A) ist (3,16). Zielposition (B) ist (3,0). Da wir uns horizontal nicht an einer durch 16 (BLOCKBREITE) teilbaren Position befinden, sind in der Horizontal-Nachfüllspalte ein paar 'Nachfüllblöcke' ('Rechts-Blöcke') vorhanden:
Auch hier ist die Horizontal-Nachfüllspalte nach den normalen Scroll-Routinen nicht dort, wo sie sein sollte, sofern sie Nachfüllblöcke enthält. Tut sie das nicht, dann ist alles in Ordnung und wir brauchen nichts zu korrigieren. Meistens werden wir aber nicht so viel Glück haben. Dann müssen wir zwei Blöcke blitten. Zum ersten ist das der jetzt(!) ganz oben-liegende bzw. erste Nachfüllblock (1. Pfeil) der Horizontal-Nachfüllreihe. Dieser Block war ein normaler Block, muß aber zu einem Nachfüllblock (grün) werden. Zum zweiten ist das der vormals(!) ganz-unten liegende Nachfüllblock (2. Pfeil). Dieser Block muß zu einem Normal-Block werden. Hier müssen wir wieder die verschiedenen 'Zustände' der Nachfüllspalte beachten. War die letzte Horizontal-Scroll-Richtung links, dann ist alles in Ordnung. War sie aber rechts, dann wurde durch sie die erste Planeline jenes normalen Blocks überblittet, der unter dem liegt, den wir überblitten. Beim Nach-Rechts-Scrollen wurde zum Glück ein Backup von dieser Planeline gemacht, sodaß wir sie jetzt restaurieren. Danach können wir unseren Block - ein 'Normal/Links-Block' blitten, natürlich nachdem wir von jener Planeline ein Backup gemacht haben, die der Blit vom darüberliegenden Nachfüllblock zerstören wird. Wir müssen die Letzte-Scroll-Richtung-Variable schließlich noch auf LINKS setzten, um den 'Zustand' der Nachfüllspalte auch später und an anderen Stellen richtig bestimmen zu können.
Was gibt's sonst noch zu sagen? Beim Modulo-Trick gibt's ein paar kleine Änderungen. Wegen dem horizontalen Scrolling werden vom Videochip mehr als 320 Pixel pro Zeile gelesen. Je nach FETCH Modus sind das 16 (1x), 32 (2x) oder 64 (4x) Pixel. Das muß in der Berechnung des Spezial-Modulos berücksichtigt werden. Es ist aber nicht notwendig, die Berechnung in die UpdateCopperlist() Funktion zu verlagern, obwohl die Adresse, auf die wir die Planepointer in der VIDEOSPLIT Rasterzeile umbiegen müssen, im Gegensatz zum Scroller_YUnlimited2 Algorithmus nicht mehr konstant ist. Wir können uns das sparen, weil der Offset zwischen alter Adresse und neuer Adresse konstant bleibt. Damit bleibt auch der Spezial-Modulo stets konstant. In die UpdateCopperlist() Funktion verlagern müssen wir aber die Routinen, die die Hiwords setzen, weil die VIDEOSPLIT-Planeadressen wie bereits gesagt, nicht konstant sind. Sie werden zwar nur vom Horizontalscrolling beeinflußt, aber leider ist unsere Bitmap nicht entsprechend aligned, um garantieren zu können, daß die Hiwords konstant bleiben.
Noch einige Bemerkungen zum Quelltext des Demoprogrammes. Horizontal sind die ersten BLOCKBREITE (16) Pixel und vertikal die ersten BLOCKHÖHE (16) Pixel des Levels nicht sichtbar. Ist die Levelposition (mapposx,mapposy) dann sieht der User den folgenden Levelbereich:
(mapposx + BLOCKWIDTH,mapposy + BLOCKHEIGHT) -
(mapposx + BLOCKWIDTH + SCREENWIDTH - 1,mapposy + BLOCKHEIGHT + SCREENHEIGHT - 1)
Will man in die Bitmap etwas hineinblitten, z. B. Blitter Objekte (BOBs), dann muß man das im aktuell sichtbaren Bitmapbereich machen. Dieser Bereich ist:
(videoposx + BLOCKWIDTH,(videoposy + BLOCKHEIGHT) % BITMAPHEIGHT) -
(videoposx + BLOCKWIDTH + SCREENWIDTH - 1,(videoposy + BLOCKHEIGHT + SCREENHEIGHT - 1) % BITMAPHEIGHT)
Die Start-Koordinaten dürfen auf ein Vielfaches von BLOCKWIDTH bzw. BLOCKHEIGHT ab-, die End-Koordinaten aufgerundet werden. Damit ergibt sich ein blitbarer Bereich von (SCREENWIDTH + BLOCKWIDTH) x (SCREENHEIGHT + BLOCKHEIGHT) Pixeln. Auch bei diesem Algorithmus kann es vorkommen, daß die Ende-Y-Koordinate über der Start-Y-Koordinate liegt, d. h. kleiner ist. Das liegt am Videosplitting und bedeutet nichts anderes, als daß der Bereich von der Startkoordinate bis zum Ende der Bitmap geht, dann an den Anfang der Bitmap "wrappt" und dort noch bis zur Endkoordinate reicht. Für das Blitten in den Blitbereich folgt daraus, daß man sich die Blithöhe und die errechnete Blit-Ziel-Y-Position (blitbereich_strty + ziely) genau anschauen muß:
Wenn BLITZIELY + BLITHÖHE <= BITMAPHÖHE dann:Ganz normal an Y-Position BLITZIELY blittenandernfalls, wenn BLITZIELY >= BITMAPHÖHE dann:Ganz normal an Y-Position (BLITZIELY - BITMAPHÖHE) blittenandernfalls:Die ersten (BITMAPHÖHE - BLITZIELY) Pixelzeilen an Y-Position BLITZIELY blitten
Die letzten BLITHÖHE - (BITMAPHÖHE - BLITZIELY) Pixelzeilen an Y-Positionen 0 blitten.