Erstellt: 8. Dezember 2013 (zuletzt geändert: 2. Januar 2022)

Weihnachten 2013

Es weihnachtet…

C64 Studio, AMCE & TASM

Da wir heute den 2. Advent haben und ich mich langsam in die Winterpause verabschiede, wollen wir noch kurz für etwas weihnachtliche Stimmung auf dem C64 sorgen.

Schneefall auf dem C64

Wir wollen es also auf dem C64 schneien lassen. Für die Schneeflocken verwenden wir ein Sprite, das in X- & Y-Richtung verdoppelt wird. Also ein neues Projekt erstellt und los gehts…

RASTER          = $30               ;Hier den 1. Raster-IRQ auslösen
WAITINIT        = $0a               ;Schneefallgeschwindigkeit

;*** Startadresse 
*=$0801
;*** BASIC-Zeile: 2013 SYS 2064:NEW
 !word main-2, 2013 
 !byte $9e
 !text " 2064:"
 !byte $a2,$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 #%01111111                     ;Timer-IRQs abschalten
 sta $dc0d
 lda $dc0d                          ;zur Sicherheit bestätigen

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

 jsr initSprites                    ;Sprites vorbereitsn

 lda #$0d                           ;hellgrün
 sta $d020                          ;als Rahmenfarbe

 lda #$05                           ;grün
 sta $d021                          ;für den Hintergrund

 jsr setCharColor                   ;Zeichenfarbe auf Rot setzen

 cli                                ;Interrupts erlauben
 rts                                ;zurück zum BASIC

Der Anfang beinhaltet wieder die Einrichtung eines Rasterzeilen-Interrupts, die von uns gewünschte Rasterzeile wird über die Konstante RASTER bestimmt. Außerdem initialisieren wir die Sprites jsr initSprites und sorgen mit roter Zeichenfarbe jsr setCharColor und grünem Hintergrund $d021 sowie Rahmen $d020 für etwas Weihnachtsflair.

Sprites initialisieren

initSprites
 lda #sprite/64                     ;Nr. für das Sprite ermitteln
 sta $07f8                          ;pro 'Zeile' 7 Sprites, immer dasselbe
 sta $07f9
 sta $07fa
 sta $07fb
 sta $07fc
 sta $07fd
 sta $07fe

 lda #$01                           ;weiß für die 7 Sprites
 sta $d027
 sta $d028
 sta $d029
 sta $d02a
 sta $d02b
 sta $d02c
 sta $d02d

XPOS=24
 lda #XPOS                          ;X-Position
 sta $d000
 lda #XPOS+48                  
 sta $d002
 lda #XPOS+(2*48)
 sta $d004
 lda #XPOS+(3*48)
 sta $d006
 lda #XPOS+(4*48)
 sta $d008
XPOS2=(XPOS+(5*48))-256             ;neue X-Posi ab Position 256 (wg. max. X-BIT)
 lda #XPOS2                 
 sta $d00a
 lda #XPOS2+48                
 sta $d00c
 
 lda #%01100000                     ;max. X für Sprite 5&6 setzen
 sta $d010
 lda #$00
 sta $d01c                          ;alle einfarbig
 sta $d01b                          ;und vor der Hintergrundgrafik
 lda #%01111111
 sta $d01d                          ;doppelte Breite
 sta $d017                          ;und Höhe
 sta $d015                          ;sichtbar schalten
 rts                                ;zurück zum Aufrufer

Hier bereiten wir unsere Sprites vor. Um die gesamte Anzeige, die bekanntlich 320 x 200 Punkte aufweist, mit Sprites zu füllen, benötigen wir, bei doppelter Größe, sieben Sprites in der X-Richtung (48 * 7 = 336) und fünf in Y-Richtung (5 * 42 = 210). Sorgen wir also dafür, dass die Sprites, für die jeweilige Zeile, korrekt positioniert und eingerichtet werden.

Mit lda #sprite/64 berechnen wir die Nr. des 64-Byte-Blocks für unser Sprite. Da wir für alle sieben dasselbe Sprite verwenden, schreiben wir diese Adresse für die Sprites 0 bis 6 in die Sprite-Pointer. Dann setzten wir die Farbe dieser Sprites auf weiß und setzen auch noch die X-Position auf die richtigen Werte. Die Sprites beginnen links mit Sprite-0 ab dem Pixel 24 und dann folgt alle 48 Bildpunkte das nächste Sprite. Beachten müssen wir natürlich, dass die letzten beiden Sprites an einer X-Position über 255 beginnen.

Abschließend sorgen wir noch für die Anzeige von einfarbigen Sprites, die vor dem Hintergrund erscheinen und in X- & Y-Richtung verdoppelt sind.

Da die Sprites später nur noch auf der Y-Achse verschoben werden, reicht es diese Funktion einmalig beim Programmstart aufzurufen.

Zeichenfarbe setzen

setCharColor
 ldx #$00                           ;256 Schleifendurchläufe
 lda #$02                           ;Zeichenfarbe: rot
nextColor
 sta $d800,X                        ;1. Page im Color-RAM
 sta $d900,X                        ;2.
 sta $da00,X                        ;3.
 sta $dB00-24,X                     ;4. Page (24 Zeichen weniger)
 dex
 bne nextColor
 sta $286                           ;auch die aktuelle Zeichenfarbe auf rot
 rts                                ;zurück zum Aufrufer

Um die Zeichenfarbe auf rot zu setzen, schreiben wir einfach ins COLOR-RAM für jedes Zeichen den Wert für rot. Die Schleife solltet ihr vom BS-Löschen kennen, nur dass wir hier eben ins Farb-RAM schreiben. Damit auch neue Zeichen rot erscheinen, schreiben wir den Wert abschließend auch nach $286, hier merkt sich das Betriebssystem die aktuelle Zeichenfarbe.

Der Interrupt

myIRQ
 ldx RowCnt                         ;aktuelle Schnee-Zeile ins X-Register
 lda YPos,X                         ;neue Y-Position
 clc                                ;Sprites etwas nach dem IRQ-Anzeigen
 adc #$02
 sta $d001                          ;für die 7 Sprites
 sta $d003
 sta $d005
 sta $d007
 sta $d009
 sta $d00b
 sta $d00d
 lda #%00000001                     ;IRQ bestätigen
 sta $d019
 cpx #$04                           ;wurden alle Sprite-Zeilen dargestellt?
 beq Exit                           ;falls ja -> @exit:
 inx                                ;sonst erhöhen
 stx RowCnt                         ;und speicheren
 lda YPos,X                         ;nächste IRQ-Zeile holen
 sta $d012                          ;Zeile für nächsten Rasterinterrupt
 pla                                ;dann Register wiederherstellen
 tay
 pla
 tax
 pla
 rti                                ;und IRQ verlassen

Unser Rasterzeilen-Interrupt holt sich zunächst die aktuelle Zeile ins X-Register. Dann werden alle sieben Sprites auf die passende Y-Position gesetzt. Die IRQ-Zeile haben wir der Einfachheit in einer Tabelle bei YPos abgelegt. Für die Sprites addieren wir noch einen kleinen Offset von zwei Zeilen. Die ermittelte Position wird natürlich für alle Sprites gesetzt. Dann bestätigen wir den Raster-IRQ und prüfen, ob dies die letzte Spritezeile war. Falls ja geht es bei Exit weiter, sonst erhöhen wir RowCnt, holen die nächste Rasterzeile und verlassen den Interrupt. Wir lösen also für jede Spritezeile alle 42 Zeilen einen neuen Interrupt aus.

exit
 lda #$00                           ;alle Sprite-Zeilen wurden dargestellt
 sta RowCnt                         ;also auf 0 zurücksetzen
 lda #RASTER
 sta $d012                          ;Zeile für nächsten Rasterinterrupt

Wurden alle Spritezeilen dargestellt, dann beginnen wir wieder von vorne. Dazu wird RowCnt zurück auf 0 gestellt und der Rasterzeilen-Interrupt auf die erste Zeile laut unserer Konstanten RASTER gesetzt.

Die Schneeflocken sollen sich natürlich noch etwas bewegen, dazu kopieren wir die Spritedaten einfach, wie beim Color-Cycling zyklisch. Um die Animation zu timen, verwenden wir einen weiteren Zähler Wait.

 dec Wait                           ;Warteschleife verringern
 bne toSystem                       ;falls nicht abgelaufen -> toSystem
 lda #WAITINIT                      ;sonst Startwert 
 sta Wait                           ;zurücksetzen
 ldy Sprite+63                      ;letztes BYTE des Sprites merken
 ldx #63                            ;63 BYTES verschieben
nextByte
 lda Sprite-1,X                     ;BYTE holen
 sta Sprite,X                       ;und kopieren
 dex                                ;Schleifenzähler verringern
 bne nextByte                       ;solange größer 0 -> nextByte
 sty Sprite                         ;sonst, letztes BYTE an die erste Stelle
toSystem
 jmp $ea31                          ;zur System-Routine

Wir verringern Wait also einfach. Ist der Wert größer null, dann verlassen wir den Interrupt bei toSystem direkt Richtung System-Routine. Wenn der Zähler auf 0 geht, dann setzen wir ihn wieder auf den Anfangswert, kopieren die Spritedaten und laufen ebenfalls zum Sprung zur System-Routine durch.

Variablen

Am Ende folgen natürlich noch unsere Variablen und die Spritedaten.

Wait
 !byte WAITINIT                     ;Wartezeit für die Schneegeschwindigkeit

YPos                                ;Sprite-Y Positionen
 !byte RASTER,RASTER+42
 !byte RASTER+84,RASTER+126
 !byte RASTER+168 

RowCnt
 !byte 0                            ;aktuelle Sprite-Zeile

!align 63,0
Sprite                              ;das 'Schnee'-Sprite
 !byte  $00,$00,$00
 !byte  $40,$00,$00
 !byte  $00,$00,$00
 !byte  $00,$00,$00
 !byte  $00,$80,$10
 !byte  $00,$00,$00
 !byte  $00,$00,$00
 !byte  $00,$00,$00
 !byte  $00,$01,$00
 !byte  $00,$00,$00
 !byte  $00,$00,$00
 !byte  $08,$00,$00
 !byte  $00,$20,$00
 !byte  $00,$00,$00
 !byte  $00,$00,$00
 !byte  $00,$00,$40
 !byte  $00,$00,$00
 !byte  $00,$08,$00
 !byte  $00,$00,$00
 !byte  $10,$00,$00
 !byte  $00,$00,$04
 !byte  $01

Hier findet ihr auch unsere Tabelle mit den Y-Positionen (ok, eigentlich ist es die Rasterzeile für den Interrupt).

Schneeflöckchen, Weißröckchen…

Frohe Weihnachten 2013
Frohe Weihnachten 2013

Ich hoffe euch ist aufgefallen, dass wir hier 35 Sprites gleichzeitig verwenden.

Um die Stimmung noch etwas zu steigern findet ihr im Download eine Fassung mit Musik. Dazu sind, neben dem Musikstück, nur zwei weitere Befehle notwendig.


Ich mache nun etwas Pause und hoffe das erste Jahr auf dieser Seite hat euch gefallen und ihr besucht sie auch 2014 wieder.

Frohe Weihnachten und einen guten Rutsch ins neue Jahr,
Jörn


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

Loading...


Zurück

Schreibe einen Kommentar

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

Protected by WP Anti Spam