DisplayList für Neueinsteiger #1
Moderator: Rockford
- Dr. Irata
- Beiträge: 1089
- Registriert: 24.08.2021 14:40
- Has thanked: 155 times
- Been thanked: 329 times
- Kontaktdaten:
DisplayList für Neueinsteiger #1
DisplayList #1
Wenn man (so wie ich damals in den 80-igern) Programme in einer Hochsprache entwickelt - damals auf dem Atari 800 z.B. in BASIC, dann ist man nicht unbedingt darauf angewiesen ein tieferes Verständnis der grafischen Bildschirmausgabe zu besitzen. Das BASIC hat bereits entsprechende Befehle integriert und übersetzt am Ende alles in den entsprechenden Maschinencode. So ist es dann einfach z.B. eine „Hallo Welt“- Ausgabe zu programmieren:
10 Print „Hallo Welt“
20 Goto 10
Ein entsprechender Print-Befehl existiert in Assembler nicht und wenn man etwas auf den Bildschirm bekommen möchte, dann stößt man recht bald unweigerlich auf die DisplayList. So erging es auch mir!
Aber was genau passiert denn da? Der Name zunächst ist völlig irreführend, denn es handelt sich dabei gar nicht um eine Bildschirm Liste, sondern um Programmanweisungen eines ganz eigenen Prozessors - dem ANTIC. Vielfach gehört, aber wie genau erzeugt dieser Chip das Bild und wie kann ich das beeinflussen und steuern?
Die Idee eines solchen Prozessors war zwar damals nicht neu, für den Heimcomputerbereich aber schon fast revolutionär. Der ANTIC liest dabei Daten aus dem Hauptspeicher, verarbeitet sie und baut dann entsprechend den Bildschirm auf.
Zusätzlich sorgt der ANTIC-Prozessor auch für die Generierung der Player-/Missile Grafik.
Der Antik kann nur lesen und keine Daten in den Prozessor zurückschreiben, um dieses Problem zu lösen gibt es die Schattenregister…
Die Befehle, die der Anti verarbeiten kann sind eigentlich recht simpel. Es gibt einen Vectorbefehl, wo angegeben ist, wo der Bildschirm anfängt und einen Sprungbefehl, der saget, wo die Displaylist wieder startet. Alle anderen Displaylisteinträge sind keine Befehle im eigentlichen Sinn, sondern stellen nur Werte dar, wie die einzelnen Zeilen aufgebaut werden.
Wenn man jetzt weiß, an welcher Speicherstelle der Bildschirm bei Graphics 0 (in Basic) anfängt, kann man relativ einfach durch ein Poke-Befehl im Basic oder durch LDA / STA in Assembler eine Ausgabe auf den Bildschirm machen:
Zum Experimentieren empfehle ich das in Basic, das kann man dann relativ einfach in Assembler umsetzen:
Poke 40000,33 läßt links oben ein A entstehen, denn dort fängt der Bildschirm im Speicher an… und dieser Anfang wird in der DL festgelegt!
In den Speicherstellen 560 (LoBi) und 561 (HiBi) steht die Adresse des DL:
Print Peek(560)
32
Print Peek(561)
156
Print 32+256*156
39968
Am Beispiel von Graphics 0 fängt die DL also an der Stelle 39968 im Hauptspeicher an.
Hier geht es los mit drei Einträgen 112
? Peek(39968), Peek(39969), Peek(39970)
112 112 112
Das sind die drei schwarzen Zeilen am oberen Rand, die einfach leer sind.
Poke 39968,2 würde eine leere Textzeile am Oberrad erzeugen (die man aber nicht beschreiben kann).
An Stelle 4 des DL (also bei Speicherstelle 39971 kommt ein erster echter Befehl: 64 - dieser benennt die Adresse des Bildschirmstartes mit den zwei folgenden Stellen (Stelle 5 und 6):
Peek(39972) liefert 64 und Peek(39973) liefert 156
64+256*156 ergibt 40000 - also die Startadresse des Bildschirmes.
Will man also die Startadresse des Bildschirmes ändern (wird z.B. scrollen wichtig), dann ändert man einfach diese beiden Adressen entsprechend!
Danach folgen 23 x die Speichereinträge 2 - diese legen letztlich den Textmodus für Graphics 0 fest und danach kommt der Sprungbefehl (65) mit den nachfolgenden beiden Speichereinträgen, die festlegen wohin gesprungen werden soll - nämlich wieder zum Anfang der DL, die ja ständig wiederholt abgearbeitet werden muss.
Warum nur 23x2 ? Wir haben ja 24 Zeilen! Das steckt witzigerweise in Stelle 4 der DL im Befehl mit drin. Der Befehl an Stelle 4 der DL ist eigentlich Dezimal 64, in der Stelle 4 steht aber 66. Hier wird einfach schon die erste zu generierende Zeile zum Befehl addiert. 64+2=66
Ich denke, die Atari-Entwickler wollten damit ein wenig Verwirrung stiften
Das wars eigentlich schon, was den Aufbau der DL angeht. Im Anhang noch eine schöne Übersicht über die DL bei Graphic 0.
In Teil 2 wird man dann erfahren, was es für Auswirkungen haben kann die DL zu verändern, wie flexibel man alles mischen kann und wie man einfach eigene Grafikmodi erstellen kann.
Wenn man (so wie ich damals in den 80-igern) Programme in einer Hochsprache entwickelt - damals auf dem Atari 800 z.B. in BASIC, dann ist man nicht unbedingt darauf angewiesen ein tieferes Verständnis der grafischen Bildschirmausgabe zu besitzen. Das BASIC hat bereits entsprechende Befehle integriert und übersetzt am Ende alles in den entsprechenden Maschinencode. So ist es dann einfach z.B. eine „Hallo Welt“- Ausgabe zu programmieren:
10 Print „Hallo Welt“
20 Goto 10
Ein entsprechender Print-Befehl existiert in Assembler nicht und wenn man etwas auf den Bildschirm bekommen möchte, dann stößt man recht bald unweigerlich auf die DisplayList. So erging es auch mir!
Aber was genau passiert denn da? Der Name zunächst ist völlig irreführend, denn es handelt sich dabei gar nicht um eine Bildschirm Liste, sondern um Programmanweisungen eines ganz eigenen Prozessors - dem ANTIC. Vielfach gehört, aber wie genau erzeugt dieser Chip das Bild und wie kann ich das beeinflussen und steuern?
Die Idee eines solchen Prozessors war zwar damals nicht neu, für den Heimcomputerbereich aber schon fast revolutionär. Der ANTIC liest dabei Daten aus dem Hauptspeicher, verarbeitet sie und baut dann entsprechend den Bildschirm auf.
Zusätzlich sorgt der ANTIC-Prozessor auch für die Generierung der Player-/Missile Grafik.
Der Antik kann nur lesen und keine Daten in den Prozessor zurückschreiben, um dieses Problem zu lösen gibt es die Schattenregister…
Die Befehle, die der Anti verarbeiten kann sind eigentlich recht simpel. Es gibt einen Vectorbefehl, wo angegeben ist, wo der Bildschirm anfängt und einen Sprungbefehl, der saget, wo die Displaylist wieder startet. Alle anderen Displaylisteinträge sind keine Befehle im eigentlichen Sinn, sondern stellen nur Werte dar, wie die einzelnen Zeilen aufgebaut werden.
Wenn man jetzt weiß, an welcher Speicherstelle der Bildschirm bei Graphics 0 (in Basic) anfängt, kann man relativ einfach durch ein Poke-Befehl im Basic oder durch LDA / STA in Assembler eine Ausgabe auf den Bildschirm machen:
Zum Experimentieren empfehle ich das in Basic, das kann man dann relativ einfach in Assembler umsetzen:
Poke 40000,33 läßt links oben ein A entstehen, denn dort fängt der Bildschirm im Speicher an… und dieser Anfang wird in der DL festgelegt!
In den Speicherstellen 560 (LoBi) und 561 (HiBi) steht die Adresse des DL:
Print Peek(560)
32
Print Peek(561)
156
Print 32+256*156
39968
Am Beispiel von Graphics 0 fängt die DL also an der Stelle 39968 im Hauptspeicher an.
Hier geht es los mit drei Einträgen 112
? Peek(39968), Peek(39969), Peek(39970)
112 112 112
Das sind die drei schwarzen Zeilen am oberen Rand, die einfach leer sind.
Poke 39968,2 würde eine leere Textzeile am Oberrad erzeugen (die man aber nicht beschreiben kann).
An Stelle 4 des DL (also bei Speicherstelle 39971 kommt ein erster echter Befehl: 64 - dieser benennt die Adresse des Bildschirmstartes mit den zwei folgenden Stellen (Stelle 5 und 6):
Peek(39972) liefert 64 und Peek(39973) liefert 156
64+256*156 ergibt 40000 - also die Startadresse des Bildschirmes.
Will man also die Startadresse des Bildschirmes ändern (wird z.B. scrollen wichtig), dann ändert man einfach diese beiden Adressen entsprechend!
Danach folgen 23 x die Speichereinträge 2 - diese legen letztlich den Textmodus für Graphics 0 fest und danach kommt der Sprungbefehl (65) mit den nachfolgenden beiden Speichereinträgen, die festlegen wohin gesprungen werden soll - nämlich wieder zum Anfang der DL, die ja ständig wiederholt abgearbeitet werden muss.
Warum nur 23x2 ? Wir haben ja 24 Zeilen! Das steckt witzigerweise in Stelle 4 der DL im Befehl mit drin. Der Befehl an Stelle 4 der DL ist eigentlich Dezimal 64, in der Stelle 4 steht aber 66. Hier wird einfach schon die erste zu generierende Zeile zum Befehl addiert. 64+2=66
Ich denke, die Atari-Entwickler wollten damit ein wenig Verwirrung stiften
Das wars eigentlich schon, was den Aufbau der DL angeht. Im Anhang noch eine schöne Übersicht über die DL bei Graphic 0.
In Teil 2 wird man dann erfahren, was es für Auswirkungen haben kann die DL zu verändern, wie flexibel man alles mischen kann und wie man einfach eigene Grafikmodi erstellen kann.
- Dr. Irata
- Beiträge: 1089
- Registriert: 24.08.2021 14:40
- Has thanked: 155 times
- Been thanked: 329 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
Hier noch kurz mein Listing für "Hallo Welt":
Basic:
10 Print "Hallo Welt"
20 Goto 10
Assembler:
Dieser Assemblercode ist hier bewusst ganz einfach gewählt!
Etwas komplexer wird es dann hier:
Das Programm startet nicht bei 4000, sondern bei 400F !!
Man sieht an diesem Beispiel wie komplex die Programmierung einfacher Anwendungen in Assembler werden kann.
Zur Ausgabe von Hallo Welt wurde zudem in diesem Beispiel die CIOV des Ataris benutzt, man könnte den Text natürlich auch direkt auf den Bildschirm ausgeben - was allerdings in diesem Fall etwas weniger elegant ist.
Dies würde dann den Text "Hallo Welt!" quasi Buchstabe für Buchstabe zerlegen und dann in den Bildschirmspeicher direkt kopieren - ähnlich wie im ersten etwas plumpen Listing.
Basic:
10 Print "Hallo Welt"
20 Goto 10
Assembler:
Code: Alles auswählen
10 ;Hallo Welt Demo einfach
20 *= $4000
30 LDA #40
40 STA $9C40
50 LDA #33
60 STA $9C41
70 LDA #44
80 STA $9C42
90 STA $9C43
100 LDA #47
110 STA $9C44
120 LDA #55
130 STA $9C46
140 LDA #37
150 STA $9C47
160 LDA #44
170 STA $9C48
180 LDA #52
190 STA $9C49
200 LDA #00
210 STA $9C45
220 STA $9C4A
Etwas komplexer wird es dann hier:
Code: Alles auswählen
10 ;Hallo Welt Demo Komplex
20 .OPT OBJ
30 *= $4000
40 RET = $9B
50 IOCB = $0340
60 CIOV = $E456
70 DEVICE .BYTE "E:",RET
80 TEXT .BYTE "HALLO WELT!",RET
90 LDX #$20
100 LDA #$03
110 STA $0342,X
120 LDA #DEVICE&255
130 STA $0344,X
140 LDA #DEVICE/256
150 STA $0345,X
160 LDA #$08
170 STA $034A,X
180 LDA #$00
190 STA $034B,X
200 JSR CIOV
210 LDA #$09
220 STA $0342,X
230 LDA #TEXT&255
240 STA $0344,X
250 LDA #TEXT/256
260 STA $0345,X
270 LDA #$00
280 STA $0348,X
290 LDA #$FF
300 STA $0349,X
310 LDA #$FF
320 STA $02FC
330 LP JSR CIOV
340 LDA $02FC
350 CMP #$FF
360 BNE STOP
370 JMP LP
380 STOP BRK
390 .END
Man sieht an diesem Beispiel wie komplex die Programmierung einfacher Anwendungen in Assembler werden kann.
Zur Ausgabe von Hallo Welt wurde zudem in diesem Beispiel die CIOV des Ataris benutzt, man könnte den Text natürlich auch direkt auf den Bildschirm ausgeben - was allerdings in diesem Fall etwas weniger elegant ist.
Dies würde dann den Text "Hallo Welt!" quasi Buchstabe für Buchstabe zerlegen und dann in den Bildschirmspeicher direkt kopieren - ähnlich wie im ersten etwas plumpen Listing.
Zuletzt geändert von Dr. Irata am 03.09.2021 21:37, insgesamt 3-mal geändert.
- cas
- Beiträge: 974
- Registriert: 18.06.2021 21:01
- Wohnort: Solar System
- Has thanked: 240 times
- Been thanked: 555 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
Umschliesse Quellcode mit [ code ] [ /code ] Bloecken (nur ohne die Leerzeichen hinter [ und ]), z.B.:
Code: Alles auswählen
10 ;Hallo Welt Demo einfach
20 *= $4000
30 LDA #40
40 STA $9C40
50 LDA #33
60 STA $9C41
70 LDA #44
80 STA $9C42
90 STA $9C43
[...]
In deinen Beispielen sind typografische Anfuehrungszeichen, wie sie von Textverarbeitungen erzeugt werden. Die kennt der Atari nicht, daher verschwinden die. Ggf. oben im Post durch echte Anfuehrungszeichen "" ersetzen.
- Dr. Irata
- Beiträge: 1089
- Registriert: 24.08.2021 14:40
- Has thanked: 155 times
- Been thanked: 329 times
- Kontaktdaten:
Grobscroll durch Manipulation der Displaylist
Der Graphikbildschirm hat im Textmodus 24 Zeilen a 40. Jede Zeile in der Displaylist bekommt also eine 2 eingeschrieben (die ersten 24 Scanlines bleiben leer).
Die erste Zeile hat dabei nicht den Wert 2 sondern 66 (64+2) - wobei die 64 einen Adressbefehl darstellt - nämlich den des Bildschirmanfanges. Es folgen dann die 23 nächsten Zeilen mit dem Wert 2 und danach kommt noch der Sprungbefehl mit Adresse des Displaylistanfanges.
Nun möchten wir folgendes machen: In jede Zeile schreibe ich statt einer 2 eine 66 (alles dezimal) rein mit der jeweiligen um eine Zeile höheren Adresse für den Bildschirm:
66 64 156 (40000)
66 104 156 (40040)
66 144 156 (40080)
66 184 156
66 224 156
.......... usw
am Ende wieder der Sprungbefehl für den Start der Displaylist.
Als nächstes (mein Grobscroll) kopiere ich einfach die Displaylist um - verschiebe also alle Zeilen um eins nach oben:
66 104 156
66 144 156
66 184 156
66 224 156
66 08 157
.....
66 64 156
Sprungbefehl Displaylistanfang
die letzte Zeile vor dem Sprungbefehl müsste dann wohl immer die vorherige erste sein.
Damit bekomme ich ein fortlaufendes Grobscroll des gesamten Bildschirmes.
Will ich jetzt einen Shooter damit machen, überschreibe ich einfach die komplette erste Zeile der Displaylist mit den neuen Landschaftsdaten (meine "letzte Reihe") - anschließend wird die erste Reihe durch Umsortierung der Displaylist letzte Reihe.
Theoretisch könnte ich auch ganz einfach 24 verschiedene Displaylist mit entsprechend versetzten Zeilen vorbereiten und dann einfach nur jeweils von Displaylist 1 zu 2 zu 3 zu .... zu 24 umschalten.
Die Displaylist wird dann noch so aufgebaut, daß der entsprechende Graphicmodus plus Feinscroll mit drin ist, der Grobscroll wird entsprechend immer einmal nach 7 Feinscrollaktionen durchgeführt.
So habe ich die Theorie verstanden.... das möchte ich demnächst mal umsetzen.
Habe ich das korrekt verstanden??
Liebe Grüße
Peter
Die erste Zeile hat dabei nicht den Wert 2 sondern 66 (64+2) - wobei die 64 einen Adressbefehl darstellt - nämlich den des Bildschirmanfanges. Es folgen dann die 23 nächsten Zeilen mit dem Wert 2 und danach kommt noch der Sprungbefehl mit Adresse des Displaylistanfanges.
Nun möchten wir folgendes machen: In jede Zeile schreibe ich statt einer 2 eine 66 (alles dezimal) rein mit der jeweiligen um eine Zeile höheren Adresse für den Bildschirm:
66 64 156 (40000)
66 104 156 (40040)
66 144 156 (40080)
66 184 156
66 224 156
.......... usw
am Ende wieder der Sprungbefehl für den Start der Displaylist.
Als nächstes (mein Grobscroll) kopiere ich einfach die Displaylist um - verschiebe also alle Zeilen um eins nach oben:
66 104 156
66 144 156
66 184 156
66 224 156
66 08 157
.....
66 64 156
Sprungbefehl Displaylistanfang
die letzte Zeile vor dem Sprungbefehl müsste dann wohl immer die vorherige erste sein.
Damit bekomme ich ein fortlaufendes Grobscroll des gesamten Bildschirmes.
Will ich jetzt einen Shooter damit machen, überschreibe ich einfach die komplette erste Zeile der Displaylist mit den neuen Landschaftsdaten (meine "letzte Reihe") - anschließend wird die erste Reihe durch Umsortierung der Displaylist letzte Reihe.
Theoretisch könnte ich auch ganz einfach 24 verschiedene Displaylist mit entsprechend versetzten Zeilen vorbereiten und dann einfach nur jeweils von Displaylist 1 zu 2 zu 3 zu .... zu 24 umschalten.
Die Displaylist wird dann noch so aufgebaut, daß der entsprechende Graphicmodus plus Feinscroll mit drin ist, der Grobscroll wird entsprechend immer einmal nach 7 Feinscrollaktionen durchgeführt.
So habe ich die Theorie verstanden.... das möchte ich demnächst mal umsetzen.
Habe ich das korrekt verstanden??
Liebe Grüße
Peter
- Kveldulfur
- Beiträge: 874
- Registriert: 17.08.2021 02:32
- Has thanked: 374 times
- Been thanked: 310 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
In dem Beispiel von mir im "Return to Phobos"-Thread sieht das Scrolling wie folgt aus.
Nur in der letzten Zeile muss man aufpassen, da dort der Code $42 steht und nicht $62 !!!
Deine Aussage trifft also zu.
Grüße
Janko
Nur in der letzten Zeile muss man aufpassen, da dort der Code $42 steht und nicht $62 !!!
Deine Aussage trifft also zu.
Grüße
Janko
Meine Projekte findest Du hier...
- Dr. Irata
- Beiträge: 1089
- Registriert: 24.08.2021 14:40
- Has thanked: 155 times
- Been thanked: 329 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
ha... so habe ich es verstanden! Cool! Das sieht ja prinzipiell viel einfacher und vor allem viel schneller aus... mit der Methode müsste man doch auch eine hochaufgelöste Graphik ganz schnell scrollen können!!
Wenn ich also eine Graphik mit 320x192 scrollen möchte, dann erstelle ich einfach 192 verschiedene Displaylisten (dann fällt ja auch noch die Rechenzeit für die Umkopiererei weg) und schalte die einfach hintereinander um und habe so einen hochaufgelösten schnellen Scroll ....
Wenn ich also eine Graphik mit 320x192 scrollen möchte, dann erstelle ich einfach 192 verschiedene Displaylisten (dann fällt ja auch noch die Rechenzeit für die Umkopiererei weg) und schalte die einfach hintereinander um und habe so einen hochaufgelösten schnellen Scroll ....
- Kveldulfur
- Beiträge: 874
- Registriert: 17.08.2021 02:32
- Has thanked: 374 times
- Been thanked: 310 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
Hallo!
Einzelne Displaylisten bei 192 Zeilen? In jeder Liste sind doch min. 200 Bytes enthalten, oder?
Also 192 Schritte x 200 Bytes = 38400 Bytes = 37,5kb = Atari voll
Oder mache ich jetzt einen Denkfehler?
Grüße
Janko
Einzelne Displaylisten bei 192 Zeilen? In jeder Liste sind doch min. 200 Bytes enthalten, oder?
Also 192 Schritte x 200 Bytes = 38400 Bytes = 37,5kb = Atari voll
Oder mache ich jetzt einen Denkfehler?
Grüße
Janko
Meine Projekte findest Du hier...
- Dr. Irata
- Beiträge: 1089
- Registriert: 24.08.2021 14:40
- Has thanked: 155 times
- Been thanked: 329 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
ähhhh .. ja das stimmt ... das geht nicht. Da müsste man umkopieren...
- Kveldulfur
- Beiträge: 874
- Registriert: 17.08.2021 02:32
- Has thanked: 374 times
- Been thanked: 310 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
Hallo Peter!
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?
192 Displayliste? Nein zu wenig Speicher
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.
Hier mein Beispiel (Quick & Dirty ) :
Gruß
Janko
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?
192 Displayliste? Nein zu wenig Speicher
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.
Hier mein Beispiel (Quick & Dirty ) :
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
Janko
Meine Projekte findest Du hier...
- Dr. Irata
- Beiträge: 1089
- Registriert: 24.08.2021 14:40
- Has thanked: 155 times
- Been thanked: 329 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
Guten Morgen Janko,
ich habe mir das Listing gleich mal rübergezogen und ausprobiert... beeindruckend!
Tatsächlich hatte ich mal ganz am Anfang mit Scrolling experimentiert unter Basic und das ging dort auch nur relativ zügig und schnell mit 2 verschiedenen Displays und dann umschalten... so hätte ich das jetzt nach meinem Projekt Phobos versucht - du hast das jetzt umgesetzt!! Das läuft echt gut. Respekt. Was ich noch besser finde ist, daß du auch noch einen Zufallsgenerator für eine einfache Landschaft eingebaut hast. Klasse!! Der Code scheint aufwendig, aber das Ergebnis ist ja entscheidend und der eigentliche Programmablauf um 8k zu scrollen läuft fast ohne CPU-Belastung.
Im Grunde müsste man das jetzt noch für verschiedene interessante Grafikmodi umsetzen und veröffentlichen, dann muss das nicht jeder selber neu "erfinden".
Klasse gemacht, Janko!!
Ich habe gestern ein wenig Zeit gehabt und neben der ganzen schlimmen Berichterstattung aus der Welt und vor allem aus der Ukraine mein Projekt weitergemacht.
Neue Items sind drin - die Schranken! Dabei wollte ich die Schranken so gestalten, daß sie ständig animiert sind und dann als weiteres Item relativ einfach in die Landschaft reingeprintet werden können über meine Routine "letzte Reihe". Die Schranke muss in vernünftiger Zeit ein- bzw. ausgeschaltet werden, dieses Timing hat mich etwas Mühe und Zeit gekostet. Am Ende habe ich es ans "blinken" gekoppelt und mit ein paar Anpassungen läuft das jetzt ganz gut.
Jetzt kommt noch eine weitere "Laufschranke" und noch weitere Landschaft und noch ein paar Sonderitems.
Für das Endlevel muss ich mir noch was schönes ausdenken...
Und danach gehe ich das nächste Projekt an... es wird wieder ein Shooter, der aber ganz anders aufgebaut sein soll...
Liebe Grüße
Peter
ich habe mir das Listing gleich mal rübergezogen und ausprobiert... beeindruckend!
Tatsächlich hatte ich mal ganz am Anfang mit Scrolling experimentiert unter Basic und das ging dort auch nur relativ zügig und schnell mit 2 verschiedenen Displays und dann umschalten... so hätte ich das jetzt nach meinem Projekt Phobos versucht - du hast das jetzt umgesetzt!! Das läuft echt gut. Respekt. Was ich noch besser finde ist, daß du auch noch einen Zufallsgenerator für eine einfache Landschaft eingebaut hast. Klasse!! Der Code scheint aufwendig, aber das Ergebnis ist ja entscheidend und der eigentliche Programmablauf um 8k zu scrollen läuft fast ohne CPU-Belastung.
Im Grunde müsste man das jetzt noch für verschiedene interessante Grafikmodi umsetzen und veröffentlichen, dann muss das nicht jeder selber neu "erfinden".
Klasse gemacht, Janko!!
Ich habe gestern ein wenig Zeit gehabt und neben der ganzen schlimmen Berichterstattung aus der Welt und vor allem aus der Ukraine mein Projekt weitergemacht.
Neue Items sind drin - die Schranken! Dabei wollte ich die Schranken so gestalten, daß sie ständig animiert sind und dann als weiteres Item relativ einfach in die Landschaft reingeprintet werden können über meine Routine "letzte Reihe". Die Schranke muss in vernünftiger Zeit ein- bzw. ausgeschaltet werden, dieses Timing hat mich etwas Mühe und Zeit gekostet. Am Ende habe ich es ans "blinken" gekoppelt und mit ein paar Anpassungen läuft das jetzt ganz gut.
Jetzt kommt noch eine weitere "Laufschranke" und noch weitere Landschaft und noch ein paar Sonderitems.
Für das Endlevel muss ich mir noch was schönes ausdenken...
Und danach gehe ich das nächste Projekt an... es wird wieder ein Shooter, der aber ganz anders aufgebaut sein soll...
Liebe Grüße
Peter
- Kveldulfur
- Beiträge: 874
- Registriert: 17.08.2021 02:32
- Has thanked: 374 times
- Been thanked: 310 times
- Kontaktdaten:
Re: DisplayList für Neueinsteiger #1
Danke! Freut mich, dass es Dir gefällt.
Grüße
Janko
Grüße
Janko
Meine Projekte findest Du hier...
Wer ist online?
Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast