Erstellt: 21. Juli 2013 (zuletzt geändert: 1. November 2021)

Text „sanft“ anzeigen

Einen Text pixelweise anzeigen

C64 Studio, AMCE & TASM

Da es zur Zeit viel zu heiß ist und ich mich nur schwer konzentrieren kann, kommt hier mal wieder ein sehr simpler Effekt.

Möchte man den Blick auf eine Textzeile ziehen, dann ist es evtl. nicht so vorteilhaft, diese direkt als ganzes anzuzeigen. Befinden sich mehrere Infos auf dem Bildschirm, dann geht die Zeile evtl. unter. In solchen Fällen bietet es sich an, etwas Bewegung ins Spiel zubringen und so den Blick darauf zulenken.

Eine Textzeile zeichenweise ausgeben

Diese Aufgabe sollte eigentlich jeder selbst bewerkstelligen können, da sie aber Basis für unseren Effekt ist hier ein kleines Beispielprogramm.

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

main
 sei                                ;IRQs sperren
 lda #<irq                          ;LSB
 sta $0314          
 lda #>irq                          ;MSB
 sta $0315                          ;in den RAM-Vektor
 jsr clrScreen                      ;BS löschen
 cli                                ;Interrupts wieder erlauben

 jmp *                              ;Endlosschleife



;*** eigene Interrupt-Routine
irq                               
 dec charCounter                    ;Warteschleife verringern
 bne irq0                           ;wenn größer null -> irq0
 ldx charPos                        ;Zeichenposition ins X-Reg.
 lda infotext,X                     ;Zeichen in den Akku
 beq irqExit                        ;NULL = Ende!
 sta $0428,X                        ;Zeichen ausgeben
 lda #$08                           ;Warteschleife wieder
 sta charCounter                    ;zurücksetzen
 inc charPos                        ;Zeichenposition erhöhen

irq0
irqExit
 jmp $ea31                          ;weiter zur System-Routine



;*** Bildschirm löschen
clrScreen
 ldx #$00                           ;Schleifenzähler (256 Zeichen je Page)
 lda #" "                           ;alles mit Leerzeichen füllen
nextChar
 sta $0400,X                        ;1. Page des BS-Speichers
 sta $0500,X                        ;2. Page
 sta $0600,X                        ;3. Page
 sta $0700-24,X                     ;4. Page (-24 wegen der Sprite-Register)
 dex                                ;Schleifenzähler verringern
 bne nextChar                       ;Solange größer 0 -> nextChar
 rts                                ;sonst, zurück



;Textzeile $00 = ENDE
infotext
 !scr "* (c) 2018 by www.retro-programming.de *"
 !byte 0


;Zähler für Zeichenbreite = 8 Pixel
charCounter
 !byte 8


;Nr. des nächsten Zeichen
charPos
 !byte 0

Für das Timing hängen wir uns in den bekannten Timer-Interrupt und legen die Adresse unserer IRQ-Routine ganz einfach an $0314/15 ab, außerdem löschen wir noch den Bildschirm clrScreen.
Die Interrupt-Funktion ist dann relativ simpel. Da 60 Zeichen in der Sekunde doch etwas schnell ist, verzögern wir die Ausgabe mit einem kleinen Zähler charCounter. Erreicht dieser null, dann holen wir die Position des nächsten Zeichens charPos ins X-Register und laden damit das zugehörige Zeichen aus unserem Text infotext in den Akku. Nur solange das Zeichen größer null ist, geben wir es auf dem Bildschirm aus, setzen unseren Zähler charCounter zurück und erhöhen charPos. Dann wird zur Systemroutine nach $ea31 gesprungen. Stört euch bitte nicht am Label irq0:, dies benötigen wir erst beim nächsten Schritt.

Startet ihr das Programm jetzt, dann erscheint unsere Textzeile zeichenweise. Unterlegt ihr jedes Zeichen mit einem Ton (z. B. dem Geräusch einer Schreibmaschine) habt ihr schon einen netten Effekt.

Wie werden die Zeichen jetzt pixelweise angezeigt?

Um ehrlich zu sein, gar nicht! Wir täuschen ein pixelweises Einblenden nur vor. Dazu platzieren wir ein Sprite, dass die selbe Farbe wie der Hintergrund und die Größe eines Zeichens hat, direkt über der Stelle, an der das Zeichen ausgegeben wird. Dann geben wir das Zeichen, wie oben im Beispielprogramm, an dieser Stelle aus. Das Zeichen verschwindet hinter dem Sprite und ist erstmal unsichtbar. Jetzt bewegen wir das Sprite und lassen so das Zeichen „sanft“ erscheinen. Dies wiederholen wir für alle Zeichen. Das hört sich jetzt evtl. komplizierter an, als es ist. Prinzipiell haben wir nämlich eben schon alle Vorbereitungen getroffen.

Also ergänzen wir unser Progrämmchen einfach…

Fügt ganz zu Beginn z. B. vor das sei folgenden Aufruf hinzu, um unser Sprite vorzubereiten.

jsr initSprite                     ;Sprite setzen

 

Die benötigte Funktion sieht dann so aus:

;*** Das Sprite zum Verdecken der Zeichen
initSprite
 lda #sprite/64                     ;Nr. des 64-BYTE-Blocks
 sta $07f8                          ;für Sprite-0 setzen
 lda $d021                          ;Sprite-0 Farbe wie Hintergrund
 sta $d027                          ;für Sprite-0
 lda #$10                           ;Start für X-
 sta $d000
 lda #$3a                           ;und Y-Position
 sta $d001                              
 lda #$00
 sta $d017                          ;zur Sicherheit doppelte Höhe
 sta $d01d                          ;und Breite deaktivieren
 sta $d01b                          ;Sprite VOR dem Hintergrund
 sta $d010                          ;höchstes BIT auf Null setzen
 lda #%00000001                     ;Sprite-0 sichtbar
 sta $d015                          ;schalten
 rts                                ;zurück

Die Nr. des 64-Byte-Blocks für das Sprite lassen wir wieder vom Assembler berechnen. Da wir die ersten 16KB verwenden, können wir das so machen. Verschiebt ihr den sichtbaren Bereich des VIC-II, dann müsst ihr, bei dieser Art der Berechnung, noch eine Kleinigkeit beachten, das sollte euch aber selbst einfallen. Die Einrichtung des Sprites sollte soweit bekannt sein. Einzige Besonderheiten sind, dass wir die Spritefarbe auf die Hintergrundfarbe $d021 setzen und die Startposition so wählen, dass das Sprite in der zweiten Textzeile erscheinen wird.

Jetzt müssen wir unsere IRQ-Routine noch anpassen. Dazu sind zunächst folgende drei Zeilen nötig, die direkt hinter dem bisher unnötigen Label irq01 eingefügt werden.

irq0
 inc $d000                          ;X-Position erhöhen
 bne irqExit                        ;solange < 256 -> RAUS
 inc $d010                          ;sonst höchstes BIT setzen

irqExit

Hier erhöhen wir einfach bei jedem IRQ die X-Position und sorgen natürlich auch dafür, dass ggf. das höchste BIT für die X-Position gesetzt wird. Da wir unsere Zählschleife immer mit 8 starten, ist schon alles perfekt aufeinander abgestimmt. Ein Zeichen ist schließlich genau 8-Pixel breit. Das Sprite befindet sich so für jedes Zeichen an der richtigen Stelle und wir haben den Eindruck, dass der Text ganz soft eingeblendet wird.

Dann wollen wir noch dafür sorgen, dass die Spritebewegung auch wieder gestoppt wird, sobald der gesamte Text ausgegeben wurde. Ändert dazu das beq irqExit weiter oben, in beq irqStop und fügt folgenden Block hinter das Ende der Interrupt-Funktion ein.

irqExit
 jmp $ea31                          ;weiter zur System-Routine

irqStop
 dec $d015                          ;Sprite ausblenden
 lda #$31                           ;Adresse der System-Routine
 sta $0314                              
 lda #$ea
 sta $0315                          ;nach $0314/15
 jmp $ea31                          ;und ein letztes Mal zur System-Routine

Hier wird einfach das Sprite abgeschaltet und der RAM-Vektor zurück auf die Adresse der System-Routine gesetzt.

Natürlich brauchen wir noch ein passendes Sprite. Das legen wir einfach mit Byte-Anweisungen fest. Wir brauchen schließlich nur ein 8×8 Pixel großes, einfarbiges Sprite.

;*** Das 8x8 Pixel große Sprite
*=((*-1)/64)*64+64
sprite
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00

Wie gewohnt sorgen wir dafür, dass das Sprite an einer durch 64 teilbaren Adresse im Speicher liegt. Für die Turbo Assembler-Nutzer, habe ich hier mal eine andere Möglichkeit verwendet, ein Align zu emplementieren: *=((*-1)/64)*64+64. Diese Zeile entspricht einem !align 63,0 vom C64 Studio bzw. ACME (also dem Ausrichten an der nächsten durch 64 teilbaren Adresse).
Denkt daran, dass der Stern * nicht nur zur Multiplikation dient, sondern auch für die aktuelle Adresse, die der Assembler für diese Zeile ermittelt hat, steht.

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

main
 jsr initSprite                     ;Sprite setzen
 sei                                ;IRQs sperren
 lda #<irq                          ;LSB
 sta $0314          
 lda #>irq                          ;MSB
 sta $0315                          ;in den RAM-Vektor
 jsr clrScreen                      ;BS löschen
 cli                                ;Interrupts wieder erlauben

 jmp *                              ;Endlosschleife



;*** eigene Interrupt-Routine
irq
 dec charCounter                    ;Warteschleife verringern
 bne irq0                           ;wenn größer null -> irq_0:
 ldx charPos                        ;Zeichenposition ins X-Reg.
 lda infotext,X                     ;Zeichen in den Akku
 beq irqStop                        ;NULL = Ende!
 sta $0428,X                        ;Zeichen ausgeben
 lda #$08                           ;Warteschleife wieder
 sta charCounter                    ;zurücksetzen
 inc charPos                        ;Zeichenposition erhöhen

irq0
 inc $d000                          ;X-Position erhöhen
 bne irqExit                        ;solange < 256 -> RAUS
 inc $d010                          ;sonst höchstes BIT setzen
 
irqExit
 jmp $ea31                          ;weiter zur System-Routine

irqStop
 dec $d015                          ;Sprite ausblenden
 lda #$31                           ;Adresse der System-Routine
 sta $0314                              
 lda #$ea
 sta $0315                          ;nach $0314/15
 jmp $ea31                          ;und ein letztes Mal zur System-Routine


;*** Bildschirm löschen
clrScreen
 ldx #$00                           ;Schleifenzähler (256 Zeichen je Page)
 lda #" "                           ;alles mit Leerzeichen füllen
nextChar
 sta $0400,X                        ;1. Page des BS-Speichers
 sta $0500,X                        ;2. Page
 sta $0600,X                        ;3. Page
 sta $0700-24,X                     ;4. Page (-24 wegen der Sprite-Register)
 dex                                ;Schleifenzähler verringern
 bne nextChar                       ;Solange größer 0 -> nextChar
 rts                                ;sonst, zurück



;*** Das Sprite zum Verdecken der Zeichen
initSprite
 lda #sprite/64                     ;Nr. des 64-BYTE-Blocks
 sta $07f8                          ;für Sprite-0 setzen
 lda $d021                          ;Sprite-0 Farbe wie Hintergrund
 sta $d027                          ;für Sprite-0
 lda #$10                           ;Start für X-
 sta $d000
 lda #$3a                           ;und Y-Position
 sta $d001                              
 lda #$00
 sta $d017                          ;zur Sicherheit doppelte Höhe
 sta $d01d                          ;und Breite deaktivieren
 sta $d01b                          ;Sprite VOR dem Hintergrund
 sta $d010                          ;höchstes BIT auf Null setzen
 lda #%00000001                     ;Sprite-0 sichtbar
 sta $d015                          ;schalten
 rts                                ;zurück



;*** Textzeile $00 = ENDE
infotext
 !scr "* (c) 2018 by www.retro-programming.de *"
 !byte 0


;*** Zähler für Zeichenbreite = 8 Pixel
charCounter
 !byte 8


;*** Nr. des nächsten Zeichen
charPos
 !byte 0


;*** Das 8x8 Pixel große Sprite
*=((*-1)/64)*64+64
sprite
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $ff,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00
 !byte $00,$00,$00

Jetzt seid ihr wieder gefragt. Hängt z. B. hinter den unduchsichtigen Bereich noch ein Schachbrettmuster oder eine andere Formen, um das Erscheinen zu verändern. Warum muss das Sprite unsichtbar sein? Es könnte auch ein Auto oder Flugzeug sein, hinter dem der Text erscheint. Verwendet animierte oder mehrere Sprites, um weitere Effekte zu erzielen und kombiniert dies z. B. mit dem Color-Cycling. Natürlich lässt sich diese Technik auch verwenden, um Texte verschwinden zu lassen.

Ein erweitertes Beispiel könnt ihr im D64-Image herunterladen…


Schrott!!Naja...Geht so...Ganz gut...SUPER! (8 Bewertungen | Ø 5,00 von 5 | 100,00%)

Loading...


Zurück

Schreibe einen Kommentar

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

Protected by WP Anti Spam