Erstellt: 6. Januar 2019

Flexible Line Distance (FLD)

Größere Zeilenabstände durch FLD

C64 Studio, AMCE & TASMHinter FLD verbirgt sich erstmal nichts anderes, als die Möglichkeit, einen beliebigen Zeilenabstand für die Bildschirmausgabe zu verwenden. Was das genau bedeutet, wie man diesen realisiert und was man damit machen kann, erfahrt ihr in den nächsten Minuten.

Wir benötigen hier zwar keinen, aber ihr solltet trotzdem die Texte zum Rasterzeilen-IRQ und vorallem zu den Bad Lines gelesen haben!

FLD – Was ist das?

FLD steht für Flexible Line Distance, das bedeutet soviel wie flexibler Zeilenabstand. Wie ihr wisst, bietet der C64 euch nach dem Einschalten den Textmodus mit 25 Zeilen zu je 40 Zeichen an. Der Abstand zwischen den einzelnen Zeilen beträgt normalerweise 0 (Null) Pixel, mittels FLD kann man nun für beliebig große Abstände zwischen den einzelnen Zeilen sorgen.

FLD – Funktionsweise

Wenn ihr bei den Bad Lines aufgepasst habt, dann wisst ihr, dass diese entstehen, weil der VIC-II extra Zeit benötigt, um die nächste Zeichenzeile vorzubereiten. Im Umkehrschluß bedeutet dies aber auch, dass erst nach einer Bad Line die nächste Zeichenzeile vom VIC-II dargestellt wird. Im Gegensatz zu einer FLI – Grafik, wo wir für zusätzliche Bad Lines sorgen mussten, müssen wir für den FLD-Effekt das Auftreten von Bad Lines verschieben.

Wichtig ist dabei: Das klappt nur für eine ganze Zeichenzeile!
Sobald der VIC mit der Zeichenzeile beginnt, werden auch alle acht Pixelzeilen ausgegeben! Ihr könnt per FLD also z. B. eine Textzeile nicht nach vier Zeilen splitten!

Da wir nur den Start einer Zeichenzeile verschieben können, bleibt die Reihenfolge der Zeilen immer gleich, ihr könnt also hiermit nicht Zeile drei vor Zeile eins anzeigen. Es ist auch nur möglich, die Zeilen (von ihrer „normalen“ Position aus) weiter nach unten zu verschieben.

FLD – Das Beispielprogramm

Wir fangen unser FLD-Beispiel ganz einfach an:

!to "fld.prg",cbm

FIXEDLINES  = 3                     ;Feste Zeichenzeilen
STARTLINE   = 48+FIXEDLINES*8       ;Start immer ganze Textzeile, wg. Bad Line
SKIPLINES   = 16                    ;Größe der Lücke in Pixelzeilen

*=$0801
;** BASIC-Zeile: 2019 SYS 2062
 !word main-2, 2019 
 !byte $9e
 !text " 2062"
 !byte $00,$00,$00

main
 sei                                ;Interrupts sperren

Mit FIXEDLINES legen wir fest, wieviele Zeichenzeilen komplett angezeigt werden sollen, bevor der FLD-Effekt einsetzt. Die STARTLINE bestimmt, in welcher Rasterzeile wir mit dem Unterdrücken der Bad Lines beginnen wollen und SKIPLINES legt fest, wieviele Rasterzeilen übersprungen werden sollen, bevor wir wieder Bad Lines zulassen.
Dann folgt der bekannte BASIC-Start und hinter main sperren wir erstmal die Interrupts, die uns sonst das Timing verhageln würden.

Jetzt folgt eine äußere Schleife, die dafür sorgt, dass jeder Bildaufbau wieder mit den selben Voraussetzungen beginnt.

@loop1
 jsr waitForNewFrame                ;Auf erste Rasterzeile warten
 
 lda #%00011011                     ;Standardwerte für $D011
 sta $d011                          ;setzen
 
 lda #STARTLINE                     ;Warten, bis die gewünschte Zeile erreicht ist.
 cmp $d012
 bne *-3

 ldx #SKIPLINES                     ;Anzahl der zu überspringenden Zeilen ins X-Reg. holen

Hinter @loop1 springen wir erstmal nach waitForNewFrame. Die Funktion (wie sie genau aussieht, sehen wir weiter unten) wartet darauf, dass der Rasterstrahl wieder an der ersten Position ankommt, um das nächste Bild zu zeichnen.
Anschließend schreiben wir nach $d011 die Standardwerte (25 Zeilen, Textmodus, Bildschirmausgabe ein, Y-Scrollposition = 3), wie sie auch nach dem Einschalten vorliegen. Dies ist notwendig, da wir $d011 in der nächsten Schleife ändern werden.
Jetzt warten wir auf unsere STARTLINE. Dazu holen wir uns diese in den Akku und vergleichen diesen Wert mit dem Inhalt des Rasterzeilenregisters $d012 (ihr erinnert euch: hier steht immer die aktuelle Rasterzeile, die der VIC-II gerade am Wickel hat). Sobald die gewünschte Zeile erreicht ist, holen wir uns SKIPLINES ins X-Register, das als Schleifenzähler dient.

Jetzt folgt eine zweite Schleife, die dafür sorgt, dass keine Bad Lines mehr auftreten. Eine Bad Line wird bekanntlich nur im sichtbaren Bereich (im Rahmen gibt es ja keine) ausgelöst, wenn die unteren drei Bits der aktuellen Rasterzeile mit der Y-Scroll-Position aus $d011 übereinstimmt. Unsere nächste Schleife wird nun dafür sorgen, dass (zumindest solange wir wollen) die Y-Scroll-Position nie mit den unteren drei Bits der aktuellen Rasterzeile übereinstimmt.

@loop2 
 lda $d012                          ;auf nächste Zeile warten
 cmp $d012
 beq *-3

 clc                                ;Y-Scroll-Position um eins erhöhen
 lda $d011
 adc #1
 and #%00000111
 ora #%00011000
 sta $d011                          ;und zurück nach $d011 schreiben
 
 dex                                ;Anzahl der Leerzeilen minus 1
 bne @loop2                         ;falls nicht 0, $d011 weiter verändern
 
 jmp @loop1                         ;Und wieder auf den nächsten Bildaufbau warten

Hinter @loop2 warten wir auf den Beginn der nächsten Rasterzeile. Sobald eine neue Zeile beginnt, löschen wir das Carry-Flag, holen uns $d011 in den Akku und addieren 1 hinzu, um die Y-Scroll-Position zu erhöhen. Da wir nur die unteren drei Bits benötigen, blenden wir per and den Rest aus und setzen mittels ora noch die Bits für Bildschirmausgabe (ein) und 25 Zeilen. Zum Schluß schreiben wir den neuen Wert nach $d011 zurück.
Dann verringern wir unseren Schleifenzähler im X-Register und wiederholen die eben beschriebene Prozedur, für alle zu überspringenden Zeilen.
Sobald für alle gewünschten Zeilen die Bad Lines verhindert wurden, springen wir zurück an den Anfang zu @loop1, um wieder auf das Zeichnen des nächsten Bildes zu warten.

Jetzt fehlt nur noch die Funktion…

waitForNewFrame
 lda $d011                      
 bpl *-3                            ;solange $d011 positiv ist, warten...
 lda $d011                      
 bmi *-3                            ;solange $d011 negativ ist, warten...
 rts                                ;jetzt wurde das höchste BIT in $d011 gelöscht -> ein neuer Bildschirmaufbau beginnt.

Wie ihr wisst, gibt es mehr als 256 Rasterzeilen, daher dient das höchste Bit in $d011 sozusagen als 9. Bit für die Rasterzeilenposition, die wir in $d012 finden. Unsere kleine Routine wartet also erstmal darauf, dass in $d011 das höchste Bit gesetzt wird. Sobald dies der Fall ist, befindet sich der Rasterstrahl an einer Position über 255. Danach warten wir darauf, dass das höchste Bit wieder gelöscht wird. Dies passiert, sobald der Rasterstrahl vom Ende der letzten, zurück an den Anfang der ersten Rasterzeile gestellt wird. Dadurch wissen wir, wann der VIC-II mit dem Aufbau des nächsten Bildes beginnt.

Ein exaktes Timing ist hier nicht nötigt, daher können wir auf Interrupts verzichten.

FLD – Erster Start

Sobald ihr das Programm nun startet, werdet ihr euch vor Begeisterung wohl kaum noch zurückhalten können:

Erster FLD Test.
Erster FLD Test.

Super eine (evtl.) schwarze Lücke, na toll. 😉

Sollte bei euch die Lücke nicht schwarz sein, dann liegt das mal wieder an der Speicherstelle $3fff. Wie bereits an anderer Stelle erwähnt, wenn der VIC-II nicht mehr weiß, woher er die Daten für die Anzeige nehmen soll, dann greift er auf das letzte Byte der für ihn sichtbaren 16KB zurück. Da wir den VIC-II-Speicherbereich nicht verschoben haben, ist dies hier die erwähnte Adresse $3fff. Schreibt daher am besten erstmal direkt hinter main den Wert #$ff nach $3fff.

!to "fld.prg",cbm

FIXEDLINES  = 3                     ;Feste Zeichenzeilen
STARTLINE   = 48+FIXEDLINES*8       ;Start immer ganze Textzeile, wg. Bad Line
SKIPLINES   = 16                    ;Größe der Lücke in Pixelzeilen

*=$0801
;** BASIC-Zeile: 2019 SYS 2062
 !word main-2, 2019 
 !byte $9e
 !text " 2062"
 !byte $00,$00,$00

main
 lda #$ff
 sta $3fff
 sei                                ;Interrupts sperren

@loop1
 jsr waitForNewFrame                ;Auf erste Rasterzeile warten
 
 lda #%00011011                     ;Standardwerte für $D011
 sta $d011                          ;setzen
 
 lda #STARTLINE                     ;Warten, bis die gewünschte Zeile erreicht ist.
 cmp $d012
 bne *-3

 ldx #SKIPLINES                     ;Anzahl der zu überspringenden Zeilen ins X-Reg. holen
 
@loop2 
 lda $d012                          ;auf nächste Zeile warten
 cmp $d012
 beq *-3

 clc                                ;Y-Scroll-Position um eins erhöhen
 lda $d011
 adc #1
 and #%00000111
 ora #%00011000
 sta $d011                          ;und zurück nach $d011 schreiben
 
 dex                                ;Anzahl der Leerzeilen minus 1
 bne @loop2                         ;falls nicht 0, $d011 weiter verändern
 
 jmp @loop1                         ;Und wieder auf den nächsten Bildaufbau warten


waitForNewFrame
 lda $d011                      
 bpl *-3                            ;solange $d011 positiv ist, warten...
 lda $d011                      
 bmi *-3                            ;solange $d011 negativ ist, warten...
 rts                                ;jetzt wurde das höchste BIT in $d011 gelöscht -> ein neuer Bildschirmaufbau beginnt.

Auch wenn das Ergebnis auf den ersten Blick relativ enttäuschend aussieht, es ist mehr geschehen, als ihr jetzt vielleicht annehmt.

Wir haben eben immerhin den Bildschirm um 16 Pixelzeilen nach unten gescrollt, ohne dass wir Daten umkopieren mussten!

Ändert doch mal die Werte für  FIXEDLINES und SKIPLINES (mit 0 klappt es noch nicht, darum kümmern wir uns aber gleich), um euch die Auswirkung der beiden Werte genauer anzusehen. Dabei werdet ihr feststellen, dass wir den kompletten Bildschirm um eine beliebige Anzahl an Pixelzeilen nach unten verschieben können.

So, wie ihr eben manuell einige Werte geändert habt, können wir das natürlich auch per Programm machen…

FLD in Bewegung

In der bisherigen Form ist der Effekt dann doch etwas langweilig. Lasst uns daher mal etwas Bewegung in die Sache bringen. Wir werden den Bildschirm jetzt von unten nach oben ins Bild „laufen“ lassen. Nehmt dazu bitte die gelb hervorgehobenen Änderungen vor.

!to "fld.prg",cbm

FIXEDLINES  = 3                     ;Feste Zeichenzeilen
STARTLINE   = 48+FIXEDLINES*8       ;Start immer ganze Textzeile, wg. Bad Line
SKIPLINES   = 45                    ;Größe der Lücke in Pixelzeilen

*=$0801
;** BASIC-Zeile: 2018 SYS 2062
 !word main-2, 2018 
 !byte $9e
 !text " 2062"
 !byte $00,$00,$00

main
 lda #$ff                           ;Füllmuster für die „undefinierten“ Bereiche
 sta $3fff
 
 sei                                ;Interrupts sperren
 
@loop 
 lda #SKIPLINES                     ;Anzahl der zu überspringenden
 sta linesToSkip                    ;Zeilen merken
 
@loop1
 jsr waitForNewFrame                ;Auf erste Rasterzeile warten
 
 lda #%00011011                     ;Standardwerte für $D011
 sta $d011                          ;setzen
 
 lda #STARTLINE                     ;Warten, bis die gewünschte Zeile erreicht ist.
 cmp $d012
 bne *-3

 ldx linesToSkip                    ;Anzahl der zu überspringenden Zeilen ins X-Reg. holen
 beq @loop                          ;falls 0 -> alles zurück auf Anfang
 
@loop2 
 lda $d012                          ;auf nächste Zeile warten
 cmp $d012
 beq *-3

 clc                                ;Y-Scroll-Position um eins erhöhen
 lda $d011
 adc #1
 and #%00000111
 ora #%00011000
 sta $d011                          ;und zurück nach $d011 schreiben
 
 dex                                ;Anzahl der Leerzeilen minus 1
 bne @loop2                         ;falls nicht 0, $d011 weiter verändern

 dec linesToSkip                    ;Anzahl der Leerzeilen für nächsten Durchlauf verringern
 
 jmp @loop1                         ;Und wieder auf den nächsten Bildaufbau warten


waitForNewFrame
 lda $d011                      
 bpl *-3                            ;solange $d011 positiv ist, warten...
 lda $d011                      
 bmi *-3                            ;solange $d011 negativ ist, warten...
 rts                                ;jetzt wurde das höchste BIT in $d011 gelöscht -> ein neuer Bildschirmaufbau beginnt.
 

linesToSkip
 !byte SKIPLINES

Die Änderungen im Überblick:

  • 5: Für unseren Test nehmen wir eine Lücke von 45 Pixelzeilen.
  • 20: Neues Label @loop, da wir eine weitere Schleife benötigen.
  • 21 & 22: Da wir die Anzahl der zu überspringenden Zeilen verändern wollen, speichern wir den Startwert aus der Konstanten SKIPLINES beim Label linesToSkip ab.
  • 34: Jetzt holen wir uns die Anzahl der zu überspringenden Zeilen vom Label linesToSkip, statt aus der Konstanten, ins X-Register.
  • 35: Falls keine Zeilen übersprungen werden müssen (Wert = 0), beginnen wir wieder von vorne.
  • 52: Die Anzahl der zu überspringenden Zeilen beim Label linesToSkip verringern.
  • 65 & 66: Hier merken wir uns jetzt die zu überspringenden Zeilen.

Wenn ihr diese Version nun startet, sollte euer Ergebnis ungefähr so aussehen…

FLD in Bewegung
FLD in Bewegung

Auch hier könnt ihr wieder mit den Werten FIXEDLINES und SKIPLINES (nun geht auch die Null) experimentieren. Setzt z. B. FIXEDLINES = 0 und SKIPLINES = 200, um den Effekt auf den gesamten Bildschirm auszudehnen.

Den gesamten Bildschirm per FLD bewegen.
Den gesamten Bildschirm per FLD bewegen.

Wenn ihr jetzt auf den unteren Rand achtet, seht ihr ein kleines Problem. Auch dort kommt es, durch das Scrolling, zu schwarzen Zeilen. Diese könnt ihr bei Bedarf durch verschiedene Maßnahmen kaschieren. Ihr könnt z. B. die Hintergrundfarbe auf schwarz setzen oder in $3fff eine Null ablegen. Durch die Aktivierung des 24 Zeilenmodus verschwinden diese Zeilen ebenfalls. Auch ein Überdecken mit Sprites wäre denkbar. Probiert die verschiedenen Möglichkeiten bei Bedarf einfach mal aus.

Schlußbemerkung

Den Effekt könnt ihr jetzt noch weiter verfeinern. Ihr könnt das Bild natürlich auch wieder nach unten „fahren“. Es sind auch mehrere getrennte „Lücken“ möglich, ihr könnt so einzelne Zeilen über den Bildschirm „fliegen“ lassen und das Bild Zeile für Zeile auf- bzw. abbauen.

Und ganz wichtig: Das alles funktioniert auch im Bitmap-Modus!

FLD im Bitmap-Modus
FLD im Bitmap-Modus

Kombiniert FLD mit anderen Effekten.

FLD, Splt-Screen, Scrolling und Color-Cycling
FLD, Split-Screen, Scrolling und Color-Cycling

Die beiden letzten Beispiele findet ihr auf dem folgenden D64-Image. Da die obigen GIFs nur eine Annäherung sind, empfehle ich euch den Download.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (9 Bewertungen | Ø 4,89 von 5 | 97,78%)

Loading...


Zurück

4 Gedanken zu „Flexible Line Distance (FLD)“

  1. Hallo,

    Ich wollte hier nur mal schnell Danke sagen, für die Mühe, die du dir mit dieser Seite gegeben hast.
    Mein erster Computer war der C64. Damals habe ich mich primär mit Spielen und ein bisschen Cracken beschäftigt. Zweiteres aber nie auf sehr hohem Niveau. Dafür fehlte mir die Ausdauer.
    Irgendwie hat mich der C64 nie losgelassen. Er steht auch seit Jahren wieder einsatzbereit in meinem Büro. Bei der Suche nach Wegen zur Konservierung meiner Disks bin ich auch über deine Seite gestolpert und tigere mich grade wieder in Assemblerwelt rein.

    LG

  2. Cool, Du bist wieder mit einem neuen Beitrag da.
    Vielleicht kommt ja auch demnächst ein Beitrag zum Voll-Bildschirm scrollen ohne Wackler durch umschalten des Bildschirmspeichers.
    Übrigens, im Download ist “nur” das untere beispiel enthalten. Auf der Seite schreibst Du “Die beiden letzten Beispiele findet”.
    Ich hoffe Du hast in 2019 wieder etwas mehr Zeit um Deine Seite anzureichern. Ich bin auf jeden Fall mit dabei.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Protected by WP Anti Spam