Erstellt: 30. Juni 2013 (zuletzt geändert: 1. November 2021)

Landung 002

Keep watching the sky

C64 Studio

Nach einer etwas längeren Vorbereitungszeit, soll nun ein blauer Himmel über dem Canyon entstehen.
Da die Volour den Sinkflug von Space Commander Rick Razor bemerkt haben und in erhöhter Alarmbereitschaft sind haben sie auch noch ein Laser-Raster über den Canyon gelegt, so dass das Landungsschiff den Canyon nicht mehr verlassen kann!

ACHTUNG: Das Wissen aus den Beiträgen Interrupts, Ein erster NMI und besonders alles, was zu Der Rasterzeileninterrupt gehört, wird vorausgesetzt!!

Das „Rahmen“-Programm

Wer sich das Programm aus dem letzten Beitrag Landung 001 im ZIP-File einmal angesehen hat, wird das folgende Listing schon kennen. Hier gibt es nichts wirklich Neues, alles wurde so ähnlich schon beim Puzzle gezeigt.

;###########################################################################
;### Autor   : Jörn Kierstein                                            ###
;### Erstellt: 04.01.2014                                                ###
;### IDE     : C64 Studio 5.3                                            ###
;###                                                                     ###
;### (c) 2014, 2018 by www.retro-programming.de                          ###
;###########################################################################

!to "landung.prg",cbm

;*** Konstanten einbinden
!source "..\_Includes_\system_const.asm"
!source "..\_Includes_\love_const.asm"



!zone BASIC_Start
;*** Startadresse
*=$0801

;*** BASIC-Zeile
 !word main-2
 !word 2018
 !text $9E," 2062",$00,$00,$00

!zone Main
;*******************************************************************************
;*** Einstieg ins Assemblerprogramm
;*******************************************************************************
main
 jsr initLander                        ;Level starten 
 
gameloop
 jmp gameloop                          ;Hauptschleife

 
 
!zone initLander
;*******************************************************************************
;*** Leveldaten zurücksetzen
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: -
;*******************************************************************************
;*** ändert  : A, X, Y, SR
;*******************************************************************************
initLander
 jsr drawCanyon
 rts



!zone drawCanyon
;*******************************************************************************
;*** Den Canyon zeichnen
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: -
;*******************************************************************************
;*** ändert  : A, X, Y, SR
;*******************************************************************************
drawCanyon
 lda #COLOR_ORANGE
 sta VIC_BORDERCOLOR
 lda #COLOR_DARKGREY
 sta VIC_BACKGROUNDCOLOR
 ;*** Canyon anzeigen
 ldx #<screenCanyon                 ;LSB des Canyonbildes ins X-Register
 ldy #>screenCanyon                 ;MSB des Canyonbildes ins Y-Register
 jsr drawScreen                     ;Bild ausgeben
 rts                                ;zurück



;*******************************************************************************
;*** Allgemeine Funktionen einbinden
;*******************************************************************************
!source "..\_Includes_\love_lib.asm"



!zone Data
;*******************************************************************************
;*** Daten
;*******************************************************************************

;*** Der Canyon
screenCanyon
 !media "Canyon.charscreen",charcolor

Neu sind hier eigentlich nur die !source-Anweisungen, die aber auch schon in Landung 001 erwähnt wurden. Sie dienen nur dazu, das Programm etwas übersichtlicher zu halten, indem wir, wie bereits erwähnt, mehrfach verwendete Konstanten und Routinen auslagern.
Der Rest sollte eigentlich kein Problem darstellen. Es wird direkt zum Start nach initLander gesprungen, um die Leveldaten zurückzustellen. Aktuell wird nur der Canyon gezeichnet. Auch die Funktionen fürs Zeichnen wurden beim Puzzle bereits verwendet. Nach der Rückkehr vom Zeichnen, bleibt das Programm einfach in einer Endlos-Schleife bei gameloop hängen.

Den Raster-IRQ einrichten

Um die Rahmenfarbe unterschiedlich einzufärben, wird jetzt fast 1:1 das Flaggen-Beispiel verwendet. Der einzige Unterschied ist die Verteilung der Farben und dass eine Farbe blinkt.

Dazu werden drei Konstanten eingefügt:

RASTERIRQ_SKY       = $00           ;ab hier die Himmelfarbe
RASTERIRQ_LASER     = $30           ;        das 'Laser-Raster'
RASTERIRQ_CANYON    = $32           ;        die Canyon-Farbe

In diesen Konstanten steht jeweils, wo die Farbe für den Himmel, Laser und Canyon beginnen soll.

Danach wird die Initialisierung, wie unten gelb markiert, eingefügt.

main
 jsr initLander                     ;Level starten 

;*** Raster-IRQ einrichten
 sei                                ;IRQs sperren
 lda #<landerIRQ                    ;Routine unserer Rasten-Routine
 sta JT_IRQVECTOR                   ;im den RAM-Vector speichern
 lda #>landerIRQ                    ;auch das MSB
 sta JT_IRQVECTOR+1
 lda #%00000001                     ;Dem VIC-II mitteilen, dass er 
 sta VIC_IRQMASK                    ;Raster-IRQs auslösen soll
 lda #RASTERIRQ_SKY                 ;Erster Raster-IRQ für den Himmel
 sta VIC_RASTERROWPOS                         
 lda VIC_CONTROLREG1                ;Höchstes BIT für die Rasterzeile
 and #%01111111                     ;löschen
 sta VIC_CONTROLREG1
 cli                                ;IRQs wieder erlauben

gameloop
 jmp gameloop                       ;Hauptschleife

Die neuen Konstanten wurden zu system_const.asm hinzugefügt, das ja zu Beginn mittels !source eingebunden wurde.
Das Programm sperrt zunächst alle Interrupts und legt die Adresse der Interrupt-Routine landerIRQ im RAM-Vector JT_IRQVECTOR = $0314 / 15 ab. Dann wird die aktuelle Interruptmaske VIC_IRQMASK = $d01a so gesetzt, dass der VIC-II erstmal nur Raster-IRQs erzeugt. Anschließend muss der VIC-II noch wissen, wann er überhaupt einen Rasterinterrupt auslösen soll. Der Himmel beginnt bei Zeile 0 RASTERIRQ_SKY = $0, also diesen Wert ins Register für die Rasterzeile VIC_RASTERROWPOS = $d012 schreiben. Da die Rasterzeile aber neun Bits benötigt, zur Sicherheit auch noch dieses löschen. Es befindet sich in Bit 7 vom Kontrollregister 1 VIC_CONTROLREG1 = $d011. Schon ist die Initialisierung des Raster-IRQs abgeschlossen und die Interrupts können wieder freigegeben werden.

Der eigentliche Rasterinterrupt

Jetzt fehlt nur noch die landerIRQ-Routine. Diese soll IRQs vom VIC-II verarbeiten und andere an die System-Funktion weiterleiten.

!zone landerIRQ
;*******************************************************************************
;*** Interrupthandler
;***
;*** Rasterinterrupts werden hier verarbeitet,
;*** andere Interrupts werden an die System-Routine $EA31 weitergeleitet.
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: -
;*******************************************************************************
;*** ändert  : -
;*******************************************************************************
landerIRQ
 lda VIC_IRQSTATUS                  ;prüfen ob der IRQ vom VIC-II kam
 bmi doRasterIRQ                    ;falls ja zur Raster-Routine
 lda CIA1_IRQCONTROL                ;sonst CIA-IRQ bestätigen
 cli                                ;Interrupts erlauben
 jmp ROM_IRQFUNCTION                ;und zur System-Funktion springen

Die Funktion holt sich direkt den Interruptstatus VIC_IRQSTATUS = $d019 in den Akku. Falls der VIC-II einen Interrupt ausgelöst hat, dann ist dort das höchste Bit gesetzt, also kann mit einer Prüfung, ob der Wert, der in den Akku geholt wurde, negativ ist, unterschieden werden, ob die Routine zur System-Funktion springt oder den Interrupt selbst verarbeitet. Ist der Akku nicht negativ, dann werden die CIA1-Interrupts durch lesen des CIA1-Kontrollregisters CIA1_IRQCONTROL = $dc0d bestätigt, weitere Interrupts über cli erlaubt und schließlich zur ROM-Routine gesprungen ROM_IRQFUNCTION = $ea31.

doRasterIRQ
 sta VIC_IRQSTATUS                  ;VIC-IRQ bestätigen
 lda VIC_RASTERROWPOS               ;aktuelle Rasterzeile in den Akku
 bne .laser                         ;Wenn nicht 0, dann auf 'Laser' prüfen
 lda #COLOR_LIGHTBLUE               ;sonst hellblau in den Akku
 sta VIC_BORDERCOLOR                ;die Rahmenfarbe auf darauf setzen
 lda #RASTERIRQ_LASER               ;nächsten Raster-IRQ beim Laser
 sta VIC_RASTERROWPOS
 jmp .exit                          ;und IRQ verlassen

Wenn das höchste BIT in VIC_IRQSTATUS gesetzt war, landet das Programm bei doRasterIRQ. Aktuell findet keine weitere Unterscheidung statt, welcher IRQ es eigentlich war, da z. Zt. nur Raster-IRQs vom VIC-II möglich sind. Das Verarbeiten der VIC-Interrupts muss diesem mitgeteilt werden, dazu wird der aktuelle Register-Inhalt wieder nach VIC_IRQSTATUS zurückgeschrieben, dieser befindet sich ja noch im Akku. Anschließend wird die aktuelle Rasterzeile in den Akku geladen. Hier habe ich mir einen Vergleich mit cmp gespart, setzt man RASTERIRQ_SKY aber auf einen anderen Wert als 0, dann muss natürlich ein Vergleich her. So reicht es jetzt allerdings mit bne zu prüfen, ob der Rasterstrahl in Zeile 0 ist, wenn nicht, wird zur nächsten Prüfung nach .laser gesprungen. Sonst setzt das Programm die Rahmenfarbe auf hellblau und teilt dem VIC dann mit, dass der nächste Raster-IRQ beim erreichen der Zeile in RASTERIRQ_LASER gewünscht ist. Das wars dann und es geht zum .exit.

.laser
 cmp #RASTERIRQ_LASER               ;Aktuelle Rasterzeile=Beginn des Lasers?
 bne .canyon                        ;falls nicht, weiter zum Canyon
 inc LaserFlash                     ;'Farbe' fürs Laser-Raster erhöhen,
 lda LaserFlash                     ;in den Akku holen
 sta VIC_BORDERCOLOR                ;und Rahmenfarbe damit setzen
 lda #RASTERIRQ_CANYON              ;nächsten Raster-IRQ beim Canyon
 sta VIC_RASTERROWPOS
 jmp .exit                          ;IRQ verlassen

Wenn der Strahl nicht in der Startzeile für den Himmel ist, dann landet man bei .laser. Hier wird geprüft, ob der Rasterstrahl in der Zeile für die Lasersperre RASTERIRQ_LASER ist. Falls nicht, geht es zum letzten Abschnitt nach .canyon, sonst läuft fast alles wie eben ab. Aber da die Lasersperre gefährlich wirken soll, wird sie zum Blinken gebracht. Nun klappt es natürlich nicht, einfach $d020 zu erhöhen. Da ab Zeile 0 ja die Rahmenfarbe immer auf hellblau gesetzt wird, würde sich durch ein inc VICBORDERCOLOR die Farbe immer nur auf grau (14 für hellblau +1 = 15 für hellgrau) ändern. Daher wird hier eine Variable im Speicher LaserFlash laufend erhöht und als Rahmenfarbe verwendet. Dann wird noch dem VIC die Zeile für den letzten Raster-IRQ RASTERIRQ_CANYON mitgeteilt und zum .exit gesprungen.

.canyon      
 lda #COLOR_ORANGE                  ;hier beginnt auf jeden Fall der Canyon
 sta VIC_BORDERCOLOR                ;also Canyon-Farbe in den Rahmen
 lda #RASTERIRQ_SKY                 ;und nächsten Raster-IRQ für den Himmel
 sta VIC_RASTERROWPOS

Traf die Position des Rasterstrahls bei keiner der vorigen Prüfungen zu, dann geht es bei .canyon weiter. Hier wird nun einfach die Rahmenfarbe, auf die des Canyons gesetzt und für den nächsten Raster-IRQ wieder der Beginn des Himmels eingetragen. Danach läuft das Programm direkt zu .exit weiter.

.exit
 pla                                ;Register zurückholen
 tay                                ;Y
 pla
 tax                                ;X
 pla                                ;Akku

 rti                                ;IRQ verlassen

Beim EXIT werden einfach die Register wieder vom Stack geholt und der Interrupt mit rti verlassen.

Die Hilfsvariable LaserFlash für das Blinken des Lasers, wurde weiter unten, bei Data eingefügt.

LaserFlash
 !byte $00                          ;Rahmenfarbe fürs Laser-Raster

Jetzt sieht alles wie gewünscht aus:

Der Rasterzeileninterrupt in Aktion
Der Rasterzeileninterrupt in Aktion
;###########################################################################
;### Autor   : Jörn Kierstein                                            ###
;### Erstellt: 04.01.2014                                                ###
;### IDE     : C64 Studio 5.3                                            ###
;###                                                                     ###
;### (c) 2014, 2018 by www.retro-programming.de                          ###
;###########################################################################

!to "landung.prg",cbm

;*** Konstanten einbinden
!source "..\_Includes_\system_const.asm"
!source "..\_Includes_\love_const.asm"

RASTERIRQ_SKY       = $00           ;ab hier die Himmelfarbe
RASTERIRQ_LASER     = $30           ;        das 'Laser-Raster'
RASTERIRQ_CANYON    = $32           ;        die Canyon-Farbe



!zone BASIC_Start
;*** Startadresse
*=$0801

;*** BASIC-Zeile
 !word main-2
 !word 2018
 !text $9E," 2062",$00,$00,$00

!zone Main
;*******************************************************************************
;*** Einstieg ins Assemblerprogramm
;*******************************************************************************
main
 jsr initLander                     ;Level starten 

;*** Raster-IRQ einrichten
 sei                                ;IRQs sperren
 lda #<landerIRQ                    ;Routine unserer Rasten-Routine
 sta JT_IRQVECTOR                   ;im den RAM-Vector speichern
 lda #>landerIRQ                    ;auch das MSB
 sta JT_IRQVECTOR+1
 lda VIC_IRQMASK                    ;Raster-IRQs auslösen soll
 ora #%00000001                     ;Dem VIC-II mitteilen, dass er 
 sta VIC_IRQMASK                    ;Raster-IRQs auslösen soll
 lda #RASTERIRQ_SKY                 ;Erster Raster-IRQ für den Himmel
 sta VIC_RASTERROWPOS                         
 lda VIC_CONTROLREG1                ;Höchstes BIT für die Rasterzeile
 and #%01111111                     ;löschen
 sta VIC_CONTROLREG1
 cli                                ;IRQs wieder erlauben

gameloop
 jmp gameloop                       ;Hauptschleife



!zone initLander
;*******************************************************************************
;*** Leveldaten zurücksetzen
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: -
;*******************************************************************************
;*** ändert  : A, X, Y, SR
;*******************************************************************************
initLander
 jsr drawCanyon
 rts



!zone drawCanyon
;*******************************************************************************
;*** Den Canyon zeichnen
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: -
;*******************************************************************************
;*** ändert  : A, X, Y, SR
;*******************************************************************************
drawCanyon
 lda #COLOR_ORANGE
 sta VIC_BORDERCOLOR
 lda #COLOR_DARKGREY
 sta VIC_BACKGROUNDCOLOR
 ;*** Canyon anzeigen
 ldx #<screenCanyon                 ;LSB des Canyonbildes ins X-Register
 ldy #>screenCanyon                 ;MSB des Canyonbildes ins Y-Register
 jsr drawScreen                     ;Bild ausgeben
 rts                                ;zurück



!zone landerIRQ
;*******************************************************************************
;*** Interrupthandler
;***
;*** Rasterinterrupts werden hier verarbeitet,
;*** andere Interrupts werden an die System-Routine $EA31 weitergeleitet.
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: -
;*******************************************************************************
;*** ändert  : -
;*******************************************************************************
landerIRQ
 lda VIC_IRQSTATUS                  ;prüfen ob der IRQ vom VIC-II kam
 bmi doRasterIRQ                    ;falls ja zur Raster-Routine
 lda CIA1_IRQCONTROL                ;sonst CIA-IRQ bestätigen
 cli                                ;Interrupts erlauben
 jmp ROM_IRQFUNCTION                ;und zur System-Funktion springen
doRasterIRQ
 sta VIC_IRQSTATUS                  ;VIC-IRQ bestätigen
 lda VIC_RASTERROWPOS               ;aktuelle Rasterzeile in den Akku
 bne .laser                         ;Wenn nicht 0, dann auf 'Laser' prüfen
 lda #COLOR_LIGHTBLUE               ;sonst hellblau in den Akku
 sta VIC_BORDERCOLOR                ;die Rahmenfarbe auf darauf setzen
 lda #RASTERIRQ_LASER               ;nächsten Raster-IRQ beim Laser
 sta VIC_RASTERROWPOS                
 jmp .exit                          ;und IRQ verlassen
.laser
 cmp #RASTERIRQ_LASER               ;Aktuelle Rasterzeile=Beginn des Lasers?
 bne .canyon                        ;falls nicht, weiter zum Canyon
 inc LaserFlash                     ;'Farbe' fürs Laser-Raster erhöhen,
 lda LaserFlash                     ;in den Akku holen
 sta VIC_BORDERCOLOR                ;und Rahmenfarbe damit setzen
 lda #RASTERIRQ_CANYON              ;nächsten Raster-IRQ beim Canyon
 sta VIC_RASTERROWPOS
 jmp .exit                          ;IRQ verlassen
.canyon      
 lda #COLOR_ORANGE                  ;hier beginnt auf jeden Fall der Canyon
 sta VIC_BORDERCOLOR                ;also Canyon-Farbe in den Rahmen
 lda #RASTERIRQ_SKY                 ;und nächsten Raster-IRQ für den Himmel
 sta VIC_RASTERROWPOS
.exit
 pla                                ;Register zurückholen
 tay                                ;Y
 pla
 tax                                ;X
 pla                                ;Akku

 rti                                ;IRQ verlassen



;*******************************************************************************
;*** Allgemeine Funktionen einbinden
;*******************************************************************************
!source "..\_Includes_\love_lib.asm"



!zone Data
;*******************************************************************************
;*** Daten
;*******************************************************************************
LaserFlash
 !byte $00                          ;Rahmenfarbe fürs Laser-Raster

;*** Der Canyon
screenCanyon
 !media "Canyon.charscreen",charcolor

Oops, da war ich doch etwas redseliger als geplant. Beim nächsten Mal geht es dann wieder um Sprites. Das Landungsschiff wird in die Szene aufgenommen.


Schrott!!Naja...Geht so...Ganz gut...SUPER! (3 Bewertungen | Ø 4,33 von 5 | 86,67%)

Loading...


ZurückWeiter

Schreibe einen Kommentar

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

Protected by WP Anti Spam