Wellen auf dem Bildschirm

  • Na, das war nicht die Frage, oder? Aber:
    Hey, was für ein simpler aber cooler Effekt! :thumbsup:
    Bitte beachten: Telespielatorgesetz (TspG)
    Verstöße gegen das TspG werden umgehend und gnadenlos von Supererdbeeregeahndet!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Telespielator ()

  • t0m3000 schrieb:

    seit Tagen versuche ich den OneLiner vom Basic in Assembler zu bekommen, jedoch ohne Erfolg.

    Habt ihr eine Idee wie man da vorgehen könnte?
    Willst Du eine fertige Lösung oder Hinweise, um es selbst hinzubekommen? Falls letzteres: erklär mal wie weit Du bist und woran es hängt. Die Kernalfunktion $ffd2 und die Interpreterfunktion $ab1e kennst Du?
    Yes, I'm the guy responsible for the ACME cross assembler
  • Der Effekt ist schick, aber es ist ein typischer Basic-Effekt, der funktioniert, weil er langsam ist.
    Dabei ist der Print-Befehl ja schon besonders schnell.

    Ohne künstliche Verzögerung kann ich mir gut vorstellen, dass der Effekt in Assembler so schnell ist, dass man ihn optisch nicht mehr genießen kann. Das sieht man dann wenn es soweit ist und kann ggf. künstlich bremsen. Die Schleifenmechanik in Asm ist ja viel schneller.

    Wenn man das Ganze ohne Basic-Aufrufe abbilden will, wird das nicht nur zu schnell, sondern man muss sich auch überlegen wie man das "Hochscrollen" des Bildschirms bewirken will, denn mit Poken ins ScreenRAM allein ist es ja nicht getan. Aus meiner Sicht zu umständlich und auch zuviel für eine Anfänger-Übung.
  • Mac Bacon schrieb:

    t0m3000 schrieb:

    seit Tagen versuche ich den OneLiner vom Basic in Assembler zu bekommen, jedoch ohne Erfolg.

    Habt ihr eine Idee wie man da vorgehen könnte?
    Willst Du eine fertige Lösung oder Hinweise, um es selbst hinzubekommen? Falls letzteres: erklär mal wie weit Du bist und woran es hängt. Die Kernalfunktion $ffd2 und die Interpreterfunktion $ab1e kennst Du?
    Wenn ich ehrlich sein soll, wäre mir eine Lösung am liebsten. Denn ich habe wirklich keine Lösung dafür zur Hand. Die beiden Funktionen kenne ich noch nicht, bin erst seit kurzem auf dem C64 am coden.

    Ich denke aber auch, dass ASM so schnell sein wird, dass der Effekt nicht so zu Stande kommt.
  • t0m3000 schrieb:

    Wenn ich ehrlich sein soll, wäre mir eine Lösung am liebsten.

    Quellcode

    1. loop lda #<string
    2. ldy #>string
    3. jsr $ab1e
    4. jmp loop
    5. string !by $af, $d2, $c6, $c3, $c4, $c5, $b7
    6. !by $c5, $c4, $c3, $c6, $d2, $af, 0

    t0m3000 schrieb:

    Die beiden Funktionen kenne ich noch nicht
    $ffd2 sendet das Byte im Akku zum aktuellen Ausgabekanal (d.h. zum Bildschirm, solange die Ausgabe nicht irgendwohin umgeleitet wurde).
    $ab1e gibt den nullterminierten String aus, dessen Adresse per A/Y übergeben wurde. Die Ausgabe erfolgt via $ffd2, allerdings ist dies eine Basic-Funktion, d.h. es gibt diverse Bedingungen zu beachten: Die Länge ist auf 255 Zeichen limitiert und bestimmte Zeichen wie z.B. Anführungszeichen können nicht verwendet werden.

    t0m3000 schrieb:

    Ich denke aber auch, dass ASM so schnell sein wird, dass der Effekt nicht so zu Stande kommt.
    An der Geschwindigkeit ändert sich so kaum etwas, denn die meiste Zeit wird hier eh vom Scrolling verbraucht.
    Yes, I'm the guy responsible for the ACME cross assembler
  • Hallo zusammen,

    Das Ganze etwas aufgehübscht, weil ich einfach Zeit hatte.

    Vorschau:

    Quellcode

    1. *=$801
    2. !basic init
    3. init lda #0 ; Hintergrund Schwarz
    4. sta $d020
    5. sta $d021
    6. lda #<$d800 ; Adresse Color Ram holen
    7. sta $fb
    8. lda #>$d800
    9. sta $fb+1
    10. lda #<color ; Adresse color holen
    11. sta $fd
    12. lda #>color
    13. sta $fd+1
    14. ldx #24 ; Farben aus color in Color Ram kopieren
    15. -- ldy #39
    16. - lda ($fd),y
    17. sta ($fb),y
    18. dey
    19. bpl -
    20. clc
    21. lda $fb
    22. adc #<40
    23. sta $fb
    24. lda $fb+1
    25. adc #>40
    26. sta $fb+1
    27. clc
    28. lda $fd
    29. adc #<40
    30. sta $fd
    31. lda $fd+1
    32. adc #>40
    33. sta $fd+1
    34. dex
    35. bpl --
    36. loop lda #<$400 ; Screen Ram holen
    37. sta $fb
    38. lda #>$400
    39. sta $fb+1
    40. -- ldy #12 ; String in Color Ram schreiben
    41. - lda String,y
    42. sta ($fb),y
    43. dey
    44. bpl -
    45. clc
    46. lda $fb
    47. adc #<13
    48. sta $fb
    49. lda $fb+1
    50. adc #>13
    51. sta $fb+1
    52. lda $fc
    53. cmp #$08
    54. bne --
    55. lda String ; String nach links rotieren
    56. pha
    57. ldy #1
    58. - lda String,y
    59. dey
    60. sta String,y
    61. iny
    62. iny
    63. tya
    64. cmp #13
    65. bne -
    66. pla
    67. ldy #12
    68. sta String,y
    69. - lda $d012 ; 2 VBlank abwarten
    70. cmp #251
    71. bne -
    72. - cmp $d012
    73. beq -
    74. - lda $d012
    75. cmp #251
    76. bne -
    77. jmp loop
    78. rts
    79. String !byte 111,82,70,67,68,69,119 ; Wellen String
    80. !byte 69,68,67,70,82,111
    81. color !for LINES = 0 to 24 ; Farben für Color Ram
    82. !fill 5,$0b
    83. !fill 5,$0c
    84. !fill 5,$0f
    85. !fill 10,$01
    86. !fill 5,$0f
    87. !fill 5,$0c
    88. !fill 5,$0b
    89. !end
    Alles anzeigen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von Deus ()

  • Mac Bacon schrieb:

    An der Geschwindigkeit ändert sich so kaum etwas, denn die meiste Zeit wird hier eh vom Scrolling verbraucht.
    Also den Unterschied merkst schon gewaltig, vor allem kriegt man so das Tearing weg und kann gemütlich einen VSync einbauen.


    Bytebreaker schrieb:

    Der Effekt ist schick, aber es ist ein typischer Basic-Effekt, der funktioniert, weil er langsam ist.
    Dabei ist der Print-Befehl ja schon besonders schnell.

    Ohne künstliche Verzögerung kann ich mir gut vorstellen, dass der Effekt in Assembler so schnell ist, dass man ihn optisch nicht mehr genießen kann. Das sieht man dann wenn es soweit ist und kann ggf. künstlich bremsen. Die Schleifenmechanik in Asm ist ja viel schneller.

    Wenn man das Ganze ohne Basic-Aufrufe abbilden will, wird das nicht nur zu schnell, sondern man muss sich auch überlegen wie man das "Hochscrollen" des Bildschirms bewirken will, denn mit Poken ins ScreenRAM allein ist es ja nicht getan. Aus meiner Sicht zu umständlich und auch zuviel für eine Anfänger-Übung.
    Der Trick ist es den String zu rotieren, kannst das Hochscrollen völlig fallen lassen.
  • Ob ich jetzt eine Zeile, um eine Zeile, hochkopiere oder die identische Zeile durch das rotieren des Strings erzeuge und so exakt das Selbe in den Screenram kopiere macht keinen Unterschied. (Außer natürlich ein Stückchen längerer, langsamerer Code.)

    Und die Raffinesse ist aus Basic heraus zu verstehen. Aus ML/ASM ist es dann der Rollstuhl, laufen mit gebrochenen Beinen.

    Funktioniert übrigens auch mit den vertikalen Linien.
  • Das ist nett. :)

    Würdest du den Quellcode posten?

    Es dürfte ähnlich sein wie oben nur mit entsprechenden Offsets +40 Zeichen und +1 Zeichen. Die Linien werden in einer doppelten for next Schleife von oben nach unten und von links nach rechts gemalt denke ich.

    Poste doch den Code, es ist eine gute Anfängerübung und vielleicht fällt jemandem eine Kürzungsmöglichkeit oder dergleichen auf. Auf die Art habe ich hier auch viel lernen dürfen.
  • Quellcode

    1. String !byte 116,84,71,66,72,89,106 ; Wellen String Vertical
    2. !byte 89,72,66,71,84,116
    3. color !for LINES = 0 to 24 ; Farben für Color Ram vertical lines
    4. !byte 0,9,6,11, 2,8,4,14, 12,10,5,15, 3,13,7,1
    5. !fill 8,1
    6. !byte 1,7,13,3, 15,5,10,12, 14,4,8,2, 11,6,9,0
    7. !end
    Das ist die ganze Änderung zu oben. ;)

    Ich schreib linear in den ScreenRam, nur eine Schleife.
    Der String hat 13 Zeichen.
    Das ergibt in der Zeile 39 Zeichen, somit verrutscht in der nächsten Zeile die Ausgabe um ein Zeichen.
    Die nächste Zeile fängt also mit 12 Zeichen an, die danach mit 11 Zeichen aus dem String. So erzeugt das denn Offset um +1.
    Ich brauch mich also um das Zeilende nicht zu kümmern und schreib einfach weiter.

    Um jetzt aber nicht jedesmal den gleichen Screen Ram zu schreiben, rotiere ich am ScreenEnde den String um ein Zeichen nach links.

    Dazwischen warte ich dann noch 2 mal auf den Raster, damit kein Tearing/Flackern auftritt und die Geschwindigkeit reduziert wird.
  • Ach und noch was, ich fang das Ende des Screen rams nicht sauber ab, ich schreib bis maximal $400+12 Screen Daten, kann also alles böse ins Auge gehen.
    Ich zerschieße auf jedenfall die Sprite Adressen. Bei einer Datenmenge von $3E8 sollte man abbrechen.
    Hab ich zum Schluss vergessen noch sauber zu korrigieren.
  • Deus schrieb:

    Ob ich jetzt eine Zeile, um eine Zeile, hochkopiere oder die identische Zeile durch das rotieren des Strings erzeuge und so exakt das Selbe in den Screenram kopiere macht keinen Unterschied. (Außer natürlich ein Stückchen längerer, langsamerer Code.)
    Du hast dir aber schon den Artikel über die Barber-Pole-Illusion durchgelesen?

    Deus schrieb:

    Und die Raffinesse ist aus Basic heraus zu verstehen.
    Nochmal: es funktioniert in BASIC genau nur aufgrund der Barber-Pole-Illusion, welche hier die senkrechte Bewegung des Scrollens in eine waagerechte Bewegung der Wellen "umwandelt". Das geht hier auch überhaupt nur, weil ein Vielfaches der ausgedruckten Zeichenkette genau die Zeilenbreite-1 ist (3x13 = 39 = 40-1). Mit anderen Längen funktioniert die Illusion nicht mehr und man sieht auch in BASIC wieder 'nur' das normale Hochscrollen.

    Umgekehrt kann ich in Maschinensprache mit der "straightforward"-Implementierung alles mögliche nach links oder rechts schieben, ohne daß der zu erzielende Effekt auf die Barber-Pole-Illusion zurückgreifen muß. Die Welle kann also z.B. auch 12 Zeichen oder 14 Zeichen lang sein. Nur ist DA dann überhaupt nichts tricky dran - der Maschinencode macht einfach im Speicher das, was man auch auf dem Bildschirm *sieht*.

    Deus schrieb:

    Aus ML/ASM ist es dann der Rollstuhl, laufen mit gebrochenen Beinen.
    Ich hab' übrigens auch schon ein paar Programme in Maschinensprache geschrieben. Das hält mich nicht davon ab, den BASIC-Einzeiler in seiner Einfachheit richtig gut zu finden.
  • Wie oben im Quellcode und in meiner Erklärung beschrieben, nutze ich genau die Ein-Zeichen-Differenz einer Zeile aus.
    Ich schreibe den Ram linear. Nur die Implementierung des Zeilen nach oben kopierens "simuliere" ich mit dem rotierenden String.
    Ist wesentlich unaufwendiger, da ich nur 13 Zeichen umkopieren muss und nicht 40x25. Macht den Code einfacher.

    Ich kenne die Barber-Pole-Illusion, ist mir auch als solche bekannt. Und ja, das ist Teil der Illusion, die Wahl der Character macht dazu noch die Wellenform.

    Und zum Schluß noch eine Entschuldigung, wollte dir damit nicht auf den Schlips treten. Aus Basic-Sicht ist es ja auch schön simple.