Erstellt: 20. Oktober 2013 (zuletzt geändert: 1. November 2021)

Linken & rechten Rahmen öffnen

Den seitlichen Rahmen ausblenden

C64 Studio, AMCE & TASM

In Oberen & unteren Rand öffnen wurde ja bereits erklärt, wie einfach sich der Rahmen über und unter dem Ausgabebereich entfernen lässt. Nach dem Beitrag Raster-IRQ: Bad Lines ist es uns nun auch möglich den seitlichen Rahmen zu entfernen.

Die Theorie

Für den oberen & unteren Rahmen mussten wir ja nur zur richtigen Zeit die Anzeige von 25 Zeilen auf 24 und dann wieder zurück ändern. Wie ihr evtl. bei VIC-II: Die Register gesehen habt, kann man neben der Zeilenanzahl auch die der Spalten einstellen. Dazu dient das Bit 3 im Register 22 $d016, hiermit kann zwischen 40 (Standard) und 38 Spalten umgeschaltet werden. Ändern wir nun zum passenden Zeitpunkt die Breite von 40 auf 38 Spalten, dann denkt der VIC-II wieder (wie beim oberen & unteren Rahmen) der Rahmen sei bereits gezeichnet worden und er wird ausgeblendet. Anschließend müssen wir den Wert wieder auf 40 zurückstellen und das Spiel beginnt von neuem.

Leider ist die Umsetzung nicht ganz so einfach. Wir müssen dieses Mal in jeder Rasterzeile dafür sorgen, dass die Spaltenanzahl geändert und zurückgestellt wird. Dabei bereiten uns die Bad Lines natürlich zusätzliches Kopfzerbrechen. Aber fangen wir doch einfach mal an.

Ein erster Versuch

Lasst uns zunächst mal einen stabilen Raster-IRQ so einrichten, dass wir in der letzen Zeile vor dem Ausgabebereich mit unserer Routine beginnen.

RASTER          = $2f               ;Hier den 1. Raster-IRQ auslösen

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

main
 sei                                ;IRQs sperren

 lda #<myIRQ                        ;Adresse unserer Routine in
 sta $0314                          ;den RAM-Vektor
 lda #>myIRQ
 sta $0315

 lda #%00000001                     ;Raster-IRQs vom VIC-II aktivieren
 sta $d01a

 lda #RASTER                        ;Hier soll unsere Interrupt auftreten
 sta $d012                      

 lda $d011                          ;Zur Sicherheit höchstes BIT
 and #%01111111                     ;für die Rasterzeile löschen
 sta $d011

 lda #%00001000                     ;Ausgabe nicht verschieben und 40-Spalten
 sta $d016

 lda #%0111111                      ;Timer-IRQs abschalten
 sta $dc0d
 lda $dc0d                          ;zur Sicherheit bestätigen

 lda #%00000001                     ;Sicherheitshalber auch den
 sta $d019                          ;Raster-IRQ bestätigen

 cli                                ;Interrupts erlauben
 rts                                ;zurück zum BASIC

;*** Selbst gebautes align...
*=((*-1)/1024)*1024+1024            ;etwas Platz lassen & Pagegrenze 'vermeiden'
myIRQ
;*** Wenn wir hier landen, sind bereits 38-45 Taktzyklen in der
;*** aktuellen Rasterzeile (ab jetzt als STARTROW bezeichnet) vergangen!

;*** Zweiten IRQ einrichten
;*** Da die Zeit bei aktivierten ROM nicht reicht, können wir den
;*** 2. Raster-IRQ erst in der übernächsten Zeile (STARTROW+2) bekommen.
 lda #<doubleIRQ                    ;(2 TZ) 2. Raster-IRQ einrichten
 sta $0314                          ;(4 TZ)
 lda #>doubleIRQ                    ;(2 TZ)
 sta $0315                          ;(4 TZ)
 tsx                                ;(2 TZ) Stackpointer im X-Reg. retten
 stx doubleIRQ+1                    ;(4 TZ) und fürs zurückholen sichern!
 nop                                ;(2 TZ)
 nop                                ;(2 TZ)
 nop                                ;(2 TZ)
 lda #%00000001                     ;(2 TZ) 1. Raster-IRQ später bestätigen
                                    ;------
                                    ;26 TZ

;*** Jetzt sind 64-71 Taktzyklen vergangen und wir sind
;*** auf jeden Fall in nächsten Rasterzeile (STARTROW+1)!
;*** Verbraucht wurden dort 1-8 TZ
 inc $d012                          ;(6 TZ) 2. IRQ in der übernächsten Zeile STARTROW+2
                                    ;       $D012 wurde bereits automatisch erhöht
 sta $d019                          ;(4 TZ) IRQ bestätigen
 cli                                ;(2 TZ) Interrupts für den 2. Raster-IRQ
                                    ;       wieder freigeben

;*** Wir befinden uns in Rasterzeile STARTROW+1 und 
;*** haben bisher 13-20 Zyklen verbraucht

;*** etwas Zeit verschwenden...
 ldx #$08                           ;            2 TZ
 dex                                ;8 * 2 TZ = 16 TZ
 bne *-1                            ;7 * 3 TZ = 21 TZ
                                    ;1 * 2 TZ =  2 TZ
                                    ;          ------
                                    ;           41 TZ

;*** Bis hier sind 54-61 Taktzyklen vergangen, jetzt auf den IRQ warten...
;*** Der nächste Rasterinterrupt wird während dieser NOPs auftreten!
 nop                                ;2 TZ (56)
 nop                                ;2 TZ (58)
 nop                                ;2 TZ (60)
 nop                                ;2 TZ (62)
 nop                                ;2 TZ (64)
 nop                                ;2 TZ (66)

doubleIRQ:
;*** Wir sind nun in Rasterzeile STARTROW+2 und
;*** haben bisher genau 38 oder 39 Taktzyklen benötigt!!
;*** Wir können so sicher sein, da der IRQ während der NOPs auftrat.

;*** Jetzt exakt soviele Taktzyklen 'verschwenden', wie in 
;*** dieser Zeile noch zu verarbeiten sind (also 24 oder 25).
 ldx #$00                           ;(2 TZ) Platzhalter für 1. Stackpointer
 txs                                ;(2 TZ) Stackpointer vom 1. IRQ wiederherstellen
 nop                                ;(2 TZ)
 nop                                ;(2 TZ)
 nop                                ;(2 TZ)
 nop                                ;(2 TZ)
 bit $01                            ;(3 TZ)
 lda #$00                           ;(2 TZ) Farbe in den Akku
 ldx $d012                          ;(4 TZ)
 cpx $d012                          ;(4 TZ) sind wir noch in Rasterzeile STARTROW+2?
                                    ;======
                                    ;25 TZ = 63 oder 64 TZ!!!

 beq myIRQMain                      ;(3 TZ) wenn JA einen letzten Takt 'verschwenden'
                                    ;(2 TZ) sonst einfach weiterlaufen...

;*** Wir beginnen also immer exakt nach 3 TZ in der dritten Rasterzeile (STARTROW+3)
;*** nach dem 1. Raster-IRQ (den hatten wir ja für Zeile STARTROW festgelegt)

Dies sollte jetzt keinen mehr vor Probleme stellen, es wird ein Raster-IRQ für Zeile 47 $2f eingerichtet. Da unsere bekannte Routine für den stabilen Raster-IRQ drei Zeilen benötigt, landen wir somit nach 3TZ in Zeile 50. Dies ist bekanntlich die letzte Zeile vor dem Ausgabebereich und somit die letzte vor der 1. Bad Line. Einzige Änderung zum bekannten Vorgehen ist, dass wir #%00001000 nach $d016 schreiben. Wir verhindern damit, dass die Ausgabe seitlich verschoben ist und aktivieren zur Sicherheit die 40-Spalten.

Die eigentliche Arbeit wird jetzt wieder ab myIRQMain erledigt.

myIRQMain
;*** Die restliche Zeit in dieser Zeile abwarten...
;*** Dies ist auch die letzte Zeile vor der 1. Bad Line!!
                                    ;s. oben     3TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 ldx #$0b                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 54TZ
                                    ;===============
                                    ;           63TZ

;*** Bad Line
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
                                    ;===============
                                    ;           20TZ

Hier lassen wir erstmal die letzte Zeile vor der ersten Bad Line und die folgende Bad Line einfach verstreichen. Wir warten also 63TZ und 20TZ.

 

;*** 1. Zeile nach Bad Line
 nop                                ;            2TZ
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten

Der richtige Zeitpunkt, um die Anzeige von 40 auf 38 Spalten zu ändern, ist nach 56TZ in der Rasterzeile. Dort wird das letzte Zeichen der aktuellen Zeile ausgegeben. Also warten wir erstmal 50 Taktzyklen um dann mit einem dec $d016 auf 38 Spalten um zuschalten. Das klappt hier so, da wir dort am Programmbeginn #%00001000 hinterlegt haben. Nach dem dec $d016 geht das Bit 3 also auf 0. Dass sich die Werte fürs Scrolling ändern, ist nicht weiter wild, wir machen dies ja direkt mit dem folgenden inc $d016 wieder Rückgängig.

Nun folgt wieder das bekannte Ende des Interrupts:

 lda #<myIRQ                        ;Original IRQ-Vektor setzen
 sta $0314
 lda #>myIRQ
 sta $0315
 lda #RASTER                        ;ursprüngliche Rasterzeile zurücksetzen
 sta $d012
 lda #%00000001                     ;IRQ bestätigen
 sta $d019
 jmp $ea31                          ;zur System-Routine

Vektoren zurücksetzen, Zeile für den 1. Raster-IRQ eintragen, Interrupt bestätigen und zur System-Routine.

Ein Start sollte jetzt folgende Ausgabe erzeugen. Mit einem POKE 53281,1 könnt ihr die Hintergrundfarbe ändern und so feststellen, dass diese auch durch den offenen Rahmen sichtbar ist.

Der Rahmen wurde (zumindest für eine Zeile) geöffnet.
Der Rahmen wurde (zumindest für eine Zeile) geöffnet.

Außerdem fällt euch bestimmt auf, dass der Rahmen rechts beim Ausgabebereich geöffnet wird und dieses bis in die nächste Zeile links anhält.

Weitere Zeilen öffnen

Um jetzt einen größeren Bereich zu öffen, müssen wir das Vorgehen, wie bereits angekündigt, in jeder Zeile wiederholen. Ersetzt also alles ab myIRQMain mit den folgenden Programmzeilen:

myIRQMain
 ;*** Die restliche Zeit in dieser Zeile abwarten...
 ;*** Dies ist auch die letzte Zeile vor der 1. Bad Line!!
                                    ;s. oben     3TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 ldx #$0b                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 54TZ
                                    ;===============
                                    ;           63TZ

;*** Bad Line
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
                                    ;===============
                                    ;           20TZ

;*** 1. Zeile nach Bad Line
 nop                                ;            2TZ
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ

;*** 2. Zeile nach Bad Line
 bit $01                            ;            3TZ inkl. 1TZ für letzte Zeile
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ

;*** 3. Zeile nach Bad Line
 bit $01                            ;            3TZ inkl. 1TZ für letzte Zeile
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ
;*** 4. Zeile nach Bad Line
 bit $01                            ;            3TZ inkl. 1TZ für letzte Zeile
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ
;*** 5. Zeile nach Bad Line
 bit $01                            ;            3TZ inkl. 1TZ für letzte Zeile
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ
 ;*** 6. Zeile nach Bad Line
 bit $01                            ;            3TZ inkl. 1TZ für letzte Zeile
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ
;*** 7. Zeile nach Bad Line
 bit $01                            ;            3TZ inkl. 1TZ für letzte Zeile
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ

;*** Bad Line
 bit $01                            ;            3TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
 nop                                ;            2TZ
                                    ;===============
                                    ;           20TZ

;*** 1. Zeile nach Bad Line
 nop                                ;            2TZ
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ

;*** 2. Zeile nach Bad Line
 bit $01                            ;            3TZ inkl. 1TZ für letzte Zeile
 nop                                ;            2TZ
 ldx #$09                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 44TZ
                                    ;===============
                                    ;           50TZ
 dec $d016                          ;            6TZ nach 56TZ 38-Spalten
 inc $d016                          ;            6TZ dann zurück auf 40 Spalten
                                    ;===============
                                    ;           62TZ

 lda #<myIRQ                        ;Original IRQ-Vektor setzen
 sta $0314
 lda #>myIRQ
 sta $0315
 lda #RASTER                        ;ursprüngliche Rasterzeile zurücksetzen
 sta $d012
 lda #%00000001                     ;IRQ bestätigen
 sta $d019
 jmp $ea31                          ;zur System-Routine

Hier haben wir nun den Rahmen für mehrere Zeilen geöffnet. Die Bad Lines lassen wir erstmal wieder aus.

Hintergrundfarbe zur Kontrolle geändert (Rahmen debuggen ist aktiv).
Hintergrundfarbe zur Kontrolle geändert (Rahmen debuggen ist aktiv).

Die nächste (ausgelassene) Bad Line erkennt ihr an der hellblauen Linie, die unseren Rahmen durchkreuzt. Der Source wird durch das Kopieren der einzelnen Codeblöcke für jede Rasterzeile auch immer unübersichtlicher, daher laßt uns abschließend ein paar Funktionen basteln, um für etwas Ordnung zu sorgen. Außerdem wollen wir die Bad Lines mit dem bekannten Scrolling überspringen, damit der Rahmen endlich durchgängig geöffnet wird. Dass wir dann aber keinen Ausgabebereich mehr haben ist wohl klar.

Durchgängigen Block öffnen

Also fügen wir erstmal an den Programmbeginn, vor das cli folgende beiden Zeilen hinzu:

main
 lda #$00                           ;Bitmuster für den VIC-II
 sta $3fff                          ;falls er nicht weiß, was angezeigt werden soll
 
 sei                                ;IRQs sperren

Da der VIC-II durch unser Scrollen keine gültigen Daten für den Ausgabebereich mehr bekommt, greift er (wie bereits bei Oberen & unteren Rand öffnen erklärt) auf das Byte bei $3fff zurück. Damit wir einen definierten Zustand erhalten, füllen wir es zur Sicherheit mit $00.

Nun bauen wir uns drei kleine Sub-Routinen. Zum besseren Verständnis möchte ich euch jetzt noch darauf hinweisen, dass wir immer so zu den Routinen springen, dass die jeweilige Funktion mit dem 50 Taktzyklus beginnt. Der erste Befehl ist stets ein dec $d016.

Die erste Routine kümmert sich um die letzte Zeile vor einer Bad Line.

;*** Kümmert sich um die letzte Zeile vor einer BadLine
beforeBadLine
 dec $d016                          ;            6TZ: nach 50 TZ
 dec $d011                          ;            6TZ
 inc $d016                          ;            6TZ
 ldx #$06                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 29TZ
 nop                                ;            2TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

Wir öffnen mit dem ersten Befehl den Rahmen (OK eigentlich ändern wir die Spaltenanzahl auf 38). Da gleich eine unerwünschte Bad Line folgt, scrollen wir den Ausgabebereich um eine Zeile. Dann stellen wir zurück auf 40 Spalten und verbummeln den Rest der Zeile.
Diese Funktion müssen wir also immer direkt vor einer Bad Line aufrufen!

Nach einer Bad Line wollen wir wieder zurückscrollen, also:

;*** Kümmert sich um die erste Zeile nach einer BadLine
afterBadLine
 dec $d016                          ;            6TZ: nach 50 TZ
 inc $d011                          ;            6TZ
 inc $d016                          ;            6TZ
 ldx #$06                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 26TZ
 nop                                ;            2TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

Diese Routine ist bis auf einen Befehl mit beforeBadLine identisch. Nur dass wir hier mit inc $d011 wieder zurückscrollen.
Diese Funktion muss also immer direkt nach einer Bad Line ausgeführt werden!

Da es nun keine Bad Lines mehr gibt, brauchen wir nur noch eine Funktion, die sich um alle anderen Zeilen kümmert:

;*** Kümmert sich um 'normale' Zeilen
normalLine
 dec $d016                          ;            6TZ: nach 50 TZ
 inc $d016                          ;            6TZ
 ldx #$07                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 34TZ
 bit $01                            ;            3TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

Hier öffnen wir einfach nur den seitlichen Rahmen und warten, bis die Zeit für diese Zeile rum ist.
Diese Routine also einfach für alle anderen Rasterzeilen aufrufen.

Jetzt noch unser Programm ab myIRQMain anpassen:

myIRQMain
 ;*** abwarten, bis der 44TZ erreicht wird (s. JSR)
                                    ;s. oben     3TZ
 ldx #$08                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 39TZ
                                    ;===============
 ;1. Block                          ;           44TZ!
 jsr beforeBadLine                  ;            6TZ -> immer nach 50TZ springen
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

Wie ihr seht, lassen wir 44TZ in der ersten Zeile verstreichen, da diese auch die letzte Zeile vor einer Bad Line ist, springen wir dann zu beforeBadLine. Anschließend geht es zu normalLine, da es durch das Scrolling keine Bad Line gibt und zu guter Letzt wird mit afterBadLine das Scrolling zurückgesetzt. Nun folgen fünf normale Zeilen und wir haben einen 8 Zeilen Block geschafft (OK eigentlich gehört ein kommendes beforeBadLine noch dazu). Aber wir können nun durch einfaches Kopieren dieser acht Zeilen unseren Rahmen durchgängig öffnen.

Fügen wir also noch ein paar Blöcke hinzu und schließen die Funktion dann auch ab. Ich zeige hier den kompletten Bereich ab myIRQMain, also vorsicht, falls ihr die Abschnitte von oben bereits in den Source aufgenommen habt.

myIRQMain
 ;*** abwarten, bis der 44TZ erreicht wird (s. JSR)
                                    ;s. oben     3TZ
 ldx #$08                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 39TZ
                                    ;===============
 ;1. Block                          ;           44TZ!
 jsr beforeBadLine                  ;            6TZ -> immer nach 50TZ springen
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;2. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;3. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;4. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;5. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 lda #<myIRQ                        ;Original IRQ-Vektor setzen
 sta $0314
 lda #>myIRQ
 sta $0315
 lda #RASTER                        ;ursprüngliche Rasterzeile zurücksetzen
 sta $d012
 lda #%00000001                     ;IRQ bestätigen
 sta $d019
 jmp $ea31                          ;zum Schluß zum 'Timer-Interrupt' springen

;*** Kümmert sich um die letzte Zeile vor einer BadLine
beforeBadLine
 dec $d016                          ;            6TZ: nach 50 TZ
 dec $d011                          ;            6TZ
 inc $d016                          ;            6TZ
 ldx #$06                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 29TZ
 nop                                ;            2TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ
                                    
;*** Kümmert sich um die erste Zeile nach einer BadLine
afterBadLine
 dec $d016                          ;            6TZ: nach 50 TZ
 inc $d011                          ;            6TZ
 inc $d016                          ;            6TZ
 ldx #$06                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 26TZ
 nop                                ;            2TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

;*** Kümmert sich um 'normale' Zeilen
normalLine
 dec $d016                          ;            6TZ: nach 50 TZ
 inc $d016                          ;            6TZ
 ldx #$07                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 34TZ
 bit $01                            ;            3TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

Hier gibt es einfach nur den 2. bis 5. Block, dann wird der Raster-IRQ verlassen. Ganz zum Schluß findet ihr die drei neuen Routinen.

Jetzt haben wir endlich einen durchgängig geöffneten Rahmen. Bei uns zur Zeit zwar nur in den ersten fünf Textzeilen, aber wie ihr den Rest öffnet, wisst ihr nun auch.

Ein durchgängig geöffneter Rahmen (Rahmen debuggen aktiv).
Ein durchgängig geöffneter Rahmen (Rahmen debuggen aktiv).

Oben, unten, links & rechts öffnen

Um den seitlichen Rahmen auch ober- und unterhalb des Ausgabebereichs zu öffnen, müssen, wie bereits bei Oberen & unteren Rand öffnen erwähnt, beide Rahmen entfernt werden. Da bereits beides beschrieben wurde, braucht ihr diese beiden Vorgehensweisen nur kombinieren.

Ändert doch mal die Konstante RASTER am Programmbeginn in RASTER = $20 und ersetzt dann alles ab myIRQMain mit dem folgenden Block.

myIRQMain
;*** abwarten, bis der 44TZ erreicht wird (s. JSR)
                                    ;s. oben     3TZ
 lda $d011                          ;            4TZ auf 25 Zeilen umstellen
 ora #%00001000                     ;            2TZ
 sta $d011                          ;            4TZ
 ldx #$06                           ;            2TZ
 dex
 bne *-1                            ;X*5TZ-1TZ= 29TZ
                                    ;===============
 ;Rahmen                            ;           44TZ!
 jsr normalLine                     ;            6TZ -> immer nach 50TZ springen
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;1. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;2. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;3. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;4. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 ;5. Block
 jsr beforeBadLine
 jsr normalLine
 jsr afterBadLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine
 jsr normalLine

 lda #<myIRQ2                       ;IRQ-Vektor oberen & unteren Rahmen öffnen
 sta $0314
 lda #>myIRQ2
 sta $0315
 lda #$fa                           ;passende Zeile zum Rahmen öffnen
 sta $d012
 lda #%00000001                     ;IRQ bestätigen
 sta $d019
 jmp $ea31                          ;zum Schluß zum 'Timer-Interrupt' springen

myIRQ2
 lda $d011                          ;auf 24 Zeilen umschalten
 and #%11110111
 sta $d011
 lda #<myIRQ                        ;Original IRQ-Vektor setzen
 sta $0314
 lda #>myIRQ
 sta $0315
 lda #RASTER                        ;ursprüngliche Rasterzeile zurücksetzen
 sta $d012
 lda #%00000001                     ;IRQ bestätigen
 sta $d019
 pla                                ;Register zurückholen
 tay
 pla
 tax
 pla
 rti                                ;IRQ-Verlassen

beforeBadLine
 dec $d016                          ;            6TZ: nach 50 TZ
 dec $d011                          ;            6TZ
 inc $d016                          ;            6TZ
 ldx #$06                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 29TZ
 nop                                ;            2TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

normalLine
 dec $d016                          ;            6TZ: nach 50 TZ
 inc $d016                          ;            6TZ
 ldx #$07                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 34TZ
 bit $01                            ;            3TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

afterBadLine
 dec $d016                          ;            6TZ: nach 50 TZ
 inc $d011                          ;            6TZ
 inc $d016                          ;            6TZ
 ldx #$06                           ;            2TZ
 dex                    
 bne *-1                            ;X*5TZ-1TZ= 26TZ
 nop                                ;            2TZ
 rts                                ;            6TZ
                                    ;===============
                                    ;           57TZ + nächstes JSR = 63TZ

Hier beginnt das Öffnen des seitlichen Randes schon in Zeile 32. Da sich dort der obere Rahmen befindet, öffnen wir mit einem weiteren IRQ myIRQ2 auch den oberen & unteren Rand.
Hinter myIRQMain setzen wir die Anzeige zunächst auf 25 Zeilen. Dann verbummeln wir wieder den Rest der Zeile, bis wir im 44TZ angekommen sind. Anschließend rufen wir 15 mal normalLine auf. Dies sind die Zeilen im Rahmen. Danach geht es mit den eben entwickelten Blöcken weiter. Zum Schluß setzen wir den RAM-Vektor aber auf einen weiteren Raster-IRQ myIRQ2, den wir in Zeile $fa auftreten lassen.

Bei myIRQ2 wird nur auf 24 Zeilen umgeschaltet, dann der Hauptinterrupt myIRQ in den Vektor geschrieben und schließlich der Interrupt bestätigt und verlassen.

Den Rahmen teilweise an allen vier Seiten entfernt (Rahmen debuggen ist aktiv).
Den Rahmen teilweise an allen vier Seiten entfernt (Rahmen debuggen ist aktiv).

Wie man den gesamten Rahmen öffnet, sollte jetzt kein Problem mehr sein, dass könnt ihr ja mal selbst in Angriff nehmen. Ihr dürft euch nur nicht bei den Taktzyklen verzählen. Da wir durchs Scrollen dann aber keine Ausgabe mehr haben, könnt ihr aktuell wenig damit anfangen. Solltet ihr auf die Idee kommen Sprites zu verwenden, dann werdet ihr euer „blaues Wunder“ erleben. Es klappt dann nichts mehr, dass Thema wird im Beitrag Raster-IRQ: Sprites & Timing behandelt.

Vorsicht, evtl. gibt es Darstellungsprobleme!

Bedenkt auch, dass der Rahmen nicht aus Spass vorhanden ist. Unter VICE ist es kein Problem den vollen Rahmen auszunutzen. Läuft euer Programm aber auf einem echten C64, der evtl. auch noch an einem Röhrenmonitor angeschlossen ist, dann sieht die Sache schon anders aus. Das Problem könnt ihr auf den beiden folgenden Bildern sehen.

Deus Ex Machina (VICE)
Deus Ex Machina unter WinVICE…

...und das Bild auf einem SX-64.
…und auf einem SX-64.

Ein Vergleich mit WinVICE und einem SX-64 ist zwar nicht ganz fair (beim SX-64 ist der Rahmen sehr dünn) aber er illustiert das Problem sehr gut.


Abschließend noch ein kleines Beispielprogramm, dass ich zum Testen geschrieben habe. Es öffnet im oberen Bereich komplett den Rahmen, zeigt alle 8 Sprites an und bewegt diese von links nach rechts über die gesamte Breite. Das BASIC bleibt verfügbar.

Im oberen Bereich wurde der Rahmen komplett entfernt.
Im oberen Bereich wurde der Rahmen komplett entfernt.

Wer es in Bewegung sehen möchte, kann sich das Beispiel als D64-Image herunterladen:


Schrott!!Naja...Geht so...Ganz gut...SUPER! (9 Bewertungen | Ø 4,56 von 5 | 91,11%)

Loading...


Zurück

Schreibe einen Kommentar

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

Protected by WP Anti Spam