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.

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:

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.

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.

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.

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.

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.

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.

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.

Jetzt sieht alles wie gewünscht aus:

Der Rasterzeileninterrupt in Aktion
Der Rasterzeileninterrupt in Aktion


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