Drei Fragen zu Pixel Perfect

  • Drei Fragen zu Pixel Perfect

    Da dieses tolle Tool irgendwie an mir vorübergegangen ist, erst heute - nach Jahren also - meine Fragen aus GoDot-Sicht dazu. Sie drehen sich um das gepackte Bildformat, das ungepackte habe ich schon im Kasten. Herausgefunden habe ich erstmal Folgendes: Das gepackte Bild fängt vier Bytes früher an (statt an $3c00 an $3bfc) und wird nach einem einfachen RLE gepackt (Indikator, Zähler, Byte), der Indikator ist das Byte an $3bff und lautet $11. Jetzt die Fragen.

    1. Ich stelle fest, dass der Zähler immer um eins niedriger ist als die Anzahl der gezählten Bytes. PP zählt also mit $00 los. Wie geht PP mit 256 Wiederholungen um? Ist das $11, $00, $xx?
    2. Wie behandelt PP ein Vorkommen des Packbytes selber? $11, $01, $11? Oder anders?
    3. Was bedeuten die drei allerersten Bytes im File? Bei einem Beispielbild steht da dreimal $10, es kann sich also nicht um Farben handeln (für Border oder Hintergrund oder so, der Hintergrund steht eh an $7f7f).

    Würde gern schnell den Saver komplettieren und dann noch den IFLI-Lader mit PP updaten. Wer kennt sich also aus und kann helfen?

    Arndt
    GoDot C64 Image Processing
    www.godot64.de
  • Ich habe gerade mal in den code geschaut

    GoDot schrieb:

    1. Ich stelle fest, dass der Zähler immer um eins niedriger ist als die Anzahl der gezählten Bytes. PP zählt also mit $00 los. Wie geht PP mit 256 Wiederholungen um? Ist das $11, $00, $xx?
    Stimmt, der gespeicherte Zähler ist immer gleich runlength-1. Daraus folgt das bei einem Run mit einer Länge von 256 Zeichen der Wert $ff als Zähler abgespeichert wird. Höher als $ff kann der Zähler auch nicht werden.
    256 Wiederholungen eines Zeichens (also einen run von insgesamt 257 Zeichen länge) würde in Form eines Runs + einem darauf folgenden Literal codiert werden.

    GoDot schrieb:

    2. Wie behandelt PP ein Vorkommen des Packbytes selber? $11, $01, $11?
    Genau so. Der Escapecode wird immer in Form eines Runs gespeichert. Der zugehöre Zähler kann von $00-$ff gehen, wodurch sich Sequenzen von 1-256 aufeinanderfolgenden Escapecodes darstellen lassen. (bei allen anderen Bytes wird zuvor geprüft ob die runlänge > 3 ist. falls ja wird ein run codiert, falls nicht werden die Bytes einfach so ausgegeben)

    GoDot schrieb:

    3. Was bedeuten die drei allerersten Bytes im File? Bei einem Beispielbild steht da dreimal $10, es kann sich also nicht um Farben handeln (für Border oder Hintergrund oder so, der Hintergrund steht eh an $7f7f).
    K.A... Ich konnte auf die Schnelle keinen Programmteil entdecken welcher diese Bytes beschreibt. Möglicherweise ist es eine Magicnumber?
    Dateien
    • pp.txt

      (6,76 kB, 15 mal heruntergeladen, zuletzt: )
  • Rapid Eraser schrieb:

    Möglicherweise ist es eine Magicnumber?
    Ah, vielen Dank für die Infos! Der Quelltext ist sehr nützlich, das bedeutet nämlich, dass ich statt der $11 (die ich im Beispielbild als Escape-Code gefunden habe) auch irgendeinen anderen verwenden kann. Eine Optimierung dieses Codes halte ich sowieso für überbewertet, weshalb ich in GoDot (und dann in Zukunft sicher auch im Saver für Pixel Perfect) einfach $AD verwende. Liegt bei meinem Namen irgendwie nahe, hehe... ;)

    Meine Encodierungsroutine erscheint mir kürzer. Hier der Code:

    Brainfuck-Quellcode

    1. ; ----------------------------------------- Compress algorithm
    2. ; indicator, counter, byte (counter counts minus 1)
    3. pack bit packflag ; Flag, ob gepackt werden soll oder nicht
    4. bmi wl4
    5. jmp bsout ; dann eben nicht...
    6. wl4 cmp gbyte ; letztes Byte (startet mit $00 als Initwert)
    7. beq incr
    8. p255 pha ; laufendes Byte
    9. lda cnt ; Zähler, beim ersten Mal 0
    10. beq wl1
    11. cmp #$ff ; maximum compress?
    12. beq wl0 ; ja, Code-Sequenz ausgeben
    13. cmp #4 ; Zähler größer als 3?
    14. bcs wl0 ; ja, Code-Sequenz ausgeben
    15. lda gbyte ; letztes Byte gleich Escape-Code?
    16. cmp #$11 ; (war im File also $11)
    17. bne wl2 ; nein, dann einfach ausgeben (und Zähler um 1 erhöhen)
    18. ; sonst out: $11 $01 $11
    19. wl0 lda #$11 ; out: $11
    20. jsr bsout
    21. dec cnt ; Zähler minus 1
    22. lda cnt ; out: counter
    23. jsr bsout
    24. lda #1 ; jetzt Zähler auf 1
    25. sta cnt
    26. lda gbyte ; out: Byte
    27. wl2 jsr bsout
    28. dec cnt ; wenn Zähler=1 war, weiter:
    29. bne wl2
    30. wl1 pla ; laufendes Byte zu letztem Byte wandeln
    31. sta gbyte
    32. incr inc cnt ; Zähler erhöhen
    33. lda cnt ; 255 erreicht?
    34. cmp #$ff ; könnte man weglassen, dann würden 256 Bytes kodiert (oder?)
    35. bne wl3 ; nein, fertig
    36. lda gbyte ; sonst: Code-Sequenz ausgeben
    37. jsr p255
    38. dec cnt ; Zähler korrigieren
    39. wl3 rts ; fertig
    Alles anzeigen
    Dafür hat mein Code den Nachteil, nicht 256 zu erreichen. Ist aber zu verkraften, finde ich.

    Bleiben die drei $10 am Fileanfang: Die bedeuten was, denn wenn ich sie ändere, wird das Bild nicht mehr ordentlich dargestellt. Außerdem scheint das gepackte Bild seine Hintergrundfarbe irgendwo anders herzubeziehen als das ungepackte, denn im obigen Fall kriege ich immer Weiß (ich setze aber generell Schwarz...)

    Arndt
    GoDot C64 Image Processing
    www.godot64.de
  • Kann es sein, dass die $10 den ebenfalls um 1 verringerten Indicator darstellt, der in dieser Datei verwendet wird, und dass der Indikator in jedem File anders ist? So macht es jedenfalls der Packalgorithmus der Gfx/Anims in Bards Tale 1 von Burgerbecky.
    Dort sind die zwei verschiedenen Indikatoren in jedem File anders und werden ermittelt durch die ersten Bytes, die in den Bilddaten nicht vorkommen, um ein Escapen zu vermeiden.
    Life's good! :thumbup:
  • GoDot schrieb:

    Eine Optimierung dieses Codes halte ich sowieso für überbewertet, weshalb ich in GoDot (und dann in Zukunft sicher auch im Saver für Pixel Perfect) einfach $AD verwende. Liegt bei meinem Namen irgendwie nahe, hehe... ;)
    Ah, nein, mit $AD funktioniert es leider nicht. Aber ein $RE würde gehen. :whistling:

    GoDot schrieb:

    Bleiben die drei $10 am Fileanfang: Die bedeuten was, denn wenn ich sie ändere, wird das Bild nicht mehr ordentlich dargestellt.
    Du sollst eine Magicnumber ja auch nicht ändern, Arndt. :P

    Wenn ich das richtig erkannt habe dann wird nach dem Laden eins Bildes, egal ob gepackt oder ungepackt, die folgende Routine aufgerufen (die Daten werden nach Adresse $4000 geladen):

    Quellcode

    1. .C:1b1d A2 02 LDX #$02
    2. .C:1b1f BD 00 40 LDA $4000,X
    3. .C:1b22 C9 10 CMP #$10
    4. .C:1b24 D0 2D BNE $1B53
    5. .C:1b26 CA DEX
    6. .C:1b27 10 F6 BPL $1B1F
    7. ...
    8. .C:1b53 20 47 24 JSR $2447
    9. .C:1b56 4C A4 1A JMP $1AA4
    10. ...
    11. ; hier wird lustig im Speicher herumkopiert
    12. .C:2447 78 SEI
    13. .C:2448 A9 34 LDA #$34
    14. .C:244a 85 01 STA $01
    15. .C:244c AD 7F 83 LDA $837F
    16. .C:244f 48 PHA
    17. .C:2450 A2 3F LDX #$3F
    18. .C:2452 BD 00 C3 LDA $C300,X
    19. .C:2455 9D 00 FF STA $FF00,X
    20. .C:2458 CA DEX
    21. .C:2459 10 F7 BPL $2452
    22. .C:245b A9 C2 LDA #$C2
    23. .C:245d A2 FE LDX #$FE
    24. .C:245f A0 3F LDY #$3F
    25. .C:2461 20 3D 3D JSR $3D3D ; kopiere Bereich von 8400-c2ff nach c000-fe00 (oder so ähnlich...)
    26. .C:2464 A9 40 LDA #$40
    27. .C:2466 A2 BC LDX #$BC
    28. .C:2468 A0 04 LDY #$04
    29. .C:246a 20 BA 20 JSR $20BA ; kopiere Bereich von 4000-43ff nach bc00-bfff
    30. .C:246d A9 44 LDA #$44
    31. .C:246f A2 40 LDX #$40
    32. .C:2471 A0 40 LDY #$40
    33. .C:2473 20 BA 20 JSR $20BA ; kopiere Bereich von 4400-8400 nach 4000-8000
    34. .C:2476 A9 BC LDA #$BC
    35. .C:2478 A2 80 LDX #$80
    36. .C:247a A0 04 LDY #$04
    37. .C:247c 20 BA 20 JSR $20BA ; kopiere Bereich von bc00-bfff nach 8000-83ff
    38. .C:247f 68 PLA
    39. .C:2480 8D 7F 7F STA $7F7F
    40. .C:2483 E6 01 INC $01
    41. .C:2485 60 RTS
    Alles anzeigen
    Schaut für mich ersteinmal so aus als würde die $10 $10 $10 tatsächlich nur zur Unterscheidung von gepackten und ungepackten Bildern dienen.

    GoDot schrieb:

    Außerdem scheint das gepackte Bild seine Hintergrundfarbe irgendwo anders herzubeziehen als das ungepackte, denn im obigen Fall kriege ich immer Weiß (ich setze aber generell Schwarz...)
    Hast du mal probiert ein Bild mit verschiedenen Hintergrundfarben abzuspeichern? Da müsste man im Vergleich ja herausbekommen wo die Farbe gespeichert steht.


    PS: bei der Kommentierung des Packers habe ich mich bei den Kommentaren gegen Ende hin glaube ich mit Input- und Output-Buffer vertan. Und wahrscheinilch stecken da auch noch andere Fehler drin... Darauf sei ein geneigter Leser hiermit hingewiesen.
  • Rapid Eraser schrieb:

    C:2447 78 SEI
    .C:2448 A9 34 LDA #$34
    .C:244a 85 01 STA $01
    .C:244c AD 7F 83 LDA $837F
    .C:244f 48 PHA
    Ah! Da steht also, dass beim gepackten Bild die Hintergrundfarbe nicht aus der Bitmap des ersten Teilbildes (von $7f7f) geholt wird, sondern nun aus dem ersten Videoram des zweiten Teilbildes (von $837f). Das probier ich gleich mal aus. :)

    Und: $AD funktioniert, hehe. Mit $RE hättest du ein Problem. :P

    Arndt
    GoDot C64 Image Processing
    www.godot64.de
  • Ich hab mal reingeschaut. Die Stelle ist mitten im gepackten Code, d.h. die Hintergrundfarbe bei einem gepackten Bild ist nach dem Laden im Editor immer zufällig! Das ist ein Bug! Die Adresse $837f macht keinen Sinn! In meinem Bild (wo Weiß herauskommt) steht da $61, das Lo-Nibble ist $01, also weiß.

    Was nun?

    Arndt
    GoDot C64 Image Processing
    www.godot64.de
  • GoDot schrieb:

    Ich hab mal reingeschaut. Die Stelle ist mitten im gepackten Code, d.h. die Hintergrundfarbe bei einem gepackten Bild ist nach dem Laden im Editor immer zufällig!

    Hmm, ich habe den Code noch anders verstanden. Getestet habe ich es nicht, aber für mich sieht das Konzept folgendermaßen aus:
    1) lade das Imagefile (egal ob gepackt oder ungepackt) nach Adresse $4000
    2) überprüfe anhand von $10 $10 $10 ob die Daten gepackt sind
    2a) falls ja dann entpacke sie nach Adresse $4000 (ab $1b29/$1b59). anschließend stehen sie im gleichen Format wie ein ungepacktes Bild im Speicher (das sollte ja so aussehen wie in den docs beschrieben):
    $3c00-$4000 $d800 memory
    $4000-$6000 color memory 1
    $6000-$7f40 bitmap 1
    $7f7f background color
    $8000-$a000 color memory 2
    $a000-$bf40 bitmap 2
    3) egal ob das Bild von Anfang an ungepackt war oder gerade entpackt wurde, die Daten ab $4000 müssen nun im Speicher neu arrangiert werden damit der VIC das Bild darstellen kann (ab $2447). Da die Daten gegenüber der obigen Tabelle einen Offset von $0400 haben (sie liegen ja ab $4000 im Speicher und nicht ab $3c00) findet sich die Hintergrundfarbe dementsprechend nicht bei $7f7f sondern bei $837f. Der Wert wird vor dem rearrangieren gerettet (ab $244c), dann wird "color memory 2" nach $8000-$a000 kopiert - wodurch $837f freilich überschrieben wird - und zum Schluß wird die gerettete Hintergrundfarbe nach $7f7f geschrieben (ab $247f), wo sie ja auch hin soll.
    Dateien
    • ppl.txt

      (6,4 kB, 13 mal heruntergeladen, zuletzt: )
  • Rapid Eraser schrieb:

    1) lade das Imagefile (egal ob gepackt oder ungepackt) nach Adresse $4000
    2) überprüfe anhand von $10 $10 $10 ob die Daten gepackt sind
    2a) falls ja dann entpacke sie nach Adresse $4000 (ab $1b29/$1b59). anschließend stehen sie im gleichen Format wie ein ungepacktes Bild im Speicher
    Ja, nach dem Source-Text zu urteilen, soll das wohl so sein. Hm. Da muss dann was schief gehen. Bei allen anderen Bildern, die ich getestet habe, kommt ebenfalls Weiß raus. Mir fällt da nur ein, dass ich das Ganze auf VICE teste und der Autor ausdrücklich sagt, PP sei für die Real Machine geschrieben. Leider macht es mein alter (erster und nunmehr einziger) C64 nicht mehr (er steht hier als zu bewunderndes Ausstellungsstück im Regal), ich kann das nicht selber verifizieren. Der Saver ist auf godot64.de zum Download (im dritten D64, Name: svr.PixelPerfect). Vielleicht ist das Problem ja gar keins.

    Hehe, und ich weiß jetzt, was dreimal $10 sein soll: "ppp" in Bildschirmcode! :) Na, sowas! :)

    Arndt
    GoDot C64 Image Processing
    www.godot64.de
  • GoDot schrieb:

    Da muss dann was schief gehen. Bei allen anderen Bildern, die ich getestet habe, kommt ebenfalls Weiß raus. Mir fällt da nur ein, dass ich das Ganze auf VICE teste und der Autor ausdrücklich sagt, PP sei für die Real Machine geschrieben.
    Ich habe es auch nur mit vice v2.4 getestet, und dort zumindest kann Perfect Pixel selber die Hintergrundfarbe korrekt speichern/laden (getestet nur mit dem Beispielbild).

    Wenn ich in der post-load-routine

    Quellcode

    1. .C:2447 78 SEI
    2. .C:2448 A9 34 LDA #$34
    3. .C:244a 85 01 STA $01
    4. .C:244c AD 7F 83 LDA $837F
    5. .C:244f 48 PHA
    das LDA $837f in z.B.

    Quellcode

    1. .C:244c AD 7F 83 LDA #$06
    2. .C:244e EA NOP
    ändere, dann setzt er nach dem Laden auch tatsächlich diese Hintergrundfarbe. In $837f sollte also durchaus die Farbe drin stehen.
    Wie sahen denn deine Tests aus? Magst du mir mal die Sourcen für deine pack/depack-routinen per pm senden?




    GoDot schrieb:

    Hehe, und ich weiß jetzt, was dreimal $10 sein soll: "ppp" in Bildschirmcode! :) Na, sowas! :)
    Aahhhsoooistdas... 8o
  • Da haben wir's ja schon:

    Brainfuck-Quellcode

    1. ; ----------------------------------------- Write .Y zero bytes
    2. write0 lda #0 ; $7f7f = bkground (in this 0-chunk)
    3. wr0 jsr pack
    4. dey
    5. bne wr0
    6. rts
    7. [...]
    8. ; ----------------------------------------- Compress algorithm
    9. ; indicator, counter, byte (counter counts minus 1)
    10. pack bit packflag
    11. bmi wl4
    12. jmp bsout
    13. wl4 cmp gbyte
    14. beq incr
    15. [...]
    16. incr inc cnt
    17. lda cnt
    18. cmp #$ff
    19. bne wl3
    20. [...]
    21. wl3 rts
    Alles anzeigen
    JSR PACK verändert den Accu. Wenn man in WRITE0 das BNE WR0 durch BNE WRITE0 ersetzt dann klappt's. (zumindest bei dem PP-Beispielbild hat er dann korrekt schwarz als BG-Color abgespeichert. ansonsten hatte er in dem Bereich halt immer Einsen (cnt) ausgegeben).
  • Neu

    GoDot schrieb:

    Oh Mann! 8\| Danke!
    Es war mir ein Vergnügen. *verbeug*

    GoDot schrieb:

    Jetzt ist alles fertig: Saver (wieder mal mit eurer Hilfe!) und ebenso der Lader (der jetzt vier bzw. fünf Formate automatisch erkennt). Download auf der Downloadseite von GoDot.
    Lol, ein Freund von mir würde das nun gleich zum Anlass nehmen in seiner nächsten Bewerbung zu schreiben das er "Co-Autor einer Middleware einer inter-plattform orientierten Multimedia-Solution" sei (oder so ähnlich; er konnte noch viel besser schwätzen als ich).
    Hmm, er hatte seinerzeit (vermutlich aufgrund einer solchen Bewerbung) auch sofort eine Greencard bekommen und ist die die USA abgedampft. Mittlerweile lebt und arbeitet er in Australien und macht ordentlich Kohle. Vielleicht sollte ich es ja auch mal auf diese Weise versuchen..? :gruebel

    ZeroZero schrieb:

    Cool!!! Good job!
    Ganz meine Meinung. :thumbup:
  • Benutzer online 2

    2 Besucher