DT 85 15
From C64 Diskmag Wiki
Hallo liebe DT-Leser,
_______________________
es ist mal wieder soweit, ein neues Pro-
gramm erwartet Euch in der DT Ass-Ru-
brik. Wie beim ersten Teil geht es auch
heute noch einmal um das Thema Lauf-
schrift. Nur unterscheidet sich die
Technik, die ich diesmal verwendet habe,
von der aus dem ersten Teil nicht uner-
heblich. Heute will ich Euch mal zeigen,
wie man eine Laufschrift in einem Sprite
verarbeiten kann. Das Thema lautet somit
"SPRITE-SCROLLER"
"SPRITE-SCROLLER"
Die Technik, die dahinter steckt, ist eigentlich trivial, vorausgesetzt, man weiß, wie ein Sprite aufgebaut ist und wie man Sprites anzeigen und manipulie- ren kann. Eingefleischte Basicprogram- mierer werden hier keine Schwierigkeiten haben. Dieser Effekt lässt sich jedoch nur ra- tional in Maschinensprache realisieren, Basic ist dafür einfach zu langsam. Auch diesmal läuft die Laufschrift im IRQ ab. Es ist ratsam, sich das Programm vorher mal anzusehen, damit Ihr auch wisst, wo- von ich hier rede. ;)
Gut, die Laufschrift läuft in einem Sprite bzw. "durch" mehrere Sprites. Es ist also nicht so, dass jedes Sprite ei- nen Buchstaben darstellt und der Lauf- schrift-Text einfach durch diese durch- gerollt wird (das ist eine weitere Mög- lichkeit für eine Laufschrift). Hier be- nutzen wir einen normalen 1x1-Zeichen- satz, in diesem Fall den des C64, den ROM-Zeichensatz, den wir dann von rechts nach links durch 8 Sprites durchrollen lassen. Ein Sprite besteht aus 64 Bytes. Füllt man ein Sprite mit z.B. dem Wert 255, so geschieht das von links nach rechts (und
nicht wie im Hires-Modus von oben nach
unten). Um nun z.B. den Buchstaben "A"
(Wert $01) in ein Sprite zu übertragen,
so geschieht dies folgendermaßen:
Sprite liegt ab: $2000
Buchstabe A ab: $3000 (nur Beispiele)
ldy #$00
ldx #$00
a1 lda $3000,y
sta $2000,x
inx
inx
inx
iny
cpy #$08
bne a1
rts
Hier seht Ihr, dass man jedes Byte des
Buchstabens in jede dritte Speicherstel-
le des Sprites schreiben muss, um den
Buchstaben ordentlich im Sprite darzu-
stellen. Im normalen Modus sind nur 8
Sprites erlaubt, also verwenden wir auch
alle für die Laufschrift.
In jedes Sprite passen jeweils 3 Buch-
staben.
Diese befinden sich im oberen Bereich
der Sprites, den ersten 24 Bytes.
Sprite1 Sprite2 Sprite3 Sprite4 Sprite5 ABC DEF GHI JKL MNO Sprite6 Sprite7 Sprite8 PQR STU VWX Der Laufschrifttext würde dann hier so aussehen: ABCDEFGHIJKLMNOPQRSTUVWX Die Laufschrift kann somit nur aus max. 24 sichtbaren Zeichen bestehen. Der Text an sich kann so lang sein wie man ihn braucht. Dazu später mehr im Code.
Das Prinzip dahinter sollte jetzt ei- gentlich klar sein, zumindest wie die Zeichen in den Sprites erscheinen sol- len. Die Technik, die dahinter steckt, ist simpel: Die Zeichen bzw. die Bits der Zeichen werden mit dem Befehl ASL von rechts nach links einfach durch die Sprites ge- rollt. Dabei muss auf das Carry-Flag ge- achtet werden, damit die Bits auch or- dentlich transportiert werden. Dazu nun im Programm mehr, dabei werde ich jedoch nur im Kern des Programms etwas ausführ- licher:
*= $0810
lda #1
sta $d011
lda #0
sta $d020
sta $d021
lda #15
sta $0286
lda #$93
jsr $ffd2
lda #26
sta $d018
lda #$08
jsr $ffd2
> Bildschirmeinstellungen.
ldy #$00
a1 lda screen,y
sta $0400,y
lda screen+256,y
sta $0500,y
lda screen+512,y
sta $0600,y
lda screen+768,y
sta $0700,y
iny
bne a1
> Der Bildschirm wird mit den Daten aus
> dem Label "Screen" gefüllt.
ldy #$00
lda #11
a2 sta $d800+(5*40)+9,y
sta $d800+(6*40)+9,y
sta $d800+(7*40)+9,y
iny
cpy #$16
bne a2
> Das "Digital Talk"-Logo wird auf dem
> Bildschirm positioniert.
ldy #$00
lda #$ff
a3 sta $2ff8,y
iny
cpy #$08
bne a3
> Der Zeichensatz für das Logo steht ab
> $2800 (s.u.). Hier wird ein Zeichen
> gefüllt und zwar das letzte Zeichen
> des Zeichensatzes.
sei
lda #$33
sta $01
ldy #$00
a4 lda $d000,y
sta $3000,y
lda $d100,y
sta $3100,y
lda $d200,y
sta $3200,y
lda $d300,y
sta $3300,y
lda #0
sta $2000,y
sta $2100,y
iny
bne a4
lda #$37
sta $01
cli
> Der ROM-Zeichensatz respektive ein
> Teil davon wird nach $3000 kopiert.
> Dieser wird für die Laufschrift
> benötigt. Die Sprites stehen ab $2000,
> dieser Bereich wird mit #0 gefüllt.
lda #$00
sta $57
sta $58
sta $5a
sta $5b
sta $5c
> Speicherstellen und Zähler werden
> freigemacht.
lda #255
sta $d000+21
ldy #$00
ldx #128
a5 txa
sta 2040,y
lda #15
sta $d000+39,y
inx
iny
cpy #$08
bne a5
ldx #87
stx $d000
ldx #87+(1*24)
stx $d002
ldx #87+(2*24)
stx $d004
ldx #87+(3*24)
stx $d006
ldx #87+(4*24)
stx $d008
ldx #87+(5*24)
stx $d00a
ldx #87+(6*24)
stx $d00c
ldx #87+(7*24)
stx $d00e
> Bis hier werden die Sprites
> eingeschaltet und auf dem Bildschirm
> positioniert. Auch wird die Farbe auf
> Hellgrau gesetzt ($0f = #15).
jsr irq
jmp *
> Der IRQ wird angesprungen, danach wird
> mit JMP * das Programm quasi
> angehalten. Alles, was man dann sieht,
> läuft ausschließlich im IRQ ab.
irq sei
lda #$81
sta $d01a
lda #$7f
sta $dc0d
lda #$00
sta $d012
ldx #<irq1
ldy #>irq1
stx $0314
sty $0315
cli
lda #27
sta $d011
rts
irq1 asl $d019
> Hier die bekannten Einstellungen für
> den IRQ. Ich hoffe, da nichts mehr
> erklären zu müssen.
jsr sprmove
> Hier wird für die vertikale Bewegung
> des Sprite-Scrollers eine kleine
> Routine angesprungen, die für die
> nette Hüpfbewegung des Scrollers
> verantwortlich ist. Dieser Sprite-
> Sinus wurde mir von dflame zur
> Verfügung gestellt. Herzlichen Dank
> nochmal!! :)
irqq lda $58
bne irq2
ldy #$30
ldx #$00
stx $fa
sty $fb
inc $58
lda #$00
sta $02
irq02 ldy $57
lda txt,y
bne irq01
lda #$00
sta $57
jmp irq02
irq01 inc $57
asl
rol $02
asl
rol $02
asl
rol $02
clc
adc $fa
sta $fa
lda $02
adc $fb
sta $fb
ldy #$00
irq0 lda ($fa),y
sta $02c0,y
iny
cpy #$08
bne irq0
> Jetzt gehts ins Eingemachte. Hier
> werden die Zeichen berechnet und
> zwischengespeichert. Der Text der > Laufschrift steht ab Label "txt". > Von dort wird ein Zeichen gelesen und > danach berechnet, wo dieses Zeichen > sich in unserem zuvor kopierten ROM- > Zeichensatz befindet. Dafür muss man > den Wert des Zeichens * 8 nehmen und > den Wert zu $3000 rechnen ($fa/$fb). > Am Ende wird das aktuelle Zeichen nach > $02c0-$02c7 geschrieben. Dort kann es > dann gleich verändert werden. Diese > Zwischenspeicherung ist notwendig, > weil wir ja sonst nach jedem Zeichen > den ROM-Zeichensatz neu kopieren > müssten, weil jedes Zeichen durch den > ASL-Befehl gleich geleert wird.
> Der Wert in $5a wird übrigens von 0
> auf 1 gestellt, weil ja nicht nach
> jedem Durchgang ein neues Zeichen
> berechnet werden darf, sondern erst,
> wenn alle 8 Bits eines Zeichens
> abgearbeitet wurden.
irq2 ldy #$00
ldx #$00
irq4 asl $02c0,x
bcc irq3
lda #$01
clc
adc 8642,y
sta 8642,y
irq3 iny
iny
iny
inx
cpx #$08
bne irq4
> Nun werden die ersten 8 Bits des
> aktuellen Zeichens per ASL-Befehl in
> die Sprites übertragen. Genauer gesagt
> in Sprite Nr. 8, das ganz rechts
> steht. Dieses Sprite steht ab Adresse
> 8640 (Hex $21c0, ich habe ausnahms-
> weise mal mit dezimalen Adressen
> gearbeitet). In Adresse 8642 beginnt
> somit das erste Zeichen. Dort werden
> die Bits einfach hinzuaddiert.
inc $5a
lda $5a
cmp #$08
bne irq5
lda #$00
sta $58
sta $5a
> $5a dient als Zähler für die Anzahl
> der Durchgänge für ein Zeichen. Steht
> dieser auf 8, so wurden alle 8 Bits
> des aktuellen Zeichens verarbeitet und
> beim nächsten Durchgang wird das
> nächste Zeichen aus dem Laufschrift-
> text genommen.
> Was nun kommt (von Label "irq5" und
> "irq27"), sollte klar sein. Jede
> Stelle in den Sprites, von links nach
> rechts gesehen, in die ein Zeichen
> passt, wird per ASL-Befehl um ein Bit
> nach links gerückt. Dabei wird jeweils
> mit dem BCC-Befehl auf ein belegtes
> Bit reagiert und dieses auf die Stelle
> davor hinzuaddiert. Dies bewirkt am
> Ende ein Durchrollen der jeweiligen
> Bits und somit einen weichen Scroller.
irq5 ldy #$00
ldx #$00
irq6 asl 8192,x
> 8192-8199 wird NUR nach links
> geschoben. Hierbei ist es nicht
> notwendig, auf die Bits zu achten,
> weil hier der Scroller eh zu Ende ist
> und die Bits einfach links
> verschwinden können.
asl 8193,x
bcc irq7
lda #$01
clc
adc 8192,x
sta 8192,x
irq7 asl 8194,x
bcc irq8
lda #$01
clc
adc 8193,x
sta 8193,x
irq8 asl 8256,x
bcc irq9
lda #$01
clc
adc 8194,x
sta 8194,x
irq9 asl 8257,x
bcc irq10
lda #$01
clc
adc 8256,x
sta 8256,x
irq10 asl 8258,x
bcc irq11
lda #$01
clc
adc 8257,x
sta 8257,x
irq11 asl 8320,x
bcc irq12
lda #$01
clc
adc 8258,x
sta 8258,x
irq12 asl 8321,x
bcc irq13
lda #$01
clc
adc 8320,x
sta 8320,x
irq13 asl 8322,x
bcc irq14
lda #$01
clc
adc 8321,x
sta 8321,x
irq14 asl 8384,x
bcc irq15
lda #$01
clc
adc 8322,x
sta 8322,x
irq15 asl 8385,x
bcc irq16
lda #$01
clc
adc 8384,x
sta 8384,x
irq16 asl 8386,x
bcc irq17
lda #$01
clc
adc 8385,x
sta 8385,x
irq17 asl 8448,x
bcc irq18
lda #$01
clc
adc 8386,x
sta 8386,x
irq18 asl 8449,x
bcc irq188
lda #$01
clc
adc 8448,x
sta 8448,x
irq188 asl 8450,x
bcc irq19
lda #$01
clc
adc 8449,x
sta 8449,x
irq19 asl 8512,x
bcc irq20
lda #$01
clc
adc 8450,x
sta 8450,x
irq20 asl 8513,x
bcc irq21
lda #$01
clc
adc 8512,x
sta 8512,x
irq21 asl 8514,x
bcc irq22
lda #$01
clc
adc 8513,x
sta 8513,x
irq22 asl 8576,x
bcc irq23
lda #$01
clc
adc 8514,x
sta 8514,x
irq23 asl 8577,x
bcc irq24
lda #$01
clc
adc 8576,x
sta 8576,x
irq24 asl 8578,x
bcc irq255
lda #$01
clc
adc 8577,x
sta 8577,x
irq255 asl 8640,x
bcc irq25
lda #$01
clc
adc 8578,x
sta 8578,x
irq25 asl 8641,x
bcc irq26
lda #$01
clc
adc 8640,x
sta 8640,x
irq26 asl 8642,x
bcc irq27
lda #$01
clc
adc 8641,x
sta 8641,x
irq27 inx
inx
inx
iny
cpy #$08
beq irqend
jmp irq6
> Diese ganze Prozedur muss natürlich
> 8 mal durchlaufen werden, für jedes
> Byte eines Zeichens, das aus 8 Bytes
> besteht.
irqend jmp $ea31
> Ende der Irq-Routine.
<++++++++++++++++++++++++++++++++++++++>
sprmove lda #$5c
ldy #$00
ldx #$00
spr1 sta $d001,y
iny
iny
inx
cpx #$08
bne spr1
spr2 ldx #$9f
lda sinus,x
cmp #$3c
bne spr3
lda #$ff
sta $d01b
spr3 cmp #$80
bne spr4
lda #$00
sta $d01b
spr4 lda sinus,x
clc
adc #$05
sta sprmove+1
inc spr2+1
rts
> Dies ist die kleine Routine, die den
> Scroller von oben nach unten "hüpfen"
> lässt. Unter anderem sorgt diese
> dafür, dass sich der Sprite-Scroller
> abwechselnd hinter bzw. vor dem
> Digital Talk-Logo befindet. Dies wird
> in der Adresse $d01b kontrolliert.
<-------------------------------------->
txt .byte $03,$08,$09,$03,$0f,$20
.byte $0f,$06,$20,$03,$09,$16
.byte $09,$14,$01,$13,$20,$00
> Hier steht der kurze Laufschrifttext.
> Dieser kann hier nur max. 255 Zeichen
> lang sein. Man kann das Programm
> jedoch so modifizieren, dass der Text
> auch länger sein kann. Vielleicht eine
> kleine Aufgabe für Euch??? ;-)
sinus .byte $46,$45,$45,$44,$44,$43
.byte $42,$41,$40,$3f,$3e,$3d
.byte $3d,$3c,$3c,$3c,$3c,$3d
usw.
> Hier stehen die Werte für die Sinus-
> Routine.
<-------------------------------------->
logo .byte $01,$02,$03,$04,$05,$06
.byte $03,$07,$08,$09,$0a,$03
.byte $0b,$00,$0c,$0d,$0e,$0f
usw.
> Hier stehen die Werte für das Logo.
<-------------------------------------->
screen .byte $ff,$ff,$ff,$ff,$ff,$ff
.byte $ff,$ff,$ff,$ff,$ff,$ff
.byte $ff,$ff,$ff,$ff,$ff,$ff
usw.
> Hier stehen die Werte für den
> Bildschirm.
<-------------------------------------->
*= $2800
.byte $00,$00,$00,$00,$00,$00
.byte $00,$00,$00,$7f,$7f,$7f
.byte $7f,$7f,$7d,$7c,$00,$00
usw.
> Ab $2800 steht der Zeichensatz für das
> Logo.
Das war's dann soweit.
Solltet Ihr Fragen, Wünsche oder Anre-
gungen haben, dann schreibt doch einfach
an die DT-Redaktion.
Auch hoffe ich, dass auch dieser Ass-
Kurs ein wenig interessant für Euch war.
Dann bis zum nächsten Mal...
Euer
XXXXXXXXXXXXXXXXXX
CHICO/CIVITAS
_