Irgendwie hast Du mich neugierig gemacht ein Scrolling für 320x192 Punkte hinzu bekommen
7,5k zu scrollen, kann man nur über Displaylist-Manipulation hinbekommen, aber wie?
1 Liste Rotieren lassen, wie in meinem Beispiel für den Textmodus Gr. 0 ? Das wären fast 600 Bytes, die ständig 1/50s rotieren...
In Endeffekt habe ich nun zwei Displaylisten und lasse darin den MemScan wandern. Also $40 in der Displaylist mit der Angabe des Speicherbereiches.
Es müssen nun 15 Bytes ständig neu gesetzt werden. Die Logik ist aufwendig, wird wegen unterschiedlichen Zuständen nur tlw. immer abgearbeitet.
Insgesamt scheint das Scrolling gut zu funktionieren.
Code: Alles auswählen
; ############################################################################
; # Programm um den Bildschirm im Grafikmodus 8 (320x192) zu scrollen,
; # ohne den Speicherbereich zu verschieben
; #
; # ZeroPage A0 bis A5 werden für notwendige Zeiger genutzt
; # Der Bildschirmspeicher liegt ab Adresse $2150 bis $3F4F
; # Die Displaylist wird in den Bereich $2000 geschrieben
; #
; # Das Programm selbst beginnt ab Adresse $4000, direkt hinterm
; # Bildschirmspeicher
; #
org $4000
icl 'Systemkonstanten.asm'
; ############################################################################
; ### Variabeln definieren
ScrMemZero equ $a0
DListZero equ $a2
LastLine equ $a4
ScrMemZ .word $2150
DListZ .word $2000
VScrollPos .byte 99
VScrollCnt .byte 00
; ############################################################################
; ### Daten definieren
; # DisplayList
; # Da der ANTIC nur 4K-Daten verarbeiten kann, muss man den Bildschirm in zwei
; # Bereiche aufteilen, die jeweils < 4096 Bytes haben.
; # Beim scrollen muss man dies berücksichtigen, weshalb ich in zwei Abschnitten
; # scrolle und deshalb 2 Displaylisten benötige
; # Jeweils mit vertauschten 4K Block
; # Um einen zusammenhängenden Bild-Bereich zu haben, beginnt man bei
; # $2150 und endet bei $3F4F
DList1 .byte $70,$70,$70
.byte $4F,$50,$21 ; Der MEMSCAN wird hier beim scrollen
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; regelmäßig der neuen Situation angepasst
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F
.byte $4F,$00,$30 ; Dieser MEMSCAN wird "nach oben" wandern,
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; und immer auf die selbe Adresse zeigen
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F
.byte $4F,$28,$3F ; Dieser MEMSCAN wird einmalig korigiert und
; anschließend wander er ebenfalls "hoch"
.byte $41,$00,$20
.byte $ff
DList2 .byte $70,$70,$70
.byte $4F,$00,$30 ; Der MEMSCAN wird hier beim scrollen
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; regelmäßig der neuen Situation angepasst
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $4F,$50,$21 ; Dieser MEMSCAN wird "nach oben" wandern,
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F ; und immer auf die selbe Adresse zeigen
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F,$0F
.byte $0F,$0F
.byte $4F,$D8,$2F ; Dieser MEMSCAN wird einmalig korigiert und
; anschließend wander er ebenfalls "hoch"
.byte $41,$00,$20
.byte $ff
; ############################################################################
; # VSync
; #
.proc WaitVSync ; VBI abwarten
lda RTCLOK+2
Loop cmp RTCLOK+2
beq Loop
rts
.end
; #############################################################################
; ### Speicherbereiche initialisieren
.proc MemInI
lda ScrMemZ ; Speicherbereich des Bildbildschirm
sta ScrMemZero ; in die ZeroPage kopieren
lda ScrMemZ+1
sta ScrMemZero+1
lda DListZ ; Speicherbereich der Displaylist
sta DListZero ; in die ZeroPage kopieren
lda DListZ+1
sta DListZero+1
jsr ScreenMem ; Bildschirm löschen (leeren)
jsr DListLoad.First ; Erste Displaylist einladen
jsr WaitVSync ; VBI abwarten
lda DlistZ ; Displaylist laden
sta SDLSTL
lda DlistZ+1
sta SDLSTL+1
jsr WaitVSync ; Erneut VBI abwarten
rts
.end
; ############################################################################
; # Clear Screen
; #
; # Sicherstellen, dass der Bildschirm sauber ist
; #
.proc ScreenMem
ldx #$00
ldy #$00
lda #$00 ; Routine um den Bildschirm
@ sta (ScrMemZero),y ; zu löschen
iny ; Da insgesamt 7,5k gelöscht
bne @- ; werden müssen,
inx ; wird der Vorgang
cpx #$1E ; in mehrere 256er Läufe
beq @+
inc ScrMemZero+1
jmp @-
@ inc ScrMemZero+1
ldy #$B0 ; und einem Restlauf
@ dey ; aufgeteilt
cpy #$00
beq @+
lda #$00
sta (ScrMemZero),y
jmp @-
@ lda ScrMemZ ; ZeroPage-Variable
sta ScrMemZero ; wieder herstellen
lda ScrMemZ+1
sta ScrMemZero+1
rts
.end
; ############################################################################
; # Displaylist einrichten
; #
; # Es gibt zwei Displaylisten, die je nach Scrollposition eingeblendet werden müssen
; #
.proc DListLoad
First ldy #$00 ; Die Displaylist
Loop lda DList1,y ; muss in den Bereich ab $2000
cmp #$ff ; eingelesen werden
beq @+ ; $ff ist dabei das Signal
sta (DlistZero),y ; das alles gelesen wurde
iny
jmp Loop
@ rts
Second ldy #$00
Loop2 lda DList2,y ; Ein zweiter Loop für die
cmp #$ff ; zweite Displaylist
beq @+
sta (DlistZero),y
iny
jmp Loop2
@ rts
.end
; ############################################################################
; # VScroll - Routine um Grafikmodus 320 x 192 zu scollen
; #
.proc VScroll
lda move ; In Move wird festgehalten
cmp #$02 ; Ob man im ersten Durchlauf = 0 ist
bcc @+ ; Mehr als Durchlauf der 1. Häfte hat = 1
jmp SecondDLI ; Oder gar in der 2. Hälfte sich befindet >2
@ lda VScrollPos ; VScrollPos wieder verringert
cmp #$06 ; bis zur 6, um nicht wichtige Einträge zu
beq Restore1 ; überschreiben
dec VScrollPos ; Bei 6 wird die 2. Displaylist aktiviert
ldy #$03 ; y wird auf die 1 Memory-Scanzeile der Displaylist
jsr DListSetMem ; ausgerichtet und dieser dann hochgezählt
ldy VScrollPos ; y nun auf den ersten Wander-Memscan setzen
jsr DListSet1UPF ; und wandern lassen
lda Move
cmp #$01
beq @+
ldy #199
jmp FirstMove1 ; Im ersten Durchgang wird der 3. Memscan nur
@ tya ; verändert auf $2150
clc
adc #97
tay
jsr DListSet1UPF ; In weiteren Durchgängen wird dieser wandern
@ jmp Count
SecondDLI lda VScrollPos ; für die zweite Displaylist prüfen, ob das
cmp #$06 ; Ende der Durchläufe erreicht ist
beq Restore2 ; Dann wieder auf Displaylist 1 zurück ändern
dec VScrollPos
ldy #$03 ; y wieder auf den 1 Memory-Scann der Displaylist
jsr DListSetMem ; setzen und hochzählen
ldy VScrollPos
jsr DListSet1UPF ; Hier wieder den 2. Scan wandern lassen
lda Move ; Erster Durchlauf der 2. Displaylist = 5
cmp #$06
beq @+
ldy #199
jmp FirstMove2 ; Im ersten Durchlauf nur die Adresse korrigieren
@ tya
clc
adc #93
tay
jsr DListSet1UPF ; Im weiteren Durchlauf den Memscan wandern lassen
@ jmp Count ; Zähler für "LastLine" wo neuer Inhalt reingeschrieben
; werden kann
; -- Unterprogramme
FirstMove1 lda #$01 ; Move auf 1 setzen
sta Move
lda #$50 ; Speicherbereich auf $2150 setzen
sta (DlistZero),y
sta LastLine
iny
lda #$21
sta (DlistZero),y
sta LastLine+1
rts
Restore1 jsr DListLoad.Second ; Zweite Displaylist aktivieren
lda #103 ; Und Variabeln neu setzen
sta VScrollPos ; fürs wandern
lda #5 ; Move auf 5
sta Move
lda #$d8 ; Speicher auf $2fd8 setzen
sta LastLine
lda #$2f
sta LastLine+1
rts
FirstMove2 lda #$06 ; Move auf 6 setzen
sta Move
lda #$00 ; und Speicher auf $3000
sta (DlistZero),y ; ändern
sta LastLine
iny
lda #$30
sta (DlistZero),y
sta LastLine+1
rts
Restore2 jsr DListLoad.First ; Displaylist 1 wieder aktivieren
lda #99 ; Variabeln neu setzen
sta VScrollPos
lda #0 ; Move wieder auf 0
sta Move
lda #$28 ; Speicherbereich auf $3f28 setzen
sta LastLine
lda #$3f
sta LastLine+1
inc VScrollCnt
rts
DListSet1UPF lda #$4F ; Routine, um die Memscan-Zeile
sta (DlistZero),y ; wandern zu lassen
iny
iny
lda (DlistZero),y
dey
sta (DlistZero),y
iny
iny
lda (DlistZero),y
dey
sta (DlistZero),y
iny
lda #$0f
sta (DlistZero),y
rts
DListSetMem clc ; Nur den Speicher hochzählen
iny ; der im Memscan steht
lda (DlistZero),y
adc #$28
sta (DlistZero),y
iny
lda (DlistZero),y
adc #$00
@ sta (DlistZero),y
rts
Count clc ; LastLine berechnen
lda LastLine
adc #$28
sta LastLine
lda LastLine+1
adc #$00
sta LastLine+1
rts
Move .byte $00
.end
; ############################################################################
; ### Spielfeld generieren
; ###
; ### Irgendetwas darstellen
; ###
.proc Spielfeld
HoleRichtung lda RANDOM
cmp #$55
bcc GeheLinks
cmp #$aa
bcs GeheRechts
GeheGeradeaus lda #$00
sta Richtung
rts
GeheLinks lda Richtung
cmp #$02
beq @+
lda Links
cmp LinksMin
bcc @+
lda #$01
sta Richtung
rts
@ lda #$00
sta Richtung
rts
GeheRechts lda Richtung
cmp #$01
beq @-
lda Rechts
cmp RechtsMax
bcs @-
lda #$02
sta Richtung
rts
Start jsr HoleRichtung
lda Richtung
cmp #$01
beq LLinks
bcc GGeradeaus
bcs RRechts
rts
GGeradeaus ldy #$00
lda #$ff
@ sta (LastLine),y
iny
cpy Links
bcc @-
dey
lda LinksFein
sta (LastLine),y
iny
lda #$00
@ sta (LastLine),y
iny
cpy Rechts
bcc @-
lda RechtsFein
ldy Rechts
@ sta (LastLine),y
lda #$ff
iny
cpy #$28
bcc @-
rts
LLinks lda LinksFein
cmp #$00
beq @+
clc
asl
sta LinksFein
eor #$ff
sta RechtsFein
jmp GGeradeaus
@ lda #$ff
sta LinksFein
lda #$00
sta RechtsFein
dec Links
dec Rechts
jmp GGeradeaus
RRechts lda RechtsFein
cmp #$00
beq @+
clc
lsr
sta RechtsFein
eor #$ff
sta LinksFein
jmp GGeradeaus
@ lda #$ff
sta RechtsFein
lda #$00
sta LinksFein
inc Links
inc Rechts
jmp GGeradeaus
LinksFein .byte $ff
Links .byte $14
RechtsFein .byte $ff
Rechts .byte $1E
Richtung .byte $00 ; 0 = Geradeaus 1 = Links 2 = Rechts
LinksMin .byte $08
RechtsMax .byte $20
.end
; #############################################################################
; ### Hauptprogramm
.proc main
jsr MemInI
;lda #$0A
;sta color2
Loop jsr WaitVSync
jsr VScroll
jsr Spielfeld.Start
jmp Loop
.end
; #############################################################################
run main