Fragen zu Displaylist in Assembler etc.


Fragen zu Displaylist in Assembler etc.

von Jan1980 » Do 20. Feb 2020, 23:28
Hallo.

Ich beschäftige mich seit ca einem Jahr generell mit Assembler. Ich habe mich mit dem C64 beschäftigt, da es mir für den Anfang einfacher schien, weil ich mit dem Gerät aufgewachsen bin und die Hardware gut kenne. Außerdem hab ich für meinen Imsai 8080 ein Floppy-Bios mit Monitor-Programm und einigen Transfer-Tools programmiert. Also ich behaupte jetzt einfach mal, es sind zumindest Grundkenntnisse in MOS6502 und Intel8080 Assembler vorhanden.

Da ich großer Atari Fan bin, will ich jetzt versuchen, das erlernte an meinem Atari 800XL bzw. über WUDSN für meinen Atari 800XL um zu setzen. Es ist eine neue Herausforderung und ich freue mich darauf !

Was mir natürlich direkt positiv aufgefallen ist, ist die Displaylist und wie leicht man damit zB eine Textlinie zum (fine)-scrollen kriegt. Dafür musste ich beim Cevi so einiges mehr tippen.. :-)

Jetzt stehe ich hier vor einem Berg von neuen bzw. anderen Adressen, vor jede Menge Grafik Modes, vor einem
frei definierbarem Screen-RAM, was für mich neu ist. Und natürlich habe ich einige Fragen.


1. Schattenregister vs. Hardwareregister. Wie ist die Refresh Rate von den Schattenregistern ? Wenn ich zB an das hw-Register $2c8 eine andere Bordercolor schreibe, bleibt diese erhalten. Wenn ich an das dementsprechende Schattenregister den Farbwert schreibe, ändert sich die Farbe nur ganz kurz. Ist der Refresh bei jedem Bildaufbau ? Also während jedem vertical blank ?

2. Die Adresse des Screen-Memory steht ja an den Zeropage Adressen $58 und $59. Wenn ich indirekt adressiere, kann ich mein "Hello World !!!" auch auf dem Bildschirm ausgeben.

Code: Alles auswählen
      org $2000
;
      .proc main
         
      lda #0
      tay
      tax
;
loop   
      lda text,y
      sta ($58),y
      iny
      bne loop
      jmp *
      .end main
;
;
text
      .byte "Hello World !!!"
;
      run main


Aber wenn ich die Screenadresse ändere, geht es nicht. Ich hatte mir das so vorgestellt:

Code: Alles auswählen
screenadr=$3000
;
      org $2000
;
      .proc main
         
      lda #0
      tay
      tax
;
      lda #<screenadr
      sta $58
      lda #>screenadr
      sta $59
;
;
loop   
      lda text,y
      sta $3000,y
      iny
      bne loop
      jmp *
      .end main
;
;
text
      .byte "Hello World !!!"
;
      run main


Im Debugger steht dann die Adresse $3000 an $58 und $59, aber die Bildschirmausgabe funktioniert nicht. Was mache ich falsch ?

3. Player/Missiles. Gibt es die Möglichkeit PMs zu spiegeln ? Also wenn zB das Auto den linken Bildschirmrand erreicht, spiegele ich das Sprite und die Motorhaube steht plötzlich nach rechts.

4. Wenn ich einen Startscreen mit der Displaylist erstelle, wie kann ich die Displaylist anschließend wieder leeren ? Also ich hatte eine Routine geschrieben, die nach drücken des Feuerknopfes in das nächste Bild springen soll, aber ich kriege das Bild einfach nicht mehr weg. Gibts irgendeine Adresse, die die DL resettet. Ich hatte auch nach der Joystickabfrage ein Unterprogramm geschrieben, das eine andere Adresse bzw. im Assembler ein anderes Label in die Vectoradressen $230 und $231 schreibt. Dann geht zwar das alte Bild weg, aber ich kann die neue Displaylist nicht aufbauen. Es kommen nur 3 blaue Balken oben. Egal, was ich in die neue Displaylist reinschreibe.

5. Bei C64 hab ich den Bildschirm über Rasterzeileninterrupts gesplittet. zB oben die Punkte, in der Mitte das Spiel oder was auch immer und unten noch ein Lauftext. Kann ich das beim Atari rein über die Displaylist relaisieren ?

6. Das mit dem Scrolling via Displaylist ist mir nicht aus dem Kopf gegangen. Ich habe ein kleines Programm geschrieben, wo man mit dem Joystick über mehrere Bildschirme scrollen kann. Oben die Punkte-Anzeige soll stehen bleiben, in der Mitte die 21 Zeilen sollen scrollen und unten die Sterne stehen bleiben.

a) Wie beende ich die definitionbytes unten ? Der Text der Scrolltextes vermischt sich mit den Sternen. Wie krieg ich es hin, dass er nur das nimmt, was in dem dementsprechenden .db Fenster steht. Beim Intel Assembler hatte ich da eine Byte festgelegt, das den Ende des Blocks festlegt. Somit wusste die Konsole, dass sie zurückspringen soll. Wie mach ich das im WUDSN ?

b) Wie bringe ich das Scrolling zum stoppen, wenn ich am linken bzw. rechten Rand bin ?

c) Wie krieg ich das Ding langsamer ? :-) Ich hab schon einen Zähler über $14 eingebaut und eine verschachtelte Schleife hatte ich auch probiert.

d) Schaut euch mal meine Unterroutinen für rechts und links an. Da verschiebe ich jede Zeile einzeln. Gibt es da eine elegantere Lösung ?

Code: Alles auswählen
      org $2000
;
      .proc main

      lda #<dlist
      sta $230
      lda #>dlist
      sta $231
      
      
start
      
      
loop   lda $278
      tax
      and #$04
      bne notleft
      jsr left
notleft txa
      and #$08
      bne loop
      jsr right
      jmp start
      
      .end main
      run main
      
      .local dlist
      .byte $70,$70,$70
lms    .byte $52,a(points)
      .byte $70
lms3   .byte $52,a(text)
lms4   .byte $52,a(text)
lms5   .byte $52,a(text)
lms6   .byte $52,a(text)
lms7   .byte $52,a(text)
lms8   .byte $52,a(text)
lms9   .byte $52,a(text)
lmsa   .byte $52,a(text)
lmsb   .byte $52,a(text)
lmsc   .byte $52,a(text)
lmsd   .byte $52,a(text)
lmse   .byte $52,a(text)
lmsf   .byte $52,a(text)
lms10   .byte $52,a(text)
lms11   .byte $52,a(text)
lms12   .byte $52,a(text)
lms13   .byte $52,a(text)
lms14   .byte $52,a(text)
lms15   .byte $52,a(text)
lms16   .byte $52,a(text)
lms17   .byte $52,a(boden)
lms18   .byte $52,a(boden)
      .byte $41,a(dlist)
      .endl

      .local left
      ;dec dlist.lms+1
      ;dec dlist.lms2+1
      dec dlist.lms3+1
      dec dlist.lms4+1
      dec dlist.lms5+1
      dec dlist.lms6+1
      dec dlist.lms7+1
      dec dlist.lms8+1
      dec dlist.lms9+1
      dec dlist.lmsa+1
      dec dlist.lmsb+1
      dec dlist.lmsc+1
      dec dlist.lmsd+1
      dec dlist.lmse+1
      dec dlist.lmsf+1
      dec dlist.lms10+1
      dec dlist.lms11+1
      dec dlist.lms12+1
      dec dlist.lms13+1
      dec dlist.lms14+1
      dec dlist.lms15+1
      dec dlist.lms16+1
      ;dec dlist.lms17+1
      ;dec dlist.lms18+1
      jsr delay
      rts
      .endl
      
      .local right
      ;inc dlist.lms+1
      ;inc dlist.lms2+1
      inc dlist.lms3+1
      inc dlist.lms4+1
      inc dlist.lms5+1
      inc dlist.lms6+1
      inc dlist.lms7+1
      inc dlist.lms8+1
      inc dlist.lms9+1
      inc dlist.lmsa+1
      inc dlist.lmsb+1
      inc dlist.lmsc+1
      inc dlist.lmsd+1
      inc dlist.lmse+1
      inc dlist.lmsf+1
      inc dlist.lms10+1
      inc dlist.lms11+1
      inc dlist.lms12+1
      inc dlist.lms13+1
      inc dlist.lms14+1
      inc dlist.lms15+1
      inc dlist.lms16+1
      ;inc dlist.lms17+1
      ;inc dlist.lms18+1
      jsr delay
      rts
      .endl      
      
      .local delay
dloop   lda $14
      and #$07
      bne dloop
      rts
      .endl
      
      
      
      .align 120
      .local text   
      .byte "    Hallo das is ein Text, der laenger als der Bildschirm sein soll, ich will den Bildschirm scrollen,..............."   ; 120 Zeichen = 3 Bildschirme
      .endl
      
      
      .align 120
      .local boden   
      .byte "*********************************************************************************************************************"
      .endl
      
      ;org $3300
      .align 13
      .local points
      .byte "    Punkte: "
      .endl
      



Und zu guter Letzt. Bin ich mit meinem Bildschirmscrolling via Displaylist überhaupt auf dem richtigen Weg ? Oder doch besser das Screen-RAM verschieben ? Da hätte ich dann aber das Problem, wenn ich eins abziehe, rückt das Zeichen aus der zweiten Reihe nach und nicht das erste aus Zeile 1 von Seite 2....


Vielen Dank !

Gruß Jan

Re: Fragen zu Displaylist in Assembler etc.

von Jan1980 » Fr 21. Feb 2020, 01:33
Ok, bzgl des Zählers wegen dem Delay hat sich der Fehlerteufel eingeschlichen. Trotzdem könnte es etwas langsamer sein.. :-)

Hier der neuere Source:

Code: Alles auswählen
;
;   Bildschirm scrollen
;
;
;

      org $2000
;
      .proc main

      lda #<dlist
      sta $230
      lda #>dlist
      sta $231
      
      
start
      
      
loop   lda $278
      tax
      and #$04
      bne notleft
      jsr left
notleft txa
      and #$08
      bne loop
      jsr right
      jmp start
      
      .end main
      run main
      
      .local dlist
      .byte $70,$70,$70
lms    .byte $52,a(points)
      .byte $70
lms3   .byte $52,a(text)
lms4   .byte $52,a(text)
lms5   .byte $52,a(text)
lms6   .byte $52,a(text)
lms7   .byte $52,a(text)
lms8   .byte $52,a(text)
lms9   .byte $52,a(text)
lmsa   .byte $52,a(text)
lmsb   .byte $52,a(text)
lmsc   .byte $52,a(text)
lmsd   .byte $52,a(text)
lmse   .byte $52,a(text)
lmsf   .byte $52,a(text)
lms10   .byte $52,a(text)
lms11   .byte $52,a(text)
lms12   .byte $52,a(text)
lms13   .byte $52,a(text)
lms14   .byte $52,a(text)
lms15   .byte $52,a(text)
lms16   .byte $52,a(text)
lms17   .byte $52,a(boden)
lms18   .byte $52,a(boden)
      .byte $41,a(dlist)
      .endl

      .local left
      ;dec dlist.lms+1
      ;dec dlist.lms2+1
      dec dlist.lms3+1
      dec dlist.lms4+1
      dec dlist.lms5+1
      dec dlist.lms6+1
      dec dlist.lms7+1
      dec dlist.lms8+1
      dec dlist.lms9+1
      dec dlist.lmsa+1
      dec dlist.lmsb+1
      dec dlist.lmsc+1
      dec dlist.lmsd+1
      dec dlist.lmse+1
      dec dlist.lmsf+1
      dec dlist.lms10+1
      dec dlist.lms11+1
      dec dlist.lms12+1
      dec dlist.lms13+1
      dec dlist.lms14+1
      dec dlist.lms15+1
      dec dlist.lms16+1
      ;dec dlist.lms17+1
      ;dec dlist.lms18+1
      jsr delay
      rts
      .endl
      
      .local right
      ;inc dlist.lms+1
      ;inc dlist.lms2+1
      inc dlist.lms3+1
      inc dlist.lms4+1
      inc dlist.lms5+1
      inc dlist.lms6+1
      inc dlist.lms7+1
      inc dlist.lms8+1
      inc dlist.lms9+1
      inc dlist.lmsa+1
      inc dlist.lmsb+1
      inc dlist.lmsc+1
      inc dlist.lmsd+1
      inc dlist.lmse+1
      inc dlist.lmsf+1
      inc dlist.lms10+1
      inc dlist.lms11+1
      inc dlist.lms12+1
      inc dlist.lms13+1
      inc dlist.lms14+1
      inc dlist.lms15+1
      inc dlist.lms16+1
      ;inc dlist.lms17+1
      ;inc dlist.lms18+1
      jsr delay
      rts
      .endl      
      
      .local delay
      lda $14
dloop   cmp $14
      beq dloop
      rts
      .endl
      
      
      
      .align 120
      .local text   
      .byte "    Hallo das is ein Text, der laenger als der Bildschirm sein soll, ich will den Bildschirm scrollen,..............."   ; 120 Zeichen = 3 Bildschirme
      .endl
      
      
      .align 120
      .local boden   
      .byte "*********************************************************************************************************************"
      .endl
      
      ;org $3300
      .align 13
      .local points
      .byte "    Punkte: "
      .endl
      
      



Gruß Jan

Re: Fragen zu Displaylist in Assembler etc.

von FlorianD » Fr 21. Feb 2020, 17:03
1. Schattenregister vs. Hardwareregister. Wie ist die Refresh Rate von den Schattenregistern ? Wenn ich zB an das hw-Register $2c8 eine andere Bordercolor schreibe, bleibt diese erhalten. Wenn ich an das dementsprechende Schattenregister den Farbwert schreibe, ändert sich die Farbe nur ganz kurz. Ist der Refresh bei jedem Bildaufbau ? Also während jedem vertical blank ?


$02C8 ist das Schattenregister, $D01A das Hardwareregister
das was in $02C8 steht, wird zu Beginn des VBIs in die Hardwareregister übertragen.
Während des Bildaufbaus kannst Du $D01A ändern, dann kriegst Du ein Flimmern oder, wenn Du vor jedem STA $D01A ein STA WSYNC ; (WSYNC=$D40A) machst, den bekannten Regenbogeneffekt.



3. Player/Missiles. Gibt es die Möglichkeit PMs zu spiegeln ? Also wenn zB das Auto den linken Bildschirmrand erreicht, spiegele ich das Sprite und die Motorhaube steht plötzlich nach rechts.

Nein, nicht als Hardwarefunktion. Das musst Du "per Hand" machen.




Lies mal das Buch "De Re ATARI", da sind fast alle Deine Fragen zu Scrolling und DLs beantwortet.
Findest Du z.B. bei https://www.atariarchives.org/dere/

Re: Fragen zu Displaylist in Assembler etc.

von Jan1980 » Fr 21. Feb 2020, 20:09
Vielen Dank für die Antwort ! Das mit den Schattenregistern hatte ich dann wohl verwechselt.

Ja, das Buch hat mir Tigerduck bereits empfohlen und da bin ich dran. Es liest sich sehr gut ! Ich habe es noch nicht ganz durch. Aber wenn ich es durch habe, werde ich Thema für Thema nochmal versuchen in WUDSN um zu setzen. Manchmal ist man halt zu ungeduldig, wenn man an einem Code hängt und nicht weiterkommt... :-)

Gibt es eigentlich für Atari sowas wie eine Codebase, wo Leute verschiedene Beispielprogramme bzw. Sources veröffentlichen ?

Die Videos von Jac! und von 8 Bit and more sind super, die hab ich mir alle mehrmals angeschaut und in WUDSN und im Atari Assembler Editor nachgeschrieben und analysiert. Außerdem hab ich angefangen, die Sources von dem Fuji-Assemblerkurs zu analysieren.

Gruß Jan

Re: Fragen zu Displaylist in Assembler etc.

von FlorianD » Fr 21. Feb 2020, 20:52
die Memory Map des ATARI Wiki kennst Du hoffentlich?
https://atariwiki.org/wiki/Wiki.jsp?page=Memory%20Map
da ist viel Info drin.

auch über Themen: https://atariwiki.org/wiki/Wiki.jsp?page=Topic%20list

Fragen zu Displaylist in Assembler etc.

von Erhard » Sa 22. Feb 2020, 11:01
Hi,

Jan1980 hat geschrieben:Bin ich mit meinem Bildschirmscrolling via Displaylist überhaupt auf dem richtigen Weg ?


der "richtige Weg" hängt davon ab, was Du machen willst.

Hier ein paar grundätzliche Tips (im Bereich Spieleprogrammierung und WUDSN bin ich allerdings Anfänger):

- beim Programmieren von Spielen oder Demos werden BASIC und das eingebaute Betriebssystem meist überflüssig und deshalb abgeschaltet. Das hat zur Folge, daß Du alle Schattenregister vergessen kannst und außerdem mußt Du alle zwinged erforderlichen Interruptroutinen selber zur Verfügung stellen und Du arbeitest eigentlich nur noch mit den Hardwareregistern

- (schönes) Scrolling ist immer eine Mischung aus Finescrolling und Änderung der Speicheradressen. Du verschiebst also nicht die Daten im Speicher sondern änderst in der Display List die Adressen, ab wo diese die Daten lesen soll

- wenn etwas horizontal über 6 Bildschirmbreiten gehen soll brauchst Du pro Zeile den entsprechenden Speicher. Wenn Du sowas wie eine 360 Grad Panoramaumsicht haben willst würde ich annehmen, daß Du bei 6 Bildschirmbreiten sogar 7 Breiten im Speicher brauchst, wobei in der siebten das Gleiche liegt wie in der ersten, weil Du sonst nicht ohne Sprung von der 6. in die 1. kommst. Vielleicht geht das auch eleganter, da gibt es klügere Köpfe als mich

- wenn Du Fragen zu einem langen Listing hast fände ich es hilfreich, wenn Du Zeilennummern voranstellen würdest, die Du dann in der Frage referenzieren kannst. Oder Labels oder Kommentare. Zeilennummern kann man üblicherweise mit Editoren wie UltraEdit automatisiert einfügen lassen.

Jan1980 hat geschrieben:Aber wenn ich die Screenadresse ändere, geht es nicht. Ich hatte mir das so vorgestellt:


Das Ändern der Bildschirmadresse in $58 führt meines Wissens nicht dazu, daß die Display List diesen Speicherbereich zum Auslesen des Bildschirminhaltes verwendet. Ich glaube, $58 ist eher eine Stelle, wo man schnell mal nachschauen kann, wo das Betriebssystem gerade den Textspeicher hingesetzt hat.

Jan1980 hat geschrieben:4. Wenn ich einen Startscreen mit der Displaylist erstelle, wie kann ich die Displaylist anschließend wieder leeren ?


Eine Display List wird nicht "geleert". Ohne Display List mit eingetragenen Speicheradressen zum Auslesen von Speicherinhalten gibt es kein Bild. Bei den Speicheradressen gibt es auch Speichergrenzen zu beachten. Wenn Du die DL änderst und danach wieder anders haben willst mußt Du sie nochmal ändern. Aber aus Deiner Frage kann ich nicht mal klar erkennen, ob Du wirklich die DL ändern willst oder nur den Speicherbereich, den sie anzeigt. Übrigens gibt es auch einige Beschränkungen, wo die DL je nach Größe der DL im Speicher liegen darf.

Jan1980 hat geschrieben:5. Bei C64 hab ich den Bildschirm über Rasterzeileninterrupts gesplittet. zB oben die Punkte, in der Mitte das Spiel oder was auch immer und unten noch ein Lauftext. Kann ich das beim Atari rein über die Displaylist relaisieren ?


Das geht m.W.ausschließlich über die DL. Unter Beachtung der notwendigen Programmierung drumherum.

Jan1980 hat geschrieben:b) Wie bringe ich das Scrolling zum stoppen, wenn ich am linken bzw. rechten Rand bin ?


Du mußt abfragen, ob Du bei der Addition oder Subtraktion der Speicheradressen an der unteren oder oberen Grenze angekommen bist und falls ja eben keine weitere Änderung in diese Richtung erlauben:

; Joystick rechts
IF MEMADR < RECHTSMAX
MEMADR=MEMADR+1 ;mit Finescrolling wird das etwas komplizierter, aber es geht ja um das Prinzip
ENDIF

; Joystick links
IF MEMADR > LINKSMIN
MEMADR=MEMADR-1
ENDIF

Beim Scrollen über einen Grafikbildschirm brauchst Du den Test auf linken oder rechten Rand natürlich nicht in jeder DL Zeile ...

; Joystick links
IF MEMADRZ1 > LINKSMINZ1
MEMADRZ1=MEMADRZ1-1
MEMADRZ2=MEMADRZ2-1
MEMADRZ3=MEMADRZ3-1
...
ENDIF

Solche 16-Bit Rechnungen gehen auf die Zeit. Ich weiß nicht, ob das nicht eleganter geht. Wenn man mit einer Breite von 256 Bytes auskommt reicht ja auch eine 8-Bit Rechnung, wenn man innerhalb einer Page bleibt.

CU, Erhard

Re: Fragen zu Displaylist in Assembler etc.

von DjayBee » Sa 22. Feb 2020, 11:25
Schau mal hier wenn du des Englischen mächtig bist :
http://playermissile.com/dli_tutorial/index.html

Re: Fragen zu Displaylist in Assembler etc.

von Jan1980 » Sa 22. Feb 2020, 21:39
@FlorianD und DjayBee : Nein, die Links kannte ich nicht, da muß ich mal schauen. Vielen Dank dafür !

@Erhard: Also ist die Adresse $58/$59 nur ein Zeiger bzw. eine nur lesbare Adresse an der ich eben mal kucken kann, wo das Screenram beginnt bzw. einen Text schreiben kann, wenn ich indirekt adressiere.

Langsamer bekomme ich das Scrolling auch hin, wenn ich die Delay Subroutine zB zweimal hintereinander aufrufe. Vielleicht täusche ich mich, aber ich denke, zweimal hintereinander die Routine auf zu rufen ist so eine "Wald- und Wiesenlösung" ?! Mal schauen, wie ich das anders hinkriege...
Bzgl. dieser IF.....ENDIF Lösung. If und Endif kenne ich zB vom Intel Macroassembler. Das If...then...endif bzw if not.....endif bezieht sich da aber nur auf die Art und Weise bzw. auf die Version des resultierenden Objektcodes in Bezug auf irgendwelche Equals, hat da aber keinen Einfluss auf das fertige Programm selber.

Vielen Dank für die ganzen Tipps. Ich bleibe am Ball und berichte weiter... :-)

Gruß Jan

Re: Fragen zu Displaylist in Assembler etc.

von Jan1980 » Sa 22. Feb 2020, 22:01
Ok, für das Scrollen hab ich eine Schleife hinbekommen, bei der man über den Wert des X-Registers die Geschwindigkeit des Scrollings beeinflussen kann... Die Register musste ich auf den Stack retten und nach dem eigentlichen delay wieder holen, weil es anders spätestens beim rückwärts scrollen zu Problemen mit dem umkopieren der Speicherstellen gegeben hätte...

Hier die delay-Schleife:

Code: Alles auswählen
      .local delay
      pha
      txa
      pha
      tya
      pha
      ldx #0
dloop2   lda $14
dloop   cmp $14
      beq dloop
      inx
      cpx #3         ; Je höher der Wert, desto langsamer das Scrolling
      bne dloop2
      pla
      tay
      pla
      tax
      pla
      rts
      .endl


Gruß Jan

Fragen zu Displaylist in Assembler etc.

von Erhard » Mo 24. Feb 2020, 09:33
Hi,

Jan1980 hat geschrieben:@Erhard: Also ist die Adresse $58/$59 nur ein Zeiger bzw. eine nur lesbare Adresse an der ich eben mal kucken kann, wo das Screenram beginnt bzw. einen Text schreiben kann, wenn ich indirekt adressiere.


das ist eine noch zu belegende Annahme von mir.

Jan1980 hat geschrieben:Bzgl. dieser IF.....ENDIF Lösung.


Ich hab doch extra gesacht, daß dies nur sinngemäß zu sehen ist. Ich hab das nur so dargestellt, weil ich mir in Assembler einfach nicht merken kann, wie man auf görßer als und kleiner als testet. Das müßte also in Assembler ungefähr so aussehen (wobei ich in diesem Beispiel davon ausgehe, daß die Speicheradresse für jede Display-List-Zeile an einer Seitengrenze beginnt):

Z1MEM = $4000
Z2MEM = $4100
Z3MEM = $4200
...

MEMPNT = $C0

; Joystick links
LDA MEMPNT
BEQ NOLEFT
DEC MEMPNT
NOLEFT RTS

; Joystick rechts
SEC
LDA #FF
SBC MEMPNT
BEQ NORIGHT
INC MEMPNT
NORIGHT RTS

Jan1980 hat geschrieben:Hier die delay-Schleife:


Du verschwendest in Deiner Schleife wertvolle Interrupt-Rechenzeit. Du solltest besser hergehen, und das Scrolling nur bei jedem x-ten VBI laufen lassen. Dazu kannst Du in Deiner Routine einen Zähler verwenden der sich merkt, beim wie vielten Durchlauf die Routine gerade ist:

PHA
TXA
PHA
TYA
PHA
DEC CNT
BNE NOSCROLL
JSR DOSCROLL
LDA #2
STA CNT
NOSCROLL PLA
TAY
PLA
TAX
PLA
RTI

Und wenn Du das Scrolling im VBI machst, brauchst Du auch nicht die Abfrage bei $14 - oder wofür ist die?

Außerdem muß man innerhalb eigener Programme und außerhalb von Interrupts Register nur in seltenen Fällen retten. Es ist sonst viel zu unübersichtlich, sich über weitere Bereiche zu merken, ob gerade was gerettet ist und wenn ja was und wieviel gerade auf dem Stack ist und was wieder runter muß.

Werte merkt man sich in dafür definierten Speicherzellen.

CU, Erhard

Re: Fragen zu Displaylist in Assembler etc.

von pps » Di 25. Feb 2020, 18:17
Wenn man den Bildschirm an einer anderen Adresse im Speicher haben möchte, muss man die DisplayList verändern. Es gibt dort einen LMS Befehl, gefolgt von der Adresse im low/high Format.

Natürlich kann man gleich eine komplett eigene DL machen und diese dann in dez. 560/561 einschreiben.

Re: Fragen zu Displaylist in Assembler etc.

von pps » Di 25. Feb 2020, 20:31
Jan1980 hat geschrieben:Ok, bzgl des Zählers wegen dem Delay hat sich der Fehlerteufel eingeschlichen. Trotzdem könnte es etwas langsamer sein.. :-)

Hier der neuere Source:

Code: Alles auswählen
;
;   Bildschirm scrollen
;
;
;

      org $2000
;
      .proc main

      lda #<dlist
      sta $230
      lda #>dlist
      sta $231
      
      
start
      
      
loop   lda $278
      tax
      and #$04
      bne notleft
      jsr left
notleft txa
      and #$08
      bne loop
      jsr right
      jmp start
      
      .end main
      run main
      
      .local dlist
      .byte $70,$70,$70
lms    .byte $52,a(points)
      .byte $70
lms3   .byte $52,a(text)
lms4   .byte $52,a(text)
lms5   .byte $52,a(text)
lms6   .byte $52,a(text)
lms7   .byte $52,a(text)
lms8   .byte $52,a(text)
lms9   .byte $52,a(text)
lmsa   .byte $52,a(text)
lmsb   .byte $52,a(text)
lmsc   .byte $52,a(text)
lmsd   .byte $52,a(text)
lmse   .byte $52,a(text)
lmsf   .byte $52,a(text)
lms10   .byte $52,a(text)
lms11   .byte $52,a(text)
lms12   .byte $52,a(text)
lms13   .byte $52,a(text)
lms14   .byte $52,a(text)
lms15   .byte $52,a(text)
lms16   .byte $52,a(text)
lms17   .byte $52,a(boden)
lms18   .byte $52,a(boden)
      .byte $41,a(dlist)
      .endl

      .local left
      ;dec dlist.lms+1
      ;dec dlist.lms2+1
      dec dlist.lms3+1
      dec dlist.lms4+1
      dec dlist.lms5+1
      dec dlist.lms6+1
      dec dlist.lms7+1
      dec dlist.lms8+1
      dec dlist.lms9+1
      dec dlist.lmsa+1
      dec dlist.lmsb+1
      dec dlist.lmsc+1
      dec dlist.lmsd+1
      dec dlist.lmse+1
      dec dlist.lmsf+1
      dec dlist.lms10+1
      dec dlist.lms11+1
      dec dlist.lms12+1
      dec dlist.lms13+1
      dec dlist.lms14+1
      dec dlist.lms15+1
      dec dlist.lms16+1
      ;dec dlist.lms17+1
      ;dec dlist.lms18+1
      jsr delay
      rts
      .endl
      
      .local right
      ;inc dlist.lms+1
      ;inc dlist.lms2+1
      inc dlist.lms3+1
      inc dlist.lms4+1
      inc dlist.lms5+1
      inc dlist.lms6+1
      inc dlist.lms7+1
      inc dlist.lms8+1
      inc dlist.lms9+1
      inc dlist.lmsa+1
      inc dlist.lmsb+1
      inc dlist.lmsc+1
      inc dlist.lmsd+1
      inc dlist.lmse+1
      inc dlist.lmsf+1
      inc dlist.lms10+1
      inc dlist.lms11+1
      inc dlist.lms12+1
      inc dlist.lms13+1
      inc dlist.lms14+1
      inc dlist.lms15+1
      inc dlist.lms16+1
      ;inc dlist.lms17+1
      ;inc dlist.lms18+1
      jsr delay
      rts
      .endl      
      
      .local delay
      lda $14
dloop   cmp $14
      beq dloop
      rts
      .endl
      
      
      
      .align 120
      .local text   
      .byte "    Hallo das is ein Text, der laenger als der Bildschirm sein soll, ich will den Bildschirm scrollen,..............."   ; 120 Zeichen = 3 Bildschirme
      .endl
      
      
      .align 120
      .local boden   
      .byte "*********************************************************************************************************************"
      .endl
      
      ;org $3300
      .align 13
      .local points
      .byte "    Punkte: "
      .endl
      
      



Gruß Jan

Hier fällt mir auf, dass das run main direkt hinter .end main kommt und danach weitere Sachen in den Speicher geladen werden. Wird ein solches Programm von Diskette (oder auch Kassette) am ATARI geladen, wird es sehr wahrscheinlich Probleme bringen, da das Programm mit dem run main sofort gestartet wird, während noch nicht alle Daten geladen wurden. Soweit ich es sehe, gibt es hier keine Makros, also muss das run main als letztes in diesem Source code stehen. Am Emulator klappt das meist ohne Probleme auch so, da das komplette Programm hier in den Speicher "gepresst" wird, als wäre der ATARI so gebaut, und danach der run oder ein ini Befehl ausgeführt wird.

Zum Scrollen...

Es wird hier je Änderung des schnellen "Uhr Registers" ein komplettes Byte verschoben. Das ist noch lange kein Fine Scrolling. Das Programm führt den Code genauso aus, wenn bei der DL statt $52 (LMS ($40) +Hscroll (+$10) +Grafikstufe 0 (+$2)) nur $42 (LMS+Gfx0) geschrieben wäre.

Möchte man Fine Scrollen, muss man noch mit dem entsprechenden Scrollregister die einzelnen Zwischenschritte durchlaufen, also nicht immer einen kompletten Buchstaben verschieben (wie bei allen Rechnern ohne Fine Scrolling normal). Dazu benötigt man dann hier das Register HSCROL ($d404) in das bei Grafikstufe 0 die Werte 3,2,1 und 0 gehören. Bei 0 angelangt, wird dann erst der Buchstabe verschoben und der Zähler (HSCROL) wieder auf 3 gesetzt bzw. nach rechts scrollen dann bei 3 wieder auf 0.

Re: Fragen zu Displaylist in Assembler etc.

von Jan1980 » Di 25. Feb 2020, 22:30
Vielen Dank für die Antworten !

Mittleriweile bin ich auch etwas weitergekommen. Die Delay-Schleife werde ich noch etwas überarbeiten. Ohne die Register auf den Stack zu retten, hatte das mit dem Rückwärtsscrolling nicht funktioniert. Anstatt das X-Register als Zähler für die Anzahl der Ausführung der dazu verschachtelten Schleife zu nutzen, hatte ich mir eh überlegt, dazu eine Speicherstelle zu verwenden auf der Zeropage. Dann kann ich diese Speicherstelle aus dem Hauptprogramm abändern und somit den Bildschirm schneller oder langsamer scrollen lassen.

Dass der Bildschirmspeicher über die Displaylist defininiert wird, weiß ich mittlerweile. Er beginnt da wo zB mein .bytes "Hello world" steht. Was mir immer noch unklar ist, was das mit den Adressen $58 und $59 auf sich hat. Da ändert sich nämlich nichts, wenn ich zwei Displaylists nacheinander abbilden lasse, obwohl diese an verschiedenen Speicherstellen stehen.

Es war noch etwas anderes unklar. Ich hatte ja gefragt, warum er meine .bytes-Zeilen direkt hintereinander Schreiben will. Die Antwort ist sehr einfach. Ich hatte das ja von meiner Intel 8080 am Terminal Geschichte im Hinterkopf für die Ascii Übertragung. Da sieht das dann so aus:

Code: Alles auswählen
text1:             .db "Hallo Welt",$0a,$0d,$03
         text2               .db "Hallo Atari-Freunde",$0a,$0d,$03


Also wenn ich aus der Konsole Text1 aufrufe wird der angezeigt, wenn ich text2 aufrufe, wird er automatisch eine Zeile unten drunter eingeblendet, mit $03 springt er zurück in den Code. Zuerst kommt der Text, dann Ascii $0a für LineFeed, dann $0d für carriage return und dann Ascii $03 für End of text. Das hatte ich am Atari auch probiert, hab dann die dementsprechenden Zeichen aus dem Zeichensatz angezeigt bekommen... :mrgreen:
Wenn ich das so am Atari mache, schreibt der Atari so viel wie möglich in eine Zeile. Er springt also nicht in die nächste Zeile. Und in der Displaylist wird Zeile für Zeile definiert.
Die Antwort ist wahrscheinlich so einfach, dass sie nicht in einem Buch steht.

AUCH EIN LEERZEICHEN IST EIN ZEICHEN ! :mrgreen:

Also muß ich jede Zeile mit 40 bzw 20 Zeichen definieren, je nachdem, in welchem Modus er ist.

Also im 40 Zeichen-Modus so:

Code: Alles auswählen
.local text1
         .dbytes "               Hallo Welt               "
         .endl
;
         .local text2
         .dbytes "          Hallo Atari-Freunde           "
         .endl




Ich hatte ja einen Code geschrieben mit 2 aufeinander folgenden Displaylists. Die erste Displaylist wurde angezeigt, nach drücken des Feuerknopfes sollte die neue Displaylist angezeigt werden. Ich bekam die erste aber nicht vom Schirm.
Laut Buch muß der Antic ausgeschaltet werden über $22f, dann die neue Displaylist definiert werden und dann der Antic wieder eingeschaltet werden. Also so:

Code: Alles auswählen
org $2000
lda #<dlist1
sta $230
lda #>dlist1
sta $231

jloop lda $284               ;Feuerknopfabfrage
        and #$01             
        bne jloop

lda #0                         ; Antic aus
sta $22f

lda #<dlist2
sta $230
lda #>dlist2
sta $231

lda #$22                       ; Antic ein
sta $22f

jmp *                          ; Endlosschleife


dlist1.....

dlist2...



Vielen Dank noch für den Tip mit dem Scrolling und dem "run main". Ich hatte bis jetzt noch nicht am Atari selber probiert. Die Sources, die ich hier geschrieben habe, hab ich gerade im Browserfenster geschrieben, deswegen fehlen .proc main, .end main usw.


Gruß Jan

Re: Fragen zu Displaylist in Assembler etc.

von slx » Di 25. Feb 2020, 23:51
Man kann auch verschiedene Display Lists machen und je nach Bedarf (Titel, Level, usw.) die jeweils benötigte Display List aktivieren.

Das geht auch modular, weil man ja innerhalb der Display List zu einer anderen Stelle im Speicher "springen" kann, an der die Display List weitergeht.

Fragen zu Displaylist in Assembler etc.

von Erhard » Mi 26. Feb 2020, 10:09
Jan1980 hat geschrieben:Wenn ich das so am Atari mache, schreibt der Atari so viel wie möglich in eine Zeile


Wenn Du ein Carriage Return (CR) in den Bildschirmspeicher POKEst, wird kein ausgeführt.

Wenn Du willst, daß das ausgeführt wird, dann darfst Du das

- entweder nicht in den Bildschirmspeicher schreiben, sondern Du mußt Deine Bytes an die im Betriebssystem eingebaute Routine übergeben, die Text auf dem Bildschirm ausgibt, was aber u.U. nicht geht, wenn Du selber mit der DL rumfudelst

- oder Du mußt beim POKEn in den Bildschirmspeicher das CR nicht POKEn, sondern die erste Speicheradresse für die nächste Zeile ausrechnen und den Rest dann ab da hinschreiben

CU, Erhard

Re: Fragen zu Displaylist in Assembler etc.

von pps » Mi 26. Feb 2020, 21:23
Ein Tip für den Joysticktest:
Baue Dir eine kleine Tabelle, in der alle gewünschten Werte des Joustickregisters mit Zahlen gesetzt sind, bei nur 2 möglichen Richtungen (hier im Beispiel hoch und runter) kann man einfach 1 und -1(255) nehmen. Dann den Wert des Registers STICK0 ins y Register des 6502 laden und als Index für die Tabelle nehmen, schon hat man im Akku den Wert, in welche Richtung es gehen soll und man kann das dann später im Programm einfach nutzen.

Mein Beispielcode gibt also immer 0, wenn keine der gewünschten Richtungen gedrückt wird, und 1 bei hoch bzw. -1 bei runter zurück in der "Variablen" joy0
Code: Alles auswählen
.proc joytest
* stick0=632 dez.
   ldy stick0
   lda joy,y
   sta joy0
   rts
.endp
joy
   dta b(0,0,0,0,0,0,0,0,0,0,0,0,0,255,1,0)


Für Rechts/Links wäre die kleine Tabelle dann so:
0,0,0,0,0,0,1,0,0,0,255,0,0,0,0

Wenn der Nutzer auch beim schräg Drücken die selbe Richtung erzeugen soll, dann so:
0,0,0,0,1,1,1,0,255,255,255,0,0,0,0