Erstellt: 20. März 2016 (zuletzt geändert: 26. Dezember 2018)

VIC-II: Grafikmodes – MCI

Mehr Details, dank MCI (Multi Color Interlaced)

C64 Studio & AMCE

Neben FLI, ist der MCI Modus wohl der wichtigste „neue“ Grafikmodus des C64. Diese beiden stellen die Basis für viele weitere Modi dar (z. B. IFLI oder SHI). Werfen wir mal einen Blick auf MCI und wie er funktioniert.

Ihr solltet bereits die Beiträge VIC-II: Grafikmodes – BITMAP (Multi-Color) und VIC-II: Speicherbereiche festlegen gelesen haben! Außerdem ist es sicherlich hilfreich, die VIC-II Register griffbereit zuhaben.

MCI – Funktionsprinzip

Als Programmierer könnt ihr euch zunächst mal freuen, der Multi Color Interlaced (MCI) Modus funktioniert nämlich technisch viel einfacher, als z. B. FLI. Ihr braucht eigentlich nur zwei passende Bitmaps und müsst ein Wenig scrollen. Für den Grafiker wird es aber etwas aufwendiger, da die Bilder speziell angepasst sein müssen.
Die Idee hinter MCI ist, dass ihr abwechselend, zwei entsprechend vorbereitete Bitmaps anzeigt, die um einen Pixel versetzt sind. Dadurch wirkt das Bild am C64 detailreicher, es zuckt aber auch ständig hin und her.

Aber seht besser selbst…

Das Bild (bzw. die Bilder)

Da ich absolut keine künstlerische Ader habe, war ich so frei und habe mir für unseren Test ein MCI Bild stibitzt. Es nennt sich „Take me home“, stammt von Leon von der Singular Crew und wurde 2007 veröffentlicht.
Hier könnt ihr euch das Original herunterladen.

Das Programm

Beginnen wir einfach damit, dass wir zunächst die erste Grafik anzeigen. Dafür müssen wir nur ein kleines Programm erstellen, dass euch im Großen und Ganzen schon geläufig sein sollte. Da ihr ja bereits VIC-II: Grafikmodes – Bitmap (Multi-Color) gelesen habt, gibt es eigentlich nichts Neues.

Hier einfach das komplette Listing…

;*** VIC-II Speicher-Konstanten
VICBANKNO               = 0                             ;Nr. (0 - 3) der 16KB Bank                              | Standard: 0
VICSCREENBLOCKNO        = 1                             ;Nr. (0 -15) des 1KB-Blocks für den Textbildschirm      | Standard: 1
VICCHARSETBLOCKNO       = 2                             ;Nr. (0 - 7) des 2KB-Blocks für den Zeichensatz         | Standard: 2
VICBITMAPBBLOCKNO       = 1                             ;Nr. (0 - 1) des 8KB-Blocks für die BITMAP-Grafik       | Standard: 0
VICBASEADR              = VICBANKNO*16384               ;Startadresse der gewählten VIC-Bank                    | Standard: $0000
VICCHARSETADR           = VICBASEADR+VICCHARSETBLOCKNO*2048        ;Adresse des Zeichensatzes                   | Standard: $1000 ($d000)
VICSCREENRAM            = VICBASEADR+VICSCREENBLOCKNO*1024         ;Adresse des Bildschirmspeichers
VICBITMAPADR            = VICBASEADR+VICBITMAPBBLOCKNO*8192        ;Adresse der BITMAP
VICCOLORRAM             = $d800



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

!zone main
main
    ;Bitmap-Modus aktivieren
    lda $d011                       ;VIC-II Register 17 in den Akku
    ora #%00100000                  ;Bitmap-Modus
    sta $d011                       ;aktivieren

    lda $d016                       ;VIC-II Register 22 in den Akku
    ora #%00010000                  ;Multi-Color über BIT-4
    sta $d016                       ;aktivieren
    
    ;*** Start des Bitmapspeichers festlegen
    lda $d018                       ;VIC-II Register 24 in den Akku holen
    and #%11110111                  ;Mit BIT-3
    ora #VICBITMAPBBLOCKNO*8        ;den Beginn des Bitmap-
    sta $d018                       ;festlegen
        
    jsr copyColor                   ;Farben kopieren
     
    jmp *                           ;Endlosschleife



!zone copyColor    
copyColor
    lda #0                          ;Rahmenfarbe schwarz
    sta $d020
    lda #15                         ;Hintergrundfarbe hellgrau
    sta $d021    
    ldx #0                          ;Schleifenzähler initialisieren
.loop    
    lda color,X                     ;Farben ins Color-RAM kopieren
    sta VICCOLORRAM,X
    lda color+256,X
    sta VICCOLORRAM+256,X
    lda color+512,X
    sta VICCOLORRAM+512,X
    lda color+768,X
    sta VICCOLORRAM+768,X    
    
    lda char,X                      ;Farben in den Bildschirmspeicher kopieren
    sta VICSCREENRAM,X    
    lda char+256,X
    sta VICSCREENRAM+256,X    
    lda char+512,X
    sta VICSCREENRAM+512,X    
    lda char+768,X
    sta VICSCREENRAM+768,X    
    
    dex                             ;Schleifenzähler verringern
    bne .loop                       ;die nächsten BYTES kopieren
    
    rts                             ;zurück zum Aufrufer



;Daten fürs Farb-RAM (wird nur 1x benötigt)
color
    !bin "MCI_CR.bin"

;Farben der 1. Bitmap für den Bildschrimspeicher
char    
    !bin "MCI_SR_1.bin"

*=$2000
;1. Bitmap
    !bin "MCI_BM_1.bin"

Wie ihr seht, beginnt das Programm mit einer Reihe Konstanten. Wir brauchen nicht alle, aber da die nur für den Assembler von Interesse sind, schaden sie auch nicht. Zu Beginn aktivieren wir zunächst den Multi-Color-Bitmap-Modus. Wir lassen die VIC-Speicherbereiche auf Standard und sorgen einzig in $d018 dafür, dass der Bitmapspeicher in der zweiten Hälfte der ersten 16KB großen VIC-Bank, also bei $2000, beginnt.
Dann kopieren wir mit jsr copyColor die benötigten Farbwerte in den Bildschirmspeicher und ins Color-RAM. Außerdem setzen wir dort die Rahmen- und Hintergrundfarbe. Die Routine sollte euch schon aus VIC-II: Grafikmodes – BITMAP (Multi-Color) bekannt sein, da haben wir sie für die Anzeige des Koala-Bildes genutzt.
Zum Schluß bleibt das Programm einfach in einer Endlosschleife „hängen“.

Jetzt brauchen wir natürlich noch die Daten für das Bild. Ich habe dieses Mal auf das Koala-Format verzichtet und einfach getrennte Dateien für Color-RAM, Bildschirmspeicher und Bitmap angelegt. Das Farb-RAM ist für beide Bilder identisch, daher brauchen wir das nur einmal. Bildschirmspeicher und Bitmap sind aber unterschiedlich, deshalb habe ich die durchnummeriert. Wir binden die drei Dateien einfach hinter unserem Programm ein und sorgen mit *=$2000 dafür, dass die Bitmap direkt an der richtigen Speicherposition liegt. Darum müssen nur, wie oben erwähnt, die Farben einmal kopiert werden.

Um das Programm starten zu können, braucht ihr jetzt natürlich noch die erwähnten Dateien. Im folgenden Download findet ihr bereits alles, was ihr bis zum Ende dieses Beispiels benötigt.


Entpackt bitte alle Dateien und kopiert sie mit ins Verzeichnis zu eurem Programmcode.

Erstellt nun das Programm und startet es. Ihr solltet folgendes Bild sehen:

Das erste Bild
Das erste Bild

Das Bild ist nun nichts anderes, als eine normale Bitmap. Wie bereits erwähnt, brauchen wir für MCI aber zwei Bilder. Lasst uns das Programm so ändern, dass wir auch die zweite Grafik anzeigen und mit den F-Tasten zwischen den Bildern umschalten können.

Wir wollen ja gleich automatisch, bei jedem neuen Bildaufbau, zwischen den beiden Grafiken hin- und herschalten. Dass wir dies nicht durch Umkopieren erreichen können, ist euch sicherlich klar. Wir müssten ja jedes Mal die 8000 Bytes der Bitmap plus den 1000 Bytes des Bildschirmspeichers kopieren. Dies schaffen wir aber nicht schnell genug. Also werden wir die zweite Grafik in eine andere VIC-Bank legen und nur die Bänke umschalten. Da ich ein fauler Hund bin, machen wir es uns mit der zweiten Grafik ganz einfach. Wir nehmen die VIC-Bank-1. Dabei legen wir den Bildschirmspeicher und die Bitmap so, dass sie relativ betrachtet, an den gleichen Positionen liegen, wie eben bei der ersten Bitmap.

Fügt dazu am Programmbeginn eine neue Konstante hinzu:

VICSCREENRAM_2          = $4400                         ;hier liegen die Farben für die 2. Bitmap

Jetzt binden wir am Programmende, hinter der ersten Bitmap von eben, noch die beiden weiteren Dateien ein. Beachtet, dass wir dieses Mal für beide Dateien eine neue Adresse angeben.

;Farben für die 2. Bitmap
*=VICSCREENRAM_2
    !bin "MCI_SR_2.bin"

*=$6000    
;2. Bitmap
    !bin "MCI_BM_2.bin"

Wenn ihr von den Adressen, den Beginn der von uns verwendeten nächsten VIC-Bank $4000 abzieht, dann landet ihr wieder bei den gleichen Adressen für den Bildschirmspeicher und die Bitmap wie eben $0400 / $2000. Daher müssen wir gleich nur die Bank umschalten, um die Bilder zu wechseln.

Fügt jetzt die folgende Funktion checkKeyboard, am besten direkt hinter jmp *, ein:

!zone checkKeyboard
checkKeyboard
    sei                             ;Interrupts sperren!
                                    ;Sonst funkt man uns evtl. dazwischen

    lda #%11111110                  ;wir wollen PA0 maskieren
    sta $DC00                       ;Wert ins Register CIA-1 Port A schreiben

    lda $DC01                       ;hole Register-Inhalt vom CIA-1 Port B
    tax                             ;im X-Register merken
    and #%00010000                  ;hier PB4 prüfen F1
    bne .checkF3                    ;wenn KEINE 0, weiter mit F3
                                    ;sonst sind wir fertig
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $DD02                       ;zum Schreiben freigeben
    lda #%00000011                  ;Bank-0 
    sta $DD00                       ;für das 1. Bild wählen
    jmp .exit                       ;und raus
.checkF3
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%00100000                  ;hier PB5 prüfen F3
    bne .checkF5                    ;wenn KEINE 0, weiter mit F5
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $DD02                       ;zum Schreiben freigeben
    lda #%00000010                  ;Bank-1 
    sta $DD00                       ;für das 2. Bild wählen
    jmp .exit                       ;und raus
.checkF5
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%01000000                  ;hier PB6 prüfen F-5
    bne .exit                       ;wenn KEINE 0, dann raus
.exit
    cli                             ;Interrupts wieder freigeben
    rts                             ;zurück zum Aufrufer

Hier prüfen wir einfach, ob F1, F3 oder F5 gedrückt wurde. Bei F1 zeigen wir das erste Bild an und bei F3 das zweite. F5 hat aktuell noch keine Funktion, damit werden wir zum Schluß das automatische Umschalten aktivieren.

Jetzt müssen wir abschließend noch den Aufruf für unsere neue Funktion einfügen. Ersetzt dazu bitte jmp * durch folgende drei Zeilen:

.loop
    jsr checkKeyboard               ;Tastatur prüfen
    jmp .loop                       ;Endlosschleife

Wenn ihr das Programm jetzt startet, seht ihr zunächst wieder die Grafk von oben. Drückt einmal F3 und ihr seht die zweite. Euch sollte auffallen, dass sich die Bilder geringfügig unterscheiden. Drückt einfach abwechselnd F1 und F3.

Das erste Bild
Das erste Bild (F1)
Das zweite Bild
Das zweite Bild (F3)

;*** VIC-II Speicher-Konstanten
VICBANKNO               = 0                             ;Nr. (0 - 3) der 16KB Bank                              | Standard: 0
VICSCREENBLOCKNO        = 1                             ;Nr. (0 -15) des 1KB-Blocks für den Textbildschirm      | Standard: 1
VICCHARSETBLOCKNO       = 2                             ;Nr. (0 - 7) des 2KB-Blocks für den Zeichensatz         | Standard: 2
VICBITMAPBBLOCKNO       = 1                             ;Nr. (0 - 1) des 8KB-Blocks für die BITMAP-Grafik       | Standard: 0
VICBASEADR              = VICBANKNO*16384               ;Startadresse der gewählten VIC-Bank                    | Standard: $0000
VICCHARSETADR           = VICBASEADR+VICCHARSETBLOCKNO*2048        ;Adresse des Zeichensatzes                   | Standard: $1000 ($d000)
VICSCREENRAM            = VICBASEADR+VICSCREENBLOCKNO*1024         ;Adresse des Bildschirmspeichers
VICSCREENRAM_2          = $4400                         ;hier liegen die Farben für die 2. Bitmap
VICBITMAPADR            = VICBASEADR+VICBITMAPBBLOCKNO*8192        ;Adresse der BITMAP
VICCOLORRAM             = $d800


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

!zone main
main
    ;Bitmap-Modus aktivieren
    lda $d011                       ;VIC-II Register 17 in den Akku
    ora #%00100000                  ;Bitmap-Modus
    sta $d011                       ;aktivieren

    lda $d016                       ;VIC-II Register 22 in den Akku
    ora #%00010000                  ;Multi-Color über BIT-4
    sta $d016                       ;aktivieren
    
    ;*** Start des Bitmapspeichers festlegen
    lda $d018                       ;VIC-II Register 24 in den Akku holen
    and #%11110111                  ;Mit BIT-3
    ora #VICBITMAPBBLOCKNO*8        ;den Beginn des Bitmap-
    sta $d018                       ;festlegen
        
    jsr copyColor                   ;Farben kopieren
     
.loop
    jsr checkKeyboard               ;Tastatur prüfen
    jmp .loop                       ;Endlosschleife


!zone checkKeyboard
checkKeyboard
    sei                             ;Interrupts sperren!
                                    ;Sonst funkt man uns evtl. dazwischen

    lda #%11111110                  ;wir wollen PA0 maskieren
    sta $dc00                       ;Wert ins Register CIA-1 Port A schreiben

    lda $dc01                       ;hole Register-Inhalt vom CIA-1 Port B
    tax                             ;im X-Register merken
    and #%00010000                  ;hier PB4 prüfen F1
    bne .checkF3                    ;wenn KEINE 0, weiter mit F3
                                    ;sonst sind wir fertig
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda #%00000011                  ;Bank-0 
    sta $dd00                       ;für das 1. Bild wählen
    jmp .exit                       ;und raus
.checkF3
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%00100000                  ;hier PB5 prüfen F3
    bne .checkF5                    ;wenn KEINE 0, weiter mit F5
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda #%00000010                  ;Bank-1 
    sta $dd00                       ;für das 2. Bild wählen
    jmp .exit                       ;und raus
.checkF5
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%01000000                  ;hier PB6 prüfen F-5
    bne .exit                       ;wenn KEINE 0, dann raus
.exit
    cli                             ;Interrupts wieder freigeben
    rts                             ;zurück zum Aufrufer



!zone copyColor    
copyColor
    lda #0                          ;Rahmenfarbe schwarz
    sta $d020
    lda #15                         ;Hintergrundfarbe hellgrau
    sta $d021    
    ldx #0                          ;Schleifenzähler initialisieren
.loop    
    lda color,X                     ;Farben ins Color-RAM kopieren
    sta VICCOLORRAM,X
    lda color+256,X
    sta VICCOLORRAM+256,X
    lda color+512,X
    sta VICCOLORRAM+512,X
    lda color+768,X
    sta VICCOLORRAM+768,X    
    
    lda char,X                      ;Farben in den Bildschirmspeicher kopieren
    sta VICSCREENRAM,X    
    lda char+256,X
    sta VICSCREENRAM+256,X    
    lda char+512,X
    sta VICSCREENRAM+512,X    
    lda char+768,X
    sta VICSCREENRAM+768,X    
    
    dex                             ;Schleifenzähler verringern
    bne .loop                       ;die nächsten BYTES kopieren
    
    rts                             ;zurück zum Aufrufer



;Daten fürs Farb-RAM (wird nur 1x benötigt)
color
    !bin "MCI_CR.bin"

;Farben der 1. Bitmap für den Bildschrimspeicher
char    
    !bin "MCI_SR_1.bin"

*=$2000
;1. Bitmap
    !bin "MCI_BM_1.bin"

;Farben für die 2. Bitmap
*=VICSCREENRAM_2
    !bin "MCI_SR_2.bin"

*=$6000    
;2. Bitmap
    !bin "MCI_BM_2.bin"

Wir nähern uns der Zielgeraden. Wie eingangs beschrieben, müssen wir die Bilder regelmäßtig umschalten und das zweite Bild um einen Pixel nach rechts scrollen. Laßt uns dies jetzt einbauen.

Damit das Umschalten kontrolliert abläuft, sollten wir es immer zum selben Zeitpunkt machen. Außerdem wäre es ratsam, dies außerhalb des sichtbaren Bereichs vorzunehmen.

Baut die folgende kleine Routine, die auf eine bestimme Rasterzeilenposition wartet, vor checkKeyboard ein. Falls euch Rasterzeilen noch fremd sind, werft mal einen Blick auf Der Rasterzeileninterrupt.

!zone waitRaster
waitRaster
    lda #255                        ;gewünschte Rasterzeile 
.wait    
    cmp $d012                       ;falls wir schon in der
    beq .wait                       ;gewünschten Zeile sind -> warten
.wait1   
    cmp $d012                       ;jetzt warten, bis die gewünschte
    bne .wait1                      ;Rasterzeile erreicht wurde
    rts                             ;zurück zum Aufrufer

Die wahrscheinlich schon bekannte Funktion wartet einfach solange, bis die im Akku stehende Rasterzeile (hier 255) erreicht wurde.

Fügt nun eine weitere Konstante zum Programm hinzu:

ZP_AUTO                 = $02

Diese verwenden wir, um zu erkennen, ob wir automatisch umschalten oder nicht. Nehmt anschließend folgende Änderungen hinter jsr copycolor ;Farben kopieren vor, die neuen Zeilen sind gelb hervorgehoben.

    jsr copycolor                   ;Farben kopieren
    
    lda #0                          ;0 = automatisch umschalten
    sta ZP_AUTO
    
.loop
    jsr waitRaster                  ;auf Rasterzeile warten
    jsr checkKeyboard               ;Tastatur prüfen
    lda ZP_AUTO                     ;ist ZP_AUTO = 0?
    bne .loop                       ;falls nicht -> .loop
    lda #%00000001                  ;Datenrichtung für BIT 0 des CIA-Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda $dd00
    eor #%00000001                  ;VIC-Bank zwischen 0 und 1 umschalten
    sta $dd00     
    lda $d016                       ;VIC-II Register 22 in den Akku
    eor #%00000001                  ;Scrollposition links / rechts um
    sta $d016                       ;einen Pixel umschalten
    jmp .loop                       ;endlos wiederholen

Wir initialisieren ZP_AUTO erstmal so, dass direkt beim Start automatisch umgeschaltet wird. Dann warten wir hinter .loop auf unsere Rasterzeile 255. Danach kontrollieren wir die Tastatur und prüfen, ob ZP_AUTO noch 0 ist. Falls nicht, springen wir einfach wieder zum Schleifenanfang. Ist der Wert noch 0, dann schalten wir um. Dazu setzen wir zur Sicherheit noch die Datenrichtung im Port A des CIA auf schreiben fürs erste Bit. Um zwischen der VIC-Bank 0 und 1 hin- und herzuschalten, brauchen wir nur das unterste Bit. Dieses lesen wir von $dd00 und schalten es mit eor %00000001 bei jedem Durchlauf um. Da wir auch scrollen müssen, verfahren wir dort genau so! Nach dem Systemstart steht die links / rechts Scrollposition immer auf %111, also ganz links! Wir lesen den Inhalt von $d016 und müssen nur das unterste Bit immer zwischen 1 und 0 umschalten.
Zum Schluß springen wir wieder an den Schleifenanfang.

Jetzt müssen wir noch auf F5 in unserer checkKeyboard-Funktion reagieren. Nehmt dazu die drei kleinen, gelb markierten, Änderungen vor:

!zone checkKeyboard
checkKeyboard
    sei                             ;Interrupts sperren!
                                    ;Sonst funkt man uns evtl. dazwischen

    lda #%11111110                  ;wir wollen PA0 maskieren
    sta $dc00                       ;Wert ins Register CIA-1 Port A schreiben

    lda $dc01                       ;hole Register-Inhalt vom CIA-1 Port B
    tax                             ;im X-Register merken
    and #%00010000                  ;hier PB4 prüfen F1
    bne .checkF3                    ;wenn KEINE 0, weiter mit F3
                                    ;sonst sind wir fertig
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda #%00000011                  ;Bank-0 
    sta $dd00                       ;für das 1. Bild wählen
    sta ZP_AUTO                     ;Automatik deaktivieren
    jmp .exit                       ;und raus
.checkF3
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%00100000                  ;hier PB5 prüfen F3
    bne .checkF5                    ;wenn KEINE 0, weiter mit F5
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda #%00000010                  ;Bank-1 
    sta $dd00                       ;für das 2. Bild wählen
    sta ZP_AUTO                     ;Automatik deaktivieren
    jmp .exit                       ;und raus
.checkF5
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%01000000                  ;hier PB6 prüfen F5
    bne .exit                       ;wenn KEINE 0, dann raus    
    sta ZP_AUTO                     ;Automatik wieder aktivieren
.exit
    cli                             ;Interrupts wieder freigeben
    rts                             ;zurück zum Aufrufer

Wir machen es uns hier ganz einfach! Der Akku hat schon immer einen passenden Wert, sodass wir diesen an den markierten Stellen nur noch ZP_AUTO schreiben müssen, damit die Automatik aktiviert bzw. deaktiviert wird.

Wenn ihr das Programm jetzt startet, stolpert ihr evtl. über zwei Probleme. Das erste fällt euch sicherlich direkt auf. Links entsteht eine unschöne weiße Line.

Die Line links stört!
Die Line links stört!

Das zweite kann auftreten, sobald ihr die Automatik mit F1 oder F3 unterbrecht und dann mit F5 fortsetzt. Dadurch kann unser Timing aus dem Tritt kommen. Ihr müsst dann evtl. wiederholt anhalten / fortfahren bis es wieder passt. Da diese Funktionen nur der Veranschaulichung dienen, kümmere ich mich nicht weiter darum. Ihr solltet aber zur Übung mal dafür sorgen, dass immer richtig angehalten und fortgestetzt wird.

Die störende Line muss aber unbedingt weg!

Die Linie entsteht durch unser Scrolling. Wie ihr durch die Linie seht, ist das Bild anscheinend viel kleiner, als der zur Verfügungstehende Ausgabebereich. Zur Kontrolle könnt ihr ja mal die Rahmenfarbe ändern:

Das eigentliche Bild braucht nicht den gesamten Platz.
Das eigentliche Bild braucht nicht den gesamten Platz.

Wir können also einfach, wie bei Scrolling – Laufschrift gesehen, die Bildschirmausgabe auf 38 Spalten reduzieren. Fügt dazu am Programmanfang, wo wir den Multi-Color-Modus aktivieren die markierte Zeile ein:

    lda $D016                       ;VIC-II Register 22 in den Akku
    ora #%00010000                  ;Multi-Color über BIT-4
    and #%11110111                  ;auf 38 Spalten umstellen
    sta $D016                       ;aktivieren

Jetzt könnt ihr das Programm wieder starten und die nervige Linie ist weg.

Erstellt ihr eigene Bilder und sollten diese bis zum Rand reichen, dann könnt ihr auch Sprites verwenden, um die Linie zu überdecken. Damit könnt ihr auf einen Pixel genau arbeiten und somit, bis auf eine vertikale Pixelzeile, den gesamten Bildschirm ausnutzen.

;*** VIC-II Speicher-Konstanten
VICBANKNO               = 0                             ;Nr. (0 - 3) der 16KB Bank                              | Standard: 0
VICSCREENBLOCKNO        = 1                             ;Nr. (0 -15) des 1KB-Blocks für den Textbildschirm      | Standard: 1
VICCHARSETBLOCKNO       = 2                             ;Nr. (0 - 7) des 2KB-Blocks für den Zeichensatz         | Standard: 2
VICBITMAPBBLOCKNO       = 1                             ;Nr. (0 - 1) des 8KB-Blocks für die BITMAP-Grafik       | Standard: 0
VICBASEADR              = VICBANKNO*16384               ;Startadresse der gewählten VIC-Bank                    | Standard: $0000
VICCHARSETADR           = VICBASEADR+VICCHARSETBLOCKNO*2048        ;Adresse des Zeichensatzes                   | Standard: $1000 ($d000)
VICSCREENRAM            = VICBASEADR+VICSCREENBLOCKNO*1024         ;Adresse des Bildschirmspeichers
VICSCREENRAM_2          = $4400                         ;hier liegen die Farben für die 2. Bitmap
VICBITMAPADR            = VICBASEADR+VICBITMAPBBLOCKNO*8192        ;Adresse der BITMAP
VICCOLORRAM             = $d800

ZP_AUTO                 = $02


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

!zone main
main
    ;Bitmap-Modus aktivieren
    lda $d011                       ;VIC-II Register 17 in den Akku
    ora #%00100000                  ;Bitmap-Modus
    sta $d011                       ;aktivieren

    lda $d016                       ;VIC-II Register 22 in den Akku
    ora #%00010000                  ;Multi-Color über BIT-4
    and #%11110111                  ;auf 38 Spalten umstellen
    sta $d016                       ;aktivieren
    
    ;*** Start des Bitmapspeichers festlegen
    lda $d018                       ;VIC-II Register 24 in den Akku holen
    and #%11110111                  ;Mit BIT-3
    ora #VICBITMAPBBLOCKNO*8        ;den Beginn des Bitmap-
    sta $d018                       ;festlegen
        
    jsr copyColor                   ;Farben kopieren
    
    lda #0                          ;0 = automatisch umschalten
    sta ZP_AUTO
    
.loop
    jsr waitRaster                  ;auf Rasterzeile warten
    jsr checkKeyboard               ;Tastatur prüfen
    lda ZP_AUTO                     ;ist ZP_AUTO = 0?
    bne .loop                       ;falls nicht -> .loop
    lda #%00000001                  ;Datenrichtung für BIT 0 des CIA-Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda $dd00
    eor #%00000001                  ;VIC-Bank zwischen 0 und 1 umschalten
    sta $dd00     
    lda $d016                       ;VIC-II Register 22 in den Akku
    eor #%00000001                  ;Scrollposition links / rechts um
    sta $d016                       ;einen Pixel umschalten
    jmp .loop                       ;endlos wiederholen



!zone waitRaster
waitRaster
    lda #255                        ;gewünschte Rasterzeile 
.wait    
    cmp $d012                       ;falls wir schon in der
    beq .wait                       ;gewünschten Zeile sind -> warten
.wait1   
    cmp $d012                       ;jetzt warten, bis die gewünschte
    bne .wait1                      ;Rasterzeile erreicht wurde
    rts                             ;zurück zum Aufrufer



!zone checkKeyboard
checkKeyboard
    sei                             ;Interrupts sperren!
                                    ;Sonst funkt man uns evtl. dazwischen

    lda #%11111110                  ;wir wollen PA0 maskieren
    sta $dc00                       ;Wert ins Register CIA-1 Port A schreiben

    lda $dc01                       ;hole Register-Inhalt vom CIA-1 Port B
    tax                             ;im X-Register merken
    and #%00010000                  ;hier PB4 prüfen F1
    bne .checkF3                    ;wenn KEINE 0, weiter mit F3
                                    ;sonst sind wir fertig
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda #%00000011                  ;Bank-0 
    sta $dd00                       ;für das 1. Bild wählen
    sta ZP_AUTO                     ;Automatik deaktivieren    
    jmp .exit                       ;und raus
.checkF3
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%00100000                  ;hier PB5 prüfen F3
    bne .checkF5                    ;wenn KEINE 0, weiter mit F5
    lda #%00000011                  ;Datenrichtung für BIT 0 & 1 des Port-A
    sta $dd02                       ;zum Schreiben freigeben
    lda #%00000010                  ;Bank-1 
    sta $dd00                       ;für das 2. Bild wählen
    sta ZP_AUTO                     ;Automatik deaktivieren    
    jmp .exit                       ;und raus
.checkF5
    txa                             ;hole Register-Inhalt vom CIA-1 Port B
    and #%01000000                  ;hier PB6 prüfen F-5
    bne .exit                       ;wenn KEINE 0, dann raus
    sta ZP_AUTO                     ;Automatik wieder aktivieren    
.exit
    cli                             ;Interrupts wieder freigeben
    rts                             ;zurück zum Aufrufer



!zone copyColor    
copyColor
    lda #0                          ;Rahmenfarbe schwarz
    sta $d020
    lda #15                         ;Hintergrundfarbe hellgrau
    sta $d021    
    ldx #0                          ;Schleifenzähler initialisieren
.loop    
    lda color,X                     ;Farben ins Color-RAM kopieren
    sta VICCOLORRAM,X
    lda color+256,X
    sta VICCOLORRAM+256,X
    lda color+512,X
    sta VICCOLORRAM+512,X
    lda color+768,X
    sta VICCOLORRAM+768,X    
    
    lda char,X                      ;Farben in den Bildschirmspeicher kopieren
    sta VICSCREENRAM,X    
    lda char+256,X
    sta VICSCREENRAM+256,X    
    lda char+512,X
    sta VICSCREENRAM+512,X    
    lda char+768,X
    sta VICSCREENRAM+768,X    
    
    dex                             ;Schleifenzähler verringern
    bne .loop                       ;die nächsten BYTES kopieren
    
    rts                             ;zurück zum Aufrufer



;Daten fürs Farb-RAM (wird nur 1x benötigt)
color
    !bin "MCI_CR.bin"

;Farben der 1. Bitmap für den Bildschrimspeicher
char    
    !bin "MCI_SR_1.bin"

*=$2000
;1. Bitmap
    !bin "MCI_BM_1.bin"

;Farben für die 2. Bitmap
*=VICSCREENRAM_2
    !bin "MCI_SR_2.bin"

*=$6000    
;2. Bitmap
    !bin "MCI_BM_2.bin"

Sobald ihr das Programm laufen lasst, sollte euer Bild ungefähr so aussehen:

Annäherung an das MCI Bild auf dem C64
Annäherung an das MCI Bild auf dem C64

Das Standbild ist selbstverständlich nur eine Annäherung an die C64 Ausgabe des MCI Bildes. Es flackert nicht, zeigt aber wie es ungefähr am C64 wirkt. Wenn ihr dieses Bild mit den beiden Einzelbildern vergleicht, dann seht ihr bestimmt, dass es viel detaillierter aussieht. Dies kommt durch die Überlagerung der beiden Bilder.

Hier noch ein Versuch als animiertes GIF. Dies wird dem aber auch nicht gerecht, die Wahrheit liegt irgendwo da draußen 😉 dazwischen und läßt sich wohl nur direkt am C64 finden.

GIF-Animation
GIF-Animation

Das Flackern bekommt ihr durch Programmänderungen leider nicht weg! Dies ist aber für sog. Interlace-Auflösungen typisch. Falls ihr einen Amiga habt / hattet kennt ihr das bestimmt, von den entsprechenden Bildschirmauflösungen. Beim Amiga hilft ein Flickerfixer, beim MCI-Modus am C64 muss man es einfach „ertragen“ 😉 .

Die MCI Bilder kommen aber auf alten Röhren sehr viel besser rüber, als auf den modernen LCD- / TFT- / LED-Bildschirmen. Durch die „alte“ Technik, ist das Bild fast ganz ruhig! Probiert es einfach selbst mal aus.

Das MCI-Bild auf meinem SX-64
Das MCI-Bild auf meinem SX-64

Wir (OK, ich war es) haben in diesem Beispiel aus Bequemlichkeit, eine Menge Platz für das MCI Bild verschwendet. Ihr könnt die Speicherbereiche natürlich auch besser positionieren und dann beim Umschalten neben der VIC-Bank auch noch die Speicheradressen ändern.


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

Loading...


Zurück

Ein Gedanke zu „VIC-II: Grafikmodes – MCI“

Schreibe einen Kommentar

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

Protected by WP Anti Spam