Hallo Besucher, der Thread wurde 2,1k mal aufgerufen und enthält 15 Antworten

letzter Beitrag von Bytebreaker am

Bytes ins SCREEN/COLOR RAM kopieren

  • Halli hallo,


    Ich bitte um eine kleine Code-Review :)


    Ich bin jetzt nicht voll der ASM und C64 Hardware Profi, aber ein par Grundlagen kenne ich und habe früher viel mit ASM für x86 gearbeitet (Demo-Scene Kram).


    Ich schreibe eine Routine die einfach einen Byte Array (Byte für Byte) in den SCREEN oder COLOR Speicher kopieren soll. Wahrscheinlich ist es nicht die schnellste Lösung, aber funktioniert schon mal:


    * ZP_POINTER_1 zeigt auf den Anfang des Byte Array's
    * ZP_POINTER_2 zeigt auf die richtige Position des SCREEN oder COLOR RAM's
    * PARAM_1 ist die Breite einer Zeile in den Byte Array
    * PARAM_2 ist die Anzahl der Zeilen

    Dieser Code Snippet ist erstmal nicht so wichtig :)


    So, wenn man den Gesamten Screen füllen will, braucht man 2000 Bytes für Zeichen und Farben was natürlich zu viel ist. Ich habe mir gedacht ich packe jetzt ein bisschen die Daten, und zwar einfach so das vor jedem Zeichen (Byte) erstmal ein Zähler (Byte) kommt wie viel mal muss man das nächste Zeichen wiederholen. Auch wenn man das Zeichen nur einmal zeichnen muss, kommt davor immer ein Zähler, in diesen Fall - eine 1.


    Zum Beispiel:
    11,22,22,33,33,33,44,44,44,44,55,55,55,55,55


    ... könnte man so zusammen schrumpfen:
    01,11,02,22,03,33,04,44,05,55


    In meinem Fall wurden die Daten für die Zeichen 25% kleiner, und für die Farben sogar 75%.


    Natürlich musste ich jetzt meine Routine umbauen, und habe auch eine Lösung gefunden. Ich habe die Routine auch sehr viel optimiert, aber trotzdem denke ich da könnte man noch ein bisschen rum schrauben. Mir gefällt das ständige updaten des Pointers nicht so gut. Die Routine benutzt auch 3 extra Speicherplätze ($c000, $c002, $c004) um Daten temporär zu Speichern.


    Ich wollte gerne eure Meinung hören, da ich, wie schon gesagt, kein Profi bin :)

    Vielen Dank!

  • Das ist so nur sinnvoll wenn Du einzelne (rechteckige) Bereiche fuellen willst.
    Wenn Du eh einen ganzen screen (bzw etwas ueber die volle Breite) wuerde man das anders angehen:
    ldx #250
    loop
    lda coldata-1+250*0,x
    sta $d800-1+250*0,x
    lda coldata-1+250*1,x
    sta $d800-1+250*1,x
    lda coldata-1+250*2,x
    sta $d800-1+250*2,x
    lda coldata-1+250*3,x
    sta $d800-1+250*3,x
    dex
    bne loop



    Aber auch in Deinem Fall wird es ein WENIG schneller wenn Du statt ldx #0 und inx den umgekehrten Weg gehst:
    ldx #breite
    blabla
    dex
    bne loop

  • Die ColorRAM Farben sind nur 4Bit, da könnten also zwei Werte in einem Byte stehen. Abhängig von der Grafik könnte man auch gleich zwei Werte in deinem "Zähler"-Byte speichern, sofern es kaum große Flächen mit gleichen Zeichen gibt. Wird aber alles langsamer und aufwändiger, wenngleich platzsparender. Am Ende ist es eine Kompromisfrage. Meistens ist die oben genannte Schleife die sinnvollste Lösung...

  • hm du koenntest die adc's auf die zeropage legen das wuerde nochmal was bringen an groesse und speed.
    dazu $c000, $c002, $c004 zu $5c+ oder $57+ machen.(jeweils 4 bytes sollten das sein)
    ich hoffe ich hab mich in den adressen nich geirrt.


    salute


    Edit:

    Code
    1. ;check if current pos in row in $c000 is the last on
    2. lda #0
    3. cmp $c000
    4. bne cprd_loopx

    koennte ma nda nich auch einfach


    Code
    1. lda $c000
    2. bne cprd_loopx

    screiben?

  • @enthusi


    Danke Dir, aber ich brauche wirklich eine Routine die auch kleinere rechteckige Bereiche füllen kann.


    @Squidward


    Für die Farben könnte man zwei Stück in einen Byte speichern, aber das Packing geht auch richtig gut mit einem Byte und den Zähler. Und ich kann die gleiche Routine benutzen wie für den SCREEN.


    @Haubitze


    Ja die $c000-$c006 sind nur temporär da, ich bin mir sicher ich finde noch ein par freie ZeroPage Stellen für die Werte. Aber die Lösung "lda $c000" ohne noch einen "cmp" zu machen finde ich gut. Ist mir nicht aufgefallen. Danke!


    @Hexworx


    Lustig, aber ich habe mich so gewöhnt das ich niemals Freie Register habe, das mir überhaupt nicht aufgefallen ist das der X nicht benutzt wird. Den X benutze ich jetzt für PARAM_1, so das ich einen von den drei $c00X entfernt habe.


    Jetzt ist mir aufgefallen das ich am Anfang den PARAM_2 ins $c002 kopiere und nur am Ende der Routine wieder für einen Check benutze. Man könnte direkt mit dem PARAM_2 arbeiten und den $c002 sparen.

  • Hallo,


    ich wollte eigentlich ein eigenes Thema öffnen aber meine Frage passt hier denke ich gut rein:


    Wenn ich im Mehrfarben Bitmap Multicolor Modus Linien färben will, dann kann ich im ersten Step ganze 8x8 Bitmap Bereiche färben durch Poken in ColorRAM und ScreenRAM.


    Dann käme die Feinjustage:
    Im Multicolor Modus kann ich in jedem 8x8 Bereich 4 Farben unterbringen, abhängig vom Muster in der Bitmap. So sollen zum Beispiel Überfärbungseffekte verhindert werden, wenn verschiedenfarbige Linien sich kreuzen.


    Wenn ich mit Tilesets arbeite, kann ich festlegen, welche "Farbregeln" für das Tileset und seine Bitmuster gelten und dadurch für Sauberkeit in der Abbildung sorgen, egal wo sie platziert wird. Es müssen nur ColorRAM, ScreenRAM und Bitmap deckungsgleich konfiguriert sein.


    Jetzt male ich aber mit einem Linien-Algorithmus, der nicht vorhersagbar ist. Ich kann für jeden geplotteten Pixel die ScreenRAM und ColorRAM Location berechnen und entsprechend färben, aber ich "überfärbe" zwangsläufig.


    Es gibt nun natürlich noch die "Korrekturoption", indem ich sage, "hier kreuzt eine Linie, alle "01" Muster in diesem 8x8 Bereich haben Farbe x und alle "10" Muster die Farbe y. Das wäre aber etwas manuelles, was man nicht dynamisch erkennen und beheben kann, liege ich da richtig?


    D.h. unser Lieblings-Computer kann nicht pixelgenau ohne manuelle Korrekturarbeit sich überlagernde Linien färben, obwohl nicht nur ein CPC das kann, sondern auch ein MSX-1? Das wäre ja echt hart, aber man müsste damit leben.

  • ich wollte eigentlich ein eigenes Thema öffnen aber meine Frage passt hier denke ich gut rein:

    Finde ich nicht, aber ich bin mir auch nicht sicher, ob ich die Frage richtig verstanden habe. :D

    Wenn ich im Mehrfarben Bitmap Multicolor Modus Linien färben will, dann kann ich im ersten Step [...]
    Dann käme die Feinjustage [...]

    Ich halte es für deutlich einleuchtender, die VIC-II-Modi gedanklich von der anderen Seite aus zu modellieren:
    Die Multicolor-Grafik ist kein "160x200-Pixel-Modus mit 16 Farben, die aber nicht unabhängig voneinander plaziert werden können".
    Besser: Die Multicolor-Grafik ist ein "160x200-Pixel-Modus mit vier Farben, von denen drei in jeder Farbkachel geändert werden können".

    D.h. unser Lieblings-Computer kann nicht pixelgenau ohne manuelle Korrekturarbeit sich überlagernde Linien färben, obwohl nicht nur ein CPC das kann, sondern auch ein MSX-1?

    Die können das auch nicht. Über den MSX weiß ich zwar nichts, hab aber auf die Schnelle dies gefunden.
    Beim CPC sieht es besser aus, da er eine doppelt so hohe Auflösung (oder Farbtiefe, je nachdem) wie der C64 hat:


    160x200 @ 2bpp (C64) vs. 160x200 @ 4bpp (CPC)
    320x200 @ 1bpp (C64) vs. 320x200 @ 2bpp (CPC)
    640x200 @ gibsgarnich (C64) vs. 640x200 @ 1bpp (CPC)


    Vergleicht man also die beiden 160x200-Pixel-Modi direkt miteinander, tritt das Color-Spill-Problem beim CPC nicht auf. Aber sobald man dort die komplette 27-Farben-Palette verwenden will, ist es wieder da, nur ist der problematische Bereich jetzt keine kleine Farbkachel, sondern der komplette Bildschirm.

  • @ Mac Bacon


    Danke für Deine Ausführungen.
    Ich habe zu Hause einen MSX-1 von Sanyo stehen.
    Da habe ich ein Listing abgetippt für Bidschirmmodus 2, das zieht Zufallslinien kreuz und quer über den Bildschirm in bis zu 16 Farben.


    Die Auflösung in Modus 2 beträgt 256x192. Mehr schafft der MSX-1 nicht, egal in welchem Modus.


    Die Linien sahen gut aus, anders als das was Du verlinkt hast, daher war ich schon am Frust schieben, warum diese Gurke das kann und der C64 nicht.

  • aber ich "überfärbe" zwangsläufig.

    Yep, ist so. Das ist der Grund, warum 3d-Programme, die ihre Linien und Polygone frei auf der Bitmap zeichnen müssen, in der Regel nur 4 Farben haben (Flight Simulator II, Driller (etc), Star Wars, Chuck Yeager's AFT...) mit einer mir bekannten Ausnahme (Space Rogue). Nicht umsonst steht das erste C beim CPC für "colour".


    Wenn Du also wirklich Linien mit bunten Farben mischen willst, mußt Du so vorgehen wie Malprogramme:
    - Setze das Farbram ($d8000) sowie das zusätzliche Multicolourram auf die Hintergrundfarbe ($d021).
    - Entspricht die gewünschte Farbe der Hintergrundfarbe kannst Du sie überall verwenden. Ansonsten:
    - Jedes Mal beim Zeichnen eines Punktes oder zumindest beim Betreten einer neuen 8x8-Kachel schaust Du im Farbram ($d800) und Multicolourram nach, ob die gewünschte Farbe dort schon vorhanden ist. Falls ja, kannst Du diese Farbe mit dem entsprechenden Bitmuster weiterverwenden.
    - Ist die Farbe nicht darunter, schaust Du nach, ob sich im Farbram oder im Multicolourram noch eine Farbe befindet, die der Hintergrundfarbe entspricht. Falls ja, ersetze diese Farbe mit der gewünschten Farbe und verwende das dazugehörige Bitmuster zum Malen.
    - Was passieren soll, wenn bereits alle Farben aufgebraucht sind, hängt von Dir ab: a) Du malst gar nichts. b) Du setzt einen Punkt in der Hintergrundfarbe. c) Du schaust über eine Tabelle nach, ob sich eine ähnliche Farbe bereits im 8x8-Feld befindet (z. B. Grün und Hellgrün). Das ist sehr aufwendig. d) Du legst einen zusätzlichen Puffer an in der Größe des Farbrams, den Du zu Beginn mit 1 initialisierst. Jedes Mal, wenn Du im Farbram keine übereinstimmende Farbe findest, gibt der Wert im Puffer die Farbe an, in der Du malen kannst. Nach dem Setzen der Farbe im Farbram erhöhst Du den Zähler. Ist der Zähler größer 3, wird er auf 1 zurückgesetzt, d. h. die zuerst gemalte Farbe wird überschrieben.
    Mehr ist leider nicht möglich, und schnell sind diese Verfahren alle nicht. Daher bei Spielen die Beschränkung auf 4 vorher festgelegte Farben.

  • Ich habe zu Hause einen MSX-1 von Sanyo stehen.Da habe ich ein Listing abgetippt für Bidschirmmodus 2, das zieht Zufallslinien kreuz und quer über den Bildschirm in bis zu 16 Farben.


    Die Auflösung in Modus 2 beträgt 256x192. Mehr schafft der MSX-1 nicht, egal in welchem Modus.


    Die Linien sahen gut aus, anders als das was Du verlinkt hast, daher war ich schon am Frust schieben, warum diese Gurke das kann und der C64 nicht.

    Hm, interessant. Wiki sagt zu Modus 2:

    The challenge of using TMS9918 mode 2 was that every 8×1 pixel area could have only two colors, foreground and background. They could be freely picked out of the 16 color palette, but for each 8x1 area, only two colors could exist. When manipulating the screen in BASIC with the LINE command, one easily could exceed the maximum 2 colors per 8×1 area and end up with "color spill".

    Mach mal einen Screenshot. ;)
    Die Farbkacheln sind also tatsächlich deutlich kleiner als beim C64, aber auch dort vorhanden.


    Mal vergleichen:
    Der TMS9918 hat 256 horizontale Pixel, liest also pro Rasterzeile 32 Byte Bitmapdaten, plus 32 Byte für die Farbinformationen.
    Der VIC hat 320 horizontale Pixel, liest also pro Rasterzeile 40 Byte Grafikdaten, plus in jeder achten Rasterzeile 40 Byte Farbinformationen. Macht gemittelt 45 Byte pro Zeile und ist damit deutlich weniger als die 64 Byte des TMS9918.

  • [...] plus in jeder achten Rasterzeile 40 Byte Farbinformationen [...]

    Es sei denn... man bringt den VIC-II mit FLI dazu, die Farbinformationen in jeder Rasterzeile neu zu lesen. Dann ist wieder Gleichstand (was die "Farbdichte" angeht). ^^


    Ich hab' für den C128 übrigens damals™ eine BASIC-Erweiterung geschrieben, die (u.a.) exakt das von Bytebreaker angesprochene Problem löst, nämlich die automatische Vergabe der Farbquellen so daß der User nur noch die physische Farbe in einem Drawbefehl anzugeben braucht. Das zusammen mit einem Befehl zum Colorcycling. :D


    Zu finden bei http://c128.net/download -> Tool Basic.


    Gruß,


    Michael

  • Hier nochmal ein C64 Color Spill, den ich in reinem V2 Basic erzeugt habe (bitte den Code nicht so genau ansehen, es ist gewurschtelt und hat nur Anschauungszwecke).


    Ich werde mich nun daran machen, diesen Color Spill algorithmisch zu beheben unter Einsatz von 4 möglichen Farben und Bitmustern.