Hello, Guest the thread was called398 times and contains 15 replays

last post from zrs1 at the

Fullscreen Multicolor Bitmap seitwärts scrollen auf NTSC in voller Geschwindigkeit?

  • Für ein Projekt habe ich heute einen Fullscreen MC Bitmap Seitwärtsscroller gebastelt. Im ersten Test hat das Ding in "voller Geschwindigkeit" gescrollt, also ein Pixel pro Frame. Auf PAL ging das, auf NTSC ging die Rechenzeit aus...


    In meinem konkreten Fall ist sowieso ein langsameres Scrolling (ein Pixel alle zwei Frames) gewünscht, passt besser zum dargestellten Inhalt. Trotzdem interessiert mich jetzt die Frage: Ist es überhaupt technisch möglich, in voller Geschwindigkeit auf NTSC zu scrollen? Man muss ja immerhin die Bitmap und das Screenram vorfüllen (double buffering) und das Color RAM "live" füllen beim Wechsel des Buffers (also alle 8 Pixel). Wenn ich das jetzt also in voller Geschwindigkeit wollte, müsste ich "nur" meinen Code optimieren, oder ist das von vorneherein aussichtslos?

  • Wuerde mich arg wundern, wenn das nicht passt?

    Du hast ja 7 Frames Zeit die bitmap umzukopieren. Wie sieht denn da Dein code aus?

    Im Moment liegen die zu scrollenden Daten ("block-")zeilenweise im Speicher, ich habe pro Zeile einen Pointer auf die nächste "Startspalte", gehe diese Pointer Zeile für Zeile durch, addiere 8 (bitmap) bzw 1 (screenram und colram) und setze sie jeweils per selbstmod in eine x-indizierte Kopierschleife... bestimmt nicht der schnellstmögliche Code, aber ich denke mal ganz schlecht ist der Ansatz auch nicht.


    Also die 7 (bzw fast 8 ) Frames habe ich Zeit für insgesamt eine Datenmenge wie 9 Textscreens (8 für die bitmap, einen für die Farben im Screenram) ... und ...

    Color ROM copy vor/hinter dem Rasterstrahl ist kein Zeitproblem.

    ... natürlich ist DAS kein Problem ;) Aber es braucht eben auch Rechenzeit, die vom restlichen Kopieren abgeht.

  • Naja, Du kopierst 8KB um in 7 frames und wenn man so will 1KB (color) "im" 8. Frame (naja, wie man das halt betrachten will ;-).

    Best case: 8000 * LDA+ STA sind 47 KB speedcode :) und 64K cycles. NTSC hat etwa 17000 cycles, PAL etwa 20000 per frame.

    Komplett unrolled brauchst Du also keine 4 Frames fuer die bitmap.

    Wie breit willst Du denn scrollen?

  • Naja, Du kopierst 8KB um in 7 frames und wenn man so will 1KB (color) "im" 8. Frame (naja, wie man das halt betrachten will ;-).

    Da fehlt 1KB, das Screen-RAM -- insgesamt sind alle 8 frames 9750 bytes zu bewegen, also 9,75 KB bzw ca 9,5 KiB. Ein bisschen weniger wird es, weil im 38col modus die 40te Spalte nie sichtbar wird.

    Best case: 8000 * LDA+ STA sind 47 KB speedcode :) und 64K cycles. NTSC hat etwa 17000 cycles, PAL etwa 20000 per frame.

    Komplett unrolled brauchst Du also keine 4 Frames fuer die bitmap.

    Ähm ja, ich denke man muss da definitiv von indexed LDA/STA ausgehen. Komplett unrolled lässt noch nicht einmal genug Platz für die beiden Buffer (die können ja leider nicht ganz "zusammenhängend" liegen), geschweigedenn für irgendwelchen zu scrollenden Inhalt ;)


    Berücksichtigen die Cycle-Zahlen bereits Badlines?


    Also die Überschlagsrechnung führt IMHO schon zu "es wird wohl eng" ...

    Wie breit willst Du denn scrollen?

    In dem Fall ging es um 138 Spalten, also knapp 3,5 Screens -- Die Daten dafür belegen im Moment $1180-$8bdd und $bf40-$cba5, und da sind noch keine Tabellen eingerechnet, um die Zeilen zu finden :)

  • Ich muesste man schauen wir ich das hier gemacht hatte - ist aber ne Weile her und ich will nicht ausschliessen, dass das nicht die volle Hoehe war.

    https://csdb.dk/release/?id=125622

    lda ,x sta,x sind dann halt knapp 10 cycles. Wenn Du schneller als 1KB pro Frame bist, dann passt das colorram in den 8. frame quasi.

    Daher 7 fuer die 8KB davor.

  • Ich muesste man schauen wir ich das hier gemacht hatte - ist aber ne Weile her und ich will nicht ausschliessen, dass das nicht die volle Hoehe war.

    https://csdb.dk/release/?id=125622

    Also wenn ich das jetzt richtig sehe hat das ja nur 4 Farben, dann fallen schonmal 1950 bytes (color- und screenram) weg ;)


    edit: murks, my bad, es ist ja hires. aber immerhin fallen 975 bytes weg, das color-ram ist bei hires ja egal :)

  • Ich stelle jetzt mal meine eigene Überschlagsrechnung an. Vorbedingung: "Speedcode" geht nicht, der würde so viel RAM brauchen, dass nichts mehr für den tatsächlich zu scrollenden Inhalt übrig ist.


    Auf NTSC haben wir pro Frame 263*65 = 17095 Cycles. Auf dem alten NTSC sind es sogar nur 262*64 = 16768.

    Für die Darstellung einer MC Bitmap brauchen wir Badlines, die belegen 25*40 = 1000 Cycles.


    Wenn wir "old NTSC" mal außen vor lassen bleiben damit gut 16000 Cycles pro Frame.


    Ohne Speedcode muss in einer Schleife kopiert werden, jedes Byte schlägt also zu Buche mit LDA,x (4) + STA,x (5) + INX (2) + BNE (3) = 14 Cycles. (STA,x kann auch 5 Cycles brauchen, BNE auch 2, nehme hier mal den häufigsten Fall)


    Pro 8 Frames müssen wie oben berechnet 9750 Bytes bewegt werden, macht für das reine kopieren schon 14 * 9750 = 136500 Cycles, pro Frame also im Schnitt 17062 Cycles.


    Schon das passt also nicht, dazu kommt noch Code um die Pointer der Kopierschleife neu zu setzen, ein Interrupt-Handler der den Hardware-Scroll steuert und ein Flag für die Kopierschleife setzt, usw.


    Man könnte aber noch "teilweise unrollen" und in einer Schleife alle Zeilen parallel behandeln. Damit lassen sich für das reine kopieren 5 Cycles pro Byte sparen. Sie kommen dafür pro Zeile dazu. Auf das Color-RAM ist das aber nicht anwendbar, da es dem Rasterstrahl folgen muss, also muss man strikt zeilenweise kopieren. Die Rechnung ist dann etwas komplizierter:


    Für 8775 Bytes (Bitmap + ScreenRAM) ist das reine kopieren 9*8775 = 78975 + 50 (Zeilen Bitmap & Screenram) * 5 = 79225 Cycles und für das ColorRam kommen 975 * 14 = 13650 Cycles dazu, insgesamt 92875 Cycles für das reine kopieren. Die 75 Startpointer (25 Zeilen je Bitmap, Screenram, Colram) neu setzen kostet 75*2*8 = 1200 Cycles, sie weiterzählen kostet 75*2*(2 [ADC] + 5[STA,y]) = 1050 Cycles -- schon sind wir bei 95125 Cycles.


    Damit wären wir bei teilweise unrollen auf im Schnitt 11890 Cycles pro Frame. Es blieben gut 4000 Cycles pro Frame für den Interrupt-Handler, sonstige Verwaltung, eventuell Musik.


    Daher behaupte ich mal die Antwort auf meine eigene Frage heißt: Ja, theoretisch sollte es mit "partially unrolled" Code gerade so sinnvoll möglich sein. Ich teste es jetzt nicht, weil wie gesagt für das aktuelle Projekt halbe Scrollgeschwindigkeit sowieso angemessener ist. Aber gut zu wissen, dass es geht. Oder findet jemand einen Fehler in der Rechnung?

  • Ich behaupte mal das ist keine Bitmap. In der Breite würde das RAM des C64 gar nicht ausreichen. Was da dargestellt wird hat viele wiederkehrende Elemente, das ist ziemlich sicher multicolor character mode. Und das ist ziemlich harmlos zu scrollen ;)

    Der 3. Level mit den Bäumen und Felsen scheint mir dafür sicher zu bunt.
    Im MC-Modus hat man ja nur die ersten 8 Farben als Zeichenfarbe, alle Farben ab Orange(8) müssen MC-Farben sein.
    Und ich sehe da 3 Graustufen in Felsen uns Stämmen, dazu Hellgrün, Orange und Braun in gleichen Rasterzeilen...

    Aber ist das denn auch ein NTSC-Spiel?

  • Was die Wiederholung von Grafikelementen betrifft, das ist

    dem begrenzten Speicherplatz geschuldet. Das macht man auch

    heute noch bei 2D-Spielen. Es werden eine Reihe von Einzel-

    grafiken (Tiles) erstellt, aus denen man dann die Gamegrafik

    zusammensetzt.


    Einen Multicolor-Zeichensatz kann man daran erkennen, dass

    nie mehr als 3 Farben mit einem Farbwert > 7 auf gleicher

    Höhe sind (wegen der Register $d021-$d023). Das Farbram kann

    hier nur Werte von 0 - 7 annehmen. Hier ein vergrößerter

    Ausschnitt der In-Game-Grafik. Auf dem kleinen Bereich sind

    bereits 5 Farben mit dem Farbwert > 7. Das heißt, es kann

    auf keinen Fall ein Multicolor-Zeichensatz sein.

  • Bin ich was froh, dass das endlich mal einer erklärt!

  • Another World von X-Ample benutzt afair AGSP um den Bitmap-Screen zu scrollen (wenn auch "nur" horizontal, also auf der X-Achse). Die Sprites für die Statusanzeige im oberen Bereich dienen dazu, um die ersten 25 Zeilen, welche für Bitmap-Grafik aufgrund AGSP nicht benutzbar sind zu nutzen (und um ein paar Taktzyklen zu verschwenden für das AGSP-timing).

    Coding-mässig ist das, was Ivo Herzeg hier gemacht hat, schon richtig, richtig genial. Mir fällt momentan auch kein Spiel ein, welches technisch auf einem ähnlichen Niveau sich befindet. (Nein, auch nicht Turrican: Hier wird - obgleich auch auf geniale Art und Weise - Charset anstelle benutzt (afair)).

  • Also AGSP (bzw hier wohl einfach VSP) finde ich durchaus auch interessant, vor allem weil mir nicht ganz klar ist, wie man damit schnelleres fullscreen-scrolling realisieren soll, da der Inhalt ja soweit ich weiß "wrappt", wenn er durch diesen Trick verschoben wird? Aber ich denke das gehört wenn dann in einen anderen Thread :D Und den Nachteil kennt ja vermutlich auch jeder: nicht wenige C64 crashen einfach, weil das RAM (jede 8. Speicherstelle AFAIR?) korrumpiert wird.


    Hier soll es also um das Scrollen ohne VIC-Tricks gehen. Nach meiner Rechnung sollte "partially unrolled" Code theoretisch ausreichen, um auch auf NTSC schnell genug zu sein. Stimmt das so? Kennt ihr Software (Intros, Demos, ...) die das tut? In einem Spiel wäre das wohl völlig inpraktikabel, weil man ja definitiv double buffering braucht.