Hello, Guest the thread was viewed6.2k times and contains 94 replies

last post from Zirias/Excess at the

Map effizient auf Screen abbilden

  • Anschauliches (und blödsinniges) Beispiel: aus

    Code
    1. .repeat 4, x
    2.         lda    $fc00+($28*x)
    3.         sta    $d800+($28*x)
    4. .endrep

    erzeugt der Präprozessor (ich nenne es einfach mal so in der Annahme, dass ein solcher vorgelagerter Durchgang die naheliegendste Implementierung ist):

    Code
    1.         lda    $fc00
    2.         sta    $d800
    3.         lda    $fc28
    4.         sta    $d828
    5.         lda    $fc50
    6.         sta    $d850
    7.         lda    $fc78
    8.         sta    $d878

    DAS wird dann wirklich in machinecode assembliert.

  • Lustig wird es, wenn man in solchen Konstrukten selbstmodifizierenden Code einbauen möchte. ;-)


    Ich habe jetzt meine Routine wie folgt umgeschrieben:

    Da ich in meinem Programm mehrere Maps mit völlig unterschiedlichen Größen auf den Bildschrim bringen möchte, habe ich mich doch für die generische Variante entschieden.

  • Lustig wird es, wenn man in solchen Konstrukten selbstmodifizierenden Code einbauen möchte. ;-)

    Hab ich doch in meinem ersten hier geposteten Beispiel getan :-D Ja, dann hilft es, zu wissen, wieviele Bytes der generierte Code am Ende wirklich belegt...

    Ahhh, sehe ich jetzt erst. Deshalb das "6*row". Sehr cool!


    Warum eigentlich 23? In Stoneage64 zähle ich 21 Zeilen an Steinen.

  • Warum eigentlich 23? In Stoneage64 zähle ich 21 Zeilen an Steinen.

    Sichtbar sind knapp 22 auf einmal. Und durch das Pixel-Scrolling werden alle 23 gebraucht, sonst Glitches am oberen oder unteren Rand. Die restlichen 2 Zeilen bleiben aber für das Status-Display reserviert.


    Ich denke verglichen mit dem was früher zum Teil so verbrochen wurde (weniger als die Hälfte vom Bildschirm für das eigentliche Game) ist das doch recht anständig geworden. Und ist dann halt auch der Grund, warum ein "naiver" Ansatz mit geschachtelten Schleifen zumindest auf NTSC entschieden zu lahm war :-D

  • Also eine Art Hochsprachen Befehl im Assembler. Ist sowas nicht ineffizient?

    Kommt drauf an in welcher Dimension :-D Diese Befehle (die einfach einen Code-Block zig mal wiederholen, angepasst mittels einer Laufvariablen) blähen natürlich den Code gewaltig auf, also in der Dimension RAM ist es "ineffizient". "Richtig" eingesetzt kommt dabei aber Code heraus, der schlicht schneller läuft. Ist übrigens ein altbekanntes Optimierungsproblem: Laufzeiteffizienz vs Speichereffizienz, pick one.

    Ich bin ja immer am Wettern, wenn ich sowas sehe. Also selbstmodifizierenden Code und redundanten Code. Das liegt daran, dass ich jahrelang beruflich Microcontroller programmiert habe (6502, Z80, 8085 usw.), wo der Code immer im ROM lief. Ich käme überhaupt nicht auf die Idee, selbstmodifizierenden Code zu schreiben, auch wenn das Programm im RAM läuft.


    Aber wenn es um Geschwindigkeit und Demos geht, dann ist natürlich alles erlaubt. :D

  • detlef – dass Code, der aus dem ROM lauffähig sein muss, selfmod verbietet, hatte ich ja schon in meinem ersten Posting erwähnt. Aber abgesehen davon: Versuch mal den 8-way Scroller für Stoneage64 ohne selfmod auf NTSC zum laufen zu kriegen (so, dass auch noch Rastertime für die eigentliche Spiellogik und die Musik bleibt), ich behaupte mal, das ist unmöglich. Also, nicht NUR was für Demos :-D

  • Also, nicht NUR was für Demos :-D

    Demos und "wenn es um Geschwindigkeit geht" hatte ich geschrieben. :thumbsup:

  • Sichtbar sind knapp 22 auf einmal.

    War eh Quatsch, was ich geschrieben habe. Ein Stein ist 9 Pixel hoch. Ich habe mal das Video angehalten und gezählt: ich erhalte dabei die Anzahl von 21*9 +3 = 192 Pixel in der Höhe. Das sind genau 24 Character-Zeilen, also mehr als deine 23. Hmm...

  • Demos und "wenn es um Geschwindigkeit geht" hatte ich geschrieben. :thumbsup:

    Da hast du recht :whistling:


    Und darum geht es auf dem C64 halt recht schnell und häufig :-D Selfmod ist eine SEHR gängige Programmiertechnik, weil vieles anders gar nicht zu schaffen ist. Heutzutage selbst bei Cartridge-Versionen in Verwendung, da läuft der Code nicht mehr direkt aus dem CRT wie damals, sondern wird vorher ins RAM kopiert. Die heutigen CRTs haben auch in der Regel Banking und damit sehr viel mehr Speicherplatz ;-)

  • Ich bin ja immer am Wettern, wenn ich sowas sehe. Also selbstmodifizierenden Code und redundanten Code.

    Mich würde, zum hervorgehobenen Teil, noch interessieren: Warum das denn? Oder auch der Zeit geschuldet, weil Platz im ROM teuer war? :-D


    Wie weiter oben schon erwähnt ist das heutzutage ja absolut üblich, etwas Laufzeiteffizienz wird gerne "erkauft" durch "Verschwendung" von RAM ;-)

  • Da ich in meinem Programm mehrere Maps mit völlig unterschiedlichen Größen auf den Bildschrim bringen möchte, habe ich mich doch für die generische Variante entschieden.

    Und das ist völlig ok! Müsstest du nur dann überdenken, wenn du wirklich an Grenzen stößt und es einfach zu langsam wird. "Generisch" ist langsamer, daran führt kein Weg vorbei, aber solange man alles gezeichnet kriegt bevor es sichtbar "glitcht" gibt es keinerlei Grund, daran etwas zu ändern :thumbup:


    edit: Nur immer NTSC bedenken, falls man das supporten will ... die 20% schnellere Framerate kann heftig in die Suppe spucken :-D

    edit2: NTSC war der Grund, warum ich von einer Map mit "Tile-Nummern" weggekommen bin und stattdessen die Map schon beim Level-Laden in Screencodes übersetze, was 4 mal so viel RAM braucht, aber nur so war das Zeichnen auf NTSC noch schnell genug. NTSC is a bitch :thumbsup:

  • Ich bin ja immer am Wettern, wenn ich sowas sehe. Also selbstmodifizierenden Code und redundanten Code.

    Mich würde, zum hervorgehobenen Teil, noch interessieren: Warum das denn? Oder auch der Zeit geschuldet, weil Platz im ROM teuer war? :-D

    Jedes gesparte ROM machte das Produkt billiger. Und weil die Stückzahlen pro Programmversion im Bereich 1000-2000 Stück lagen, lohnte keine Maskenprogrammierung. Und EPROMs waren teuer. Später gab's dann die OTP ROMs (EPROMs ohne Fenster).


    Und wenn ich kein Geschwindigkeitsproblem habe, dann muss ich ja nicht mit redundantem Code arbeiten. Das ist für mich eine Notlösung zur Geschwindigkeitsoptimierung.

  • Und wenn ich kein Geschwindigkeitsproblem habe, dann muss ich ja nicht mit redundantem Code arbeiten. Das ist für mich eine Notlösung zur Geschwindigkeitsoptimierung.

    Das ist es immer. In erster Iteration steht immer der möglichst generische platzsparende Code. Auf dem C64 ist das "Geschwindigkeitsproblem" halt immer gleich um die Ecke. Ein Luxus, dass heutzutage Speicherplatz "nichts" mehr kostet ;-)


    Ja, dachte mir schon, dass so eine Antwort kommt, das ergibt durchaus auch Sinn!

  • Es gibt ja nicht nur die Code-Optimierung, sondern auch noch die Zugriff/Daten-Optimierung. Wenn für die Map nur wenige Zeichen verwendet werden, könnte man die Zeichen auch entsprechend der Farbe im Zeichensatz ablegen. Dann kann man die Farben ohne Tabellenzugriff direkt ins Farbram schreiben, kommt ohne den Illegalen Opcode LAX oder TAX aus und spart so weitere 4 oder 6 Takte pro Zeichen ein. Außerdem sollte man dafür sorgen, dass die Routine in einer Page liegt, sonst kosten CC-Sprünge eventuell ein Takt mehr beim Ausführen.


    Die Routine für die Bildschirm / Farbram-Adresse kann man zusammen legen und optimieren.

  • könnte man die Zeichen auch entsprechend der Farbe im Zeichensatz ablegen.

    Funktioniert halt nur so lange wie keine zwei verschiedenen Zeichen die gleiche Farbe brauchen :huh:


    Aber WENN das wirklich so ist, ist das natürlich eine sehr clevere Optimierung :thumbup:


    EDIT: Man kann die Idee auch generalisieren: Das high-nibble der Farbe ist ja unbenutzt -- damit lässt sich das auf fast jedes Szenario ausweiten, WENN man auf die restlichen Zeichen im Charset verzichten kann (kann ich bei Stoneage64 leider nicht, ich brauche da Textzeichen ... aber so im Allgemeinen, coole Idee!)