Hyperscreen

Aus C64-Wiki
Zur Navigation springenZur Suche springen

Von einem Hyperscreen spricht man, wenn der Bildschirmrahmen teilweise oder ganz entfernt wird. Dadurch werden Grafikelemente in diesen Bereichen sichtbar, die sonst vom Bildschirmrahmen überdeckt worden wären. Man sagt dann auch, dass man den Rahmen öffnet. Wichtigste Anwendungen des Hyperscreen sind Rahmensprites und das Grafikformat OSCAR.


Hinweis: Die Programme und die Timing-Angaben in den nachfolgenden Abschnitten beziehen sich auf die im deutschsprachigen Raum übliche Version des VIC (6569), die einen PAL-Monitor benötigt. Für einen VIC mit NTSC-Anschluss muss das Timing leicht angepasst werden, da dort ein oder zwei Taktzyklen mehr pro Zeile zur Verfügung stehen.


Rahmeneinteilung und Darstellung[Bearbeiten | Quelltext bearbeiten]

Einteilung des Rahmens in vertikalen und horizontalen Rahmen

Bei Betrachtungen zum Hyperscreen ist es hilfreich, den Rahmen in einen vertikalen und einen horizontalen Rahmen zu unterteilen. Der vertikale Rahmen ist der Bereich, der sich oberhalb und unterhalb des normalen Sichtbereichs befindet. Der horizontale Rahmen ist der Bereich am linken und rechten Rand. Analog spricht man auch von einem vertikalen und einem horizontalen Hyperscreen.

Die vier Ecken des Bildschirms verhalten sich genau wie der Rest des horizontalen Rahmens, weshalb sie im Allgemeinen zum horizontalen Hyperscreen dazugezählt werden. Einen Unterschied gibt es aber: Wenn der horizontale Hyperscreen in den Ecken angeschaltet wird, der vertikale aber nicht, wird automatisch auch der untere und obere Rand zu einem horizontalen(!) Hyperscreen - damit ist es dann auch möglich, nur den oberen oder nur den unteren Rand zu öffnen.

Grundsätzlich wird bei einem Hyperscreen die Hintergrundfarbe dargestellt. Im Falle des vertikalen Hyperscreens besteht zusätzlich die Möglichkeit, einzelne Punkte schwarz zu färben. Das dafür verwendete Bitmuster befindet sich in Speicherzelle $3FFF des VIC-Adressbereichs; im Falle des Extended-Color-Mode wird stattdessen die Speicherzelle $39FF benutzt.

Weiterhin werden in beiden Bereichen Sprites dargestellt. Hierbei ist zu beachten, dass Sprites mit kleiner Y-Koordinate zweimal auf dem Bildschirm erscheinen: Sowohl im oberen Bereich des Rahmens, als auch im unteren. Schaltet man die Sprites in geeigneten Rasterzeilen ein und aus, kann dies vermieden werden. Alternativ kann man auch einen Sprite-Multiplexer verwenden, um im oberen und im unteren Rahmen unterschiedliche Sprites darzustellen.

Während der vertikale Hyperscreen immer vollständig oder gar nicht aktiviert ist, kann man beim horizontalen auch nur einige Zeilen öffnen. Man beachte dabei aber, dass die geöffneten Zeilen auf der linken Seite gegenüber den geöffneten Zeilen auf der rechten Seite immer um eine Zeile nach unten versetzt sind.


Techniken[Bearbeiten | Quelltext bearbeiten]

Rahmen abschalten. Oben: Rasterstrahl ist vor der Grenze. Mitte: Grenze wurde zurück gesetzt. Unten: Nachdem der Rasterstrahl weitergewandert ist, kann die Grenze wieder an die ursprüngliche Position.

In beiden Fällen geschieht das Abschalten des Rahmens dadurch, dass man dafür sorgt, dass der Rasterstrahl nie die Grenze zwischen Anzeigefenster und Rahmen erreicht, indem man diese im richtigen Zeitpunkt verschiebt. Die nebenstehende Abbildung illustriert dies: Wenn der Rasterstrahl kurz vor der Grenze angekommen ist, versetzt man diese nach links (beziehungsweise beim vertikalen Hyperscreen nach oben). Der Rasterstrahl ist dann bereits hinter der Grenze und aktiviert dadurch den Rahmen nicht. Kurz darauf kann man die Grenze wieder zurücksetzen.

Vertikaler Hyperscreen[Bearbeiten | Quelltext bearbeiten]

Beim vertikalen Hyperscreen nutzt man aus, dass man beim VIC einstellen kann, ob vom Bildschirm 24 oder 25 Zeilen angezeigt werden sollen. Befindet sich der Rasterstrahl im unteren Bereich der 25. Zeile (Rasterzeilen 248-250), löscht man Bit 3 des Registers $D011. Ab Rasterzeile 252 kann man das Bit dann wieder setzen, um den Trick beim nächsten Durchgang wiederholen zu können.

Das nachfolgende Programm zeigt, wie das geht. In richtigen Programmen kann man vor dem Rücksprung zu loop weitere Befehle ausführen. Diese dürfen aber ca. 18000 Taktzyklen nicht übersteigen. Alternativ kann man für das Timing auch einen Rasterzeilen-Interrupt benutzen.

Ausgabe des nebenstehenden Programms: Der Rahmen oben und unten wurde abgeschaltet.
*=$c000
         sei                 ; Interrupt abschalten, der stört

loop     lda #250            ; Auf Zeile 250 warten
-        cmp $d012
         bne -

         lda $d011           ; 24-Zeilen-Modus anschalten
         and #%11110111
         sta $d011

         lda #252            ; Auf Zeile 252 warten
-        cmp $d012
         bne -

         lda $d011           ; 25-Zeilen-Modus anschalten
         ora #%00001000
         sta $d011

         bne loop

Ein vertikaler Hyperscreen ist auch in BASIC möglich. Siehe hierzu den entsprechenden Abschnitt bei Rahmensprite.

Horizontaler Hyperscreen[Bearbeiten | Quelltext bearbeiten]

Beim horizontalen Hyperscreen nutzt man aus, dass man beim VIC einstellen kann, ob 38 oder 40 Spalten angezeigt werden. Befindet sich der Rasterstrahl in der 40. Spalte, löscht man Bit 3 des Registers $D016. Das Bit kann (und sollte) direkt danach wieder gesetzt werden, um den Trick in der nächsten Zeile zu wiederholen.

Beim horizontalen Hyperscreen muss man auf diese Weise jede Zeile einzeln öffnen. Zudem ist sehr gutes Timing erforderlich, da man für das Löschen von Bit 3 nur einen einzigen Taktzyklus zur Verfügung hat und zudem die Badlines und Sprites (die ja die Hauptanwendung von Hyperscreens sind) die Anzahl der Taktzyklen pro Zeile verringern.

Im nachfolgenden Beispiel wird der horizontale Hyperscreen in genau zwei Zeilen angeschaltet: Am rechten Rand sind dies die Zeilen 202 und 203, wobei letztere eine Badline ist. Links sind es die Zeilen 203 und 204.

Ausgabe des nebenstehenden Programms: In zwei Zeilen wurde der Rahmen links und rechts geöffnet. Die Artefakte dazwischen stammen vom Synchronisations-Mechanismus; siehe Text.
*=$c000
         sei              ; Interrupt abschalten, der stört nur

loop     lda #201         ; Auf Zeile 201 warten
-        cmp $d012
         bne -

         and #$07         ; Badline zur Synchronisation erzeugen
         ora #$18
         ldy $d011
         sta $d011
         sty $d011

         ldx #09          ; 51 Taktzyklen warten
-        dex
         bne -
         nop
         lda 0

         lda $d016        ; Bit 3 von $D016 löschen
         and #%11110111
         sta $d016
         ora #%00001000   ; und gleich wieder setzen
         sta $d016

         nop              ; vier Taktzyklen warten
         nop
         nop
         nop

         and #%11110111   ; Bit 3 von $D016 löschen
         sta $d016
         ora #%00001000   ; und gleich wieder setzen
         sta $d016
         jmp loop

Das Timing des Programms sieht so aus:

hyperscreen timing.png

In Zeile 201 ist zu Beginn noch keine exaktes Timing vorhanden. Durch das künstliche Erzeugen einer Badline mit sta $d011 wird der Prozessor im Laufe der Zeile abgeschaltet. Der genaue Zeitpunkt kann hierbei variieren.

Das Wiederanschalten des Prozessors erfolgt aber immer zum selben Zeitpunkt: in Taktzyklus 55. Ab hier kann man das Programm mit dem Rasterstrahl synchronisieren. Das Löschen von Bit 3 im Register $D016 muss immer im Taktzyklus 56 erfolgen. Für Zeile 201 ist es bereits zu spät, deshalb wird eine (fast) komplette Zeile gewartet, bis in Taktzyklus 56 der Schreibzugriff von sta $d016 erfolgt und dadurch den horizontalen Hyperscreen für Zeile 202 (rechts) und 203 (links) erzeugt.

Auch in Zeile 203 wird auf Taktzyklus 56 gewartet. Allerdings handelt es sich bei dieser Zeile um eine natürliche Badline. Das bedeutet, dass der Prozessor in den Takten 12 bis 54 abgeschaltet ist. Dies muss beim Timing berücksichtigt werden. Insbesondere muss der Befehl sta $d016 diesmal bereits vor dem Abschalten des Prozessors begonnen werden, damit der Speicherzugriff in Taktzyklus 56 erfolgen kann.

In der Ausgabe des Programms sind drei Blöcke zu sehen. Diese Artefakte entstehen beim künstlichen Erzeugen einer Badline. Man hat mehrere Möglichkeiten, wie man damit umgehen kann.

  1. Man kann ein anderes Verfahren zur exakten Synchronisation nutzen. Dabei muss man allerdings bedenken, dass jedes Verfahren seine Vor- und Nachteile hat. Hier wurden Badlines benutzt, weil dieses Verfahren vergleichsweise einfach ist und der Code kurz bleibt.
  2. Man kann die Blöcke kaschieren, indem man sie in der Hintergrundfarbe einfärbt (siehe nächsten Abschnitt für ein Beispiel).
  3. Man kann, nachdem einmalig eine exakte Synchronisation erzeugt wurde, diese für den Rest des Programms aufrecht erhalten, was man bei einem vollständigen horizontalen Hyperscreen ohnehin machen muss. In diesem Fall blitzen die Artefakte nur einmalig kurz auf, falls man mit einer Badline synchronisiert.


Bitmuster im vertikalen Hyperscreen[Bearbeiten | Quelltext bearbeiten]

Durch geeignetes Verändern der Speicherzelle $3FFF (im Extended-Color-Modus $39FF) kann man in einem vertikalen Hyperscreen ein Bitmuster aus schwarzen Punkten und Punkten in der Hintergrundfarbe erzeugen. Hierbei ist zu beachten, dass sich eine Änderung dieser Speicherzelle erst mit drei Taktzyklen Verzögerung auf die Ausgabe auswirkt.

Ein Beispiel[Bearbeiten | Quelltext bearbeiten]

Das nachfolgenden Programm zeigt, dass man damit durchaus auch nichttriviale Ergebnisse erreichen kann, auch wenn die Möglichkeiten eingeschränkt sind.

Ausgabe des nebenstehenden Programms: Durch einen vertikalen Hyperscreen sind Grafiken im oberen und unteren Rahmen möglich.
*=$c000
         sei            ; Interrupt abschalten

         lda #246       ; Rasterzeilen-Interrupt auf Zeile 246
         sta $d012
         lda $d011
         and #$7f
         sta $d011

         lda $d01a      ; Rasterzeilen-Interrupt anschalten
         ora #$01
         sta $d01a

         lda #<irq      ; Interrupt-Routine verbiegen
         sta $0314
         lda #>irq
         sta $0315

         cli
         rts

irq      lda $d019      ; Auf Interrupt vom VIC testen
         bmi vic_irq

         lda $dc0d      ; Timer-Interrupt bestätigen
         cli            ; und Interrupts zulassen, damit
         jmp $ea31      ; die VIC-Interrupts nicht blockiert werden

vic_irq  sta $d019      ; Interrupt bestätigen

         lda #247       ; Auf Zeile 247 warten
-        cmp $d012
         bne -

         and #$07       ; Künstlich eine Badline für exaktes
         ora #$18       ; Timing erzeugen
         ldy $d011
         sta $d011
         inc 2          ; Dummy-Befehl für blaue Farbe bei den Artefakten
         tya
         and #%11110111 ; Hyperscreen einschalten
         sta $d011      ; Der letzte Taktzyklus dieses Befehls ist bereits
                        ; in Zeile 248

         ldy #$ff       ; Index für Zeichendaten

         lda #250       ; Auf letzte Bildschirmzeile warten
-        cmp $d012
         bne -
         stx $3fff      ; für korrektes Timing

-        sta $3fff      ; Hauptschleife: schreibt die 
         stx $3fff      ; Bitdaten für die Grafik
         sta $3fff
         stx $3fff
         sta $3fff
         stx $3fff
         sta $3fff
         stx $3fff
         sta $3fff
         stx $3fff

         lda $d012      ; Hintergrundfarbe ändern
         sta $d021

         iny            ; neue Bitdaten laden
         lda tabx,y
         tax
         lda taba,y
         bne -          ; Ende der Schleife; die Schleife
                        ; dauert exakt 63 Taktzyklen

         lda #$06       ; Hintergrund wieder blau
         sta $d021

         lda #%00011011 ; Hyperscreen abschalten
         sta $d011

         lda $d019      ; Interrupt nochmal bestätigen
         sta $d019

         pla            ; Interrupt-Routine koordiniert
         tay            ; verlassen
         pla
         tax
         pla
         rti

*=$c100 ; Die nachfolgenden Tabellen dürfen wegen Timing nicht über eine
          Seiten-Grenze liegen.

taba     !by 255,255,255,255,255,255,255
         !by 195,153,159,159,159,153,195,255 ; C
         !by 195,153,159,131,153,153,195,255 ; 6
         !by 249,241,225,153,128,249,249,255 ; 4

         ; Schwarz
         !by 255,255,255,255,255,255,255,255,255,255,255,255,255,255
         !by 255,255,255,255,255,255,255,255,255,255,255,255,255,255
         !by 255,255,255,255,255,255,255,255,255,255,255,255,255,255
         !by 255,255,255,255,255,255,255

         ; Muster
         !by 195,225,240,120,60,30,15,135,195,225,240,120,60,30,15
         !by 30,60,120,240,225,195,135,15,30,60,120,240,225,195,135

         !by 255
         !by 0    ; Ende-Kennung

tabx     !by 255,255,255
         !by 255,156,156,148,128,136,156,255 ; W
         !by 195,231,231,231,231,231,195,255 ; I
         !by 153,147,135,143,135,147,153,255 ; K
         !by 195,231,231,231,231,231,195,255 ; I

         ; Schwarz
         !by 255,255,255,255,255,255,255,255,255,255,255,255,255,255
         !by 255,255,255,255,255,255,255,255,255,255,255,255,255,255
         !by 255,255,255,255,255,255,255,255,255,255,255,255,255,255
         !by 255,255,255

         ; Muster
         !by 195,135,15,30,60,120,240,225,195,135,15,30,60,120,240
         !by 120,60,30,15,135,195,225,240,120,60,30,15,135,195,225

         ; letzte Zeile blau
         !by 0

Und so sieht das Timing der Schleife aus:

hyperscreen bitpattern timing.png

Man beachte, dass der erste STA-Befehl für die Bitpattern-Daten bereits in Taktzyklus 15 schreibt, obwohl die Darstellung erst in Taktzyklus 19 beginnt. Dies liegt an der Verzögerung von 3 Taktzyklen, die nach dem Lesen des Werts in $3fff durch den VIC erfolgt.

Zusammenspiel mit Sprites[Bearbeiten | Quelltext bearbeiten]

Das Zusammenspiel von Sprites und Bitpatterns. Sprite 1 (rot) ist hinter dem Vordergrund, Sprite 0 (weiß) vor dem Vordergrund.

Ganz grundsätzlich können Sprites unabhängig von diesen Bitmustern benutzt werden.

Wenn die Sprites durch Register 27 ($D01B) des VIC hinter dem Vordergrund dargestellt werden, so überdecken die Spritepunkte zwar die farbigen Punkte des Bitmusters (die gelöschten Bits, die ja der Hintergrund sind), nicht jedoch die schwarzen Punkte (die gesetzen Bits).

Dies ist in nebenstehendem Bild gut zu sehen: Dort wurden zwei Sprites in den unteren Rahmen platziert, beide sind vollständig ausgefüllte Rechtecke. Das rote Sprite auf der linken Seite ist hinter dem (schwarzen) Vordergrund, aber vor dem (bunten) Hintergrund. Das weiße Sprite auf der rechten Seite ist vor beidem.

In Demos[Bearbeiten | Quelltext bearbeiten]

Ausschnitt aus dem Demo Krestage der Gruppe Crest: Sowohl der Schriftzug im oberen Rahmen, als auch die senkrechte Scrollschrift im unteren Rahmen werden über Bitmuster im Hyperscreen erzeugt.

Im Demo Krestage der Gruppe Crest wird diese Technik gleich zweifach angewandt:

  1. Im oberen Bereich wird mit dem Bitmuster ein Schachbrettmuster erstellt, welches zeilenweise eingefärbt ist. An der selben Stelle liegen schwarze Sprites, die einen Teil des Musters verdecken und dadurch die Schrift erzeugen.
  2. Im unteren Bereich wird senkrechte Scrollschrift dargestellt. Auch diese wird über Bitmuster im Rahmen realisiert. Diesmal sind keine Sprites im Einsatz (diese werden für den KRESTAGE-Schriftzug benötigt). Stattdessen wird ausgenutzt, dass eine Änderung der Speicherzelle $3FFF (hier in Wirklichkeit $39FF, da im Extended-Color-Modus) erst mit drei Taktzyklen Verzögerung wirksam wird, während eine Änderung der Hintergrundfarbe sich sofort auswirkt. Dadurch ist es möglich, ein Muster (statt viermal, wie im Beispiel oben) nur einmalig auf den Bildschirm zu bringen; die anderen Exemplare des Musters sind einfach schwarz auf schwarz und von daher nicht sichtbar.



Horizontaler Hyperscreen und Sprites[Bearbeiten | Quelltext bearbeiten]

Beim Öffnen des Rahmens stellen Sprites ein gewisses Problem dar, denn mit jedem Sprite verringern sich die Taktzyklen, die innerhalb einer Rasterzeile zur Verfügung stehen. Gleichzeitig sind Sprites aber auch unabdingbar für praktische Anwendungen eines horizontalen Hyperscreens, da sie die einzige Möglichkeit für eine Anzeige im geöffneten Bereich darstellen.

Hierbei gilt es, zwei Probleme zu unterscheiden: Zum einen schränkt die Anwesenheit von Sprite 0 die Aktionsmöglichkeiten im kritischen Taktzyklus 56 ein, zum anderen sorgen zu vielen Sprites in Kombination mit einer Badline dafür, das in der Zeile so wenige Taktzyklen zur Verfügung stehen, dass kein horizontaler Hyperscreen mehr erzeugt werden kann.

Sprite 0[Bearbeiten | Quelltext bearbeiten]

Der VIC schaltet gelegentlich den Prozessor ab, um zusätzliche Zugriffe auf den Speicher durchführen zu können. Für jedes Sprite in einer Zeile sind zwei zusätzliche Zugriffe notwendig. Bei Sprite 0 handelt es sich dabei um Zugriffe in den Taktzyklen 58 und 59.

In den drei Taktzyklen davor (55, 56 und 57) befindet sich der Prozessor bereits in der Vorbereitung auf das Abschalten und kann deswegen nur noch Schreibzugriffe durchführen. Sobald ein Lesezugriff erfolgen würde, wird der Prozessor angehalten. Die Änderung von Register 22 ($D016) des VIC ist ein Schreibzugriff, stellt demnach erst einmal kein Problem dar. Allerdings muss auch im Taktzyklus davor ein Schreibzugriff stattfinden und es gibt nur sehr wenige Assemblerbefehle, bei denen zwei Schreibzugriffe nacheinander erfolgen.

Neben Interrupt-Befehlen, die hier nicht genutzt werden können, sind das nur noch die sogenannten Read-Modify-Write-Befehle (ASL, LSR, ROL, ROR, INC, DEC, sowie sechs illegale Opcodes, die hier keinen zusätzlichen Nutzen bringen). Aus nicht ganz geklärten Gründen, schreiben diese Befehle im vorletzten Taktzyklus den alten Wert der Speicherzelle nochmal in diese zurück, bevor sie dann im letzten Taktzyklus den neuen Wert schreiben.

Von den oben genannten sechs Befehlen bietet sich der DEC-Befehl an, um Bit 3 zu löschen. Hierzu müssen allerdings die Bits 0-2 vor dem Befehl gelöscht sein. Im Standardzustand des Bildschirms ist das der Fall, weshalb im nachfolgenden Programm darauf verzichtet wurde, diese explizit zu löschen.

Ausgabe des nebenstehenden Programms: Ein (partieller) horizontaler Hyperscreen mit Sprite 0
*=$c000
         ldy #63          ; Spritedaten mit 255 füllen
         lda #255
-        sta 832,y
         dey
         bpl -

         lda #13          ; Spritedatenzeiger für Sprite 0 setzen
         sta 2040

         lda #190         ; Sprite 0 auf Koordinaten 190/190 setzen
         sta $d000
         sta $d001

         lda #1           ; Sprite 0 einschalten
         sta $d015

         sei              ; Interrupt abschalten, der stört nur

loop     lda #200         ; Auf Zeile 200 warten
-        cmp $d012
         bne -

         and #$07         ; Badline zur Synchronisation erzeugen
         ora #$18
         ldy $d011
         sta $d011
         sty $d011

         ldx #09          ; 50 Taktzyklen warten
-        dex
         bne -
         nop
         nop

         dec $d016        ; Bit 3 von $D016 löschen
         inc $d016        ; und gleich wieder setzen

         jmp loop

Das folgende Diagramm enthält das Timing des Programms:

hyperscreen sprite0 timing.png

In Zeile 200 wird eine künstliche Badline erzeugt, um ein exaktes Timing zu erreichen. Danach wird gewartet, bis in Zeile 201 durch den DEC-Befehl in Taktzyklus 56 der Rahmen geöffnet werden kann.

Vergleicht man die Abschaltzeiten des Prozessors, die durch Sprite 0 entstehen, in den Zeilen 200 und 201, so stellt man fest, dass in Zeile 201 nur drei Taktzyklen ausfallen, während es in Zeile 200 noch fünf waren. Das liegt daran, dass die beiden Taktzyklen vor dem Abschalten in Zeile 201 Schreibzugriffe enthalten (der DEC-Befehl wurde ja extra deswegen benutzt), während es in Zeile 200 Lesebefehle wären, die aufgeschoben werden.

Zu viele Sprites in einer Badline[Bearbeiten | Quelltext bearbeiten]

In einer Badline wird der Prozessor von Zyklus 15 bis Zyklus 54 abgeschaltet. Ist Sprite 0 angeschaltet, setzt sich die Abschaltung sogar direkt danach fort, weshalb dann in Taktzyklus 56 kein Schreibzugriff stattfinden kann. Das heißt, dass es in einer Badline, in der Sprite 0 angeschaltet ist, nicht möglich ist, einen horizontalen Hyperscreen aufrecht zu erhalten.

Wie viele Sprites sind in einer Badline möglich? Insgesamt gibt es in einer Rasterzeile 63 Taktzyklen. Von diesen gehen in einer Badline 40 ab. Mindestens sechs weitere Taktzyklen, nämlich die vor Zyklus 15, sowie die vor den ersten Sprite-Zugriffen, können nur Schreibzugriffe haben, da in dieser Zeit der Prozessor bereits dabei ist, sich auf das Abschalten vorzubereiten. Bleiben noch 17 Taktzyklen übrig. Für einen Hyperscreen werden minimal 8 Taktzyklen davon benötigt. Für die Sprites verbleiben demnach noch 9 Taktzyklen. Jedes Sprite benötigt zwei davon, weshalb man bei vier Sprites auskommt.

Jetzt könnte man hoffen, das es gelingt einen Schreibzugriff in die Abschaltphase zu verlegen, um noch ein fünftes Sprite möglich zu machen. Das klappt allerdings nicht, weil einer der Schreibzugriffe zwingend in Taktzyklus 56 sein muss und der andere dann aufgrund von ungünstigen Paritäten niemals auf einen ersten Abschaltzyklus fallen kann.

Alles in allem: Es sind maximal vier Sprites in einer Badline mit geöffnetem horizontalem Rahmen möglich.

Die benutzten Sprites kann man sich dabei nicht frei auswählen: es müssen vier aufeinanderfolgende sein und das Sprite 0 darf nicht dabei sein. Im nachfolgenden Beispiel werden die Sprites 2 bis 5 benutzt:

Ausgabe des nebenstehenden Programms: In einer Badline mit Hyperscreen sind noch bis zu vier Sprites möglich.
*=$c000
         ldy #63          ; Spritedaten mit 255 füllen
         lda #255
-        sta 832,y
         dey
         bpl -

         lda #13          ; Spritedatenzeiger setzen
         sta 2042
         sta 2043
         sta 2044
         sta 2045

         lda #190         ; Spritekoordinaten setzen
         sta $d005
         sta $d007
         sta $d009
         sta $d00b
         lda #50
         sta $d004
         lda #100
         sta $d006
         lda #150
         sta $d008
         lda #200
         sta $d00a

         lda #7           ; Sprite 5 gelb (da Hintergrund schon blau)
         sta $d02c

         lda #%00111100   ; Sprites 2-5 anschalten.
         sta $d015

         sei              ; Interrupt abschalten, der stört nur

loop     lda #201         ; Auf Zeile 201 warten
-        cmp $d012
         bne -

         and #$07         ; Badline zur Synchronisation erzeugen
         ora #$18
         ldy $d011
         sta $d011
         sty $d011

         ldx #07          ; 40 Taktzyklen warten
-        dex
         bne -
         nop
         nop

         lda #$00         ; Register vorbereiten
         ldx #$08
         ldy #$00
         sta $d016        ; Hyperscreen in Zeile 202
         stx $d016
         sta $d016,y      ; Hyperscreen in Zeile 203
         stx $d016

         jmp loop

Dem nachfolgenden Timingdiagramm kann man gleich zweierlei entnehmen:

hyperscreen badline timing.png

Zum einen sieht man, dass in der Badline (Zeile 203) nur noch sehr wenige Taktzyklen zur Verfügung stehen, die der Prozessor überhaupt nutzen kann, nämlich genau 9 Stück.

Zum anderen zeigt sich ein weiteres Problem: Es sind 9 Taktzyklen vorhanden, die beiden Speicherbefehle würden normalerweise aber nur 8 dieser 9 Taktzyklen ausschöpfen. Da es keinen Befehl gibt der nur einen Taktzyklus lang ist, muss man hier zu einem weiteren Trick greifen: Statt des STA-Befehls wird hier STA,Y benutzt. Dieser Befehl benötigt einen Taktzyklus mehr als der normale STA-Befehl, wodurch das Timing wieder stimmt.

Man kann das Limit bei der Anzahl der Sprites umgehen, indem man die Badlines ausschaltet. Das hat allerdings den Nachteil, dass man beim restlichen Inhalt des Bildschirms starke Einschränkungen in Kauf nehmen muss: So werden im Textmodus immer wieder die gleichen Zeichen ausgegeben und im Grafikmodus fehlen die Farbinformationen.

Geschichte[Bearbeiten | Quelltext bearbeiten]

Der erste vertikale Hyperscreen in einer Veröffentlichung war im Demo Flash XI vorhanden. Dieses Demo wurde am 11. Oktober 1985 veröffentlicht. Bereits im darauffolgenden Jahr fand diese Technik auch in Spielen ihre Anwendung. Hier war das Spiel Paperboy das erste.

Im Rennen um das erste Demo mit horizontalem Hyperscreen gab es ziemliche Zwistigkeiten zwischen TSI von 1001 Cracking Crew und Sodan: Im Demo ESCOS I, veröffentlicht im April 1986, sind Bilder zu sehen, die den kompletten Rahmenbereich überdecken, es wird heutzutage als das erste Demo angesehen, bei dem der horizontale Rahmen geöffnet wurde. Im Demo Sodan's Letter I vom 21. April 1986 ist Laufschrift am unteren Rand zu sehen, die den linken und rechten Rahmen mit überspannt. Dort wird auf ESCOS I Bezug genommen und behauptet früher gewesen zu sein. Ein weiteres Demo von April 1986 ist Border Letter I (von TSI), bei dem ebenfalls eine Laufschrift (mit hämischen, an Sodan gewandten Worten) am unteren Rand den linken und rechten Rahmen überspannt.

Es ist derzeit unklar, welches Spiel als erstes einen horizontalen Hyperscreen benutzt hatte. Jars' Revenge aus dem Jahr 2011 zeigt jedenfalls, dass es derartige Spiele gibt.

Siehe hierzu auch die Zeittafeln der C64-Demos, C64-Anwendungen und C64-Spiele.

Verwandte Themen[Bearbeiten | Quelltext bearbeiten]

Weblinks[Bearbeiten | Quelltext bearbeiten]